ola-0.10.5.nojsmin/0000755000175000017500000000000013134123611013453 5ustar wouterwouterola-0.10.5.nojsmin/README.developer0000644000175000017500000002042213023355232016322 0ustar wouterwouter Developer Information ############################################################################### This file provides some information for developers looking to submit patches to OLA. The first section contains some general notes, and the latter sections address particular languages. Also take a look at README which includes some relevant information for developers too. General =============================================================================== Code Reviews ------------ To have patches reviewed please push your changes to GitHub and create a Pull Request from within your fork. If you're using Google Code please enable comments on the repo. Under Administer -> Source check: Enable code reviews Allow non-members to review code Licensing --------- Think carefully about the license for each file. Code to be used by clients (./ola , ./python) should be under the LGPL, so that it may be used in commercial projects. Plugins and code used solely in olad should be under the GPL. scripts/enforce_licence.py will look for a LICENCE file in each directory, and ensure that all source files in the directory ( & subdirectories) start with the LICENCE. You can pass --fix to automatically add the licence. Unittests --------- Unittests are *highly* encouraged. At the very least please make sure any changes don't break the tests. The tests are performed with `make check` in the root ola directory. The same command can be run within a sub directory to only run a particular set of tests (although you may experience issues with this method, running from the root ola directory is guaranteed to work). Branches, Versioning & Releases ------------------------------- Version numbers take the form MAJOR.MINOR.PATCH based on http://semver.org/. The release lifecycle is: - New feature work occurs on the master branch. - Once the new features are considered stable or enough time has passed, a new minor release branch will be created, e.g. 0.10. - The minor release branch will be stablized with bugfixes, these bug fixes will also be merged back into master. - Once declared stable, a new patch branch 0 will be created e.g. 0.10.0 - Release specific changes like the version number, debian files etc. will be pushed to the patch branch. - The release will occur. - Changes on the release branch will be merged back into the minor version branch. - Bug fixes will continue on the minor version branch, leading to another patch release. What this means for you as a developer is that depending on the scope of your change, we may request that you merge it into the minor release branch rather than master. This allows us to get your change out to end uses faster than if it was merged into master directly. C++ =============================================================================== The bulk of OLA code is written in C++. This includes the daemon olad, and plugins. https://wiki.openlighting.org/index.php/OLA_developer_info describes many of the underlying classes used. C++ 11 ------ As much as we'd like to start using C++11, Ubuntu 12.04 still comes with g++ 4.6 which has partial support. Once 12.04 is end-of-lifed, we'll consider using C++ 11 constructs. Endian Issues ------------- Be aware that OLA runs on big endian systems. When dealing with wire formats always use the functions in include/ola/network/NetworkUtils.h to convert or use the BigEndianOutputStream to manage this automatically for you. Structure Packing ----------------- Structure packing syntax differs between platforms and compilers. If you declare a struct or class that needs to be packed, use the PACK() macro from ola/base/Macro.h . See below for an example of PACK() usage. Not that this macro doesn't work for enums. See plugins/espnet/EspNetPackets.h for an example of how to pack an enum. Non x86 platforms ----------------- OLA also runs on more than just x86. Some platforms like ARM can't de-reference pointers which aren't aligned. For example: PACK(struct f { uint8_t value1; uint16_t value2; }); struct f foo = {1, 2}; uint16_t *ptr = &foo.value2; // Bug! Will not be true on all platforms. if (*ptr == 2) http://www.aleph1.co.uk/chapter-10-arm-structured-alignment-faq has a good explanation. Style / Coding Standards ------------------------ We use the Google C++ Style Guide: https://google.github.io/styleguide/cppguide.html We provide formatting configuration files for some IDEs at https://github.com/OpenLightingProject/editor-configs . If you use an IDE which isn't listed there please consider submitting the formatting configuration files. Please run the cpplint.py script on all files before requesting a review, alternatively it will be run automatically by Travis CI on pull requests. cpplint.py can be downloaded here: https://github.com/google/styleguide/tree/gh-pages/cpplint Run it with: --filter=-legal/copyright,-readability/streams,-runtime/arrays Doxygen ------- The code is documented using Doxygen. There is an automatically generated version available from: https://docs.openlighting.org/ola/doc/latest/ If you want to build it yourself, install Doxygen, run ./configure in the ola root directory, then run make doxygen-doc. The files will be generated into html/ Race Conditions --------------- If possible, code should be tested with slower machines (embedded platforms, virtual machines etc.). This has discovered race conditions in the past. Valgrind -------- All code must be tested with valgrind to ensure it doesn't leak memory. Coverage (gcov) --------------- To enable the coverage tools, you need lcov and gcov installed. To enable run ./configure --enable-gcov and then build as normal. To generate the HTML pages run: mkdir /tmp/lcov tmpdir=`mktemp -d /tmp/lcov.XXXXXX` coverage="${tmpdir}/coverage.info" lcov --capture --directory ./ --output-file $coverage genhtml $coverage --output-directory /tmp/lcov Java =============================================================================== An experimental Java API is provided. Style / Coding Standards ------------------------ Please follow the Sun Java style guide. Javascript =============================================================================== Javascript is used for the olad web UI. Instructions for building the javascript can be found in javascript/README. Closure Compiler ---------------- The closure compiler catches many errors. The javascript code should build cleanly. Style / Coding Standards ------------------------ We use the Google Javascript style guide: https://google.github.io/styleguide/javascriptguide.xml A javascript linter can be downloaded from: https://developers.google.com/closure/utilities/docs/linter_howto?csw=1 Please make sure all Javascript code is lint clean. Python =============================================================================== Python is used for tools like the RDM responder tests and the device model collector. To enable these a OLA Python API is provided. Style / Coding Standards ------------------------ We use the Google Python style guide: https://google.github.io/styleguide/pyguide.html However we deviate from the standard and use 2 space indents, so it's consistent with the C++ code. It's linted and static analysis is performed using flake8, you can either run it yourself or await the Travis CI results of your pull request. flake8 can be installed following the instructions here: https://gitlab.com/pycqa/flake8/ Run it with: --max-line-length 80 --exclude *_pb2.py,.git,__pycache \ --ignore E111,E121,E127,E129 data/rdm include/ola python scripts \ tools/ola_mon tools/rdm Build System =============================================================================== Autotools is a complex beast. Even after reading two books and a using it for a decade I still feel like I hardly understand it. Useful tips ----------- * Run `make distcheck` to ensure you haven't broken anything. * Use $(srcdir), $(top_srcdir) to reference files where required. This is to support VPATH builds: http://www.gnu.org/software/automake/manual/html_node/VPATH-Builds.html * Prefer manualy dependencies over BUILT_SOURCES where possible, see http://www.gnu.org/software/automake/manual/html_node/Built-Sources-Example.html However this doesn't work in some cases (libraries?) because it overrides the automake generated rules. ola-0.10.5.nojsmin/Makefile.in0000644000175000017500000573733213134123354015550 0ustar wouterwouter# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 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@ # Copyright (C) 2004 Oren Ben-Kiki # This file is distributed under the same terms as the Automake macro files. # Generate automatic documentation using Doxygen. Goals and variables values # are controlled by the various DX_COND_??? conditionals set by autoconf. # # The provided goals are: # doxygen-doc: Generate all doxygen documentation. # doxygen-run: Run doxygen, which will generate some of the documentation # (HTML, CHM, CHI, MAN, RTF, XML) but will not do the post # processing required for the rest of it (PS, PDF, and some MAN). # doxygen-man: Rename some doxygen generated man pages. # doxygen-ps: Generate doxygen PostScript documentation. # doxygen-pdf: Generate doxygen PDF documentation. # # Note that by default these are not integrated into the automake goals. If # doxygen is used to generate man pages, you can achieve this integration by # setting man3_MANS to the list of man pages generated and then adding the # dependency: # # $(man3_MANS): doxygen-doc # # This will cause make to run doxygen and generate all the documentation. # # The following variable is intended for use in Makefile.am: # # DX_CLEANFILES = everything to clean. # # This is usually added to MOSTLYCLEANFILES. # Note: gcc 4.6.1 is pretty strict about library ordering. Libraries need to be # specified in the order they are used. i.e. a library should depend on things # to the right, not the left. # See http://www.network-theory.co.uk/docs/gccintro/gccintro_18.html # This file is included directly in Makefile.am rather than via # olad/Makefile.mk due to the order of dependencies between them; we need to # build olad/plugin_api, then the plugins, then olad # OLA Python client # ola python client VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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 = : build_triplet = @build@ host_triplet = @host@ # The genererated protobuf files don't compile with -Werror on win32 so we # disable fatal warnings on WIN32. @FATAL_WARNINGS_TRUE@@USING_WIN32_FALSE@am__append_1 = -Werror @FATAL_WARNINGS_TRUE@@USING_WIN32_FALSE@am__append_2 = -Werror -Wno-error=unused-parameter \ @FATAL_WARNINGS_TRUE@@USING_WIN32_FALSE@ -Wno-error=deprecated-declarations \ @FATAL_WARNINGS_TRUE@@USING_WIN32_FALSE@ -Wno-error=sign-compare @FATAL_WARNINGS_TRUE@@USING_WIN32_FALSE@am__append_3 = -Werror @FATAL_WARNINGS_TRUE@@USING_WIN32_FALSE@am__append_4 = -Werror -Wno-error=unused-parameter \ @FATAL_WARNINGS_TRUE@@USING_WIN32_FALSE@ -Wno-error=deprecated-declarations # Due to MinGW's handling of library archives, we need to append this. @USING_WIN32_TRUE@am__append_5 = $(CPPUNIT_LIBS) bin_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ $(am__EXEEXT_4) $(am__EXEEXT_5) olad/olad$(EXEEXT) \ $(am__EXEEXT_6) $(am__EXEEXT_7) \ tools/ola_trigger/ola_trigger$(EXEEXT) $(am__EXEEXT_8) check_PROGRAMS = $(am__EXEEXT_20) noinst_PROGRAMS = $(am__EXEEXT_21) $(am__EXEEXT_22) $(am__EXEEXT_23) \ libs/acn/e131_transmit_test$(EXEEXT) \ libs/acn/e131_loadtest$(EXEEXT) $(am__EXEEXT_24) \ $(am__EXEEXT_25) $(am__EXEEXT_26) # ------------------------------------------ @USING_WIN32_TRUE@am__append_6 = -lWs2_32 -lIphlpapi # LIBRARIES ################################################## @HAVE_LIBMICROHTTPD_TRUE@am__append_7 = common/http/libolahttp.la @USING_WIN32_TRUE@am__append_8 = \ @USING_WIN32_TRUE@ common/io/WindowsPoller.cpp \ @USING_WIN32_TRUE@ common/io/WindowsPoller.h @USING_WIN32_FALSE@am__append_9 = \ @USING_WIN32_FALSE@ common/io/SelectPoller.cpp \ @USING_WIN32_FALSE@ common/io/SelectPoller.h @HAVE_EPOLL_TRUE@am__append_10 = \ @HAVE_EPOLL_TRUE@ common/io/EPoller.h \ @HAVE_EPOLL_TRUE@ common/io/EPoller.cpp @HAVE_KQUEUE_TRUE@am__append_11 = \ @HAVE_KQUEUE_TRUE@ common/io/KQueuePoller.h \ @HAVE_KQUEUE_TRUE@ common/io/KQueuePoller.cpp @USING_WIN32_TRUE@am__append_12 = \ @USING_WIN32_TRUE@ common/network/WindowsInterfacePicker.h \ @USING_WIN32_TRUE@ common/network/WindowsInterfacePicker.cpp @USING_WIN32_FALSE@am__append_13 = \ @USING_WIN32_FALSE@ common/network/PosixInterfacePicker.h \ @USING_WIN32_FALSE@ common/network/PosixInterfacePicker.cpp # LIBRARIES ################################################## @BUILD_TESTS_TRUE@am__append_14 = common/testing/libolatesting.la \ @BUILD_TESTS_TRUE@ common/testing/libtestmain.la # TESTS ################################################ @BUILD_TESTS_TRUE@am__append_15 = data/rdm/PidDataTester @BUILD_PYTHON_LIBS_TRUE@@BUILD_TESTS_TRUE@am__append_16 = data/rdm/PidDataTest.sh @BUILD_EXAMPLES_TRUE@am__append_17 = \ @BUILD_EXAMPLES_TRUE@ doxygen/examples/callback_client_transmit \ @BUILD_EXAMPLES_TRUE@ doxygen/examples/client_disconnect \ @BUILD_EXAMPLES_TRUE@ doxygen/examples/client_thread \ @BUILD_EXAMPLES_TRUE@ doxygen/examples/fetch_plugins \ @BUILD_EXAMPLES_TRUE@ doxygen/examples/flags \ @BUILD_EXAMPLES_TRUE@ doxygen/examples/legacy_callback_client_transmit \ @BUILD_EXAMPLES_TRUE@ doxygen/examples/legacy_receiver \ @BUILD_EXAMPLES_TRUE@ doxygen/examples/legacy_streaming_client \ @BUILD_EXAMPLES_TRUE@ doxygen/examples/receiver \ @BUILD_EXAMPLES_TRUE@ doxygen/examples/stdin_handler \ @BUILD_EXAMPLES_TRUE@ doxygen/examples/streaming_client \ @BUILD_EXAMPLES_TRUE@ doxygen/examples/udp_server @BUILD_EXAMPLES_TRUE@@HAVE_DLOPEN_TRUE@am__append_18 = doxygen/examples/streaming_client_plugin # LIBRARIES ################################################## @BUILD_EXAMPLES_TRUE@am__append_19 = examples/libolaconfig.la # PROGRAMS ################################################## @BUILD_EXAMPLES_TRUE@am__append_20 = \ @BUILD_EXAMPLES_TRUE@ examples/ola_dev_info \ @BUILD_EXAMPLES_TRUE@ examples/ola_rdm_discover \ @BUILD_EXAMPLES_TRUE@ examples/ola_rdm_get \ @BUILD_EXAMPLES_TRUE@ examples/ola_recorder \ @BUILD_EXAMPLES_TRUE@ examples/ola_streaming_client \ @BUILD_EXAMPLES_TRUE@ examples/ola_timecode \ @BUILD_EXAMPLES_TRUE@ examples/ola_uni_stats @BUILD_EXAMPLES_TRUE@@USE_E131_TRUE@am__append_21 = examples/ola_e131 @BUILD_EXAMPLES_TRUE@@USE_USBPRO_TRUE@am__append_22 = examples/ola_usbpro @BUILD_EXAMPLES_TRUE@@USE_ARTNET_TRUE@am__append_23 = examples/ola_artnet @BUILD_EXAMPLES_TRUE@@HAVE_NCURSES_TRUE@am__append_24 = examples/ola_dmxconsole examples/ola_dmxmonitor @BUILD_EXAMPLES_TRUE@am__append_25 = examples/ola_throughput examples/ola_latency @BUILD_EXAMPLES_TRUE@am__append_26 = install-exec-hook-examples # TESTS_DATA ################################################## @BUILD_EXAMPLES_TRUE@am__append_27 = \ @BUILD_EXAMPLES_TRUE@ examples/testdata/dos_line_endings \ @BUILD_EXAMPLES_TRUE@ examples/testdata/multiple_unis \ @BUILD_EXAMPLES_TRUE@ examples/testdata/partial_frames \ @BUILD_EXAMPLES_TRUE@ examples/testdata/single_uni \ @BUILD_EXAMPLES_TRUE@ examples/testdata/trailing_timeout # TESTS ################################################## @BUILD_EXAMPLES_TRUE@am__append_28 = examples/RecorderVerifyTest.sh @BUILD_EXAMPLES_TRUE@am__append_29 = examples/RecorderVerifyTest.sh @INSTALL_ACN_TRUE@am__append_30 = \ @INSTALL_ACN_TRUE@ include/ola/acn/ACNPort.h \ @INSTALL_ACN_TRUE@ include/ola/acn/ACNVectors.h \ @INSTALL_ACN_TRUE@ include/ola/acn/CID.h # pkg-config ################################################## @INSTALL_E133_TRUE@am__append_31 = libs/acn/libolaacn.pc # LIBRARIES ################################################## @INSTALL_ACN_TRUE@am__append_32 = libs/acn/libolaacn.la @INSTALL_ACN_FALSE@am__append_33 = libs/acn/libolaacn.la # LIBRARIES ################################################## @USE_LIBUSB_TRUE@am__append_34 = libs/usb/libolausb.la # TESTS ################################################## @USE_LIBUSB_TRUE@am__append_35 = libs/usb/LibUsbThreadTester # LIBRARIES ################################################## # The OLA artnet plugin @USE_ARTNET_TRUE@am__append_36 = \ @USE_ARTNET_TRUE@ plugins/artnet/messages/libolaartnetconf.la \ @USE_ARTNET_TRUE@ plugins/artnet/libolaartnet.la @USE_ARTNET_TRUE@am__append_37 = plugins/artnet/messages/ArtNetConfigMessages.pb.cc \ @USE_ARTNET_TRUE@ plugins/artnet/messages/ArtNetConfigMessages.pb.h # LIBRARIES ################################################## # This is a library which isn't coupled to olad @USE_ARTNET_TRUE@am__append_38 = plugins/artnet/libolaartnetnode.la # PROGRAMS ################################################## @USE_ARTNET_TRUE@am__append_39 = plugins/artnet/artnet_loadtest # TESTS ################################################## @USE_ARTNET_TRUE@am__append_40 = plugins/artnet/ArtNetTester # LIBRARIES ################################################## @USE_DUMMY_TRUE@am__append_41 = plugins/dummy/liboladummy.la # TESTS ################################################## @USE_DUMMY_TRUE@am__append_42 = plugins/dummy/DummyPluginTester # LIBRARIES ################################################## @USE_ESPNET_TRUE@am__append_43 = plugins/espnet/libolaespnet.la # TESTS ################################################## @USE_ESPNET_TRUE@am__append_44 = plugins/espnet/EspNetTester # LIBRARIES ################################################## @USE_FTDI_TRUE@am__append_45 = plugins/ftdidmx/libolaftdidmx.la # LIBRARIES ################################################## @USE_GPIO_TRUE@am__append_46 = plugins/gpio/libolagpiocore.la \ @USE_GPIO_TRUE@ plugins/gpio/libolagpio.la # LIBRARIES ################################################## @USE_KARATE_TRUE@am__append_47 = plugins/karate/libolakarate.la # LIBRARIES ################################################## # This is a library which isn't coupled to olad @USE_KINET_TRUE@am__append_48 = plugins/kinet/libolakinetnode.la @USE_KINET_TRUE@am__append_49 = plugins/kinet/libolakinet.la # TESTS ################################################## @USE_KINET_TRUE@am__append_50 = plugins/kinet/KiNetTester # LIBRARIES ################################################## @USE_MILINST_TRUE@am__append_51 = plugins/milinst/libolamilinst.la # LIBRARIES ################################################## @USE_OPENDMX_TRUE@am__append_52 = plugins/opendmx/libolaopendmx.la # LIBRARIES ################################################## # This is a library which isn't coupled to olad @USE_OPENPIXELCONTROL_TRUE@am__append_53 = plugins/openpixelcontrol/libolaopc.la @USE_OPENPIXELCONTROL_TRUE@am__append_54 = plugins/openpixelcontrol/libolaopenpixelcontrol.la # TESTS ################################################## @USE_OPENPIXELCONTROL_TRUE@am__append_55 = \ @USE_OPENPIXELCONTROL_TRUE@ plugins/openpixelcontrol/OPCClientTester \ @USE_OPENPIXELCONTROL_TRUE@ plugins/openpixelcontrol/OPCServerTester # LIBRARIES ################################################## # This is a library which isn't coupled to olad @USE_OSC_TRUE@am__append_56 = plugins/osc/libolaoscnode.la @USE_OSC_TRUE@am__append_57 = plugins/osc/libolaosc.la # TESTS ################################################## @USE_OSC_TRUE@am__append_58 = plugins/osc/OSCTester # LIBRARIES ################################################## @USE_PATHPORT_TRUE@am__append_59 = plugins/pathport/libolapathport.la # LIBRARIES ################################################## @USE_RENARD_TRUE@am__append_60 = plugins/renard/libolarenard.la # LIBRARIES ################################################## @USE_SANDNET_TRUE@am__append_61 = plugins/sandnet/libolasandnet.la # LIBRARIES ################################################## @USE_SHOWNET_TRUE@am__append_62 = plugins/shownet/libolashownet.la # TESTS ################################################## @USE_SHOWNET_TRUE@am__append_63 = plugins/shownet/ShowNetTester # LIBRARIES ################################################## # This is a library which isn't coupled to olad @USE_SPI_TRUE@am__append_64 = plugins/spi/libolaspicore.la plugins/spi/libolaspi.la # TESTS ################################################## @USE_SPI_TRUE@am__append_65 = plugins/spi/SPITester # LIBRARIES ################################################## @USE_STAGEPROFI_TRUE@am__append_66 = plugins/stageprofi/libolastageprofi.la # LIBRARIES ################################################## @USE_LIBUSB_TRUE@am__append_67 = plugins/usbdmx/libolausbdmxwidget.la @USE_LIBUSB_TRUE@am__append_68 = plugins/usbdmx/libolausbdmx.la # The UsbPro plugin config messages. This needs to be available to client # programs. # The E1.31 plugin config messages. This needs to be available to client # programs. @USING_WIN32_FALSE@am__append_69 = plugins/usbpro/messages/UsbProConfigMessages.proto \ @USING_WIN32_FALSE@ plugins/e131/messages/E131ConfigMessages.proto # pkg-config ################################################## # pkg-config ################################################## @USING_WIN32_FALSE@am__append_70 = plugins/usbpro/messages/libolausbproconf.pc \ @USING_WIN32_FALSE@ plugins/e131/messages/libolae131conf.pc # LIBRARIES ################################################## @USING_WIN32_FALSE@am__append_71 = plugins/usbpro/messages/libolausbproconf.la @USING_WIN32_FALSE@am__append_72 = plugins/usbpro/messages/UsbProConfigMessages.pb.cc \ @USING_WIN32_FALSE@ plugins/usbpro/messages/UsbProConfigMessages.pb.h # LIBRARIES ################################################## # This is a library which isn't coupled to olad @USING_WIN32_FALSE@am__append_73 = plugins/usbpro/libolausbprowidget.la # The OLA USB Pro Plugin @USE_USBPRO_TRUE@@USING_WIN32_FALSE@am__append_74 = plugins/usbpro/libolausbpro.la # TESTS ################################################## @USE_USBPRO_TRUE@@USING_WIN32_FALSE@am__append_75 = \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/ArduinoWidgetTester \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/BaseRobeWidgetTester \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/BaseUsbProWidgetTester \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/DmxTriWidgetTester \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/DmxterWidgetTester \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/EnttecUsbProWidgetTester \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/RobeWidgetDetectorTester \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/RobeWidgetTester \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/UltraDMXProWidgetTester \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/UsbProWidgetDetectorTester \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/WidgetDetectorThreadTester # LIBRARIES ################################################## @USE_DMX4LINUX_TRUE@@USING_WIN32_FALSE@am__append_76 = plugins/dmx4linux/liboladmx4linux.la # LIBRARIES ################################################## # LIBRARIES ################################################## @USE_E131_TRUE@@USING_WIN32_FALSE@am__append_77 = plugins/e131/messages/libolae131conf.la \ @USE_E131_TRUE@@USING_WIN32_FALSE@ plugins/e131/libolae131.la @USE_E131_TRUE@@USING_WIN32_FALSE@am__append_78 = plugins/e131/messages/E131ConfigMessages.pb.cc \ @USE_E131_TRUE@@USING_WIN32_FALSE@ plugins/e131/messages/E131ConfigMessages.pb.h # LIBRARIES ################################################## @USE_UART_TRUE@@USING_WIN32_FALSE@am__append_79 = plugins/uartdmx/libolauartdmx.la @HAVE_DNSSD_TRUE@am__append_80 = olad/BonjourDiscoveryAgent.h \ @HAVE_DNSSD_TRUE@ olad/BonjourDiscoveryAgent.cpp @HAVE_AVAHI_TRUE@am__append_81 = olad/AvahiDiscoveryAgent.h olad/AvahiDiscoveryAgent.cpp @HAVE_AVAHI_TRUE@am__append_82 = $(avahi_LIBS) @HAVE_LIBMICROHTTPD_TRUE@am__append_83 = olad/HttpServerActions.cpp \ @HAVE_LIBMICROHTTPD_TRUE@ olad/OladHTTPServer.cpp \ @HAVE_LIBMICROHTTPD_TRUE@ olad/RDMHTTPModule.cpp @HAVE_LIBMICROHTTPD_TRUE@am__append_84 = common/http/libolahttp.la @USE_FTDI_TRUE@am__append_85 = -lftdi -lusb # Programs ######################### @BUILD_OLA_PROTOC_PLUGIN_TRUE@am__append_86 = protoc/ola_protoc_plugin @BUILD_PYTHON_LIBS_TRUE@am__append_87 = python/ola/rpc/Rpc_pb2.py \ @BUILD_PYTHON_LIBS_TRUE@ $(output_files) # TESTS ################################################## @BUILD_PYTHON_LIBS_TRUE@am__append_88 = python/ola/rpc/SimpleRpcControllerTest.sh \ @BUILD_PYTHON_LIBS_TRUE@ python/ola/DUBDecoderTest.py \ @BUILD_PYTHON_LIBS_TRUE@ python/ola/MACAddressTest.py \ @BUILD_PYTHON_LIBS_TRUE@ python/ola/UIDTest.py @BUILD_JA_RULE_TRUE@am__append_89 = tools/ja-rule/ja-rule \ @BUILD_JA_RULE_TRUE@ tools/ja-rule/ja-rule-controller @HAVE_SALEAE_LOGIC_TRUE@am__append_90 = tools/logic/logic_rdm_sniffer @INSTALL_RDM_TESTS_TRUE@am__append_91 = tools/rdm/DataLocation.py # pkg-config ################################################## @INSTALL_E133_TRUE@@USING_WIN32_FALSE@am__append_92 = \ @INSTALL_E133_TRUE@@USING_WIN32_FALSE@ tools/e133/libolae133common.pc \ @INSTALL_E133_TRUE@@USING_WIN32_FALSE@ tools/e133/libolae133controller.pc @INSTALL_E133_TRUE@@USING_WIN32_FALSE@am__append_93 = $(E133_LIBS) @INSTALL_E133_FALSE@@USING_WIN32_FALSE@am__append_94 = $(E133_LIBS) # PROGRAMS ################################################## @USING_WIN32_FALSE@am__append_95 = \ @USING_WIN32_FALSE@ tools/e133/basic_controller \ @USING_WIN32_FALSE@ tools/e133/basic_device \ @USING_WIN32_FALSE@ tools/e133/e133_controller \ @USING_WIN32_FALSE@ tools/e133/e133_monitor \ @USING_WIN32_FALSE@ tools/e133/e133_receiver @USE_SPI_TRUE@@USING_WIN32_FALSE@am__append_96 = plugins/spi/libolaspicore.la @USING_WIN32_FALSE@am__append_97 = tools/usbpro/download_firmware.sh @USING_WIN32_FALSE@am__append_98 = tools/usbpro/usbpro_firmware \ @USING_WIN32_FALSE@ tools/rdmpro/rdmpro_sniffer @USING_WIN32_FALSE@am__append_99 = tools/rdmpro/README.md @BUILD_TESTS_TRUE@TESTS = $(am__EXEEXT_20) $(test_scripts) subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/ac_prog_java_cc.m4 \ $(top_srcdir)/config/ac_pthread_set_name.m4 \ $(top_srcdir)/config/ac_saleae.m4 \ $(top_srcdir)/config/acx_pthread.m4 \ $(top_srcdir)/config/ax_have_epoll.m4 \ $(top_srcdir)/config/ax_prog_doxygen.m4 \ $(top_srcdir)/config/ax_python_module.m4 \ $(top_srcdir)/config/libtool.m4 \ $(top_srcdir)/config/ltoptions.m4 \ $(top_srcdir)/config/ltsugar.m4 \ $(top_srcdir)/config/ltversion.m4 \ $(top_srcdir)/config/lt~obsolete.m4 \ $(top_srcdir)/config/maven.m4 $(top_srcdir)/config/ola.m4 \ $(top_srcdir)/config/pkg.m4 $(top_srcdir)/config/resolv.m4 \ $(top_srcdir)/config/stl_hash.m4 \ $(top_srcdir)/config/ola_version.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ $(am__configure_deps) $(dist_check_SCRIPTS) \ $(am__dist_noinst_SCRIPTS_DIST) \ $(am__dist_rdmtestsexec_SCRIPTS_DIST) \ $(am__pkgpython_PYTHON_DIST) $(am__rdminit_PYTHON_DIST) \ $(am__rdmtests_PYTHON_DIST) $(am__rpcpython_PYTHON_DIST) \ $(dist_angular_DATA) $(dist_angularroute_DATA) \ $(dist_bootcss_DATA) $(dist_bootfonts_DATA) \ $(dist_bootjs_DATA) $(dist_css_DATA) $(dist_img_DATA) \ $(dist_jquery_DATA) $(dist_js_DATA) $(dist_new_DATA) \ $(dist_noinst_DATA) $(dist_piddata_DATA) \ $(am__dist_tools_rdm_testserver_images_DATA_DIST) \ $(am__dist_tools_rdm_testserver_static_DATA_DIST) \ $(dist_views_DATA) $(dist_www_DATA) $(noinst_HEADERS) \ $(am__olaacninclude_HEADERS_DIST) $(olabaseinclude_HEADERS) \ $(olaclientinclude_HEADERS) $(oladinclude_HEADERS) \ $(oladmxinclude_HEADERS) $(am__olae133include_HEADERS_DIST) \ $(olafileinclude_HEADERS) $(olahttpinclude_HEADERS) \ $(olaioinclude_HEADERS) $(olamathinclude_HEADERS) \ $(olamessaginginclude_HEADERS) $(olanetworkinclude_HEADERS) \ $(olardminclude_HEADERS) $(olarpcinclude_HEADERS) \ $(olastlinclude_HEADERS) $(olastringsinclude_HEADERS) \ $(olasysteminclude_HEADERS) $(olathreadinclude_HEADERS) \ $(olatimecodeinclude_HEADERS) $(olautilinclude_HEADERS) \ $(olawebinclude_HEADERS) $(olawininclude_HEADERS) \ $(pkginclude_HEADERS) $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = include/ola/base/Version.h libola.pc \ libolaserver.pc libs/acn/libolaacn.pc ola.spec \ plugins/artnet/messages/libolaartnetconf.pc \ plugins/e131/messages/libolae131conf.pc \ plugins/usbpro/messages/libolausbproconf.pc \ tools/e133/libolae133common.pc \ tools/e133/libolae133controller.pc CONFIG_CLEAN_VPATH_FILES = python/ola/PidStore.py \ python/ola/MACAddress.py python/ola/RDMConstants.py \ python/ola/UID.py python/ola/__init__.py 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)$(libdir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(rdmtestsexecdir)" "$(DESTDIR)$(pkgpythondir)" \ "$(DESTDIR)$(rdmtestsdir)" "$(DESTDIR)$(rpcpythondir)" \ "$(DESTDIR)$(pkgpythondir)" "$(DESTDIR)$(rdminitdir)" \ "$(DESTDIR)$(rdmtestsdir)" "$(DESTDIR)$(rpcpythondir)" \ "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(angulardir)" \ "$(DESTDIR)$(angularroutedir)" "$(DESTDIR)$(bootcssdir)" \ "$(DESTDIR)$(bootfontsdir)" "$(DESTDIR)$(bootjsdir)" \ "$(DESTDIR)$(cssdir)" "$(DESTDIR)$(imgdir)" \ "$(DESTDIR)$(jquerydir)" "$(DESTDIR)$(jsdir)" \ "$(DESTDIR)$(newdir)" "$(DESTDIR)$(piddatadir)" \ "$(DESTDIR)$(tools_rdm_testserver_imagesdir)" \ "$(DESTDIR)$(tools_rdm_testserver_staticdir)" \ "$(DESTDIR)$(viewsdir)" "$(DESTDIR)$(wwwdir)" \ "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(artnetincludedir)" \ "$(DESTDIR)$(e131includedir)" "$(DESTDIR)$(olabaseincludedir)" \ "$(DESTDIR)$(olardmincludedir)" \ "$(DESTDIR)$(olatimecodeincludedir)" \ "$(DESTDIR)$(pkgincludedir)" "$(DESTDIR)$(usbproincludedir)" \ "$(DESTDIR)$(olaacnincludedir)" \ "$(DESTDIR)$(olabaseincludedir)" \ "$(DESTDIR)$(olaclientincludedir)" \ "$(DESTDIR)$(oladincludedir)" "$(DESTDIR)$(oladmxincludedir)" \ "$(DESTDIR)$(olae133includedir)" \ "$(DESTDIR)$(olafileincludedir)" \ "$(DESTDIR)$(olahttpincludedir)" \ "$(DESTDIR)$(olaioincludedir)" \ "$(DESTDIR)$(olamathincludedir)" \ "$(DESTDIR)$(olamessagingincludedir)" \ "$(DESTDIR)$(olanetworkincludedir)" \ "$(DESTDIR)$(olardmincludedir)" \ "$(DESTDIR)$(olarpcincludedir)" \ "$(DESTDIR)$(olastlincludedir)" \ "$(DESTDIR)$(olastringsincludedir)" \ "$(DESTDIR)$(olasystemincludedir)" \ "$(DESTDIR)$(olathreadincludedir)" \ "$(DESTDIR)$(olatimecodeincludedir)" \ "$(DESTDIR)$(olautilincludedir)" \ "$(DESTDIR)$(olawebincludedir)" \ "$(DESTDIR)$(olawinincludedir)" "$(DESTDIR)$(pkgincludedir)" LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) am__DEPENDENCIES_1 = @HAVE_LIBMICROHTTPD_TRUE@common_http_libolahttp_la_DEPENDENCIES = \ @HAVE_LIBMICROHTTPD_TRUE@ $(am__DEPENDENCIES_1) am__common_http_libolahttp_la_SOURCES_DIST = \ common/http/HTTPServer.cpp common/http/OlaHTTPServer.cpp am__dirstamp = $(am__leading_dot)dirstamp @HAVE_LIBMICROHTTPD_TRUE@am_common_http_libolahttp_la_OBJECTS = \ @HAVE_LIBMICROHTTPD_TRUE@ common/http/HTTPServer.lo \ @HAVE_LIBMICROHTTPD_TRUE@ common/http/OlaHTTPServer.lo common_http_libolahttp_la_OBJECTS = \ $(am_common_http_libolahttp_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = @HAVE_LIBMICROHTTPD_TRUE@am_common_http_libolahttp_la_rpath = common_libolacommon_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) common/protocol/libolaproto.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am__common_libolacommon_la_SOURCES_DIST = common/base/Credentials.cpp \ common/base/Env.cpp common/base/Flags.cpp common/base/Init.cpp \ common/base/Logging.cpp common/base/SysExits.cpp \ common/base/Version.cpp common/dmx/RunLengthEncoder.cpp \ common/export_map/ExportMap.cpp common/file/Util.cpp \ common/io/Descriptor.cpp common/io/ExtendedSerial.cpp \ common/io/EPoller.h common/io/IOQueue.cpp \ common/io/IOStack.cpp common/io/IOUtils.cpp \ common/io/NonBlockingSender.cpp common/io/PollerInterface.cpp \ common/io/PollerInterface.h common/io/SelectServer.cpp \ common/io/Serial.cpp common/io/StdinHandler.cpp \ common/io/TimeoutManager.cpp common/io/TimeoutManager.h \ common/io/WindowsPoller.cpp common/io/WindowsPoller.h \ common/io/SelectPoller.cpp common/io/SelectPoller.h \ common/io/EPoller.cpp common/io/KQueuePoller.h \ common/io/KQueuePoller.cpp common/math/Random.cpp \ common/messaging/Descriptor.cpp common/messaging/Message.cpp \ common/messaging/MessagePrinter.cpp \ common/messaging/SchemaPrinter.cpp \ common/network/AdvancedTCPConnector.cpp \ common/network/FakeInterfacePicker.h \ common/network/HealthCheckedConnection.cpp \ common/network/IPV4Address.cpp common/network/Interface.cpp \ common/network/InterfacePicker.cpp \ common/network/MACAddress.cpp common/network/NetworkUtils.cpp \ common/network/NetworkUtilsInternal.h \ common/network/Socket.cpp common/network/SocketAddress.cpp \ common/network/SocketCloser.cpp \ common/network/SocketHelper.cpp common/network/SocketHelper.h \ common/network/TCPConnector.cpp common/network/TCPSocket.cpp \ common/network/WindowsInterfacePicker.h \ common/network/WindowsInterfacePicker.cpp \ common/network/PosixInterfacePicker.h \ common/network/PosixInterfacePicker.cpp \ common/rdm/AckTimerResponder.cpp \ common/rdm/AdvancedDimmerResponder.cpp \ common/rdm/CommandPrinter.cpp \ common/rdm/DescriptorConsistencyChecker.cpp \ common/rdm/DescriptorConsistencyChecker.h \ common/rdm/DimmerResponder.cpp common/rdm/DimmerRootDevice.cpp \ common/rdm/DimmerSubDevice.cpp common/rdm/DiscoveryAgent.cpp \ common/rdm/DiscoveryAgentTestHelper.h \ common/rdm/DummyResponder.cpp \ common/rdm/FakeNetworkManager.cpp \ common/rdm/FakeNetworkManager.h \ common/rdm/GroupSizeCalculator.cpp \ common/rdm/GroupSizeCalculator.h \ common/rdm/MessageDeserializer.cpp \ common/rdm/MessageSerializer.cpp \ common/rdm/MovingLightResponder.cpp \ common/rdm/NetworkManager.cpp common/rdm/NetworkManager.h \ common/rdm/NetworkResponder.cpp \ common/rdm/OpenLightingEnums.cpp common/rdm/PidStore.cpp \ common/rdm/PidStoreHelper.cpp common/rdm/PidStoreLoader.cpp \ common/rdm/PidStoreLoader.h \ common/rdm/QueueingRDMController.cpp common/rdm/RDMAPI.cpp \ common/rdm/RDMCommand.cpp common/rdm/RDMCommandSerializer.cpp \ common/rdm/RDMFrame.cpp common/rdm/RDMHelper.cpp \ common/rdm/RDMReply.cpp common/rdm/ResponderHelper.cpp \ common/rdm/ResponderLoadSensor.cpp \ common/rdm/ResponderPersonality.cpp \ common/rdm/ResponderSettings.cpp \ common/rdm/ResponderSlotData.cpp \ common/rdm/SensorResponder.cpp \ common/rdm/StringMessageBuilder.cpp \ common/rdm/SubDeviceDispatcher.cpp common/rdm/UID.cpp \ common/rdm/VariableFieldSizeCalculator.cpp \ common/rdm/VariableFieldSizeCalculator.h \ common/rpc/RpcChannel.cpp common/rpc/RpcChannel.h \ common/rpc/RpcSession.h common/rpc/RpcController.cpp \ common/rpc/RpcController.h common/rpc/RpcHeader.h \ common/rpc/RpcPeer.h common/rpc/RpcServer.cpp \ common/rpc/RpcServer.h common/rpc/RpcService.h \ common/strings/Format.cpp common/strings/Utils.cpp \ common/system/Limits.cpp common/system/SystemUtils.cpp \ common/thread/ConsumerThread.cpp \ common/thread/ExecutorThread.cpp common/thread/Mutex.cpp \ common/thread/PeriodicThread.cpp \ common/thread/SignalThread.cpp common/thread/Thread.cpp \ common/thread/ThreadPool.cpp common/thread/Utils.cpp \ common/timecode/TimeCode.cpp common/utils/ActionQueue.cpp \ common/utils/Clock.cpp common/utils/DmxBuffer.cpp \ common/utils/StringUtils.cpp common/utils/TokenBucket.cpp \ common/utils/Watchdog.cpp @USING_WIN32_TRUE@am__objects_1 = common/io/common_libolacommon_la-WindowsPoller.lo @USING_WIN32_FALSE@am__objects_2 = common/io/common_libolacommon_la-SelectPoller.lo @HAVE_EPOLL_TRUE@am__objects_3 = \ @HAVE_EPOLL_TRUE@ common/io/common_libolacommon_la-EPoller.lo @HAVE_KQUEUE_TRUE@am__objects_4 = common/io/common_libolacommon_la-KQueuePoller.lo @USING_WIN32_TRUE@am__objects_5 = common/network/common_libolacommon_la-WindowsInterfacePicker.lo @USING_WIN32_FALSE@am__objects_6 = common/network/common_libolacommon_la-PosixInterfacePicker.lo am_common_libolacommon_la_OBJECTS = \ common/base/common_libolacommon_la-Credentials.lo \ common/base/common_libolacommon_la-Env.lo \ common/base/common_libolacommon_la-Flags.lo \ common/base/common_libolacommon_la-Init.lo \ common/base/common_libolacommon_la-Logging.lo \ common/base/common_libolacommon_la-SysExits.lo \ common/base/common_libolacommon_la-Version.lo \ common/dmx/common_libolacommon_la-RunLengthEncoder.lo \ common/export_map/common_libolacommon_la-ExportMap.lo \ common/file/common_libolacommon_la-Util.lo \ common/io/common_libolacommon_la-Descriptor.lo \ common/io/common_libolacommon_la-ExtendedSerial.lo \ common/io/common_libolacommon_la-IOQueue.lo \ common/io/common_libolacommon_la-IOStack.lo \ common/io/common_libolacommon_la-IOUtils.lo \ common/io/common_libolacommon_la-NonBlockingSender.lo \ common/io/common_libolacommon_la-PollerInterface.lo \ common/io/common_libolacommon_la-SelectServer.lo \ common/io/common_libolacommon_la-Serial.lo \ common/io/common_libolacommon_la-StdinHandler.lo \ common/io/common_libolacommon_la-TimeoutManager.lo \ $(am__objects_1) $(am__objects_2) $(am__objects_3) \ $(am__objects_4) common/math/common_libolacommon_la-Random.lo \ common/messaging/common_libolacommon_la-Descriptor.lo \ common/messaging/common_libolacommon_la-Message.lo \ common/messaging/common_libolacommon_la-MessagePrinter.lo \ common/messaging/common_libolacommon_la-SchemaPrinter.lo \ common/network/common_libolacommon_la-AdvancedTCPConnector.lo \ common/network/common_libolacommon_la-HealthCheckedConnection.lo \ common/network/common_libolacommon_la-IPV4Address.lo \ common/network/common_libolacommon_la-Interface.lo \ common/network/common_libolacommon_la-InterfacePicker.lo \ common/network/common_libolacommon_la-MACAddress.lo \ common/network/common_libolacommon_la-NetworkUtils.lo \ common/network/common_libolacommon_la-Socket.lo \ common/network/common_libolacommon_la-SocketAddress.lo \ common/network/common_libolacommon_la-SocketCloser.lo \ common/network/common_libolacommon_la-SocketHelper.lo \ common/network/common_libolacommon_la-TCPConnector.lo \ common/network/common_libolacommon_la-TCPSocket.lo \ $(am__objects_5) $(am__objects_6) \ common/rdm/common_libolacommon_la-AckTimerResponder.lo \ common/rdm/common_libolacommon_la-AdvancedDimmerResponder.lo \ common/rdm/common_libolacommon_la-CommandPrinter.lo \ common/rdm/common_libolacommon_la-DescriptorConsistencyChecker.lo \ common/rdm/common_libolacommon_la-DimmerResponder.lo \ common/rdm/common_libolacommon_la-DimmerRootDevice.lo \ common/rdm/common_libolacommon_la-DimmerSubDevice.lo \ common/rdm/common_libolacommon_la-DiscoveryAgent.lo \ common/rdm/common_libolacommon_la-DummyResponder.lo \ common/rdm/common_libolacommon_la-FakeNetworkManager.lo \ common/rdm/common_libolacommon_la-GroupSizeCalculator.lo \ common/rdm/common_libolacommon_la-MessageDeserializer.lo \ common/rdm/common_libolacommon_la-MessageSerializer.lo \ common/rdm/common_libolacommon_la-MovingLightResponder.lo \ common/rdm/common_libolacommon_la-NetworkManager.lo \ common/rdm/common_libolacommon_la-NetworkResponder.lo \ common/rdm/common_libolacommon_la-OpenLightingEnums.lo \ common/rdm/common_libolacommon_la-PidStore.lo \ common/rdm/common_libolacommon_la-PidStoreHelper.lo \ common/rdm/common_libolacommon_la-PidStoreLoader.lo \ common/rdm/common_libolacommon_la-QueueingRDMController.lo \ common/rdm/common_libolacommon_la-RDMAPI.lo \ common/rdm/common_libolacommon_la-RDMCommand.lo \ common/rdm/common_libolacommon_la-RDMCommandSerializer.lo \ common/rdm/common_libolacommon_la-RDMFrame.lo \ common/rdm/common_libolacommon_la-RDMHelper.lo \ common/rdm/common_libolacommon_la-RDMReply.lo \ common/rdm/common_libolacommon_la-ResponderHelper.lo \ common/rdm/common_libolacommon_la-ResponderLoadSensor.lo \ common/rdm/common_libolacommon_la-ResponderPersonality.lo \ common/rdm/common_libolacommon_la-ResponderSettings.lo \ common/rdm/common_libolacommon_la-ResponderSlotData.lo \ common/rdm/common_libolacommon_la-SensorResponder.lo \ common/rdm/common_libolacommon_la-StringMessageBuilder.lo \ common/rdm/common_libolacommon_la-SubDeviceDispatcher.lo \ common/rdm/common_libolacommon_la-UID.lo \ common/rdm/common_libolacommon_la-VariableFieldSizeCalculator.lo \ common/rpc/common_libolacommon_la-RpcChannel.lo \ common/rpc/common_libolacommon_la-RpcController.lo \ common/rpc/common_libolacommon_la-RpcServer.lo \ common/strings/common_libolacommon_la-Format.lo \ common/strings/common_libolacommon_la-Utils.lo \ common/system/common_libolacommon_la-Limits.lo \ common/system/common_libolacommon_la-SystemUtils.lo \ common/thread/common_libolacommon_la-ConsumerThread.lo \ common/thread/common_libolacommon_la-ExecutorThread.lo \ common/thread/common_libolacommon_la-Mutex.lo \ common/thread/common_libolacommon_la-PeriodicThread.lo \ common/thread/common_libolacommon_la-SignalThread.lo \ common/thread/common_libolacommon_la-Thread.lo \ common/thread/common_libolacommon_la-ThreadPool.lo \ common/thread/common_libolacommon_la-Utils.lo \ common/timecode/common_libolacommon_la-TimeCode.lo \ common/utils/common_libolacommon_la-ActionQueue.lo \ common/utils/common_libolacommon_la-Clock.lo \ common/utils/common_libolacommon_la-DmxBuffer.lo \ common/utils/common_libolacommon_la-StringUtils.lo \ common/utils/common_libolacommon_la-TokenBucket.lo \ common/utils/common_libolacommon_la-Watchdog.lo nodist_common_libolacommon_la_OBJECTS = \ common/rdm/common_libolacommon_la-Pids.pb.lo \ common/rpc/common_libolacommon_la-Rpc.pb.lo common_libolacommon_la_OBJECTS = $(am_common_libolacommon_la_OBJECTS) \ $(nodist_common_libolacommon_la_OBJECTS) common_libolacommon_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ common_protocol_libolaproto_la_DEPENDENCIES = $(am__DEPENDENCIES_1) nodist_common_protocol_libolaproto_la_OBJECTS = \ common/protocol/common_protocol_libolaproto_la-Ola.pb.lo \ common/protocol/common_protocol_libolaproto_la-OlaService.pb.lo common_protocol_libolaproto_la_OBJECTS = \ $(nodist_common_protocol_libolaproto_la_OBJECTS) common_protocol_libolaproto_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_protocol_libolaproto_la_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ common_testing_libolatesting_la_LIBADD = am__common_testing_libolatesting_la_SOURCES_DIST = \ common/testing/MockUDPSocket.cpp common/testing/TestUtils.cpp @BUILD_TESTS_TRUE@am_common_testing_libolatesting_la_OBJECTS = \ @BUILD_TESTS_TRUE@ common/testing/MockUDPSocket.lo \ @BUILD_TESTS_TRUE@ common/testing/TestUtils.lo common_testing_libolatesting_la_OBJECTS = \ $(am_common_testing_libolatesting_la_OBJECTS) @BUILD_TESTS_TRUE@am_common_testing_libolatesting_la_rpath = common_testing_libtestmain_la_LIBADD = am__common_testing_libtestmain_la_SOURCES_DIST = \ common/testing/GenericTester.cpp @BUILD_TESTS_TRUE@am_common_testing_libtestmain_la_OBJECTS = \ @BUILD_TESTS_TRUE@ common/testing/GenericTester.lo common_testing_libtestmain_la_OBJECTS = \ $(am_common_testing_libtestmain_la_OBJECTS) @BUILD_TESTS_TRUE@am_common_testing_libtestmain_la_rpath = @USING_WIN32_TRUE@common_web_libolaweb_la_DEPENDENCIES = \ @USING_WIN32_TRUE@ common/libolacommon.la am_common_web_libolaweb_la_OBJECTS = common/web/Json.lo \ common/web/JsonData.lo common/web/JsonLexer.lo \ common/web/JsonParser.lo common/web/JsonPatch.lo \ common/web/JsonPatchParser.lo common/web/JsonPointer.lo \ common/web/JsonSchema.lo common/web/JsonSections.lo \ common/web/JsonTypes.lo common/web/JsonWriter.lo \ common/web/PointerTracker.lo common/web/SchemaErrorLogger.lo \ common/web/SchemaKeywords.lo common/web/SchemaParseContext.lo \ common/web/SchemaParser.lo common_web_libolaweb_la_OBJECTS = \ $(am_common_web_libolaweb_la_OBJECTS) examples_libolaconfig_la_LIBADD = am__examples_libolaconfig_la_SOURCES_DIST = \ examples/OlaConfigurator.h examples/OlaConfigurator.cpp @BUILD_EXAMPLES_TRUE@am_examples_libolaconfig_la_OBJECTS = examples/examples_libolaconfig_la-OlaConfigurator.lo examples_libolaconfig_la_OBJECTS = \ $(am_examples_libolaconfig_la_OBJECTS) examples_libolaconfig_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(examples_libolaconfig_la_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ @BUILD_EXAMPLES_TRUE@am_examples_libolaconfig_la_rpath = libs_acn_libolaacn_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ common/libolacommon.la am_libs_acn_libolaacn_la_OBJECTS = \ libs/acn/libs_acn_libolaacn_la-CID.lo \ libs/acn/libs_acn_libolaacn_la-CIDImpl.lo libs_acn_libolaacn_la_OBJECTS = $(am_libs_acn_libolaacn_la_OBJECTS) libs_acn_libolaacn_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(libs_acn_libolaacn_la_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ @INSTALL_ACN_FALSE@am_libs_acn_libolaacn_la_rpath = @INSTALL_ACN_TRUE@am_libs_acn_libolaacn_la_rpath = -rpath $(libdir) libs_acn_libolae131core_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ common/libolacommon.la libs/acn/libolaacn.la am_libs_acn_libolae131core_la_OBJECTS = \ libs/acn/libs_acn_libolae131core_la-BaseInflator.lo \ libs/acn/libs_acn_libolae131core_la-DMPAddress.lo \ libs/acn/libs_acn_libolae131core_la-DMPE131Inflator.lo \ libs/acn/libs_acn_libolae131core_la-DMPInflator.lo \ libs/acn/libs_acn_libolae131core_la-DMPPDU.lo \ libs/acn/libs_acn_libolae131core_la-E131DiscoveryInflator.lo \ libs/acn/libs_acn_libolae131core_la-E131Inflator.lo \ libs/acn/libs_acn_libolae131core_la-E131Node.lo \ libs/acn/libs_acn_libolae131core_la-E131PDU.lo \ libs/acn/libs_acn_libolae131core_la-E131Sender.lo \ libs/acn/libs_acn_libolae131core_la-E133Inflator.lo \ libs/acn/libs_acn_libolae131core_la-E133PDU.lo \ libs/acn/libs_acn_libolae131core_la-E133StatusInflator.lo \ libs/acn/libs_acn_libolae131core_la-E133StatusPDU.lo \ libs/acn/libs_acn_libolae131core_la-PDU.lo \ libs/acn/libs_acn_libolae131core_la-PreamblePacker.lo \ libs/acn/libs_acn_libolae131core_la-RDMInflator.lo \ libs/acn/libs_acn_libolae131core_la-RDMPDU.lo \ libs/acn/libs_acn_libolae131core_la-RootInflator.lo \ libs/acn/libs_acn_libolae131core_la-RootPDU.lo \ libs/acn/libs_acn_libolae131core_la-RootSender.lo \ libs/acn/libs_acn_libolae131core_la-TCPTransport.lo \ libs/acn/libs_acn_libolae131core_la-UDPTransport.lo libs_acn_libolae131core_la_OBJECTS = \ $(am_libs_acn_libolae131core_la_OBJECTS) libs_acn_libolae131core_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ @USE_LIBUSB_TRUE@libs_usb_libolausb_la_DEPENDENCIES = \ @USE_LIBUSB_TRUE@ $(am__DEPENDENCIES_1) common/libolacommon.la am__libs_usb_libolausb_la_SOURCES_DIST = libs/usb/HotplugAgent.cpp \ libs/usb/HotplugAgent.h libs/usb/JaRuleConstants.h \ libs/usb/JaRuleConstants.cpp libs/usb/JaRulePortHandle.cpp \ libs/usb/JaRulePortHandle.h libs/usb/JaRulePortHandleImpl.cpp \ libs/usb/JaRulePortHandleImpl.h libs/usb/JaRuleWidget.cpp \ libs/usb/JaRuleWidget.h libs/usb/JaRuleWidgetPort.cpp \ libs/usb/JaRuleWidgetPort.h libs/usb/LibUsbAdaptor.cpp \ libs/usb/LibUsbAdaptor.h libs/usb/LibUsbThread.cpp \ libs/usb/LibUsbThread.h libs/usb/Types.cpp libs/usb/Types.h @USE_LIBUSB_TRUE@am_libs_usb_libolausb_la_OBJECTS = libs/usb/libs_usb_libolausb_la-HotplugAgent.lo \ @USE_LIBUSB_TRUE@ libs/usb/libs_usb_libolausb_la-JaRuleConstants.lo \ @USE_LIBUSB_TRUE@ libs/usb/libs_usb_libolausb_la-JaRulePortHandle.lo \ @USE_LIBUSB_TRUE@ libs/usb/libs_usb_libolausb_la-JaRulePortHandleImpl.lo \ @USE_LIBUSB_TRUE@ libs/usb/libs_usb_libolausb_la-JaRuleWidget.lo \ @USE_LIBUSB_TRUE@ libs/usb/libs_usb_libolausb_la-JaRuleWidgetPort.lo \ @USE_LIBUSB_TRUE@ libs/usb/libs_usb_libolausb_la-LibUsbAdaptor.lo \ @USE_LIBUSB_TRUE@ libs/usb/libs_usb_libolausb_la-LibUsbThread.lo \ @USE_LIBUSB_TRUE@ libs/usb/libs_usb_libolausb_la-Types.lo libs_usb_libolausb_la_OBJECTS = $(am_libs_usb_libolausb_la_OBJECTS) libs_usb_libolausb_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(libs_usb_libolausb_la_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ @USE_LIBUSB_TRUE@am_libs_usb_libolausb_la_rpath = ola_libola_la_DEPENDENCIES = common/libolacommon.la am_ola_libola_la_OBJECTS = ola/ola_libola_la-AutoStart.lo \ ola/ola_libola_la-ClientRDMAPIShim.lo \ ola/ola_libola_la-ClientTypesFactory.lo \ ola/ola_libola_la-Module.lo \ ola/ola_libola_la-OlaCallbackClient.lo \ ola/ola_libola_la-OlaClient.lo \ ola/ola_libola_la-OlaClientCore.lo \ ola/ola_libola_la-OlaClientWrapper.lo \ ola/ola_libola_la-StreamingClient.lo ola_libola_la_OBJECTS = $(am_ola_libola_la_OBJECTS) ola_libola_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(ola_libola_la_CXXFLAGS) $(CXXFLAGS) $(ola_libola_la_LDFLAGS) \ $(LDFLAGS) -o $@ @HAVE_AVAHI_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) am__DEPENDENCIES_3 = $(am__DEPENDENCIES_2) $(am__append_84) olad_libolaserver_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ common/libolacommon.la common/web/libolaweb.la ola/libola.la \ olad/plugin_api/libolaserverplugininterface.la \ $(am__DEPENDENCIES_3) am__olad_libolaserver_la_SOURCES_DIST = olad/ClientBroker.cpp \ olad/ClientBroker.h olad/DiscoveryAgent.cpp \ olad/DiscoveryAgent.h olad/DynamicPluginLoader.cpp \ olad/DynamicPluginLoader.h olad/HttpServerActions.h \ olad/OlaServerServiceImpl.cpp olad/OlaServerServiceImpl.h \ olad/OladHTTPServer.h olad/PluginLoader.h \ olad/PluginManager.cpp olad/PluginManager.h \ olad/RDMHTTPModule.h olad/BonjourDiscoveryAgent.h \ olad/BonjourDiscoveryAgent.cpp olad/AvahiDiscoveryAgent.h \ olad/AvahiDiscoveryAgent.cpp olad/HttpServerActions.cpp \ olad/OladHTTPServer.cpp olad/RDMHTTPModule.cpp \ olad/OlaServer.cpp olad/OlaDaemon.cpp @HAVE_DNSSD_TRUE@am__objects_7 = olad/olad_libolaserver_la-BonjourDiscoveryAgent.lo @HAVE_AVAHI_TRUE@am__objects_8 = olad/olad_libolaserver_la-AvahiDiscoveryAgent.lo @HAVE_LIBMICROHTTPD_TRUE@am__objects_9 = olad/olad_libolaserver_la-HttpServerActions.lo \ @HAVE_LIBMICROHTTPD_TRUE@ olad/olad_libolaserver_la-OladHTTPServer.lo \ @HAVE_LIBMICROHTTPD_TRUE@ olad/olad_libolaserver_la-RDMHTTPModule.lo am__objects_10 = olad/olad_libolaserver_la-ClientBroker.lo \ olad/olad_libolaserver_la-DiscoveryAgent.lo \ olad/olad_libolaserver_la-DynamicPluginLoader.lo \ olad/olad_libolaserver_la-OlaServerServiceImpl.lo \ olad/olad_libolaserver_la-PluginManager.lo $(am__objects_7) \ $(am__objects_8) $(am__objects_9) am_olad_libolaserver_la_OBJECTS = $(am__objects_10) \ olad/olad_libolaserver_la-OlaServer.lo \ olad/olad_libolaserver_la-OlaDaemon.lo olad_libolaserver_la_OBJECTS = $(am_olad_libolaserver_la_OBJECTS) olad_libolaserver_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(olad_libolaserver_la_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ olad_plugin_api_libolaserverplugininterface_la_DEPENDENCIES = \ common/libolacommon.la common/web/libolaweb.la ola/libola.la am_olad_plugin_api_libolaserverplugininterface_la_OBJECTS = olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Client.lo \ olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Device.lo \ olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-DeviceManager.lo \ olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-DmxSource.lo \ olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Plugin.lo \ olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-PluginAdaptor.lo \ olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Port.lo \ olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-PortBroker.lo \ olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-PortManager.lo \ olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Preferences.lo \ olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Universe.lo \ olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-UniverseStore.lo olad_plugin_api_libolaserverplugininterface_la_OBJECTS = \ $(am_olad_plugin_api_libolaserverplugininterface_la_OBJECTS) olad_plugin_api_libolaserverplugininterface_la_LINK = $(LIBTOOL) \ $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CXXLD) \ $(olad_plugin_api_libolaserverplugininterface_la_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ @USE_ARTNET_TRUE@plugins_artnet_libolaartnet_la_DEPENDENCIES = olad/plugin_api/libolaserverplugininterface.la \ @USE_ARTNET_TRUE@ plugins/artnet/libolaartnetnode.la \ @USE_ARTNET_TRUE@ plugins/artnet/messages/libolaartnetconf.la am__plugins_artnet_libolaartnet_la_SOURCES_DIST = \ plugins/artnet/ArtNetPlugin.cpp plugins/artnet/ArtNetPlugin.h \ plugins/artnet/ArtNetDevice.cpp plugins/artnet/ArtNetDevice.h \ plugins/artnet/ArtNetPort.cpp plugins/artnet/ArtNetPort.h @USE_ARTNET_TRUE@am_plugins_artnet_libolaartnet_la_OBJECTS = plugins/artnet/plugins_artnet_libolaartnet_la-ArtNetPlugin.lo \ @USE_ARTNET_TRUE@ plugins/artnet/plugins_artnet_libolaartnet_la-ArtNetDevice.lo \ @USE_ARTNET_TRUE@ plugins/artnet/plugins_artnet_libolaartnet_la-ArtNetPort.lo plugins_artnet_libolaartnet_la_OBJECTS = \ $(am_plugins_artnet_libolaartnet_la_OBJECTS) plugins_artnet_libolaartnet_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(plugins_artnet_libolaartnet_la_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ @USE_ARTNET_TRUE@am_plugins_artnet_libolaartnet_la_rpath = -rpath \ @USE_ARTNET_TRUE@ $(libdir) @USE_ARTNET_TRUE@plugins_artnet_libolaartnetnode_la_DEPENDENCIES = \ @USE_ARTNET_TRUE@ common/libolacommon.la am__plugins_artnet_libolaartnetnode_la_SOURCES_DIST = \ plugins/artnet/ArtNetPackets.h plugins/artnet/ArtNetNode.cpp \ plugins/artnet/ArtNetNode.h @USE_ARTNET_TRUE@am_plugins_artnet_libolaartnetnode_la_OBJECTS = \ @USE_ARTNET_TRUE@ plugins/artnet/ArtNetNode.lo plugins_artnet_libolaartnetnode_la_OBJECTS = \ $(am_plugins_artnet_libolaartnetnode_la_OBJECTS) @USE_ARTNET_TRUE@am_plugins_artnet_libolaartnetnode_la_rpath = @USE_ARTNET_TRUE@plugins_artnet_messages_libolaartnetconf_la_DEPENDENCIES = \ @USE_ARTNET_TRUE@ $(am__DEPENDENCIES_1) @USE_ARTNET_TRUE@nodist_plugins_artnet_messages_libolaartnetconf_la_OBJECTS = plugins/artnet/messages/plugins_artnet_messages_libolaartnetconf_la-ArtNetConfigMessages.pb.lo plugins_artnet_messages_libolaartnetconf_la_OBJECTS = \ $(nodist_plugins_artnet_messages_libolaartnetconf_la_OBJECTS) plugins_artnet_messages_libolaartnetconf_la_LINK = $(LIBTOOL) \ $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CXXLD) \ $(plugins_artnet_messages_libolaartnetconf_la_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ @USE_ARTNET_TRUE@am_plugins_artnet_messages_libolaartnetconf_la_rpath = \ @USE_ARTNET_TRUE@ -rpath $(libdir) @USE_DMX4LINUX_TRUE@@USING_WIN32_FALSE@plugins_dmx4linux_liboladmx4linux_la_DEPENDENCIES = \ @USE_DMX4LINUX_TRUE@@USING_WIN32_FALSE@ common/libolacommon.la \ @USE_DMX4LINUX_TRUE@@USING_WIN32_FALSE@ olad/plugin_api/libolaserverplugininterface.la am__plugins_dmx4linux_liboladmx4linux_la_SOURCES_DIST = \ plugins/dmx4linux/Dmx4LinuxDevice.cpp \ plugins/dmx4linux/Dmx4LinuxDevice.h \ plugins/dmx4linux/Dmx4LinuxPlugin.cpp \ plugins/dmx4linux/Dmx4LinuxPlugin.h \ plugins/dmx4linux/Dmx4LinuxPort.cpp \ plugins/dmx4linux/Dmx4LinuxPort.h \ plugins/dmx4linux/Dmx4LinuxSocket.h @USE_DMX4LINUX_TRUE@@USING_WIN32_FALSE@am_plugins_dmx4linux_liboladmx4linux_la_OBJECTS = plugins/dmx4linux/Dmx4LinuxDevice.lo \ @USE_DMX4LINUX_TRUE@@USING_WIN32_FALSE@ plugins/dmx4linux/Dmx4LinuxPlugin.lo \ @USE_DMX4LINUX_TRUE@@USING_WIN32_FALSE@ plugins/dmx4linux/Dmx4LinuxPort.lo plugins_dmx4linux_liboladmx4linux_la_OBJECTS = \ $(am_plugins_dmx4linux_liboladmx4linux_la_OBJECTS) @USE_DMX4LINUX_TRUE@@USING_WIN32_FALSE@am_plugins_dmx4linux_liboladmx4linux_la_rpath = \ @USE_DMX4LINUX_TRUE@@USING_WIN32_FALSE@ -rpath $(libdir) @USE_DUMMY_TRUE@plugins_dummy_liboladummy_la_DEPENDENCIES = \ @USE_DUMMY_TRUE@ common/libolacommon.la \ @USE_DUMMY_TRUE@ olad/plugin_api/libolaserverplugininterface.la am__plugins_dummy_liboladummy_la_SOURCES_DIST = \ plugins/dummy/DummyDevice.cpp plugins/dummy/DummyDevice.h \ plugins/dummy/DummyPlugin.cpp plugins/dummy/DummyPlugin.h \ plugins/dummy/DummyPort.cpp plugins/dummy/DummyPort.h @USE_DUMMY_TRUE@am_plugins_dummy_liboladummy_la_OBJECTS = \ @USE_DUMMY_TRUE@ plugins/dummy/DummyDevice.lo \ @USE_DUMMY_TRUE@ plugins/dummy/DummyPlugin.lo \ @USE_DUMMY_TRUE@ plugins/dummy/DummyPort.lo plugins_dummy_liboladummy_la_OBJECTS = \ $(am_plugins_dummy_liboladummy_la_OBJECTS) @USE_DUMMY_TRUE@am_plugins_dummy_liboladummy_la_rpath = -rpath \ @USE_DUMMY_TRUE@ $(libdir) @USE_E131_TRUE@@USING_WIN32_FALSE@plugins_e131_libolae131_la_DEPENDENCIES = olad/plugin_api/libolaserverplugininterface.la \ @USE_E131_TRUE@@USING_WIN32_FALSE@ plugins/e131/messages/libolae131conf.la \ @USE_E131_TRUE@@USING_WIN32_FALSE@ libs/acn/libolae131core.la am__plugins_e131_libolae131_la_SOURCES_DIST = \ plugins/e131/E131Device.cpp plugins/e131/E131Device.h \ plugins/e131/E131Plugin.cpp plugins/e131/E131Plugin.h \ plugins/e131/E131Port.cpp plugins/e131/E131Port.h @USE_E131_TRUE@@USING_WIN32_FALSE@am_plugins_e131_libolae131_la_OBJECTS = plugins/e131/plugins_e131_libolae131_la-E131Device.lo \ @USE_E131_TRUE@@USING_WIN32_FALSE@ plugins/e131/plugins_e131_libolae131_la-E131Plugin.lo \ @USE_E131_TRUE@@USING_WIN32_FALSE@ plugins/e131/plugins_e131_libolae131_la-E131Port.lo plugins_e131_libolae131_la_OBJECTS = \ $(am_plugins_e131_libolae131_la_OBJECTS) plugins_e131_libolae131_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(plugins_e131_libolae131_la_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ @USE_E131_TRUE@@USING_WIN32_FALSE@am_plugins_e131_libolae131_la_rpath = \ @USE_E131_TRUE@@USING_WIN32_FALSE@ -rpath $(libdir) @USE_E131_TRUE@@USING_WIN32_FALSE@plugins_e131_messages_libolae131conf_la_DEPENDENCIES = \ @USE_E131_TRUE@@USING_WIN32_FALSE@ $(am__DEPENDENCIES_1) @USE_E131_TRUE@@USING_WIN32_FALSE@nodist_plugins_e131_messages_libolae131conf_la_OBJECTS = plugins/e131/messages/plugins_e131_messages_libolae131conf_la-E131ConfigMessages.pb.lo plugins_e131_messages_libolae131conf_la_OBJECTS = \ $(nodist_plugins_e131_messages_libolae131conf_la_OBJECTS) plugins_e131_messages_libolae131conf_la_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CXXLD) $(plugins_e131_messages_libolae131conf_la_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ @USE_E131_TRUE@@USING_WIN32_FALSE@am_plugins_e131_messages_libolae131conf_la_rpath = \ @USE_E131_TRUE@@USING_WIN32_FALSE@ -rpath $(libdir) @USE_ESPNET_TRUE@plugins_espnet_libolaespnet_la_DEPENDENCIES = \ @USE_ESPNET_TRUE@ common/libolacommon.la \ @USE_ESPNET_TRUE@ olad/plugin_api/libolaserverplugininterface.la am__plugins_espnet_libolaespnet_la_SOURCES_DIST = \ plugins/espnet/EspNetDevice.cpp plugins/espnet/EspNetDevice.h \ plugins/espnet/EspNetNode.cpp plugins/espnet/EspNetNode.h \ plugins/espnet/EspNetPackets.h plugins/espnet/EspNetPlugin.cpp \ plugins/espnet/EspNetPlugin.h \ plugins/espnet/EspNetPluginCommon.h \ plugins/espnet/EspNetPort.cpp plugins/espnet/EspNetPort.h \ plugins/espnet/RunLengthDecoder.cpp \ plugins/espnet/RunLengthDecoder.h @USE_ESPNET_TRUE@am_plugins_espnet_libolaespnet_la_OBJECTS = \ @USE_ESPNET_TRUE@ plugins/espnet/EspNetDevice.lo \ @USE_ESPNET_TRUE@ plugins/espnet/EspNetNode.lo \ @USE_ESPNET_TRUE@ plugins/espnet/EspNetPlugin.lo \ @USE_ESPNET_TRUE@ plugins/espnet/EspNetPort.lo \ @USE_ESPNET_TRUE@ plugins/espnet/RunLengthDecoder.lo plugins_espnet_libolaespnet_la_OBJECTS = \ $(am_plugins_espnet_libolaespnet_la_OBJECTS) @USE_ESPNET_TRUE@am_plugins_espnet_libolaespnet_la_rpath = -rpath \ @USE_ESPNET_TRUE@ $(libdir) @USE_FTDI_TRUE@plugins_ftdidmx_libolaftdidmx_la_DEPENDENCIES = \ @USE_FTDI_TRUE@ $(am__DEPENDENCIES_1) common/libolacommon.la \ @USE_FTDI_TRUE@ olad/plugin_api/libolaserverplugininterface.la am__plugins_ftdidmx_libolaftdidmx_la_SOURCES_DIST = \ plugins/ftdidmx/FtdiDmxDevice.cpp \ plugins/ftdidmx/FtdiDmxDevice.h \ plugins/ftdidmx/FtdiDmxPlugin.cpp \ plugins/ftdidmx/FtdiDmxPlugin.h plugins/ftdidmx/FtdiDmxPort.h \ plugins/ftdidmx/FtdiDmxThread.cpp \ plugins/ftdidmx/FtdiDmxThread.h plugins/ftdidmx/FtdiWidget.cpp \ plugins/ftdidmx/FtdiWidget.h @USE_FTDI_TRUE@am_plugins_ftdidmx_libolaftdidmx_la_OBJECTS = \ @USE_FTDI_TRUE@ plugins/ftdidmx/FtdiDmxDevice.lo \ @USE_FTDI_TRUE@ plugins/ftdidmx/FtdiDmxPlugin.lo \ @USE_FTDI_TRUE@ plugins/ftdidmx/FtdiDmxThread.lo \ @USE_FTDI_TRUE@ plugins/ftdidmx/FtdiWidget.lo plugins_ftdidmx_libolaftdidmx_la_OBJECTS = \ $(am_plugins_ftdidmx_libolaftdidmx_la_OBJECTS) @USE_FTDI_TRUE@am_plugins_ftdidmx_libolaftdidmx_la_rpath = -rpath \ @USE_FTDI_TRUE@ $(libdir) @USE_GPIO_TRUE@plugins_gpio_libolagpio_la_DEPENDENCIES = \ @USE_GPIO_TRUE@ common/libolacommon.la \ @USE_GPIO_TRUE@ olad/plugin_api/libolaserverplugininterface.la \ @USE_GPIO_TRUE@ plugins/gpio/libolagpiocore.la am__plugins_gpio_libolagpio_la_SOURCES_DIST = \ plugins/gpio/GPIODevice.cpp plugins/gpio/GPIODevice.h \ plugins/gpio/GPIOPlugin.cpp plugins/gpio/GPIOPlugin.h \ plugins/gpio/GPIOPort.cpp plugins/gpio/GPIOPort.h @USE_GPIO_TRUE@am_plugins_gpio_libolagpio_la_OBJECTS = \ @USE_GPIO_TRUE@ plugins/gpio/GPIODevice.lo \ @USE_GPIO_TRUE@ plugins/gpio/GPIOPlugin.lo \ @USE_GPIO_TRUE@ plugins/gpio/GPIOPort.lo plugins_gpio_libolagpio_la_OBJECTS = \ $(am_plugins_gpio_libolagpio_la_OBJECTS) @USE_GPIO_TRUE@am_plugins_gpio_libolagpio_la_rpath = -rpath $(libdir) @USE_GPIO_TRUE@plugins_gpio_libolagpiocore_la_DEPENDENCIES = \ @USE_GPIO_TRUE@ common/libolacommon.la am__plugins_gpio_libolagpiocore_la_SOURCES_DIST = \ plugins/gpio/GPIODriver.cpp plugins/gpio/GPIODriver.h @USE_GPIO_TRUE@am_plugins_gpio_libolagpiocore_la_OBJECTS = \ @USE_GPIO_TRUE@ plugins/gpio/GPIODriver.lo plugins_gpio_libolagpiocore_la_OBJECTS = \ $(am_plugins_gpio_libolagpiocore_la_OBJECTS) @USE_GPIO_TRUE@am_plugins_gpio_libolagpiocore_la_rpath = -rpath \ @USE_GPIO_TRUE@ $(libdir) @USE_KARATE_TRUE@plugins_karate_libolakarate_la_DEPENDENCIES = \ @USE_KARATE_TRUE@ common/libolacommon.la \ @USE_KARATE_TRUE@ olad/plugin_api/libolaserverplugininterface.la am__plugins_karate_libolakarate_la_SOURCES_DIST = \ plugins/karate/KaratePlugin.cpp \ plugins/karate/KarateDevice.cpp \ plugins/karate/KarateThread.cpp plugins/karate/KarateLight.cpp \ plugins/karate/KaratePlugin.h plugins/karate/KarateDevice.h \ plugins/karate/KaratePort.h plugins/karate/KarateThread.h \ plugins/karate/KarateLight.h @USE_KARATE_TRUE@am_plugins_karate_libolakarate_la_OBJECTS = \ @USE_KARATE_TRUE@ plugins/karate/KaratePlugin.lo \ @USE_KARATE_TRUE@ plugins/karate/KarateDevice.lo \ @USE_KARATE_TRUE@ plugins/karate/KarateThread.lo \ @USE_KARATE_TRUE@ plugins/karate/KarateLight.lo plugins_karate_libolakarate_la_OBJECTS = \ $(am_plugins_karate_libolakarate_la_OBJECTS) @USE_KARATE_TRUE@am_plugins_karate_libolakarate_la_rpath = -rpath \ @USE_KARATE_TRUE@ $(libdir) @USE_KINET_TRUE@plugins_kinet_libolakinet_la_DEPENDENCIES = olad/plugin_api/libolaserverplugininterface.la \ @USE_KINET_TRUE@ plugins/kinet/libolakinetnode.la am__plugins_kinet_libolakinet_la_SOURCES_DIST = \ plugins/kinet/KiNetPlugin.cpp plugins/kinet/KiNetPlugin.h \ plugins/kinet/KiNetDevice.cpp plugins/kinet/KiNetDevice.h \ plugins/kinet/KiNetPort.h @USE_KINET_TRUE@am_plugins_kinet_libolakinet_la_OBJECTS = \ @USE_KINET_TRUE@ plugins/kinet/KiNetPlugin.lo \ @USE_KINET_TRUE@ plugins/kinet/KiNetDevice.lo plugins_kinet_libolakinet_la_OBJECTS = \ $(am_plugins_kinet_libolakinet_la_OBJECTS) @USE_KINET_TRUE@am_plugins_kinet_libolakinet_la_rpath = -rpath \ @USE_KINET_TRUE@ $(libdir) @USE_KINET_TRUE@plugins_kinet_libolakinetnode_la_DEPENDENCIES = \ @USE_KINET_TRUE@ common/libolacommon.la am__plugins_kinet_libolakinetnode_la_SOURCES_DIST = \ plugins/kinet/KiNetNode.cpp plugins/kinet/KiNetNode.h @USE_KINET_TRUE@am_plugins_kinet_libolakinetnode_la_OBJECTS = \ @USE_KINET_TRUE@ plugins/kinet/KiNetNode.lo plugins_kinet_libolakinetnode_la_OBJECTS = \ $(am_plugins_kinet_libolakinetnode_la_OBJECTS) @USE_KINET_TRUE@am_plugins_kinet_libolakinetnode_la_rpath = @USE_MILINST_TRUE@plugins_milinst_libolamilinst_la_DEPENDENCIES = \ @USE_MILINST_TRUE@ common/libolacommon.la \ @USE_MILINST_TRUE@ olad/plugin_api/libolaserverplugininterface.la am__plugins_milinst_libolamilinst_la_SOURCES_DIST = \ plugins/milinst/MilInstDevice.cpp \ plugins/milinst/MilInstDevice.h \ plugins/milinst/MilInstPlugin.cpp \ plugins/milinst/MilInstPlugin.h \ plugins/milinst/MilInstPort.cpp plugins/milinst/MilInstPort.h \ plugins/milinst/MilInstWidget.cpp \ plugins/milinst/MilInstWidget.h \ plugins/milinst/MilInstWidget1463.cpp \ plugins/milinst/MilInstWidget1463.h \ plugins/milinst/MilInstWidget1553.cpp \ plugins/milinst/MilInstWidget1553.h @USE_MILINST_TRUE@am_plugins_milinst_libolamilinst_la_OBJECTS = \ @USE_MILINST_TRUE@ plugins/milinst/MilInstDevice.lo \ @USE_MILINST_TRUE@ plugins/milinst/MilInstPlugin.lo \ @USE_MILINST_TRUE@ plugins/milinst/MilInstPort.lo \ @USE_MILINST_TRUE@ plugins/milinst/MilInstWidget.lo \ @USE_MILINST_TRUE@ plugins/milinst/MilInstWidget1463.lo \ @USE_MILINST_TRUE@ plugins/milinst/MilInstWidget1553.lo plugins_milinst_libolamilinst_la_OBJECTS = \ $(am_plugins_milinst_libolamilinst_la_OBJECTS) @USE_MILINST_TRUE@am_plugins_milinst_libolamilinst_la_rpath = -rpath \ @USE_MILINST_TRUE@ $(libdir) @USE_OPENDMX_TRUE@plugins_opendmx_libolaopendmx_la_DEPENDENCIES = \ @USE_OPENDMX_TRUE@ common/libolacommon.la \ @USE_OPENDMX_TRUE@ olad/plugin_api/libolaserverplugininterface.la am__plugins_opendmx_libolaopendmx_la_SOURCES_DIST = \ plugins/opendmx/OpenDmxDevice.cpp \ plugins/opendmx/OpenDmxDevice.h \ plugins/opendmx/OpenDmxPlugin.cpp \ plugins/opendmx/OpenDmxPlugin.h plugins/opendmx/OpenDmxPort.h \ plugins/opendmx/OpenDmxThread.cpp \ plugins/opendmx/OpenDmxThread.h @USE_OPENDMX_TRUE@am_plugins_opendmx_libolaopendmx_la_OBJECTS = \ @USE_OPENDMX_TRUE@ plugins/opendmx/OpenDmxDevice.lo \ @USE_OPENDMX_TRUE@ plugins/opendmx/OpenDmxPlugin.lo \ @USE_OPENDMX_TRUE@ plugins/opendmx/OpenDmxThread.lo plugins_opendmx_libolaopendmx_la_OBJECTS = \ $(am_plugins_opendmx_libolaopendmx_la_OBJECTS) @USE_OPENDMX_TRUE@am_plugins_opendmx_libolaopendmx_la_rpath = -rpath \ @USE_OPENDMX_TRUE@ $(libdir) @USE_OPENPIXELCONTROL_TRUE@plugins_openpixelcontrol_libolaopc_la_DEPENDENCIES = \ @USE_OPENPIXELCONTROL_TRUE@ common/libolacommon.la am__plugins_openpixelcontrol_libolaopc_la_SOURCES_DIST = \ plugins/openpixelcontrol/OPCClient.cpp \ plugins/openpixelcontrol/OPCClient.h \ plugins/openpixelcontrol/OPCConstants.h \ plugins/openpixelcontrol/OPCServer.cpp \ plugins/openpixelcontrol/OPCServer.h @USE_OPENPIXELCONTROL_TRUE@am_plugins_openpixelcontrol_libolaopc_la_OBJECTS = plugins/openpixelcontrol/OPCClient.lo \ @USE_OPENPIXELCONTROL_TRUE@ plugins/openpixelcontrol/OPCServer.lo plugins_openpixelcontrol_libolaopc_la_OBJECTS = \ $(am_plugins_openpixelcontrol_libolaopc_la_OBJECTS) @USE_OPENPIXELCONTROL_TRUE@am_plugins_openpixelcontrol_libolaopc_la_rpath = @USE_OPENPIXELCONTROL_TRUE@plugins_openpixelcontrol_libolaopenpixelcontrol_la_DEPENDENCIES = \ @USE_OPENPIXELCONTROL_TRUE@ common/libolacommon.la \ @USE_OPENPIXELCONTROL_TRUE@ olad/plugin_api/libolaserverplugininterface.la \ @USE_OPENPIXELCONTROL_TRUE@ plugins/openpixelcontrol/libolaopc.la am__plugins_openpixelcontrol_libolaopenpixelcontrol_la_SOURCES_DIST = \ plugins/openpixelcontrol/OPCDevice.cpp \ plugins/openpixelcontrol/OPCDevice.h \ plugins/openpixelcontrol/OPCPlugin.cpp \ plugins/openpixelcontrol/OPCPlugin.h \ plugins/openpixelcontrol/OPCPort.cpp \ plugins/openpixelcontrol/OPCPort.h @USE_OPENPIXELCONTROL_TRUE@am_plugins_openpixelcontrol_libolaopenpixelcontrol_la_OBJECTS = plugins/openpixelcontrol/OPCDevice.lo \ @USE_OPENPIXELCONTROL_TRUE@ plugins/openpixelcontrol/OPCPlugin.lo \ @USE_OPENPIXELCONTROL_TRUE@ plugins/openpixelcontrol/OPCPort.lo plugins_openpixelcontrol_libolaopenpixelcontrol_la_OBJECTS = $(am_plugins_openpixelcontrol_libolaopenpixelcontrol_la_OBJECTS) @USE_OPENPIXELCONTROL_TRUE@am_plugins_openpixelcontrol_libolaopenpixelcontrol_la_rpath = \ @USE_OPENPIXELCONTROL_TRUE@ -rpath $(libdir) @USE_OSC_TRUE@plugins_osc_libolaosc_la_DEPENDENCIES = \ @USE_OSC_TRUE@ olad/plugin_api/libolaserverplugininterface.la \ @USE_OSC_TRUE@ plugins/osc/libolaoscnode.la am__plugins_osc_libolaosc_la_SOURCES_DIST = plugins/osc/OSCDevice.cpp \ plugins/osc/OSCDevice.h plugins/osc/OSCPlugin.cpp \ plugins/osc/OSCPlugin.h plugins/osc/OSCPort.cpp \ plugins/osc/OSCPort.h @USE_OSC_TRUE@am_plugins_osc_libolaosc_la_OBJECTS = plugins/osc/plugins_osc_libolaosc_la-OSCDevice.lo \ @USE_OSC_TRUE@ plugins/osc/plugins_osc_libolaosc_la-OSCPlugin.lo \ @USE_OSC_TRUE@ plugins/osc/plugins_osc_libolaosc_la-OSCPort.lo plugins_osc_libolaosc_la_OBJECTS = \ $(am_plugins_osc_libolaosc_la_OBJECTS) plugins_osc_libolaosc_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(plugins_osc_libolaosc_la_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ @USE_OSC_TRUE@am_plugins_osc_libolaosc_la_rpath = -rpath $(libdir) @USE_OSC_TRUE@plugins_osc_libolaoscnode_la_DEPENDENCIES = \ @USE_OSC_TRUE@ $(am__DEPENDENCIES_1) am__plugins_osc_libolaoscnode_la_SOURCES_DIST = \ plugins/osc/OSCAddressTemplate.cpp \ plugins/osc/OSCAddressTemplate.h plugins/osc/OSCNode.cpp \ plugins/osc/OSCNode.h plugins/osc/OSCTarget.h @USE_OSC_TRUE@am_plugins_osc_libolaoscnode_la_OBJECTS = plugins/osc/plugins_osc_libolaoscnode_la-OSCAddressTemplate.lo \ @USE_OSC_TRUE@ plugins/osc/plugins_osc_libolaoscnode_la-OSCNode.lo plugins_osc_libolaoscnode_la_OBJECTS = \ $(am_plugins_osc_libolaoscnode_la_OBJECTS) plugins_osc_libolaoscnode_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(plugins_osc_libolaoscnode_la_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ @USE_OSC_TRUE@am_plugins_osc_libolaoscnode_la_rpath = @USE_PATHPORT_TRUE@plugins_pathport_libolapathport_la_DEPENDENCIES = \ @USE_PATHPORT_TRUE@ common/libolacommon.la \ @USE_PATHPORT_TRUE@ olad/plugin_api/libolaserverplugininterface.la am__plugins_pathport_libolapathport_la_SOURCES_DIST = \ plugins/pathport/PathportDevice.cpp \ plugins/pathport/PathportDevice.h \ plugins/pathport/PathportNode.cpp \ plugins/pathport/PathportNode.h \ plugins/pathport/PathportPackets.h \ plugins/pathport/PathportPlugin.cpp \ plugins/pathport/PathportPlugin.h \ plugins/pathport/PathportPort.cpp \ plugins/pathport/PathportPort.h @USE_PATHPORT_TRUE@am_plugins_pathport_libolapathport_la_OBJECTS = \ @USE_PATHPORT_TRUE@ plugins/pathport/PathportDevice.lo \ @USE_PATHPORT_TRUE@ plugins/pathport/PathportNode.lo \ @USE_PATHPORT_TRUE@ plugins/pathport/PathportPlugin.lo \ @USE_PATHPORT_TRUE@ plugins/pathport/PathportPort.lo plugins_pathport_libolapathport_la_OBJECTS = \ $(am_plugins_pathport_libolapathport_la_OBJECTS) @USE_PATHPORT_TRUE@am_plugins_pathport_libolapathport_la_rpath = \ @USE_PATHPORT_TRUE@ -rpath $(libdir) @USE_RENARD_TRUE@plugins_renard_libolarenard_la_DEPENDENCIES = \ @USE_RENARD_TRUE@ common/libolacommon.la \ @USE_RENARD_TRUE@ olad/plugin_api/libolaserverplugininterface.la am__plugins_renard_libolarenard_la_SOURCES_DIST = \ plugins/renard/RenardDevice.cpp plugins/renard/RenardDevice.h \ plugins/renard/RenardPlugin.cpp plugins/renard/RenardPlugin.h \ plugins/renard/RenardPort.cpp plugins/renard/RenardPort.h \ plugins/renard/RenardWidget.cpp plugins/renard/RenardWidget.h @USE_RENARD_TRUE@am_plugins_renard_libolarenard_la_OBJECTS = \ @USE_RENARD_TRUE@ plugins/renard/RenardDevice.lo \ @USE_RENARD_TRUE@ plugins/renard/RenardPlugin.lo \ @USE_RENARD_TRUE@ plugins/renard/RenardPort.lo \ @USE_RENARD_TRUE@ plugins/renard/RenardWidget.lo plugins_renard_libolarenard_la_OBJECTS = \ $(am_plugins_renard_libolarenard_la_OBJECTS) @USE_RENARD_TRUE@am_plugins_renard_libolarenard_la_rpath = -rpath \ @USE_RENARD_TRUE@ $(libdir) @USE_SANDNET_TRUE@plugins_sandnet_libolasandnet_la_DEPENDENCIES = \ @USE_SANDNET_TRUE@ common/libolacommon.la \ @USE_SANDNET_TRUE@ olad/plugin_api/libolaserverplugininterface.la am__plugins_sandnet_libolasandnet_la_SOURCES_DIST = \ plugins/sandnet/SandNetCommon.h \ plugins/sandnet/SandNetDevice.cpp \ plugins/sandnet/SandNetDevice.h \ plugins/sandnet/SandNetNode.cpp plugins/sandnet/SandNetNode.h \ plugins/sandnet/SandNetPackets.h \ plugins/sandnet/SandNetPlugin.cpp \ plugins/sandnet/SandNetPlugin.h \ plugins/sandnet/SandNetPort.cpp plugins/sandnet/SandNetPort.h @USE_SANDNET_TRUE@am_plugins_sandnet_libolasandnet_la_OBJECTS = \ @USE_SANDNET_TRUE@ plugins/sandnet/SandNetDevice.lo \ @USE_SANDNET_TRUE@ plugins/sandnet/SandNetNode.lo \ @USE_SANDNET_TRUE@ plugins/sandnet/SandNetPlugin.lo \ @USE_SANDNET_TRUE@ plugins/sandnet/SandNetPort.lo plugins_sandnet_libolasandnet_la_OBJECTS = \ $(am_plugins_sandnet_libolasandnet_la_OBJECTS) @USE_SANDNET_TRUE@am_plugins_sandnet_libolasandnet_la_rpath = -rpath \ @USE_SANDNET_TRUE@ $(libdir) @USE_SHOWNET_TRUE@plugins_shownet_libolashownet_la_DEPENDENCIES = \ @USE_SHOWNET_TRUE@ common/libolacommon.la \ @USE_SHOWNET_TRUE@ olad/plugin_api/libolaserverplugininterface.la am__plugins_shownet_libolashownet_la_SOURCES_DIST = \ plugins/shownet/ShowNetPlugin.cpp \ plugins/shownet/ShowNetDevice.cpp \ plugins/shownet/ShowNetPort.cpp \ plugins/shownet/ShowNetNode.cpp \ plugins/shownet/ShowNetPlugin.h \ plugins/shownet/ShowNetDevice.h plugins/shownet/ShowNetPort.h \ plugins/shownet/ShowNetPackets.h plugins/shownet/ShowNetNode.h @USE_SHOWNET_TRUE@am_plugins_shownet_libolashownet_la_OBJECTS = \ @USE_SHOWNET_TRUE@ plugins/shownet/ShowNetPlugin.lo \ @USE_SHOWNET_TRUE@ plugins/shownet/ShowNetDevice.lo \ @USE_SHOWNET_TRUE@ plugins/shownet/ShowNetPort.lo \ @USE_SHOWNET_TRUE@ plugins/shownet/ShowNetNode.lo plugins_shownet_libolashownet_la_OBJECTS = \ $(am_plugins_shownet_libolashownet_la_OBJECTS) @USE_SHOWNET_TRUE@am_plugins_shownet_libolashownet_la_rpath = -rpath \ @USE_SHOWNET_TRUE@ $(libdir) @USE_SPI_TRUE@plugins_spi_libolaspi_la_DEPENDENCIES = \ @USE_SPI_TRUE@ common/libolacommon.la \ @USE_SPI_TRUE@ olad/plugin_api/libolaserverplugininterface.la \ @USE_SPI_TRUE@ plugins/spi/libolaspicore.la am__plugins_spi_libolaspi_la_SOURCES_DIST = plugins/spi/SPIDevice.cpp \ plugins/spi/SPIDevice.h plugins/spi/SPIPlugin.cpp \ plugins/spi/SPIPlugin.h plugins/spi/SPIPort.cpp \ plugins/spi/SPIPort.h @USE_SPI_TRUE@am_plugins_spi_libolaspi_la_OBJECTS = \ @USE_SPI_TRUE@ plugins/spi/SPIDevice.lo \ @USE_SPI_TRUE@ plugins/spi/SPIPlugin.lo plugins/spi/SPIPort.lo plugins_spi_libolaspi_la_OBJECTS = \ $(am_plugins_spi_libolaspi_la_OBJECTS) @USE_SPI_TRUE@am_plugins_spi_libolaspi_la_rpath = -rpath $(libdir) @USE_SPI_TRUE@plugins_spi_libolaspicore_la_DEPENDENCIES = \ @USE_SPI_TRUE@ common/libolacommon.la am__plugins_spi_libolaspicore_la_SOURCES_DIST = \ plugins/spi/SPIBackend.cpp plugins/spi/SPIBackend.h \ plugins/spi/SPIOutput.cpp plugins/spi/SPIOutput.h \ plugins/spi/SPIWriter.cpp plugins/spi/SPIWriter.h @USE_SPI_TRUE@am_plugins_spi_libolaspicore_la_OBJECTS = \ @USE_SPI_TRUE@ plugins/spi/SPIBackend.lo \ @USE_SPI_TRUE@ plugins/spi/SPIOutput.lo \ @USE_SPI_TRUE@ plugins/spi/SPIWriter.lo plugins_spi_libolaspicore_la_OBJECTS = \ $(am_plugins_spi_libolaspicore_la_OBJECTS) @USE_SPI_TRUE@am_plugins_spi_libolaspicore_la_rpath = -rpath $(libdir) @USE_STAGEPROFI_TRUE@plugins_stageprofi_libolastageprofi_la_DEPENDENCIES = \ @USE_STAGEPROFI_TRUE@ common/libolacommon.la \ @USE_STAGEPROFI_TRUE@ olad/plugin_api/libolaserverplugininterface.la am__plugins_stageprofi_libolastageprofi_la_SOURCES_DIST = \ plugins/stageprofi/StageProfiDetector.cpp \ plugins/stageprofi/StageProfiDetector.h \ plugins/stageprofi/StageProfiDevice.cpp \ plugins/stageprofi/StageProfiDevice.h \ plugins/stageprofi/StageProfiPlugin.cpp \ plugins/stageprofi/StageProfiPlugin.h \ plugins/stageprofi/StageProfiPort.cpp \ plugins/stageprofi/StageProfiPort.h \ plugins/stageprofi/StageProfiWidget.cpp \ plugins/stageprofi/StageProfiWidget.h @USE_STAGEPROFI_TRUE@am_plugins_stageprofi_libolastageprofi_la_OBJECTS = \ @USE_STAGEPROFI_TRUE@ plugins/stageprofi/StageProfiDetector.lo \ @USE_STAGEPROFI_TRUE@ plugins/stageprofi/StageProfiDevice.lo \ @USE_STAGEPROFI_TRUE@ plugins/stageprofi/StageProfiPlugin.lo \ @USE_STAGEPROFI_TRUE@ plugins/stageprofi/StageProfiPort.lo \ @USE_STAGEPROFI_TRUE@ plugins/stageprofi/StageProfiWidget.lo plugins_stageprofi_libolastageprofi_la_OBJECTS = \ $(am_plugins_stageprofi_libolastageprofi_la_OBJECTS) @USE_STAGEPROFI_TRUE@am_plugins_stageprofi_libolastageprofi_la_rpath = \ @USE_STAGEPROFI_TRUE@ -rpath $(libdir) @USE_UART_TRUE@@USING_WIN32_FALSE@plugins_uartdmx_libolauartdmx_la_DEPENDENCIES = \ @USE_UART_TRUE@@USING_WIN32_FALSE@ common/libolacommon.la \ @USE_UART_TRUE@@USING_WIN32_FALSE@ olad/plugin_api/libolaserverplugininterface.la am__plugins_uartdmx_libolauartdmx_la_SOURCES_DIST = \ plugins/uartdmx/UartDmxDevice.cpp \ plugins/uartdmx/UartDmxDevice.h \ plugins/uartdmx/UartDmxPlugin.cpp \ plugins/uartdmx/UartDmxPlugin.h plugins/uartdmx/UartDmxPort.h \ plugins/uartdmx/UartDmxThread.cpp \ plugins/uartdmx/UartDmxThread.h plugins/uartdmx/UartWidget.cpp \ plugins/uartdmx/UartWidget.h @USE_UART_TRUE@@USING_WIN32_FALSE@am_plugins_uartdmx_libolauartdmx_la_OBJECTS = plugins/uartdmx/UartDmxDevice.lo \ @USE_UART_TRUE@@USING_WIN32_FALSE@ plugins/uartdmx/UartDmxPlugin.lo \ @USE_UART_TRUE@@USING_WIN32_FALSE@ plugins/uartdmx/UartDmxThread.lo \ @USE_UART_TRUE@@USING_WIN32_FALSE@ plugins/uartdmx/UartWidget.lo plugins_uartdmx_libolauartdmx_la_OBJECTS = \ $(am_plugins_uartdmx_libolauartdmx_la_OBJECTS) @USE_UART_TRUE@@USING_WIN32_FALSE@am_plugins_uartdmx_libolauartdmx_la_rpath = \ @USE_UART_TRUE@@USING_WIN32_FALSE@ -rpath $(libdir) @USE_LIBUSB_TRUE@plugins_usbdmx_libolausbdmx_la_DEPENDENCIES = olad/plugin_api/libolaserverplugininterface.la \ @USE_LIBUSB_TRUE@ plugins/usbdmx/libolausbdmxwidget.la am__plugins_usbdmx_libolausbdmx_la_SOURCES_DIST = \ plugins/usbdmx/AsyncPluginImpl.cpp \ plugins/usbdmx/AsyncPluginImpl.h \ plugins/usbdmx/DMXCProjectsNodleU1Device.cpp \ plugins/usbdmx/DMXCProjectsNodleU1Device.h \ plugins/usbdmx/DMXCProjectsNodleU1Port.cpp \ plugins/usbdmx/DMXCProjectsNodleU1Port.h \ plugins/usbdmx/GenericDevice.cpp \ plugins/usbdmx/GenericDevice.h \ plugins/usbdmx/GenericOutputPort.cpp \ plugins/usbdmx/GenericOutputPort.h \ plugins/usbdmx/JaRuleDevice.cpp plugins/usbdmx/JaRuleDevice.h \ plugins/usbdmx/JaRuleOutputPort.cpp \ plugins/usbdmx/JaRuleOutputPort.h \ plugins/usbdmx/PluginImplInterface.h \ plugins/usbdmx/SyncPluginImpl.cpp \ plugins/usbdmx/SyncPluginImpl.h \ plugins/usbdmx/UsbDmxPlugin.cpp plugins/usbdmx/UsbDmxPlugin.h @USE_LIBUSB_TRUE@am_plugins_usbdmx_libolausbdmx_la_OBJECTS = plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-AsyncPluginImpl.lo \ @USE_LIBUSB_TRUE@ plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-DMXCProjectsNodleU1Device.lo \ @USE_LIBUSB_TRUE@ plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-DMXCProjectsNodleU1Port.lo \ @USE_LIBUSB_TRUE@ plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-GenericDevice.lo \ @USE_LIBUSB_TRUE@ plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-GenericOutputPort.lo \ @USE_LIBUSB_TRUE@ plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-JaRuleDevice.lo \ @USE_LIBUSB_TRUE@ plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-JaRuleOutputPort.lo \ @USE_LIBUSB_TRUE@ plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-SyncPluginImpl.lo \ @USE_LIBUSB_TRUE@ plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-UsbDmxPlugin.lo plugins_usbdmx_libolausbdmx_la_OBJECTS = \ $(am_plugins_usbdmx_libolausbdmx_la_OBJECTS) plugins_usbdmx_libolausbdmx_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(plugins_usbdmx_libolausbdmx_la_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ @USE_LIBUSB_TRUE@am_plugins_usbdmx_libolausbdmx_la_rpath = -rpath \ @USE_LIBUSB_TRUE@ $(libdir) @USE_LIBUSB_TRUE@plugins_usbdmx_libolausbdmxwidget_la_DEPENDENCIES = \ @USE_LIBUSB_TRUE@ $(am__DEPENDENCIES_1) common/libolacommon.la \ @USE_LIBUSB_TRUE@ libs/usb/libolausb.la am__plugins_usbdmx_libolausbdmxwidget_la_SOURCES_DIST = \ plugins/usbdmx/AnymauDMX.cpp plugins/usbdmx/AnymauDMX.h \ plugins/usbdmx/AnymauDMXFactory.cpp \ plugins/usbdmx/AnymauDMXFactory.h \ plugins/usbdmx/AsyncUsbReceiver.cpp \ plugins/usbdmx/AsyncUsbReceiver.h \ plugins/usbdmx/AsyncUsbSender.cpp \ plugins/usbdmx/AsyncUsbSender.h \ plugins/usbdmx/AsyncUsbTransceiverBase.cpp \ plugins/usbdmx/AsyncUsbTransceiverBase.h \ plugins/usbdmx/DMXCProjectsNodleU1.cpp \ plugins/usbdmx/DMXCProjectsNodleU1.h \ plugins/usbdmx/DMXCProjectsNodleU1Factory.cpp \ plugins/usbdmx/DMXCProjectsNodleU1Factory.h \ plugins/usbdmx/EurolitePro.cpp plugins/usbdmx/EurolitePro.h \ plugins/usbdmx/EuroliteProFactory.cpp \ plugins/usbdmx/EuroliteProFactory.h \ plugins/usbdmx/FirmwareLoader.h plugins/usbdmx/Flags.cpp \ plugins/usbdmx/JaRuleFactory.cpp \ plugins/usbdmx/JaRuleFactory.h \ plugins/usbdmx/ScanlimeFadecandy.cpp \ plugins/usbdmx/ScanlimeFadecandy.h \ plugins/usbdmx/ScanlimeFadecandyFactory.cpp \ plugins/usbdmx/ScanlimeFadecandyFactory.h \ plugins/usbdmx/Sunlite.cpp plugins/usbdmx/Sunlite.h \ plugins/usbdmx/SunliteFactory.cpp \ plugins/usbdmx/SunliteFactory.h \ plugins/usbdmx/SunliteFirmware.h \ plugins/usbdmx/SunliteFirmwareLoader.cpp \ plugins/usbdmx/SunliteFirmwareLoader.h \ plugins/usbdmx/SyncronizedWidgetObserver.cpp \ plugins/usbdmx/SyncronizedWidgetObserver.h \ plugins/usbdmx/ThreadedUsbReceiver.cpp \ plugins/usbdmx/ThreadedUsbReceiver.h \ plugins/usbdmx/ThreadedUsbSender.cpp \ plugins/usbdmx/ThreadedUsbSender.h \ plugins/usbdmx/VellemanK8062.cpp \ plugins/usbdmx/VellemanK8062.h \ plugins/usbdmx/VellemanK8062Factory.cpp \ plugins/usbdmx/VellemanK8062Factory.h plugins/usbdmx/Widget.h \ plugins/usbdmx/WidgetFactory.h @USE_LIBUSB_TRUE@am_plugins_usbdmx_libolausbdmxwidget_la_OBJECTS = plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AnymauDMX.lo \ @USE_LIBUSB_TRUE@ plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AnymauDMXFactory.lo \ @USE_LIBUSB_TRUE@ plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbReceiver.lo \ @USE_LIBUSB_TRUE@ plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbSender.lo \ @USE_LIBUSB_TRUE@ plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbTransceiverBase.lo \ @USE_LIBUSB_TRUE@ plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-DMXCProjectsNodleU1.lo \ @USE_LIBUSB_TRUE@ plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-DMXCProjectsNodleU1Factory.lo \ @USE_LIBUSB_TRUE@ plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-EurolitePro.lo \ @USE_LIBUSB_TRUE@ plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-EuroliteProFactory.lo \ @USE_LIBUSB_TRUE@ plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-Flags.lo \ @USE_LIBUSB_TRUE@ plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-JaRuleFactory.lo \ @USE_LIBUSB_TRUE@ plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-ScanlimeFadecandy.lo \ @USE_LIBUSB_TRUE@ plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-ScanlimeFadecandyFactory.lo \ @USE_LIBUSB_TRUE@ plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-Sunlite.lo \ @USE_LIBUSB_TRUE@ plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-SunliteFactory.lo \ @USE_LIBUSB_TRUE@ plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-SunliteFirmwareLoader.lo \ @USE_LIBUSB_TRUE@ plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-SyncronizedWidgetObserver.lo \ @USE_LIBUSB_TRUE@ plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-ThreadedUsbReceiver.lo \ @USE_LIBUSB_TRUE@ plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-ThreadedUsbSender.lo \ @USE_LIBUSB_TRUE@ plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-VellemanK8062.lo \ @USE_LIBUSB_TRUE@ plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-VellemanK8062Factory.lo plugins_usbdmx_libolausbdmxwidget_la_OBJECTS = \ $(am_plugins_usbdmx_libolausbdmxwidget_la_OBJECTS) plugins_usbdmx_libolausbdmxwidget_la_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CXXLD) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ @USE_LIBUSB_TRUE@am_plugins_usbdmx_libolausbdmxwidget_la_rpath = @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_libolausbpro_la_DEPENDENCIES = olad/plugin_api/libolaserverplugininterface.la \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/libolausbprowidget.la \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/messages/libolausbproconf.la am__plugins_usbpro_libolausbpro_la_SOURCES_DIST = \ plugins/usbpro/ArduinoRGBDevice.cpp \ plugins/usbpro/ArduinoRGBDevice.h \ plugins/usbpro/DmxTriDevice.cpp plugins/usbpro/DmxTriDevice.h \ plugins/usbpro/DmxterDevice.cpp plugins/usbpro/DmxterDevice.h \ plugins/usbpro/RobeDevice.cpp plugins/usbpro/RobeDevice.h \ plugins/usbpro/UltraDMXProDevice.cpp \ plugins/usbpro/UltraDMXProDevice.h \ plugins/usbpro/UsbProDevice.cpp plugins/usbpro/UsbProDevice.h \ plugins/usbpro/UsbSerialDevice.h \ plugins/usbpro/UsbSerialPlugin.cpp \ plugins/usbpro/UsbSerialPlugin.h @USE_USBPRO_TRUE@@USING_WIN32_FALSE@am_plugins_usbpro_libolausbpro_la_OBJECTS = plugins/usbpro/plugins_usbpro_libolausbpro_la-ArduinoRGBDevice.lo \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/plugins_usbpro_libolausbpro_la-DmxTriDevice.lo \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/plugins_usbpro_libolausbpro_la-DmxterDevice.lo \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/plugins_usbpro_libolausbpro_la-RobeDevice.lo \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/plugins_usbpro_libolausbpro_la-UltraDMXProDevice.lo \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/plugins_usbpro_libolausbpro_la-UsbProDevice.lo \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/plugins_usbpro_libolausbpro_la-UsbSerialPlugin.lo plugins_usbpro_libolausbpro_la_OBJECTS = \ $(am_plugins_usbpro_libolausbpro_la_OBJECTS) plugins_usbpro_libolausbpro_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(plugins_usbpro_libolausbpro_la_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@am_plugins_usbpro_libolausbpro_la_rpath = \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ -rpath $(libdir) @USING_WIN32_FALSE@plugins_usbpro_libolausbprowidget_la_DEPENDENCIES = \ @USING_WIN32_FALSE@ common/libolacommon.la am__plugins_usbpro_libolausbprowidget_la_SOURCES_DIST = \ plugins/usbpro/ArduinoWidget.cpp \ plugins/usbpro/ArduinoWidget.h \ plugins/usbpro/BaseRobeWidget.cpp \ plugins/usbpro/BaseRobeWidget.h \ plugins/usbpro/BaseUsbProWidget.cpp \ plugins/usbpro/BaseUsbProWidget.h \ plugins/usbpro/DmxTriWidget.cpp plugins/usbpro/DmxTriWidget.h \ plugins/usbpro/DmxterWidget.cpp plugins/usbpro/DmxterWidget.h \ plugins/usbpro/EnttecUsbProWidget.cpp \ plugins/usbpro/EnttecUsbProWidget.h \ plugins/usbpro/EnttecUsbProWidgetImpl.h \ plugins/usbpro/GenericUsbProWidget.cpp \ plugins/usbpro/GenericUsbProWidget.h \ plugins/usbpro/RobeWidget.cpp plugins/usbpro/RobeWidget.h \ plugins/usbpro/RobeWidgetDetector.cpp \ plugins/usbpro/RobeWidgetDetector.h \ plugins/usbpro/SerialWidgetInterface.h \ plugins/usbpro/UltraDMXProWidget.cpp \ plugins/usbpro/UltraDMXProWidget.h \ plugins/usbpro/UsbProWidgetDetector.cpp \ plugins/usbpro/UsbProWidgetDetector.h \ plugins/usbpro/WidgetDetectorInterface.h \ plugins/usbpro/WidgetDetectorThread.cpp \ plugins/usbpro/WidgetDetectorThread.h @USING_WIN32_FALSE@am_plugins_usbpro_libolausbprowidget_la_OBJECTS = \ @USING_WIN32_FALSE@ plugins/usbpro/ArduinoWidget.lo \ @USING_WIN32_FALSE@ plugins/usbpro/BaseRobeWidget.lo \ @USING_WIN32_FALSE@ plugins/usbpro/BaseUsbProWidget.lo \ @USING_WIN32_FALSE@ plugins/usbpro/DmxTriWidget.lo \ @USING_WIN32_FALSE@ plugins/usbpro/DmxterWidget.lo \ @USING_WIN32_FALSE@ plugins/usbpro/EnttecUsbProWidget.lo \ @USING_WIN32_FALSE@ plugins/usbpro/GenericUsbProWidget.lo \ @USING_WIN32_FALSE@ plugins/usbpro/RobeWidget.lo \ @USING_WIN32_FALSE@ plugins/usbpro/RobeWidgetDetector.lo \ @USING_WIN32_FALSE@ plugins/usbpro/UltraDMXProWidget.lo \ @USING_WIN32_FALSE@ plugins/usbpro/UsbProWidgetDetector.lo \ @USING_WIN32_FALSE@ plugins/usbpro/WidgetDetectorThread.lo plugins_usbpro_libolausbprowidget_la_OBJECTS = \ $(am_plugins_usbpro_libolausbprowidget_la_OBJECTS) @USING_WIN32_FALSE@am_plugins_usbpro_libolausbprowidget_la_rpath = @USING_WIN32_FALSE@plugins_usbpro_messages_libolausbproconf_la_DEPENDENCIES = \ @USING_WIN32_FALSE@ $(am__DEPENDENCIES_1) @USING_WIN32_FALSE@nodist_plugins_usbpro_messages_libolausbproconf_la_OBJECTS = plugins/usbpro/messages/plugins_usbpro_messages_libolausbproconf_la-UsbProConfigMessages.pb.lo plugins_usbpro_messages_libolausbproconf_la_OBJECTS = \ $(nodist_plugins_usbpro_messages_libolausbproconf_la_OBJECTS) plugins_usbpro_messages_libolausbproconf_la_LINK = $(LIBTOOL) \ $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CXXLD) \ $(plugins_usbpro_messages_libolausbproconf_la_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ @USING_WIN32_FALSE@am_plugins_usbpro_messages_libolausbproconf_la_rpath = \ @USING_WIN32_FALSE@ -rpath $(libdir) @USING_WIN32_FALSE@tools_e133_libolae133common_la_DEPENDENCIES = \ @USING_WIN32_FALSE@ libs/acn/libolae131core.la am__tools_e133_libolae133common_la_SOURCES_DIST = \ tools/e133/E133HealthCheckedConnection.cpp \ tools/e133/E133HealthCheckedConnection.h \ tools/e133/E133Receiver.cpp tools/e133/E133StatusHelper.cpp \ tools/e133/MessageBuilder.cpp @USING_WIN32_FALSE@am_tools_e133_libolae133common_la_OBJECTS = \ @USING_WIN32_FALSE@ tools/e133/E133HealthCheckedConnection.lo \ @USING_WIN32_FALSE@ tools/e133/E133Receiver.lo \ @USING_WIN32_FALSE@ tools/e133/E133StatusHelper.lo \ @USING_WIN32_FALSE@ tools/e133/MessageBuilder.lo tools_e133_libolae133common_la_OBJECTS = \ $(am_tools_e133_libolae133common_la_OBJECTS) @INSTALL_E133_FALSE@@USING_WIN32_FALSE@am_tools_e133_libolae133common_la_rpath = @INSTALL_E133_TRUE@@USING_WIN32_FALSE@am_tools_e133_libolae133common_la_rpath = \ @INSTALL_E133_TRUE@@USING_WIN32_FALSE@ -rpath $(libdir) @USING_WIN32_FALSE@tools_e133_libolae133controller_la_DEPENDENCIES = \ @USING_WIN32_FALSE@ common/libolacommon.la \ @USING_WIN32_FALSE@ libs/acn/libolae131core.la \ @USING_WIN32_FALSE@ tools/e133/libolae133common.la am__tools_e133_libolae133controller_la_SOURCES_DIST = \ tools/e133/DeviceManager.cpp tools/e133/DeviceManagerImpl.cpp \ tools/e133/DeviceManagerImpl.h @USING_WIN32_FALSE@am_tools_e133_libolae133controller_la_OBJECTS = \ @USING_WIN32_FALSE@ tools/e133/DeviceManager.lo \ @USING_WIN32_FALSE@ tools/e133/DeviceManagerImpl.lo tools_e133_libolae133controller_la_OBJECTS = \ $(am_tools_e133_libolae133controller_la_OBJECTS) @INSTALL_E133_FALSE@@USING_WIN32_FALSE@am_tools_e133_libolae133controller_la_rpath = @INSTALL_E133_TRUE@@USING_WIN32_FALSE@am_tools_e133_libolae133controller_la_rpath = \ @INSTALL_E133_TRUE@@USING_WIN32_FALSE@ -rpath $(libdir) @USING_WIN32_FALSE@tools_e133_libolae133device_la_DEPENDENCIES = \ @USING_WIN32_FALSE@ common/libolacommon.la \ @USING_WIN32_FALSE@ libs/acn/libolae131core.la \ @USING_WIN32_FALSE@ tools/e133/libolae133common.la am__tools_e133_libolae133device_la_SOURCES_DIST = \ tools/e133/DesignatedControllerConnection.cpp \ tools/e133/DesignatedControllerConnection.h \ tools/e133/E133Device.cpp tools/e133/E133Device.h \ tools/e133/E133Endpoint.cpp tools/e133/E133Endpoint.h \ tools/e133/EndpointManager.cpp tools/e133/EndpointManager.h \ tools/e133/ManagementEndpoint.cpp \ tools/e133/ManagementEndpoint.h tools/e133/SimpleE133Node.cpp \ tools/e133/SimpleE133Node.h tools/e133/TCPConnectionStats.h @USING_WIN32_FALSE@am_tools_e133_libolae133device_la_OBJECTS = tools/e133/DesignatedControllerConnection.lo \ @USING_WIN32_FALSE@ tools/e133/E133Device.lo \ @USING_WIN32_FALSE@ tools/e133/E133Endpoint.lo \ @USING_WIN32_FALSE@ tools/e133/EndpointManager.lo \ @USING_WIN32_FALSE@ tools/e133/ManagementEndpoint.lo \ @USING_WIN32_FALSE@ tools/e133/SimpleE133Node.lo tools_e133_libolae133device_la_OBJECTS = \ $(am_tools_e133_libolae133device_la_OBJECTS) @INSTALL_E133_FALSE@@USING_WIN32_FALSE@am_tools_e133_libolae133device_la_rpath = @INSTALL_E133_TRUE@@USING_WIN32_FALSE@am_tools_e133_libolae133device_la_rpath = \ @INSTALL_E133_TRUE@@USING_WIN32_FALSE@ -rpath $(libdir) tools_ola_trigger_libolatrigger_la_DEPENDENCIES = \ common/libolacommon.la am_tools_ola_trigger_libolatrigger_la_OBJECTS = \ tools/ola_trigger/Action.lo tools/ola_trigger/Context.lo \ tools/ola_trigger/DMXTrigger.lo \ tools/ola_trigger/VariableInterpolator.lo tools_ola_trigger_libolatrigger_la_OBJECTS = \ $(am_tools_ola_trigger_libolatrigger_la_OBJECTS) @BUILD_EXAMPLES_TRUE@am__EXEEXT_1 = examples/ola_dev_info$(EXEEXT) \ @BUILD_EXAMPLES_TRUE@ examples/ola_rdm_discover$(EXEEXT) \ @BUILD_EXAMPLES_TRUE@ examples/ola_rdm_get$(EXEEXT) \ @BUILD_EXAMPLES_TRUE@ examples/ola_recorder$(EXEEXT) \ @BUILD_EXAMPLES_TRUE@ examples/ola_streaming_client$(EXEEXT) \ @BUILD_EXAMPLES_TRUE@ examples/ola_timecode$(EXEEXT) \ @BUILD_EXAMPLES_TRUE@ examples/ola_uni_stats$(EXEEXT) @BUILD_EXAMPLES_TRUE@@USE_E131_TRUE@am__EXEEXT_2 = examples/ola_e131$(EXEEXT) @BUILD_EXAMPLES_TRUE@@USE_USBPRO_TRUE@am__EXEEXT_3 = examples/ola_usbpro$(EXEEXT) @BUILD_EXAMPLES_TRUE@@USE_ARTNET_TRUE@am__EXEEXT_4 = examples/ola_artnet$(EXEEXT) @BUILD_EXAMPLES_TRUE@@HAVE_NCURSES_TRUE@am__EXEEXT_5 = examples/ola_dmxconsole$(EXEEXT) \ @BUILD_EXAMPLES_TRUE@@HAVE_NCURSES_TRUE@ examples/ola_dmxmonitor$(EXEEXT) @BUILD_JA_RULE_TRUE@am__EXEEXT_6 = tools/ja-rule/ja-rule$(EXEEXT) \ @BUILD_JA_RULE_TRUE@ tools/ja-rule/ja-rule-controller$(EXEEXT) @HAVE_SALEAE_LOGIC_TRUE@am__EXEEXT_7 = tools/logic/logic_rdm_sniffer$(EXEEXT) @USING_WIN32_FALSE@am__EXEEXT_8 = \ @USING_WIN32_FALSE@ tools/usbpro/usbpro_firmware$(EXEEXT) \ @USING_WIN32_FALSE@ tools/rdmpro/rdmpro_sniffer$(EXEEXT) @BUILD_TESTS_TRUE@am__EXEEXT_9 = data/rdm/PidDataTester$(EXEEXT) @USE_LIBUSB_TRUE@am__EXEEXT_10 = libs/usb/LibUsbThreadTester$(EXEEXT) @USE_ARTNET_TRUE@am__EXEEXT_11 = plugins/artnet/ArtNetTester$(EXEEXT) @USE_DUMMY_TRUE@am__EXEEXT_12 = \ @USE_DUMMY_TRUE@ plugins/dummy/DummyPluginTester$(EXEEXT) @USE_ESPNET_TRUE@am__EXEEXT_13 = plugins/espnet/EspNetTester$(EXEEXT) @USE_KINET_TRUE@am__EXEEXT_14 = plugins/kinet/KiNetTester$(EXEEXT) @USE_OPENPIXELCONTROL_TRUE@am__EXEEXT_15 = plugins/openpixelcontrol/OPCClientTester$(EXEEXT) \ @USE_OPENPIXELCONTROL_TRUE@ plugins/openpixelcontrol/OPCServerTester$(EXEEXT) @USE_OSC_TRUE@am__EXEEXT_16 = plugins/osc/OSCTester$(EXEEXT) @USE_SHOWNET_TRUE@am__EXEEXT_17 = \ @USE_SHOWNET_TRUE@ plugins/shownet/ShowNetTester$(EXEEXT) @USE_SPI_TRUE@am__EXEEXT_18 = plugins/spi/SPITester$(EXEEXT) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@am__EXEEXT_19 = plugins/usbpro/ArduinoWidgetTester$(EXEEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/BaseRobeWidgetTester$(EXEEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/BaseUsbProWidgetTester$(EXEEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/DmxTriWidgetTester$(EXEEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/DmxterWidgetTester$(EXEEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/EnttecUsbProWidgetTester$(EXEEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/RobeWidgetDetectorTester$(EXEEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/RobeWidgetTester$(EXEEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/UltraDMXProWidgetTester$(EXEEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/UsbProWidgetDetectorTester$(EXEEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/WidgetDetectorThreadTester$(EXEEXT) am__EXEEXT_20 = common/base/CredentialsTester$(EXEEXT) \ common/base/FlagsTester$(EXEEXT) \ common/base/LoggingTester$(EXEEXT) \ common/dmx/RunLengthEncoderTester$(EXEEXT) \ common/export_map/ExportMapTester$(EXEEXT) \ common/file/UtilTester$(EXEEXT) \ common/io/DescriptorTester$(EXEEXT) \ common/io/IOQueueTester$(EXEEXT) \ common/io/IOStackTester$(EXEEXT) \ common/io/MemoryBlockTester$(EXEEXT) \ common/io/SelectServerTester$(EXEEXT) \ common/io/StreamTester$(EXEEXT) \ common/io/TimeoutManagerTester$(EXEEXT) \ common/messaging/DescriptorTester$(EXEEXT) \ common/network/HealthCheckedConnectionTester$(EXEEXT) \ common/network/NetworkTester$(EXEEXT) \ common/network/TCPConnectorTester$(EXEEXT) \ common/rdm/DiscoveryAgentTester$(EXEEXT) \ common/rdm/PidStoreTester$(EXEEXT) \ common/rdm/QueueingRDMControllerTester$(EXEEXT) \ common/rdm/RDMAPITester$(EXEEXT) \ common/rdm/RDMCommandSerializerTester$(EXEEXT) \ common/rdm/RDMCommandTester$(EXEEXT) \ common/rdm/RDMFrameTester$(EXEEXT) \ common/rdm/RDMHelperTester$(EXEEXT) \ common/rdm/RDMMessageTester$(EXEEXT) \ common/rdm/RDMReplyTester$(EXEEXT) \ common/rdm/UIDAllocatorTester$(EXEEXT) \ common/rdm/UIDTester$(EXEEXT) common/rpc/RpcTester$(EXEEXT) \ common/rpc/RpcServerTester$(EXEEXT) \ common/strings/UtilsTester$(EXEEXT) \ common/thread/ExecutorThreadTester$(EXEEXT) \ common/thread/ThreadTester$(EXEEXT) \ common/thread/FutureTester$(EXEEXT) \ common/timecode/TimeCodeTester$(EXEEXT) \ common/utils/UtilsTester$(EXEEXT) \ common/web/JsonTester$(EXEEXT) \ common/web/ParserTester$(EXEEXT) \ common/web/PtchParserTester$(EXEEXT) \ common/web/PtchTester$(EXEEXT) \ common/web/PointerTester$(EXEEXT) \ common/web/PointerTrackerTester$(EXEEXT) \ common/web/SchemaParserTester$(EXEEXT) \ common/web/SchemaTester$(EXEEXT) \ common/web/SectionsTester$(EXEEXT) $(am__EXEEXT_9) \ libs/acn/E131Tester$(EXEEXT) libs/acn/E133Tester$(EXEEXT) \ libs/acn/TransportTester$(EXEEXT) $(am__EXEEXT_10) \ ola/OlaClientTester$(EXEEXT) \ olad/plugin_api/ClientTester$(EXEEXT) \ olad/plugin_api/DeviceTester$(EXEEXT) \ olad/plugin_api/DmxSourceTester$(EXEEXT) \ olad/plugin_api/PortTester$(EXEEXT) \ olad/plugin_api/PreferencesTester$(EXEEXT) \ olad/plugin_api/UniverseTester$(EXEEXT) $(am__EXEEXT_11) \ $(am__EXEEXT_12) $(am__EXEEXT_13) $(am__EXEEXT_14) \ $(am__EXEEXT_15) $(am__EXEEXT_16) $(am__EXEEXT_17) \ $(am__EXEEXT_18) $(am__EXEEXT_19) olad/OlaTester$(EXEEXT) \ tools/ola_trigger/ActionTester$(EXEEXT) @BUILD_EXAMPLES_TRUE@am__EXEEXT_21 = doxygen/examples/callback_client_transmit$(EXEEXT) \ @BUILD_EXAMPLES_TRUE@ doxygen/examples/client_disconnect$(EXEEXT) \ @BUILD_EXAMPLES_TRUE@ doxygen/examples/client_thread$(EXEEXT) \ @BUILD_EXAMPLES_TRUE@ doxygen/examples/fetch_plugins$(EXEEXT) \ @BUILD_EXAMPLES_TRUE@ doxygen/examples/flags$(EXEEXT) \ @BUILD_EXAMPLES_TRUE@ doxygen/examples/legacy_callback_client_transmit$(EXEEXT) \ @BUILD_EXAMPLES_TRUE@ doxygen/examples/legacy_receiver$(EXEEXT) \ @BUILD_EXAMPLES_TRUE@ doxygen/examples/legacy_streaming_client$(EXEEXT) \ @BUILD_EXAMPLES_TRUE@ doxygen/examples/receiver$(EXEEXT) \ @BUILD_EXAMPLES_TRUE@ doxygen/examples/stdin_handler$(EXEEXT) \ @BUILD_EXAMPLES_TRUE@ doxygen/examples/streaming_client$(EXEEXT) \ @BUILD_EXAMPLES_TRUE@ doxygen/examples/udp_server$(EXEEXT) @BUILD_EXAMPLES_TRUE@@HAVE_DLOPEN_TRUE@am__EXEEXT_22 = doxygen/examples/streaming_client_plugin$(EXEEXT) @BUILD_EXAMPLES_TRUE@am__EXEEXT_23 = examples/ola_throughput$(EXEEXT) \ @BUILD_EXAMPLES_TRUE@ examples/ola_latency$(EXEEXT) @USE_ARTNET_TRUE@am__EXEEXT_24 = \ @USE_ARTNET_TRUE@ plugins/artnet/artnet_loadtest$(EXEEXT) @BUILD_OLA_PROTOC_PLUGIN_TRUE@am__EXEEXT_25 = protoc/ola_protoc_plugin$(EXEEXT) @USING_WIN32_FALSE@am__EXEEXT_26 = \ @USING_WIN32_FALSE@ tools/e133/basic_controller$(EXEEXT) \ @USING_WIN32_FALSE@ tools/e133/basic_device$(EXEEXT) \ @USING_WIN32_FALSE@ tools/e133/e133_controller$(EXEEXT) \ @USING_WIN32_FALSE@ tools/e133/e133_monitor$(EXEEXT) \ @USING_WIN32_FALSE@ tools/e133/e133_receiver$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) am_common_base_CredentialsTester_OBJECTS = common/base/common_base_CredentialsTester-CredentialsTest.$(OBJEXT) common_base_CredentialsTester_OBJECTS = \ $(am_common_base_CredentialsTester_OBJECTS) @USING_WIN32_TRUE@am__DEPENDENCIES_4 = $(am__DEPENDENCIES_1) am__DEPENDENCIES_5 = $(am__DEPENDENCIES_1) \ common/testing/libolatesting.la common/testing/libtestmain.la \ common/libolacommon.la $(am__DEPENDENCIES_4) common_base_CredentialsTester_DEPENDENCIES = $(am__DEPENDENCIES_5) common_base_CredentialsTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_base_CredentialsTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_common_base_FlagsTester_OBJECTS = \ common/base/common_base_FlagsTester-FlagsTest.$(OBJEXT) common_base_FlagsTester_OBJECTS = \ $(am_common_base_FlagsTester_OBJECTS) common_base_FlagsTester_DEPENDENCIES = $(am__DEPENDENCIES_5) common_base_FlagsTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_base_FlagsTester_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am_common_base_LoggingTester_OBJECTS = \ common/base/common_base_LoggingTester-LoggingTest.$(OBJEXT) common_base_LoggingTester_OBJECTS = \ $(am_common_base_LoggingTester_OBJECTS) common_base_LoggingTester_DEPENDENCIES = $(am__DEPENDENCIES_5) common_base_LoggingTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_base_LoggingTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_common_dmx_RunLengthEncoderTester_OBJECTS = common/dmx/common_dmx_RunLengthEncoderTester-RunLengthEncoderTest.$(OBJEXT) common_dmx_RunLengthEncoderTester_OBJECTS = \ $(am_common_dmx_RunLengthEncoderTester_OBJECTS) common_dmx_RunLengthEncoderTester_DEPENDENCIES = \ $(am__DEPENDENCIES_5) common_dmx_RunLengthEncoderTester_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CXXLD) $(common_dmx_RunLengthEncoderTester_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_common_export_map_ExportMapTester_OBJECTS = common/export_map/common_export_map_ExportMapTester-ExportMapTest.$(OBJEXT) common_export_map_ExportMapTester_OBJECTS = \ $(am_common_export_map_ExportMapTester_OBJECTS) common_export_map_ExportMapTester_DEPENDENCIES = \ $(am__DEPENDENCIES_5) common_export_map_ExportMapTester_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CXXLD) $(common_export_map_ExportMapTester_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_common_file_UtilTester_OBJECTS = \ common/file/common_file_UtilTester-UtilTest.$(OBJEXT) common_file_UtilTester_OBJECTS = $(am_common_file_UtilTester_OBJECTS) common_file_UtilTester_DEPENDENCIES = $(am__DEPENDENCIES_5) common_file_UtilTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_file_UtilTester_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am_common_io_DescriptorTester_OBJECTS = \ common/io/common_io_DescriptorTester-DescriptorTest.$(OBJEXT) common_io_DescriptorTester_OBJECTS = \ $(am_common_io_DescriptorTester_OBJECTS) common_io_DescriptorTester_DEPENDENCIES = $(am__DEPENDENCIES_5) common_io_DescriptorTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_io_DescriptorTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_common_io_IOQueueTester_OBJECTS = \ common/io/common_io_IOQueueTester-IOQueueTest.$(OBJEXT) common_io_IOQueueTester_OBJECTS = \ $(am_common_io_IOQueueTester_OBJECTS) common_io_IOQueueTester_DEPENDENCIES = $(am__DEPENDENCIES_5) common_io_IOQueueTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_io_IOQueueTester_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am_common_io_IOStackTester_OBJECTS = \ common/io/common_io_IOStackTester-IOStackTest.$(OBJEXT) common_io_IOStackTester_OBJECTS = \ $(am_common_io_IOStackTester_OBJECTS) common_io_IOStackTester_DEPENDENCIES = $(am__DEPENDENCIES_5) common_io_IOStackTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_io_IOStackTester_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am_common_io_MemoryBlockTester_OBJECTS = common/io/common_io_MemoryBlockTester-MemoryBlockTest.$(OBJEXT) common_io_MemoryBlockTester_OBJECTS = \ $(am_common_io_MemoryBlockTester_OBJECTS) common_io_MemoryBlockTester_DEPENDENCIES = $(am__DEPENDENCIES_5) common_io_MemoryBlockTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_io_MemoryBlockTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_common_io_SelectServerTester_OBJECTS = common/io/common_io_SelectServerTester-SelectServerTest.$(OBJEXT) \ common/io/common_io_SelectServerTester-SelectServerThreadTest.$(OBJEXT) common_io_SelectServerTester_OBJECTS = \ $(am_common_io_SelectServerTester_OBJECTS) common_io_SelectServerTester_DEPENDENCIES = $(am__DEPENDENCIES_5) common_io_SelectServerTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_io_SelectServerTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_common_io_StreamTester_OBJECTS = \ common/io/common_io_StreamTester-InputStreamTest.$(OBJEXT) \ common/io/common_io_StreamTester-OutputStreamTest.$(OBJEXT) common_io_StreamTester_OBJECTS = $(am_common_io_StreamTester_OBJECTS) common_io_StreamTester_DEPENDENCIES = $(am__DEPENDENCIES_5) common_io_StreamTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_io_StreamTester_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am_common_io_TimeoutManagerTester_OBJECTS = common/io/common_io_TimeoutManagerTester-TimeoutManagerTest.$(OBJEXT) common_io_TimeoutManagerTester_OBJECTS = \ $(am_common_io_TimeoutManagerTester_OBJECTS) common_io_TimeoutManagerTester_DEPENDENCIES = $(am__DEPENDENCIES_5) common_io_TimeoutManagerTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_io_TimeoutManagerTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_common_messaging_DescriptorTester_OBJECTS = common/messaging/common_messaging_DescriptorTester-DescriptorTest.$(OBJEXT) \ common/messaging/common_messaging_DescriptorTester-SchemaPrinterTest.$(OBJEXT) \ common/messaging/common_messaging_DescriptorTester-MessagePrinterTest.$(OBJEXT) common_messaging_DescriptorTester_OBJECTS = \ $(am_common_messaging_DescriptorTester_OBJECTS) common_messaging_DescriptorTester_DEPENDENCIES = \ $(am__DEPENDENCIES_5) common_messaging_DescriptorTester_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CXXLD) $(common_messaging_DescriptorTester_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_common_network_HealthCheckedConnectionTester_OBJECTS = common/network/common_network_HealthCheckedConnectionTester-HealthCheckedConnectionTest.$(OBJEXT) common_network_HealthCheckedConnectionTester_OBJECTS = \ $(am_common_network_HealthCheckedConnectionTester_OBJECTS) common_network_HealthCheckedConnectionTester_DEPENDENCIES = \ $(am__DEPENDENCIES_5) common_network_HealthCheckedConnectionTester_LINK = $(LIBTOOL) \ $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CXXLD) \ $(common_network_HealthCheckedConnectionTester_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_common_network_NetworkTester_OBJECTS = common/network/common_network_NetworkTester-IPV4AddressTest.$(OBJEXT) \ common/network/common_network_NetworkTester-InterfacePickerTest.$(OBJEXT) \ common/network/common_network_NetworkTester-InterfaceTest.$(OBJEXT) \ common/network/common_network_NetworkTester-MACAddressTest.$(OBJEXT) \ common/network/common_network_NetworkTester-NetworkUtilsTest.$(OBJEXT) \ common/network/common_network_NetworkTester-SocketAddressTest.$(OBJEXT) \ common/network/common_network_NetworkTester-SocketTest.$(OBJEXT) common_network_NetworkTester_OBJECTS = \ $(am_common_network_NetworkTester_OBJECTS) common_network_NetworkTester_DEPENDENCIES = $(am__DEPENDENCIES_5) common_network_NetworkTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_network_NetworkTester_CXXFLAGS) $(CXXFLAGS) \ $(common_network_NetworkTester_LDFLAGS) $(LDFLAGS) -o $@ am_common_network_TCPConnectorTester_OBJECTS = common/network/common_network_TCPConnectorTester-AdvancedTCPConnectorTest.$(OBJEXT) \ common/network/common_network_TCPConnectorTester-TCPConnectorTest.$(OBJEXT) common_network_TCPConnectorTester_OBJECTS = \ $(am_common_network_TCPConnectorTester_OBJECTS) common_network_TCPConnectorTester_DEPENDENCIES = \ $(am__DEPENDENCIES_5) common_network_TCPConnectorTester_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CXXLD) $(common_network_TCPConnectorTester_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_common_rdm_DiscoveryAgentTester_OBJECTS = common/rdm/common_rdm_DiscoveryAgentTester-DiscoveryAgentTest.$(OBJEXT) common_rdm_DiscoveryAgentTester_OBJECTS = \ $(am_common_rdm_DiscoveryAgentTester_OBJECTS) common_rdm_DiscoveryAgentTester_DEPENDENCIES = $(am__DEPENDENCIES_5) common_rdm_DiscoveryAgentTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_rdm_DiscoveryAgentTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_common_rdm_PidStoreTester_OBJECTS = common/rdm/common_rdm_PidStoreTester-DescriptorConsistencyCheckerTest.$(OBJEXT) \ common/rdm/common_rdm_PidStoreTester-PidStoreTest.$(OBJEXT) common_rdm_PidStoreTester_OBJECTS = \ $(am_common_rdm_PidStoreTester_OBJECTS) common_rdm_PidStoreTester_DEPENDENCIES = $(am__DEPENDENCIES_5) common_rdm_PidStoreTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_rdm_PidStoreTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_common_rdm_QueueingRDMControllerTester_OBJECTS = common/rdm/common_rdm_QueueingRDMControllerTester-QueueingRDMControllerTest.$(OBJEXT) common_rdm_QueueingRDMControllerTester_OBJECTS = \ $(am_common_rdm_QueueingRDMControllerTester_OBJECTS) common_rdm_QueueingRDMControllerTester_DEPENDENCIES = \ $(am__DEPENDENCIES_5) common_rdm_QueueingRDMControllerTester_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CXXLD) $(common_rdm_QueueingRDMControllerTester_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_common_rdm_RDMAPITester_OBJECTS = \ common/rdm/common_rdm_RDMAPITester-RDMAPITest.$(OBJEXT) common_rdm_RDMAPITester_OBJECTS = \ $(am_common_rdm_RDMAPITester_OBJECTS) common_rdm_RDMAPITester_DEPENDENCIES = $(am__DEPENDENCIES_5) common_rdm_RDMAPITester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_rdm_RDMAPITester_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am_common_rdm_RDMCommandSerializerTester_OBJECTS = common/rdm/common_rdm_RDMCommandSerializerTester-RDMCommandSerializerTest.$(OBJEXT) common_rdm_RDMCommandSerializerTester_OBJECTS = \ $(am_common_rdm_RDMCommandSerializerTester_OBJECTS) common_rdm_RDMCommandSerializerTester_DEPENDENCIES = \ $(am__DEPENDENCIES_5) common_rdm_RDMCommandSerializerTester_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CXXLD) $(common_rdm_RDMCommandSerializerTester_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_common_rdm_RDMCommandTester_OBJECTS = common/rdm/common_rdm_RDMCommandTester-RDMCommandTest.$(OBJEXT) common_rdm_RDMCommandTester_OBJECTS = \ $(am_common_rdm_RDMCommandTester_OBJECTS) common_rdm_RDMCommandTester_DEPENDENCIES = $(am__DEPENDENCIES_5) common_rdm_RDMCommandTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_rdm_RDMCommandTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_common_rdm_RDMFrameTester_OBJECTS = \ common/rdm/common_rdm_RDMFrameTester-RDMFrameTest.$(OBJEXT) common_rdm_RDMFrameTester_OBJECTS = \ $(am_common_rdm_RDMFrameTester_OBJECTS) common_rdm_RDMFrameTester_DEPENDENCIES = $(am__DEPENDENCIES_5) common_rdm_RDMFrameTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_rdm_RDMFrameTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_common_rdm_RDMHelperTester_OBJECTS = \ common/rdm/common_rdm_RDMHelperTester-RDMHelperTest.$(OBJEXT) common_rdm_RDMHelperTester_OBJECTS = \ $(am_common_rdm_RDMHelperTester_OBJECTS) common_rdm_RDMHelperTester_DEPENDENCIES = $(am__DEPENDENCIES_5) common_rdm_RDMHelperTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_rdm_RDMHelperTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_common_rdm_RDMMessageTester_OBJECTS = common/rdm/common_rdm_RDMMessageTester-GroupSizeCalculatorTest.$(OBJEXT) \ common/rdm/common_rdm_RDMMessageTester-MessageSerializerTest.$(OBJEXT) \ common/rdm/common_rdm_RDMMessageTester-MessageDeserializerTest.$(OBJEXT) \ common/rdm/common_rdm_RDMMessageTester-RDMMessageInterationTest.$(OBJEXT) \ common/rdm/common_rdm_RDMMessageTester-StringMessageBuilderTest.$(OBJEXT) \ common/rdm/common_rdm_RDMMessageTester-VariableFieldSizeCalculatorTest.$(OBJEXT) common_rdm_RDMMessageTester_OBJECTS = \ $(am_common_rdm_RDMMessageTester_OBJECTS) common_rdm_RDMMessageTester_DEPENDENCIES = $(am__DEPENDENCIES_5) common_rdm_RDMMessageTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_rdm_RDMMessageTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_common_rdm_RDMReplyTester_OBJECTS = \ common/rdm/common_rdm_RDMReplyTester-RDMReplyTest.$(OBJEXT) common_rdm_RDMReplyTester_OBJECTS = \ $(am_common_rdm_RDMReplyTester_OBJECTS) common_rdm_RDMReplyTester_DEPENDENCIES = $(am__DEPENDENCIES_5) common_rdm_RDMReplyTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_rdm_RDMReplyTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_common_rdm_UIDAllocatorTester_OBJECTS = common/rdm/common_rdm_UIDAllocatorTester-UIDAllocatorTest.$(OBJEXT) common_rdm_UIDAllocatorTester_OBJECTS = \ $(am_common_rdm_UIDAllocatorTester_OBJECTS) common_rdm_UIDAllocatorTester_DEPENDENCIES = $(am__DEPENDENCIES_5) common_rdm_UIDAllocatorTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_rdm_UIDAllocatorTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_common_rdm_UIDTester_OBJECTS = \ common/rdm/common_rdm_UIDTester-UIDTest.$(OBJEXT) common_rdm_UIDTester_OBJECTS = $(am_common_rdm_UIDTester_OBJECTS) common_rdm_UIDTester_DEPENDENCIES = $(am__DEPENDENCIES_5) common_rdm_UIDTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_rdm_UIDTester_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am__objects_11 = \ common/rpc/common_rpc_RpcServerTester-TestService.$(OBJEXT) am_common_rpc_RpcServerTester_OBJECTS = \ common/rpc/common_rpc_RpcServerTester-RpcServerTest.$(OBJEXT) \ $(am__objects_11) nodist_common_rpc_RpcServerTester_OBJECTS = common/rpc/common_rpc_RpcServerTester-TestService.pb.$(OBJEXT) \ common/rpc/common_rpc_RpcServerTester-TestServiceService.pb.$(OBJEXT) common_rpc_RpcServerTester_OBJECTS = \ $(am_common_rpc_RpcServerTester_OBJECTS) \ $(nodist_common_rpc_RpcServerTester_OBJECTS) common_rpc_RpcServerTester_DEPENDENCIES = $(am__DEPENDENCIES_5) \ $(am__DEPENDENCIES_1) common_rpc_RpcServerTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_rpc_RpcServerTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__objects_12 = \ common/rpc/common_rpc_RpcTester-TestService.$(OBJEXT) am_common_rpc_RpcTester_OBJECTS = \ common/rpc/common_rpc_RpcTester-RpcControllerTest.$(OBJEXT) \ common/rpc/common_rpc_RpcTester-RpcChannelTest.$(OBJEXT) \ common/rpc/common_rpc_RpcTester-RpcHeaderTest.$(OBJEXT) \ $(am__objects_12) nodist_common_rpc_RpcTester_OBJECTS = \ common/rpc/common_rpc_RpcTester-TestService.pb.$(OBJEXT) \ common/rpc/common_rpc_RpcTester-TestServiceService.pb.$(OBJEXT) common_rpc_RpcTester_OBJECTS = $(am_common_rpc_RpcTester_OBJECTS) \ $(nodist_common_rpc_RpcTester_OBJECTS) common_rpc_RpcTester_DEPENDENCIES = $(am__DEPENDENCIES_5) \ $(am__DEPENDENCIES_1) common_rpc_RpcTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_rpc_RpcTester_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am_common_strings_UtilsTester_OBJECTS = \ common/strings/common_strings_UtilsTester-UtilsTest.$(OBJEXT) common_strings_UtilsTester_OBJECTS = \ $(am_common_strings_UtilsTester_OBJECTS) common_strings_UtilsTester_DEPENDENCIES = $(am__DEPENDENCIES_5) common_strings_UtilsTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_strings_UtilsTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_common_thread_ExecutorThreadTester_OBJECTS = common/thread/common_thread_ExecutorThreadTester-ExecutorThreadTest.$(OBJEXT) common_thread_ExecutorThreadTester_OBJECTS = \ $(am_common_thread_ExecutorThreadTester_OBJECTS) common_thread_ExecutorThreadTester_DEPENDENCIES = \ $(am__DEPENDENCIES_5) common_thread_ExecutorThreadTester_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CXXLD) $(common_thread_ExecutorThreadTester_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_common_thread_FutureTester_OBJECTS = \ common/thread/common_thread_FutureTester-FutureTest.$(OBJEXT) common_thread_FutureTester_OBJECTS = \ $(am_common_thread_FutureTester_OBJECTS) common_thread_FutureTester_DEPENDENCIES = $(am__DEPENDENCIES_5) common_thread_FutureTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_thread_FutureTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_common_thread_ThreadTester_OBJECTS = common/thread/common_thread_ThreadTester-ThreadPoolTest.$(OBJEXT) \ common/thread/common_thread_ThreadTester-ThreadTest.$(OBJEXT) common_thread_ThreadTester_OBJECTS = \ $(am_common_thread_ThreadTester_OBJECTS) common_thread_ThreadTester_DEPENDENCIES = $(am__DEPENDENCIES_5) common_thread_ThreadTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_thread_ThreadTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_common_timecode_TimeCodeTester_OBJECTS = common/timecode/common_timecode_TimeCodeTester-TimeCodeTest.$(OBJEXT) common_timecode_TimeCodeTester_OBJECTS = \ $(am_common_timecode_TimeCodeTester_OBJECTS) common_timecode_TimeCodeTester_DEPENDENCIES = $(am__DEPENDENCIES_5) common_timecode_TimeCodeTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_timecode_TimeCodeTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_common_utils_UtilsTester_OBJECTS = common/utils/common_utils_UtilsTester-ActionQueueTest.$(OBJEXT) \ common/utils/common_utils_UtilsTester-BackoffTest.$(OBJEXT) \ common/utils/common_utils_UtilsTester-CallbackTest.$(OBJEXT) \ common/utils/common_utils_UtilsTester-ClockTest.$(OBJEXT) \ common/utils/common_utils_UtilsTester-DmxBufferTest.$(OBJEXT) \ common/utils/common_utils_UtilsTester-MultiCallbackTest.$(OBJEXT) \ common/utils/common_utils_UtilsTester-StringUtilsTest.$(OBJEXT) \ common/utils/common_utils_UtilsTester-TokenBucketTest.$(OBJEXT) \ common/utils/common_utils_UtilsTester-UtilsTest.$(OBJEXT) \ common/utils/common_utils_UtilsTester-WatchdogTest.$(OBJEXT) common_utils_UtilsTester_OBJECTS = \ $(am_common_utils_UtilsTester_OBJECTS) common_utils_UtilsTester_DEPENDENCIES = $(am__DEPENDENCIES_5) common_utils_UtilsTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am_common_web_JsonTester_OBJECTS = \ common/web/common_web_JsonTester-JsonTest.$(OBJEXT) common_web_JsonTester_OBJECTS = $(am_common_web_JsonTester_OBJECTS) am__DEPENDENCIES_6 = $(am__DEPENDENCIES_5) common/web/libolaweb.la common_web_JsonTester_DEPENDENCIES = $(am__DEPENDENCIES_6) common_web_JsonTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_web_JsonTester_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am_common_web_ParserTester_OBJECTS = \ common/web/common_web_ParserTester-ParserTest.$(OBJEXT) common_web_ParserTester_OBJECTS = \ $(am_common_web_ParserTester_OBJECTS) common_web_ParserTester_DEPENDENCIES = $(am__DEPENDENCIES_6) common_web_ParserTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_web_ParserTester_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am_common_web_PointerTester_OBJECTS = \ common/web/common_web_PointerTester-PointerTest.$(OBJEXT) common_web_PointerTester_OBJECTS = \ $(am_common_web_PointerTester_OBJECTS) common_web_PointerTester_DEPENDENCIES = $(am__DEPENDENCIES_6) common_web_PointerTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_web_PointerTester_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am_common_web_PointerTrackerTester_OBJECTS = common/web/common_web_PointerTrackerTester-PointerTrackerTest.$(OBJEXT) common_web_PointerTrackerTester_OBJECTS = \ $(am_common_web_PointerTrackerTester_OBJECTS) common_web_PointerTrackerTester_DEPENDENCIES = $(am__DEPENDENCIES_6) common_web_PointerTrackerTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_web_PointerTrackerTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_common_web_PtchParserTester_OBJECTS = common/web/common_web_PtchParserTester-PatchParserTest.$(OBJEXT) common_web_PtchParserTester_OBJECTS = \ $(am_common_web_PtchParserTester_OBJECTS) common_web_PtchParserTester_DEPENDENCIES = $(am__DEPENDENCIES_6) common_web_PtchParserTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_web_PtchParserTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_common_web_PtchTester_OBJECTS = \ common/web/common_web_PtchTester-PatchTest.$(OBJEXT) common_web_PtchTester_OBJECTS = $(am_common_web_PtchTester_OBJECTS) common_web_PtchTester_DEPENDENCIES = $(am__DEPENDENCIES_6) common_web_PtchTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_web_PtchTester_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am_common_web_SchemaParserTester_OBJECTS = common/web/common_web_SchemaParserTester-SchemaParserTest.$(OBJEXT) common_web_SchemaParserTester_OBJECTS = \ $(am_common_web_SchemaParserTester_OBJECTS) common_web_SchemaParserTester_DEPENDENCIES = $(am__DEPENDENCIES_6) common_web_SchemaParserTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_web_SchemaParserTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_common_web_SchemaTester_OBJECTS = \ common/web/common_web_SchemaTester-SchemaTest.$(OBJEXT) common_web_SchemaTester_OBJECTS = \ $(am_common_web_SchemaTester_OBJECTS) common_web_SchemaTester_DEPENDENCIES = $(am__DEPENDENCIES_6) common_web_SchemaTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_web_SchemaTester_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am_common_web_SectionsTester_OBJECTS = \ common/web/common_web_SectionsTester-SectionsTest.$(OBJEXT) common_web_SectionsTester_OBJECTS = \ $(am_common_web_SectionsTester_OBJECTS) common_web_SectionsTester_DEPENDENCIES = $(am__DEPENDENCIES_6) common_web_SectionsTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(common_web_SectionsTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_data_rdm_PidDataTester_OBJECTS = \ data/rdm/data_rdm_PidDataTester-PidDataTest.$(OBJEXT) data_rdm_PidDataTester_OBJECTS = $(am_data_rdm_PidDataTester_OBJECTS) data_rdm_PidDataTester_DEPENDENCIES = $(am__DEPENDENCIES_5) data_rdm_PidDataTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(data_rdm_PidDataTester_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am_doxygen_examples_callback_client_transmit_OBJECTS = \ doxygen/examples/callback_client_transmit.$(OBJEXT) doxygen_examples_callback_client_transmit_OBJECTS = \ $(am_doxygen_examples_callback_client_transmit_OBJECTS) doxygen_examples_callback_client_transmit_DEPENDENCIES = \ $(DOXYGEN_EXAMPLES_LDADD) am_doxygen_examples_client_disconnect_OBJECTS = \ doxygen/examples/client_disconnect.$(OBJEXT) doxygen_examples_client_disconnect_OBJECTS = \ $(am_doxygen_examples_client_disconnect_OBJECTS) doxygen_examples_client_disconnect_DEPENDENCIES = \ $(DOXYGEN_EXAMPLES_LDADD) am_doxygen_examples_client_thread_OBJECTS = \ doxygen/examples/client_thread.$(OBJEXT) doxygen_examples_client_thread_OBJECTS = \ $(am_doxygen_examples_client_thread_OBJECTS) doxygen_examples_client_thread_DEPENDENCIES = \ $(DOXYGEN_EXAMPLES_LDADD) am_doxygen_examples_fetch_plugins_OBJECTS = \ doxygen/examples/fetch_plugins.$(OBJEXT) doxygen_examples_fetch_plugins_OBJECTS = \ $(am_doxygen_examples_fetch_plugins_OBJECTS) doxygen_examples_fetch_plugins_DEPENDENCIES = \ $(DOXYGEN_EXAMPLES_LDADD) am_doxygen_examples_flags_OBJECTS = doxygen/examples/flags.$(OBJEXT) doxygen_examples_flags_OBJECTS = $(am_doxygen_examples_flags_OBJECTS) doxygen_examples_flags_DEPENDENCIES = $(DOXYGEN_EXAMPLES_LDADD) am_doxygen_examples_legacy_callback_client_transmit_OBJECTS = \ doxygen/examples/legacy_callback_client_transmit.$(OBJEXT) doxygen_examples_legacy_callback_client_transmit_OBJECTS = $(am_doxygen_examples_legacy_callback_client_transmit_OBJECTS) doxygen_examples_legacy_callback_client_transmit_DEPENDENCIES = \ $(DOXYGEN_EXAMPLES_LDADD) am_doxygen_examples_legacy_receiver_OBJECTS = \ doxygen/examples/legacy_receiver.$(OBJEXT) doxygen_examples_legacy_receiver_OBJECTS = \ $(am_doxygen_examples_legacy_receiver_OBJECTS) doxygen_examples_legacy_receiver_DEPENDENCIES = \ $(DOXYGEN_EXAMPLES_LDADD) am_doxygen_examples_legacy_streaming_client_OBJECTS = \ doxygen/examples/legacy_streaming_client.$(OBJEXT) doxygen_examples_legacy_streaming_client_OBJECTS = \ $(am_doxygen_examples_legacy_streaming_client_OBJECTS) doxygen_examples_legacy_streaming_client_DEPENDENCIES = \ $(DOXYGEN_EXAMPLES_LDADD) am_doxygen_examples_receiver_OBJECTS = \ doxygen/examples/receiver.$(OBJEXT) doxygen_examples_receiver_OBJECTS = \ $(am_doxygen_examples_receiver_OBJECTS) doxygen_examples_receiver_DEPENDENCIES = $(DOXYGEN_EXAMPLES_LDADD) am_doxygen_examples_stdin_handler_OBJECTS = \ doxygen/examples/stdin_handler.$(OBJEXT) doxygen_examples_stdin_handler_OBJECTS = \ $(am_doxygen_examples_stdin_handler_OBJECTS) doxygen_examples_stdin_handler_DEPENDENCIES = \ $(DOXYGEN_EXAMPLES_LDADD) am_doxygen_examples_streaming_client_OBJECTS = \ doxygen/examples/streaming_client.$(OBJEXT) doxygen_examples_streaming_client_OBJECTS = \ $(am_doxygen_examples_streaming_client_OBJECTS) doxygen_examples_streaming_client_DEPENDENCIES = \ $(DOXYGEN_EXAMPLES_LDADD) am_doxygen_examples_streaming_client_plugin_OBJECTS = \ doxygen/examples/streaming_client_plugin.$(OBJEXT) doxygen_examples_streaming_client_plugin_OBJECTS = \ $(am_doxygen_examples_streaming_client_plugin_OBJECTS) doxygen_examples_streaming_client_plugin_DEPENDENCIES = \ $(DOXYGEN_EXAMPLES_LDADD) am_doxygen_examples_udp_server_OBJECTS = \ doxygen/examples/udp_server.$(OBJEXT) doxygen_examples_udp_server_OBJECTS = \ $(am_doxygen_examples_udp_server_OBJECTS) doxygen_examples_udp_server_DEPENDENCIES = $(DOXYGEN_EXAMPLES_LDADD) am__examples_ola_artnet_SOURCES_DIST = examples/ola-artnet.cpp @BUILD_EXAMPLES_TRUE@@USE_ARTNET_TRUE@am_examples_ola_artnet_OBJECTS = examples/examples_ola_artnet-ola-artnet.$(OBJEXT) examples_ola_artnet_OBJECTS = $(am_examples_ola_artnet_OBJECTS) @BUILD_EXAMPLES_TRUE@@USE_ARTNET_TRUE@examples_ola_artnet_DEPENDENCIES = examples/libolaconfig.la \ @BUILD_EXAMPLES_TRUE@@USE_ARTNET_TRUE@ $(EXAMPLE_COMMON_LIBS) \ @BUILD_EXAMPLES_TRUE@@USE_ARTNET_TRUE@ plugins/artnet/messages/libolaartnetconf.la \ @BUILD_EXAMPLES_TRUE@@USE_ARTNET_TRUE@ $(am__DEPENDENCIES_1) examples_ola_artnet_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(examples_ola_artnet_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am__examples_ola_dev_info_SOURCES_DIST = examples/ola-client.cpp @BUILD_EXAMPLES_TRUE@am_examples_ola_dev_info_OBJECTS = \ @BUILD_EXAMPLES_TRUE@ examples/ola-client.$(OBJEXT) examples_ola_dev_info_OBJECTS = $(am_examples_ola_dev_info_OBJECTS) @BUILD_EXAMPLES_TRUE@examples_ola_dev_info_DEPENDENCIES = \ @BUILD_EXAMPLES_TRUE@ $(EXAMPLE_COMMON_LIBS) am__examples_ola_dmxconsole_SOURCES_DIST = \ examples/ola-dmxconsole.cpp @BUILD_EXAMPLES_TRUE@@HAVE_NCURSES_TRUE@am_examples_ola_dmxconsole_OBJECTS = examples/ola-dmxconsole.$(OBJEXT) examples_ola_dmxconsole_OBJECTS = \ $(am_examples_ola_dmxconsole_OBJECTS) @BUILD_EXAMPLES_TRUE@@HAVE_NCURSES_TRUE@examples_ola_dmxconsole_DEPENDENCIES = $(EXAMPLE_COMMON_LIBS) am__examples_ola_dmxmonitor_SOURCES_DIST = \ examples/ola-dmxmonitor.cpp @BUILD_EXAMPLES_TRUE@@HAVE_NCURSES_TRUE@am_examples_ola_dmxmonitor_OBJECTS = examples/ola-dmxmonitor.$(OBJEXT) examples_ola_dmxmonitor_OBJECTS = \ $(am_examples_ola_dmxmonitor_OBJECTS) @BUILD_EXAMPLES_TRUE@@HAVE_NCURSES_TRUE@examples_ola_dmxmonitor_DEPENDENCIES = $(EXAMPLE_COMMON_LIBS) am__examples_ola_e131_SOURCES_DIST = examples/ola-e131.cpp @BUILD_EXAMPLES_TRUE@@USE_E131_TRUE@am_examples_ola_e131_OBJECTS = examples/examples_ola_e131-ola-e131.$(OBJEXT) examples_ola_e131_OBJECTS = $(am_examples_ola_e131_OBJECTS) @BUILD_EXAMPLES_TRUE@@USE_E131_TRUE@examples_ola_e131_DEPENDENCIES = \ @BUILD_EXAMPLES_TRUE@@USE_E131_TRUE@ examples/libolaconfig.la \ @BUILD_EXAMPLES_TRUE@@USE_E131_TRUE@ $(EXAMPLE_COMMON_LIBS) \ @BUILD_EXAMPLES_TRUE@@USE_E131_TRUE@ plugins/e131/messages/libolae131conf.la \ @BUILD_EXAMPLES_TRUE@@USE_E131_TRUE@ $(am__DEPENDENCIES_1) examples_ola_e131_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(examples_ola_e131_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am__examples_ola_latency_SOURCES_DIST = examples/ola-latency.cpp @BUILD_EXAMPLES_TRUE@am_examples_ola_latency_OBJECTS = \ @BUILD_EXAMPLES_TRUE@ examples/ola-latency.$(OBJEXT) examples_ola_latency_OBJECTS = $(am_examples_ola_latency_OBJECTS) @BUILD_EXAMPLES_TRUE@examples_ola_latency_DEPENDENCIES = \ @BUILD_EXAMPLES_TRUE@ $(EXAMPLE_COMMON_LIBS) am__examples_ola_rdm_discover_SOURCES_DIST = \ examples/ola-rdm-discover.cpp @BUILD_EXAMPLES_TRUE@am_examples_ola_rdm_discover_OBJECTS = \ @BUILD_EXAMPLES_TRUE@ examples/ola-rdm-discover.$(OBJEXT) examples_ola_rdm_discover_OBJECTS = \ $(am_examples_ola_rdm_discover_OBJECTS) @BUILD_EXAMPLES_TRUE@examples_ola_rdm_discover_DEPENDENCIES = \ @BUILD_EXAMPLES_TRUE@ $(EXAMPLE_COMMON_LIBS) am__examples_ola_rdm_get_SOURCES_DIST = examples/ola-rdm.cpp @BUILD_EXAMPLES_TRUE@am_examples_ola_rdm_get_OBJECTS = \ @BUILD_EXAMPLES_TRUE@ examples/ola-rdm.$(OBJEXT) examples_ola_rdm_get_OBJECTS = $(am_examples_ola_rdm_get_OBJECTS) @BUILD_EXAMPLES_TRUE@examples_ola_rdm_get_DEPENDENCIES = \ @BUILD_EXAMPLES_TRUE@ $(EXAMPLE_COMMON_LIBS) am__examples_ola_recorder_SOURCES_DIST = examples/ola-recorder.cpp \ examples/ShowLoader.h examples/ShowLoader.cpp \ examples/ShowPlayer.h examples/ShowPlayer.cpp \ examples/ShowRecorder.h examples/ShowRecorder.cpp \ examples/ShowSaver.h examples/ShowSaver.cpp @BUILD_EXAMPLES_TRUE@am_examples_ola_recorder_OBJECTS = \ @BUILD_EXAMPLES_TRUE@ examples/ola-recorder.$(OBJEXT) \ @BUILD_EXAMPLES_TRUE@ examples/ShowLoader.$(OBJEXT) \ @BUILD_EXAMPLES_TRUE@ examples/ShowPlayer.$(OBJEXT) \ @BUILD_EXAMPLES_TRUE@ examples/ShowRecorder.$(OBJEXT) \ @BUILD_EXAMPLES_TRUE@ examples/ShowSaver.$(OBJEXT) examples_ola_recorder_OBJECTS = $(am_examples_ola_recorder_OBJECTS) @BUILD_EXAMPLES_TRUE@examples_ola_recorder_DEPENDENCIES = \ @BUILD_EXAMPLES_TRUE@ $(EXAMPLE_COMMON_LIBS) am__examples_ola_streaming_client_SOURCES_DIST = \ examples/ola-streaming-client.cpp @BUILD_EXAMPLES_TRUE@am_examples_ola_streaming_client_OBJECTS = \ @BUILD_EXAMPLES_TRUE@ examples/ola-streaming-client.$(OBJEXT) examples_ola_streaming_client_OBJECTS = \ $(am_examples_ola_streaming_client_OBJECTS) @BUILD_EXAMPLES_TRUE@examples_ola_streaming_client_DEPENDENCIES = \ @BUILD_EXAMPLES_TRUE@ $(EXAMPLE_COMMON_LIBS) am__examples_ola_throughput_SOURCES_DIST = \ examples/ola-throughput.cpp @BUILD_EXAMPLES_TRUE@am_examples_ola_throughput_OBJECTS = \ @BUILD_EXAMPLES_TRUE@ examples/ola-throughput.$(OBJEXT) examples_ola_throughput_OBJECTS = \ $(am_examples_ola_throughput_OBJECTS) @BUILD_EXAMPLES_TRUE@examples_ola_throughput_DEPENDENCIES = \ @BUILD_EXAMPLES_TRUE@ $(EXAMPLE_COMMON_LIBS) am__examples_ola_timecode_SOURCES_DIST = examples/ola-timecode.cpp @BUILD_EXAMPLES_TRUE@am_examples_ola_timecode_OBJECTS = \ @BUILD_EXAMPLES_TRUE@ examples/ola-timecode.$(OBJEXT) examples_ola_timecode_OBJECTS = $(am_examples_ola_timecode_OBJECTS) @BUILD_EXAMPLES_TRUE@examples_ola_timecode_DEPENDENCIES = \ @BUILD_EXAMPLES_TRUE@ $(EXAMPLE_COMMON_LIBS) am__examples_ola_uni_stats_SOURCES_DIST = examples/ola-uni-stats.cpp @BUILD_EXAMPLES_TRUE@am_examples_ola_uni_stats_OBJECTS = \ @BUILD_EXAMPLES_TRUE@ examples/ola-uni-stats.$(OBJEXT) examples_ola_uni_stats_OBJECTS = $(am_examples_ola_uni_stats_OBJECTS) @BUILD_EXAMPLES_TRUE@examples_ola_uni_stats_DEPENDENCIES = \ @BUILD_EXAMPLES_TRUE@ $(EXAMPLE_COMMON_LIBS) am__examples_ola_usbpro_SOURCES_DIST = examples/ola-usbpro.cpp @BUILD_EXAMPLES_TRUE@@USE_USBPRO_TRUE@am_examples_ola_usbpro_OBJECTS = examples/examples_ola_usbpro-ola-usbpro.$(OBJEXT) examples_ola_usbpro_OBJECTS = $(am_examples_ola_usbpro_OBJECTS) @BUILD_EXAMPLES_TRUE@@USE_USBPRO_TRUE@examples_ola_usbpro_DEPENDENCIES = examples/libolaconfig.la \ @BUILD_EXAMPLES_TRUE@@USE_USBPRO_TRUE@ $(EXAMPLE_COMMON_LIBS) \ @BUILD_EXAMPLES_TRUE@@USE_USBPRO_TRUE@ plugins/usbpro/messages/libolausbproconf.la \ @BUILD_EXAMPLES_TRUE@@USE_USBPRO_TRUE@ $(am__DEPENDENCIES_1) examples_ola_usbpro_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(examples_ola_usbpro_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am_libs_acn_E131Tester_OBJECTS = \ libs/acn/libs_acn_E131Tester-BaseInflatorTest.$(OBJEXT) \ libs/acn/libs_acn_E131Tester-CIDTest.$(OBJEXT) \ libs/acn/libs_acn_E131Tester-DMPAddressTest.$(OBJEXT) \ libs/acn/libs_acn_E131Tester-DMPInflatorTest.$(OBJEXT) \ libs/acn/libs_acn_E131Tester-DMPPDUTest.$(OBJEXT) \ libs/acn/libs_acn_E131Tester-E131InflatorTest.$(OBJEXT) \ libs/acn/libs_acn_E131Tester-E131PDUTest.$(OBJEXT) \ libs/acn/libs_acn_E131Tester-HeaderSetTest.$(OBJEXT) \ libs/acn/libs_acn_E131Tester-PDUTest.$(OBJEXT) \ libs/acn/libs_acn_E131Tester-RootInflatorTest.$(OBJEXT) \ libs/acn/libs_acn_E131Tester-RootPDUTest.$(OBJEXT) \ libs/acn/libs_acn_E131Tester-RootSenderTest.$(OBJEXT) libs_acn_E131Tester_OBJECTS = $(am_libs_acn_E131Tester_OBJECTS) libs_acn_E131Tester_DEPENDENCIES = libs/acn/libolae131core.la \ $(am__DEPENDENCIES_5) am_libs_acn_E133Tester_OBJECTS = \ libs/acn/libs_acn_E133Tester-E133InflatorTest.$(OBJEXT) \ libs/acn/libs_acn_E133Tester-E133PDUTest.$(OBJEXT) \ libs/acn/libs_acn_E133Tester-RDMPDUTest.$(OBJEXT) libs_acn_E133Tester_OBJECTS = $(am_libs_acn_E133Tester_OBJECTS) libs_acn_E133Tester_DEPENDENCIES = libs/acn/libolae131core.la \ $(am__DEPENDENCIES_5) am_libs_acn_TransportTester_OBJECTS = \ libs/acn/libs_acn_TransportTester-TCPTransportTest.$(OBJEXT) \ libs/acn/libs_acn_TransportTester-UDPTransportTest.$(OBJEXT) libs_acn_TransportTester_OBJECTS = \ $(am_libs_acn_TransportTester_OBJECTS) libs_acn_TransportTester_DEPENDENCIES = libs/acn/libolae131core.la \ $(am__DEPENDENCIES_5) am_libs_acn_e131_loadtest_OBJECTS = libs/acn/e131_loadtest.$(OBJEXT) libs_acn_e131_loadtest_OBJECTS = $(am_libs_acn_e131_loadtest_OBJECTS) libs_acn_e131_loadtest_DEPENDENCIES = libs/acn/libolae131core.la am_libs_acn_e131_transmit_test_OBJECTS = \ libs/acn/e131_transmit_test.$(OBJEXT) \ libs/acn/E131TestFramework.$(OBJEXT) libs_acn_e131_transmit_test_OBJECTS = \ $(am_libs_acn_e131_transmit_test_OBJECTS) libs_acn_e131_transmit_test_DEPENDENCIES = libs/acn/libolae131core.la am__libs_usb_LibUsbThreadTester_SOURCES_DIST = \ libs/usb/LibUsbThreadTest.cpp @USE_LIBUSB_TRUE@am_libs_usb_LibUsbThreadTester_OBJECTS = libs/usb/libs_usb_LibUsbThreadTester-LibUsbThreadTest.$(OBJEXT) libs_usb_LibUsbThreadTester_OBJECTS = \ $(am_libs_usb_LibUsbThreadTester_OBJECTS) @USE_LIBUSB_TRUE@am__DEPENDENCIES_7 = $(am__DEPENDENCIES_5) \ @USE_LIBUSB_TRUE@ $(am__DEPENDENCIES_1) libs/usb/libolausb.la @USE_LIBUSB_TRUE@libs_usb_LibUsbThreadTester_DEPENDENCIES = \ @USE_LIBUSB_TRUE@ $(am__DEPENDENCIES_7) libs_usb_LibUsbThreadTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(libs_usb_LibUsbThreadTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_ola_OlaClientTester_OBJECTS = \ ola/ola_OlaClientTester-OlaClientWrapperTest.$(OBJEXT) \ ola/ola_OlaClientTester-StreamingClientTest.$(OBJEXT) ola_OlaClientTester_OBJECTS = $(am_ola_OlaClientTester_OBJECTS) ola_OlaClientTester_DEPENDENCIES = $(am__DEPENDENCIES_5) \ $(am__DEPENDENCIES_1) common/libolacommon.la \ olad/libolaserver.la ola/libola.la ola_OlaClientTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(ola_OlaClientTester_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am_olad_OlaTester_OBJECTS = \ olad/olad_OlaTester-PluginManagerTest.$(OBJEXT) \ olad/olad_OlaTester-OlaServerServiceImplTest.$(OBJEXT) olad_OlaTester_OBJECTS = $(am_olad_OlaTester_OBJECTS) am__DEPENDENCIES_8 = $(am__DEPENDENCIES_5) $(am__DEPENDENCIES_1) \ olad/plugin_api/libolaserverplugininterface.la \ olad/libolaserver.la common/libolacommon.la olad_OlaTester_DEPENDENCIES = $(am__DEPENDENCIES_8) olad_OlaTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(olad_OlaTester_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am_olad_olad_OBJECTS = olad/Olad.$(OBJEXT) olad_olad_OBJECTS = $(am_olad_olad_OBJECTS) olad_olad_DEPENDENCIES = olad/libolaserver.la common/libolacommon.la \ ola/libola.la $(am__DEPENDENCIES_1) olad_olad_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(olad_olad_LDFLAGS) $(LDFLAGS) -o $@ am_olad_plugin_api_ClientTester_OBJECTS = olad/plugin_api/olad_plugin_api_ClientTester-ClientTest.$(OBJEXT) olad_plugin_api_ClientTester_OBJECTS = \ $(am_olad_plugin_api_ClientTester_OBJECTS) am__DEPENDENCIES_9 = $(am__DEPENDENCIES_5) $(am__DEPENDENCIES_1) \ olad/plugin_api/libolaserverplugininterface.la \ common/libolacommon.la olad_plugin_api_ClientTester_DEPENDENCIES = $(am__DEPENDENCIES_9) olad_plugin_api_ClientTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(olad_plugin_api_ClientTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_olad_plugin_api_DeviceTester_OBJECTS = olad/plugin_api/olad_plugin_api_DeviceTester-DeviceManagerTest.$(OBJEXT) \ olad/plugin_api/olad_plugin_api_DeviceTester-DeviceTest.$(OBJEXT) olad_plugin_api_DeviceTester_OBJECTS = \ $(am_olad_plugin_api_DeviceTester_OBJECTS) olad_plugin_api_DeviceTester_DEPENDENCIES = $(am__DEPENDENCIES_9) olad_plugin_api_DeviceTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(olad_plugin_api_DeviceTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_olad_plugin_api_DmxSourceTester_OBJECTS = olad/plugin_api/olad_plugin_api_DmxSourceTester-DmxSourceTest.$(OBJEXT) olad_plugin_api_DmxSourceTester_OBJECTS = \ $(am_olad_plugin_api_DmxSourceTester_OBJECTS) olad_plugin_api_DmxSourceTester_DEPENDENCIES = $(am__DEPENDENCIES_9) olad_plugin_api_DmxSourceTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(olad_plugin_api_DmxSourceTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_olad_plugin_api_PortTester_OBJECTS = \ olad/plugin_api/olad_plugin_api_PortTester-PortTest.$(OBJEXT) \ olad/plugin_api/olad_plugin_api_PortTester-PortManagerTest.$(OBJEXT) olad_plugin_api_PortTester_OBJECTS = \ $(am_olad_plugin_api_PortTester_OBJECTS) olad_plugin_api_PortTester_DEPENDENCIES = $(am__DEPENDENCIES_9) olad_plugin_api_PortTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(olad_plugin_api_PortTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_olad_plugin_api_PreferencesTester_OBJECTS = olad/plugin_api/olad_plugin_api_PreferencesTester-PreferencesTest.$(OBJEXT) olad_plugin_api_PreferencesTester_OBJECTS = \ $(am_olad_plugin_api_PreferencesTester_OBJECTS) olad_plugin_api_PreferencesTester_DEPENDENCIES = \ $(am__DEPENDENCIES_9) olad_plugin_api_PreferencesTester_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CXXLD) $(olad_plugin_api_PreferencesTester_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_olad_plugin_api_UniverseTester_OBJECTS = olad/plugin_api/olad_plugin_api_UniverseTester-UniverseTest.$(OBJEXT) olad_plugin_api_UniverseTester_OBJECTS = \ $(am_olad_plugin_api_UniverseTester_OBJECTS) olad_plugin_api_UniverseTester_DEPENDENCIES = $(am__DEPENDENCIES_9) olad_plugin_api_UniverseTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(olad_plugin_api_UniverseTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__plugins_artnet_ArtNetTester_SOURCES_DIST = \ plugins/artnet/ArtNetNodeTest.cpp @USE_ARTNET_TRUE@am_plugins_artnet_ArtNetTester_OBJECTS = plugins/artnet/plugins_artnet_ArtNetTester-ArtNetNodeTest.$(OBJEXT) plugins_artnet_ArtNetTester_OBJECTS = \ $(am_plugins_artnet_ArtNetTester_OBJECTS) @USE_ARTNET_TRUE@plugins_artnet_ArtNetTester_DEPENDENCIES = \ @USE_ARTNET_TRUE@ $(am__DEPENDENCIES_5) \ @USE_ARTNET_TRUE@ plugins/artnet/libolaartnetnode.la plugins_artnet_ArtNetTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(plugins_artnet_ArtNetTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__plugins_artnet_artnet_loadtest_SOURCES_DIST = \ plugins/artnet/artnet_loadtest.cpp @USE_ARTNET_TRUE@am_plugins_artnet_artnet_loadtest_OBJECTS = \ @USE_ARTNET_TRUE@ plugins/artnet/artnet_loadtest.$(OBJEXT) plugins_artnet_artnet_loadtest_OBJECTS = \ $(am_plugins_artnet_artnet_loadtest_OBJECTS) @USE_ARTNET_TRUE@plugins_artnet_artnet_loadtest_DEPENDENCIES = \ @USE_ARTNET_TRUE@ plugins/artnet/libolaartnetnode.la am__plugins_dummy_DummyPluginTester_SOURCES_DIST = \ plugins/dummy/DummyPortTest.cpp @USE_DUMMY_TRUE@am_plugins_dummy_DummyPluginTester_OBJECTS = plugins/dummy/plugins_dummy_DummyPluginTester-DummyPortTest.$(OBJEXT) plugins_dummy_DummyPluginTester_OBJECTS = \ $(am_plugins_dummy_DummyPluginTester_OBJECTS) @USE_DUMMY_TRUE@plugins_dummy_DummyPluginTester_DEPENDENCIES = \ @USE_DUMMY_TRUE@ $(am__DEPENDENCIES_5) \ @USE_DUMMY_TRUE@ $(top_builddir)/olad/plugin_api/libolaserverplugininterface.la \ @USE_DUMMY_TRUE@ $(top_builddir)/olad/libolaserver.la \ @USE_DUMMY_TRUE@ plugins/dummy/liboladummy.la \ @USE_DUMMY_TRUE@ common/libolacommon.la plugins_dummy_DummyPluginTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(plugins_dummy_DummyPluginTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__plugins_espnet_EspNetTester_SOURCES_DIST = \ plugins/espnet/RunLengthDecoderTest.cpp \ plugins/espnet/RunLengthDecoder.cpp @USE_ESPNET_TRUE@am_plugins_espnet_EspNetTester_OBJECTS = plugins/espnet/plugins_espnet_EspNetTester-RunLengthDecoderTest.$(OBJEXT) \ @USE_ESPNET_TRUE@ plugins/espnet/plugins_espnet_EspNetTester-RunLengthDecoder.$(OBJEXT) plugins_espnet_EspNetTester_OBJECTS = \ $(am_plugins_espnet_EspNetTester_OBJECTS) @USE_ESPNET_TRUE@plugins_espnet_EspNetTester_DEPENDENCIES = \ @USE_ESPNET_TRUE@ $(am__DEPENDENCIES_5) common/libolacommon.la plugins_espnet_EspNetTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(plugins_espnet_EspNetTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__plugins_kinet_KiNetTester_SOURCES_DIST = \ plugins/kinet/KiNetNodeTest.cpp @USE_KINET_TRUE@am_plugins_kinet_KiNetTester_OBJECTS = plugins/kinet/plugins_kinet_KiNetTester-KiNetNodeTest.$(OBJEXT) plugins_kinet_KiNetTester_OBJECTS = \ $(am_plugins_kinet_KiNetTester_OBJECTS) @USE_KINET_TRUE@plugins_kinet_KiNetTester_DEPENDENCIES = \ @USE_KINET_TRUE@ $(am__DEPENDENCIES_5) \ @USE_KINET_TRUE@ plugins/kinet/libolakinetnode.la plugins_kinet_KiNetTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(plugins_kinet_KiNetTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__plugins_openpixelcontrol_OPCClientTester_SOURCES_DIST = \ plugins/openpixelcontrol/OPCClientTest.cpp @USE_OPENPIXELCONTROL_TRUE@am_plugins_openpixelcontrol_OPCClientTester_OBJECTS = plugins/openpixelcontrol/plugins_openpixelcontrol_OPCClientTester-OPCClientTest.$(OBJEXT) plugins_openpixelcontrol_OPCClientTester_OBJECTS = \ $(am_plugins_openpixelcontrol_OPCClientTester_OBJECTS) @USE_OPENPIXELCONTROL_TRUE@plugins_openpixelcontrol_OPCClientTester_DEPENDENCIES = \ @USE_OPENPIXELCONTROL_TRUE@ $(am__DEPENDENCIES_5) \ @USE_OPENPIXELCONTROL_TRUE@ plugins/openpixelcontrol/libolaopc.la plugins_openpixelcontrol_OPCClientTester_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CXXLD) $(plugins_openpixelcontrol_OPCClientTester_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__plugins_openpixelcontrol_OPCServerTester_SOURCES_DIST = \ plugins/openpixelcontrol/OPCServerTest.cpp @USE_OPENPIXELCONTROL_TRUE@am_plugins_openpixelcontrol_OPCServerTester_OBJECTS = plugins/openpixelcontrol/plugins_openpixelcontrol_OPCServerTester-OPCServerTest.$(OBJEXT) plugins_openpixelcontrol_OPCServerTester_OBJECTS = \ $(am_plugins_openpixelcontrol_OPCServerTester_OBJECTS) @USE_OPENPIXELCONTROL_TRUE@plugins_openpixelcontrol_OPCServerTester_DEPENDENCIES = \ @USE_OPENPIXELCONTROL_TRUE@ $(am__DEPENDENCIES_5) \ @USE_OPENPIXELCONTROL_TRUE@ plugins/openpixelcontrol/libolaopc.la plugins_openpixelcontrol_OPCServerTester_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CXXLD) $(plugins_openpixelcontrol_OPCServerTester_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__plugins_osc_OSCTester_SOURCES_DIST = \ plugins/osc/OSCAddressTemplateTest.cpp \ plugins/osc/OSCNodeTest.cpp @USE_OSC_TRUE@am_plugins_osc_OSCTester_OBJECTS = plugins/osc/plugins_osc_OSCTester-OSCAddressTemplateTest.$(OBJEXT) \ @USE_OSC_TRUE@ plugins/osc/plugins_osc_OSCTester-OSCNodeTest.$(OBJEXT) plugins_osc_OSCTester_OBJECTS = $(am_plugins_osc_OSCTester_OBJECTS) @USE_OSC_TRUE@plugins_osc_OSCTester_DEPENDENCIES = \ @USE_OSC_TRUE@ $(am__DEPENDENCIES_5) \ @USE_OSC_TRUE@ plugins/osc/libolaoscnode.la \ @USE_OSC_TRUE@ common/libolacommon.la plugins_osc_OSCTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(plugins_osc_OSCTester_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am__plugins_shownet_ShowNetTester_SOURCES_DIST = \ plugins/shownet/ShowNetNode.cpp \ plugins/shownet/ShowNetNodeTest.cpp @USE_SHOWNET_TRUE@am_plugins_shownet_ShowNetTester_OBJECTS = plugins/shownet/plugins_shownet_ShowNetTester-ShowNetNode.$(OBJEXT) \ @USE_SHOWNET_TRUE@ plugins/shownet/plugins_shownet_ShowNetTester-ShowNetNodeTest.$(OBJEXT) plugins_shownet_ShowNetTester_OBJECTS = \ $(am_plugins_shownet_ShowNetTester_OBJECTS) @USE_SHOWNET_TRUE@plugins_shownet_ShowNetTester_DEPENDENCIES = \ @USE_SHOWNET_TRUE@ $(am__DEPENDENCIES_5) common/libolacommon.la plugins_shownet_ShowNetTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(plugins_shownet_ShowNetTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__plugins_spi_SPITester_SOURCES_DIST = \ plugins/spi/SPIBackendTest.cpp plugins/spi/SPIOutputTest.cpp \ plugins/spi/FakeSPIWriter.cpp plugins/spi/FakeSPIWriter.h @USE_SPI_TRUE@am_plugins_spi_SPITester_OBJECTS = plugins/spi/plugins_spi_SPITester-SPIBackendTest.$(OBJEXT) \ @USE_SPI_TRUE@ plugins/spi/plugins_spi_SPITester-SPIOutputTest.$(OBJEXT) \ @USE_SPI_TRUE@ plugins/spi/plugins_spi_SPITester-FakeSPIWriter.$(OBJEXT) plugins_spi_SPITester_OBJECTS = $(am_plugins_spi_SPITester_OBJECTS) @USE_SPI_TRUE@plugins_spi_SPITester_DEPENDENCIES = \ @USE_SPI_TRUE@ $(am__DEPENDENCIES_5) \ @USE_SPI_TRUE@ plugins/spi/libolaspicore.la \ @USE_SPI_TRUE@ common/libolacommon.la plugins_spi_SPITester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(plugins_spi_SPITester_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am__plugins_usbpro_ArduinoWidgetTester_SOURCES_DIST = \ plugins/usbpro/ArduinoWidgetTest.cpp \ plugins/usbpro/CommonWidgetTest.cpp \ plugins/usbpro/CommonWidgetTest.h \ plugins/usbpro/MockEndpoint.cpp plugins/usbpro/MockEndpoint.h @USE_USBPRO_TRUE@@USING_WIN32_FALSE@am__objects_13 = plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-CommonWidgetTest.$(OBJEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-MockEndpoint.$(OBJEXT) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@am_plugins_usbpro_ArduinoWidgetTester_OBJECTS = plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-ArduinoWidgetTest.$(OBJEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(am__objects_13) plugins_usbpro_ArduinoWidgetTester_OBJECTS = \ $(am_plugins_usbpro_ArduinoWidgetTester_OBJECTS) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@am__DEPENDENCIES_10 = \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(am__DEPENDENCIES_5) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/libolausbprowidget.la @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_ArduinoWidgetTester_DEPENDENCIES = \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(am__DEPENDENCIES_10) plugins_usbpro_ArduinoWidgetTester_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CXXLD) $(plugins_usbpro_ArduinoWidgetTester_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__plugins_usbpro_BaseRobeWidgetTester_SOURCES_DIST = \ plugins/usbpro/BaseRobeWidgetTest.cpp \ plugins/usbpro/CommonWidgetTest.cpp \ plugins/usbpro/CommonWidgetTest.h \ plugins/usbpro/MockEndpoint.cpp plugins/usbpro/MockEndpoint.h @USE_USBPRO_TRUE@@USING_WIN32_FALSE@am__objects_14 = plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-CommonWidgetTest.$(OBJEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-MockEndpoint.$(OBJEXT) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@am_plugins_usbpro_BaseRobeWidgetTester_OBJECTS = plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-BaseRobeWidgetTest.$(OBJEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(am__objects_14) plugins_usbpro_BaseRobeWidgetTester_OBJECTS = \ $(am_plugins_usbpro_BaseRobeWidgetTester_OBJECTS) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_BaseRobeWidgetTester_DEPENDENCIES = \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(am__DEPENDENCIES_10) plugins_usbpro_BaseRobeWidgetTester_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CXXLD) $(plugins_usbpro_BaseRobeWidgetTester_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__plugins_usbpro_BaseUsbProWidgetTester_SOURCES_DIST = \ plugins/usbpro/BaseUsbProWidgetTest.cpp \ plugins/usbpro/CommonWidgetTest.cpp \ plugins/usbpro/CommonWidgetTest.h \ plugins/usbpro/MockEndpoint.cpp plugins/usbpro/MockEndpoint.h @USE_USBPRO_TRUE@@USING_WIN32_FALSE@am__objects_15 = plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-CommonWidgetTest.$(OBJEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-MockEndpoint.$(OBJEXT) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@am_plugins_usbpro_BaseUsbProWidgetTester_OBJECTS = plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-BaseUsbProWidgetTest.$(OBJEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(am__objects_15) plugins_usbpro_BaseUsbProWidgetTester_OBJECTS = \ $(am_plugins_usbpro_BaseUsbProWidgetTester_OBJECTS) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_BaseUsbProWidgetTester_DEPENDENCIES = \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(am__DEPENDENCIES_10) plugins_usbpro_BaseUsbProWidgetTester_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CXXLD) $(plugins_usbpro_BaseUsbProWidgetTester_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__plugins_usbpro_DmxTriWidgetTester_SOURCES_DIST = \ plugins/usbpro/DmxTriWidgetTest.cpp \ plugins/usbpro/CommonWidgetTest.cpp \ plugins/usbpro/CommonWidgetTest.h \ plugins/usbpro/MockEndpoint.cpp plugins/usbpro/MockEndpoint.h @USE_USBPRO_TRUE@@USING_WIN32_FALSE@am__objects_16 = plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-CommonWidgetTest.$(OBJEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-MockEndpoint.$(OBJEXT) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@am_plugins_usbpro_DmxTriWidgetTester_OBJECTS = plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-DmxTriWidgetTest.$(OBJEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(am__objects_16) plugins_usbpro_DmxTriWidgetTester_OBJECTS = \ $(am_plugins_usbpro_DmxTriWidgetTester_OBJECTS) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_DmxTriWidgetTester_DEPENDENCIES = \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(am__DEPENDENCIES_10) plugins_usbpro_DmxTriWidgetTester_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CXXLD) $(plugins_usbpro_DmxTriWidgetTester_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__plugins_usbpro_DmxterWidgetTester_SOURCES_DIST = \ plugins/usbpro/DmxterWidgetTest.cpp \ plugins/usbpro/CommonWidgetTest.cpp \ plugins/usbpro/CommonWidgetTest.h \ plugins/usbpro/MockEndpoint.cpp plugins/usbpro/MockEndpoint.h @USE_USBPRO_TRUE@@USING_WIN32_FALSE@am__objects_17 = plugins/usbpro/plugins_usbpro_DmxterWidgetTester-CommonWidgetTest.$(OBJEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/plugins_usbpro_DmxterWidgetTester-MockEndpoint.$(OBJEXT) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@am_plugins_usbpro_DmxterWidgetTester_OBJECTS = plugins/usbpro/plugins_usbpro_DmxterWidgetTester-DmxterWidgetTest.$(OBJEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(am__objects_17) plugins_usbpro_DmxterWidgetTester_OBJECTS = \ $(am_plugins_usbpro_DmxterWidgetTester_OBJECTS) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_DmxterWidgetTester_DEPENDENCIES = \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(am__DEPENDENCIES_10) plugins_usbpro_DmxterWidgetTester_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CXXLD) $(plugins_usbpro_DmxterWidgetTester_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__plugins_usbpro_EnttecUsbProWidgetTester_SOURCES_DIST = \ plugins/usbpro/EnttecUsbProWidgetTest.cpp \ plugins/usbpro/CommonWidgetTest.cpp \ plugins/usbpro/CommonWidgetTest.h \ plugins/usbpro/MockEndpoint.cpp plugins/usbpro/MockEndpoint.h @USE_USBPRO_TRUE@@USING_WIN32_FALSE@am__objects_18 = plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-CommonWidgetTest.$(OBJEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-MockEndpoint.$(OBJEXT) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@am_plugins_usbpro_EnttecUsbProWidgetTester_OBJECTS = plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-EnttecUsbProWidgetTest.$(OBJEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(am__objects_18) plugins_usbpro_EnttecUsbProWidgetTester_OBJECTS = \ $(am_plugins_usbpro_EnttecUsbProWidgetTester_OBJECTS) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_EnttecUsbProWidgetTester_DEPENDENCIES = \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(am__DEPENDENCIES_10) plugins_usbpro_EnttecUsbProWidgetTester_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CXXLD) $(plugins_usbpro_EnttecUsbProWidgetTester_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__plugins_usbpro_RobeWidgetDetectorTester_SOURCES_DIST = \ plugins/usbpro/RobeWidgetDetectorTest.cpp \ plugins/usbpro/CommonWidgetTest.cpp \ plugins/usbpro/CommonWidgetTest.h \ plugins/usbpro/MockEndpoint.cpp plugins/usbpro/MockEndpoint.h @USE_USBPRO_TRUE@@USING_WIN32_FALSE@am__objects_19 = plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-CommonWidgetTest.$(OBJEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-MockEndpoint.$(OBJEXT) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@am_plugins_usbpro_RobeWidgetDetectorTester_OBJECTS = plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-RobeWidgetDetectorTest.$(OBJEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(am__objects_19) plugins_usbpro_RobeWidgetDetectorTester_OBJECTS = \ $(am_plugins_usbpro_RobeWidgetDetectorTester_OBJECTS) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_RobeWidgetDetectorTester_DEPENDENCIES = \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(am__DEPENDENCIES_10) plugins_usbpro_RobeWidgetDetectorTester_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CXXLD) $(plugins_usbpro_RobeWidgetDetectorTester_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__plugins_usbpro_RobeWidgetTester_SOURCES_DIST = \ plugins/usbpro/RobeWidgetTest.cpp \ plugins/usbpro/CommonWidgetTest.cpp \ plugins/usbpro/CommonWidgetTest.h \ plugins/usbpro/MockEndpoint.cpp plugins/usbpro/MockEndpoint.h @USE_USBPRO_TRUE@@USING_WIN32_FALSE@am__objects_20 = plugins/usbpro/plugins_usbpro_RobeWidgetTester-CommonWidgetTest.$(OBJEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/plugins_usbpro_RobeWidgetTester-MockEndpoint.$(OBJEXT) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@am_plugins_usbpro_RobeWidgetTester_OBJECTS = plugins/usbpro/plugins_usbpro_RobeWidgetTester-RobeWidgetTest.$(OBJEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(am__objects_20) plugins_usbpro_RobeWidgetTester_OBJECTS = \ $(am_plugins_usbpro_RobeWidgetTester_OBJECTS) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_RobeWidgetTester_DEPENDENCIES = \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(am__DEPENDENCIES_10) plugins_usbpro_RobeWidgetTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(plugins_usbpro_RobeWidgetTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__plugins_usbpro_UltraDMXProWidgetTester_SOURCES_DIST = \ plugins/usbpro/UltraDMXProWidgetTest.cpp \ plugins/usbpro/CommonWidgetTest.cpp \ plugins/usbpro/CommonWidgetTest.h \ plugins/usbpro/MockEndpoint.cpp plugins/usbpro/MockEndpoint.h @USE_USBPRO_TRUE@@USING_WIN32_FALSE@am__objects_21 = plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-CommonWidgetTest.$(OBJEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-MockEndpoint.$(OBJEXT) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@am_plugins_usbpro_UltraDMXProWidgetTester_OBJECTS = plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-UltraDMXProWidgetTest.$(OBJEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(am__objects_21) plugins_usbpro_UltraDMXProWidgetTester_OBJECTS = \ $(am_plugins_usbpro_UltraDMXProWidgetTester_OBJECTS) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_UltraDMXProWidgetTester_DEPENDENCIES = \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(am__DEPENDENCIES_10) plugins_usbpro_UltraDMXProWidgetTester_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CXXLD) $(plugins_usbpro_UltraDMXProWidgetTester_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__plugins_usbpro_UsbProWidgetDetectorTester_SOURCES_DIST = \ plugins/usbpro/UsbProWidgetDetectorTest.cpp \ plugins/usbpro/CommonWidgetTest.cpp \ plugins/usbpro/CommonWidgetTest.h \ plugins/usbpro/MockEndpoint.cpp plugins/usbpro/MockEndpoint.h @USE_USBPRO_TRUE@@USING_WIN32_FALSE@am__objects_22 = plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-CommonWidgetTest.$(OBJEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-MockEndpoint.$(OBJEXT) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@am_plugins_usbpro_UsbProWidgetDetectorTester_OBJECTS = plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-UsbProWidgetDetectorTest.$(OBJEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(am__objects_22) plugins_usbpro_UsbProWidgetDetectorTester_OBJECTS = \ $(am_plugins_usbpro_UsbProWidgetDetectorTester_OBJECTS) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_UsbProWidgetDetectorTester_DEPENDENCIES = \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(am__DEPENDENCIES_10) plugins_usbpro_UsbProWidgetDetectorTester_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CXXLD) $(plugins_usbpro_UsbProWidgetDetectorTester_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__plugins_usbpro_WidgetDetectorThreadTester_SOURCES_DIST = \ plugins/usbpro/WidgetDetectorThreadTest.cpp \ plugins/usbpro/CommonWidgetTest.cpp \ plugins/usbpro/CommonWidgetTest.h \ plugins/usbpro/MockEndpoint.cpp plugins/usbpro/MockEndpoint.h @USE_USBPRO_TRUE@@USING_WIN32_FALSE@am__objects_23 = plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-CommonWidgetTest.$(OBJEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-MockEndpoint.$(OBJEXT) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@am_plugins_usbpro_WidgetDetectorThreadTester_OBJECTS = plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-WidgetDetectorThreadTest.$(OBJEXT) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(am__objects_23) plugins_usbpro_WidgetDetectorThreadTester_OBJECTS = \ $(am_plugins_usbpro_WidgetDetectorThreadTester_OBJECTS) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_WidgetDetectorThreadTester_DEPENDENCIES = \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(am__DEPENDENCIES_10) plugins_usbpro_WidgetDetectorThreadTester_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CXXLD) $(plugins_usbpro_WidgetDetectorThreadTester_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__protoc_ola_protoc_plugin_SOURCES_DIST = \ protoc/CppFileGenerator.cpp protoc/CppFileGenerator.h \ protoc/CppGenerator.cpp protoc/CppGenerator.h \ protoc/GeneratorHelpers.cpp protoc/GeneratorHelpers.h \ protoc/ServiceGenerator.cpp protoc/ServiceGenerator.h \ protoc/StrUtil.cpp protoc/StrUtil.h \ protoc/ola-protoc-generator-plugin.cpp @BUILD_OLA_PROTOC_PLUGIN_TRUE@am_protoc_ola_protoc_plugin_OBJECTS = protoc/protoc_ola_protoc_plugin-CppFileGenerator.$(OBJEXT) \ @BUILD_OLA_PROTOC_PLUGIN_TRUE@ protoc/protoc_ola_protoc_plugin-CppGenerator.$(OBJEXT) \ @BUILD_OLA_PROTOC_PLUGIN_TRUE@ protoc/protoc_ola_protoc_plugin-GeneratorHelpers.$(OBJEXT) \ @BUILD_OLA_PROTOC_PLUGIN_TRUE@ protoc/protoc_ola_protoc_plugin-ServiceGenerator.$(OBJEXT) \ @BUILD_OLA_PROTOC_PLUGIN_TRUE@ protoc/protoc_ola_protoc_plugin-StrUtil.$(OBJEXT) \ @BUILD_OLA_PROTOC_PLUGIN_TRUE@ protoc/protoc_ola_protoc_plugin-ola-protoc-generator-plugin.$(OBJEXT) protoc_ola_protoc_plugin_OBJECTS = \ $(am_protoc_ola_protoc_plugin_OBJECTS) @BUILD_OLA_PROTOC_PLUGIN_TRUE@protoc_ola_protoc_plugin_DEPENDENCIES = \ @BUILD_OLA_PROTOC_PLUGIN_TRUE@ $(am__DEPENDENCIES_1) protoc_ola_protoc_plugin_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(protoc_ola_protoc_plugin_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am__tools_e133_basic_controller_SOURCES_DIST = \ tools/e133/basic-controller.cpp @USING_WIN32_FALSE@am_tools_e133_basic_controller_OBJECTS = \ @USING_WIN32_FALSE@ tools/e133/basic-controller.$(OBJEXT) tools_e133_basic_controller_OBJECTS = \ $(am_tools_e133_basic_controller_OBJECTS) @USING_WIN32_FALSE@tools_e133_basic_controller_DEPENDENCIES = \ @USING_WIN32_FALSE@ common/libolacommon.la \ @USING_WIN32_FALSE@ libs/acn/libolaacn.la \ @USING_WIN32_FALSE@ tools/e133/libolae133common.la am__tools_e133_basic_device_SOURCES_DIST = \ tools/e133/basic-device.cpp @USING_WIN32_FALSE@am_tools_e133_basic_device_OBJECTS = \ @USING_WIN32_FALSE@ tools/e133/basic-device.$(OBJEXT) tools_e133_basic_device_OBJECTS = \ $(am_tools_e133_basic_device_OBJECTS) @USING_WIN32_FALSE@tools_e133_basic_device_DEPENDENCIES = \ @USING_WIN32_FALSE@ common/libolacommon.la \ @USING_WIN32_FALSE@ libs/acn/libolaacn.la \ @USING_WIN32_FALSE@ tools/e133/libolae133common.la am__tools_e133_e133_controller_SOURCES_DIST = \ tools/e133/e133-controller.cpp @USING_WIN32_FALSE@am_tools_e133_e133_controller_OBJECTS = \ @USING_WIN32_FALSE@ tools/e133/e133-controller.$(OBJEXT) tools_e133_e133_controller_OBJECTS = \ $(am_tools_e133_e133_controller_OBJECTS) @USING_WIN32_FALSE@tools_e133_e133_controller_DEPENDENCIES = \ @USING_WIN32_FALSE@ common/libolacommon.la \ @USING_WIN32_FALSE@ libs/acn/libolae131core.la \ @USING_WIN32_FALSE@ tools/e133/libolae133common.la \ @USING_WIN32_FALSE@ tools/e133/libolae133controller.la am__tools_e133_e133_monitor_SOURCES_DIST = \ tools/e133/e133-monitor.cpp @USING_WIN32_FALSE@am_tools_e133_e133_monitor_OBJECTS = \ @USING_WIN32_FALSE@ tools/e133/e133-monitor.$(OBJEXT) tools_e133_e133_monitor_OBJECTS = \ $(am_tools_e133_e133_monitor_OBJECTS) @USING_WIN32_FALSE@tools_e133_e133_monitor_DEPENDENCIES = \ @USING_WIN32_FALSE@ common/libolacommon.la \ @USING_WIN32_FALSE@ libs/acn/libolaacn.la \ @USING_WIN32_FALSE@ tools/e133/libolae133common.la \ @USING_WIN32_FALSE@ tools/e133/libolae133controller.la am__tools_e133_e133_receiver_SOURCES_DIST = \ tools/e133/e133-receiver.cpp @USING_WIN32_FALSE@am_tools_e133_e133_receiver_OBJECTS = \ @USING_WIN32_FALSE@ tools/e133/e133-receiver.$(OBJEXT) tools_e133_e133_receiver_OBJECTS = \ $(am_tools_e133_e133_receiver_OBJECTS) @USING_WIN32_FALSE@tools_e133_e133_receiver_DEPENDENCIES = \ @USING_WIN32_FALSE@ common/libolacommon.la \ @USING_WIN32_FALSE@ libs/acn/libolaacn.la \ @USING_WIN32_FALSE@ plugins/usbpro/libolausbprowidget.la \ @USING_WIN32_FALSE@ tools/e133/libolae133device.la \ @USING_WIN32_FALSE@ $(am__append_96) am_tools_ja_rule_ja_rule_OBJECTS = tools/ja-rule/tools_ja_rule_ja_rule-USBDeviceManager.$(OBJEXT) \ tools/ja-rule/tools_ja_rule_ja_rule-ja-rule.$(OBJEXT) tools_ja_rule_ja_rule_OBJECTS = $(am_tools_ja_rule_ja_rule_OBJECTS) tools_ja_rule_ja_rule_DEPENDENCIES = $(am__DEPENDENCIES_1) \ common/libolacommon.la plugins/usbdmx/libolausbdmxwidget.la \ libs/usb/libolausb.la tools_ja_rule_ja_rule_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(tools_ja_rule_ja_rule_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am_tools_ja_rule_ja_rule_controller_OBJECTS = tools/ja-rule/tools_ja_rule_ja_rule_controller-USBDeviceManager.$(OBJEXT) \ tools/ja-rule/tools_ja_rule_ja_rule_controller-ja-rule-controller.$(OBJEXT) tools_ja_rule_ja_rule_controller_OBJECTS = \ $(am_tools_ja_rule_ja_rule_controller_OBJECTS) tools_ja_rule_ja_rule_controller_DEPENDENCIES = $(am__DEPENDENCIES_1) \ common/libolacommon.la plugins/usbdmx/libolausbdmxwidget.la \ libs/usb/libolausb.la tools_ja_rule_ja_rule_controller_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CXXLD) $(tools_ja_rule_ja_rule_controller_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_tools_logic_logic_rdm_sniffer_OBJECTS = \ tools/logic/DMXSignalProcessor.$(OBJEXT) \ tools/logic/logic-rdm-sniffer.$(OBJEXT) tools_logic_logic_rdm_sniffer_OBJECTS = \ $(am_tools_logic_logic_rdm_sniffer_OBJECTS) tools_logic_logic_rdm_sniffer_DEPENDENCIES = common/libolacommon.la \ $(am__DEPENDENCIES_1) am_tools_ola_trigger_ActionTester_OBJECTS = tools/ola_trigger/tools_ola_trigger_ActionTester-ActionTest.$(OBJEXT) \ tools/ola_trigger/tools_ola_trigger_ActionTester-ContextTest.$(OBJEXT) \ tools/ola_trigger/tools_ola_trigger_ActionTester-DMXTriggerTest.$(OBJEXT) \ tools/ola_trigger/tools_ola_trigger_ActionTester-IntervalTest.$(OBJEXT) \ tools/ola_trigger/tools_ola_trigger_ActionTester-SlotTest.$(OBJEXT) \ tools/ola_trigger/tools_ola_trigger_ActionTester-VariableInterpolatorTest.$(OBJEXT) tools_ola_trigger_ActionTester_OBJECTS = \ $(am_tools_ola_trigger_ActionTester_OBJECTS) tools_ola_trigger_ActionTester_DEPENDENCIES = $(am__DEPENDENCIES_5) \ tools/ola_trigger/libolatrigger.la tools_ola_trigger_ActionTester_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(tools_ola_trigger_ActionTester_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_tools_ola_trigger_ola_trigger_OBJECTS = tools/ola_trigger/tools_ola_trigger_ola_trigger-ParserActions.$(OBJEXT) \ tools/ola_trigger/tools_ola_trigger_ola_trigger-ola-trigger.$(OBJEXT) nodist_tools_ola_trigger_ola_trigger_OBJECTS = tools/ola_trigger/tools_ola_trigger_ola_trigger-config.tab.$(OBJEXT) \ tools/ola_trigger/tools_ola_trigger_ola_trigger-lex.yy.$(OBJEXT) tools_ola_trigger_ola_trigger_OBJECTS = \ $(am_tools_ola_trigger_ola_trigger_OBJECTS) \ $(nodist_tools_ola_trigger_ola_trigger_OBJECTS) tools_ola_trigger_ola_trigger_DEPENDENCIES = common/libolacommon.la \ ola/libola.la tools/ola_trigger/libolatrigger.la \ $(am__DEPENDENCIES_1) tools_ola_trigger_ola_trigger_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(tools_ola_trigger_ola_trigger_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__tools_rdmpro_rdmpro_sniffer_SOURCES_DIST = \ tools/rdmpro/rdm-sniffer.cpp @USING_WIN32_FALSE@am_tools_rdmpro_rdmpro_sniffer_OBJECTS = \ @USING_WIN32_FALSE@ tools/rdmpro/rdm-sniffer.$(OBJEXT) tools_rdmpro_rdmpro_sniffer_OBJECTS = \ $(am_tools_rdmpro_rdmpro_sniffer_OBJECTS) @USING_WIN32_FALSE@tools_rdmpro_rdmpro_sniffer_DEPENDENCIES = \ @USING_WIN32_FALSE@ common/libolacommon.la \ @USING_WIN32_FALSE@ plugins/usbpro/libolausbprowidget.la am__tools_usbpro_usbpro_firmware_SOURCES_DIST = \ tools/usbpro/usbpro-firmware.cpp @USING_WIN32_FALSE@am_tools_usbpro_usbpro_firmware_OBJECTS = \ @USING_WIN32_FALSE@ tools/usbpro/usbpro-firmware.$(OBJEXT) tools_usbpro_usbpro_firmware_OBJECTS = \ $(am_tools_usbpro_usbpro_firmware_OBJECTS) @USING_WIN32_FALSE@tools_usbpro_usbpro_firmware_DEPENDENCIES = \ @USING_WIN32_FALSE@ common/libolacommon.la \ @USING_WIN32_FALSE@ plugins/usbpro/libolausbprowidget.la am__dist_noinst_SCRIPTS_DIST = data/rdm/download.sh \ data/rdm/PidDataTest.py include/ola/rdm/make_rdm_codes.sh \ include/ola/timecode/make_timecode.sh \ include/ola/gen_callbacks.py include/ola/make_plugin_id.sh \ python/examples/ola_artnet_params.py \ python/examples/ola_candidate_ports.py \ python/examples/ola_devices.py \ python/examples/ola_patch_unpatch.py \ python/examples/ola_plugin_info.py \ python/examples/ola_rdm_discover.py \ python/examples/ola_rdm_get.py python/examples/ola_recv_dmx.py \ python/examples/ola_send_dmx.py \ python/examples/ola_simple_fade.py \ python/examples/ola_universe_info.py \ python/examples/rdm_compare.py python/examples/rdm_snapshot.py \ tools/usbpro/download_firmware.sh am__dist_rdmtestsexec_SCRIPTS_DIST = tools/rdm/rdm_model_collector.py \ tools/rdm/rdm_responder_test.py tools/rdm/rdm_test_server.py SCRIPTS = $(dist_noinst_SCRIPTS) $(dist_rdmtestsexec_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/config/depcomp am__depfiles_maybe = depfiles am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(common_http_libolahttp_la_SOURCES) \ $(common_libolacommon_la_SOURCES) \ $(nodist_common_libolacommon_la_SOURCES) \ $(nodist_common_protocol_libolaproto_la_SOURCES) \ $(common_testing_libolatesting_la_SOURCES) \ $(common_testing_libtestmain_la_SOURCES) \ $(common_web_libolaweb_la_SOURCES) \ $(examples_libolaconfig_la_SOURCES) \ $(libs_acn_libolaacn_la_SOURCES) \ $(libs_acn_libolae131core_la_SOURCES) \ $(libs_usb_libolausb_la_SOURCES) $(ola_libola_la_SOURCES) \ $(olad_libolaserver_la_SOURCES) \ $(olad_plugin_api_libolaserverplugininterface_la_SOURCES) \ $(plugins_artnet_libolaartnet_la_SOURCES) \ $(plugins_artnet_libolaartnetnode_la_SOURCES) \ $(nodist_plugins_artnet_messages_libolaartnetconf_la_SOURCES) \ $(plugins_dmx4linux_liboladmx4linux_la_SOURCES) \ $(plugins_dummy_liboladummy_la_SOURCES) \ $(plugins_e131_libolae131_la_SOURCES) \ $(nodist_plugins_e131_messages_libolae131conf_la_SOURCES) \ $(plugins_espnet_libolaespnet_la_SOURCES) \ $(plugins_ftdidmx_libolaftdidmx_la_SOURCES) \ $(plugins_gpio_libolagpio_la_SOURCES) \ $(plugins_gpio_libolagpiocore_la_SOURCES) \ $(plugins_karate_libolakarate_la_SOURCES) \ $(plugins_kinet_libolakinet_la_SOURCES) \ $(plugins_kinet_libolakinetnode_la_SOURCES) \ $(plugins_milinst_libolamilinst_la_SOURCES) \ $(plugins_opendmx_libolaopendmx_la_SOURCES) \ $(plugins_openpixelcontrol_libolaopc_la_SOURCES) \ $(plugins_openpixelcontrol_libolaopenpixelcontrol_la_SOURCES) \ $(plugins_osc_libolaosc_la_SOURCES) \ $(plugins_osc_libolaoscnode_la_SOURCES) \ $(plugins_pathport_libolapathport_la_SOURCES) \ $(plugins_renard_libolarenard_la_SOURCES) \ $(plugins_sandnet_libolasandnet_la_SOURCES) \ $(plugins_shownet_libolashownet_la_SOURCES) \ $(plugins_spi_libolaspi_la_SOURCES) \ $(plugins_spi_libolaspicore_la_SOURCES) \ $(plugins_stageprofi_libolastageprofi_la_SOURCES) \ $(plugins_uartdmx_libolauartdmx_la_SOURCES) \ $(plugins_usbdmx_libolausbdmx_la_SOURCES) \ $(plugins_usbdmx_libolausbdmxwidget_la_SOURCES) \ $(plugins_usbpro_libolausbpro_la_SOURCES) \ $(plugins_usbpro_libolausbprowidget_la_SOURCES) \ $(nodist_plugins_usbpro_messages_libolausbproconf_la_SOURCES) \ $(tools_e133_libolae133common_la_SOURCES) \ $(tools_e133_libolae133controller_la_SOURCES) \ $(tools_e133_libolae133device_la_SOURCES) \ $(tools_ola_trigger_libolatrigger_la_SOURCES) \ $(common_base_CredentialsTester_SOURCES) \ $(common_base_FlagsTester_SOURCES) \ $(common_base_LoggingTester_SOURCES) \ $(common_dmx_RunLengthEncoderTester_SOURCES) \ $(common_export_map_ExportMapTester_SOURCES) \ $(common_file_UtilTester_SOURCES) \ $(common_io_DescriptorTester_SOURCES) \ $(common_io_IOQueueTester_SOURCES) \ $(common_io_IOStackTester_SOURCES) \ $(common_io_MemoryBlockTester_SOURCES) \ $(common_io_SelectServerTester_SOURCES) \ $(common_io_StreamTester_SOURCES) \ $(common_io_TimeoutManagerTester_SOURCES) \ $(common_messaging_DescriptorTester_SOURCES) \ $(common_network_HealthCheckedConnectionTester_SOURCES) \ $(common_network_NetworkTester_SOURCES) \ $(common_network_TCPConnectorTester_SOURCES) \ $(common_rdm_DiscoveryAgentTester_SOURCES) \ $(common_rdm_PidStoreTester_SOURCES) \ $(common_rdm_QueueingRDMControllerTester_SOURCES) \ $(common_rdm_RDMAPITester_SOURCES) \ $(common_rdm_RDMCommandSerializerTester_SOURCES) \ $(common_rdm_RDMCommandTester_SOURCES) \ $(common_rdm_RDMFrameTester_SOURCES) \ $(common_rdm_RDMHelperTester_SOURCES) \ $(common_rdm_RDMMessageTester_SOURCES) \ $(common_rdm_RDMReplyTester_SOURCES) \ $(common_rdm_UIDAllocatorTester_SOURCES) \ $(common_rdm_UIDTester_SOURCES) \ $(common_rpc_RpcServerTester_SOURCES) \ $(nodist_common_rpc_RpcServerTester_SOURCES) \ $(common_rpc_RpcTester_SOURCES) \ $(nodist_common_rpc_RpcTester_SOURCES) \ $(common_strings_UtilsTester_SOURCES) \ $(common_thread_ExecutorThreadTester_SOURCES) \ $(common_thread_FutureTester_SOURCES) \ $(common_thread_ThreadTester_SOURCES) \ $(common_timecode_TimeCodeTester_SOURCES) \ $(common_utils_UtilsTester_SOURCES) \ $(common_web_JsonTester_SOURCES) \ $(common_web_ParserTester_SOURCES) \ $(common_web_PointerTester_SOURCES) \ $(common_web_PointerTrackerTester_SOURCES) \ $(common_web_PtchParserTester_SOURCES) \ $(common_web_PtchTester_SOURCES) \ $(common_web_SchemaParserTester_SOURCES) \ $(common_web_SchemaTester_SOURCES) \ $(common_web_SectionsTester_SOURCES) \ $(data_rdm_PidDataTester_SOURCES) \ $(doxygen_examples_callback_client_transmit_SOURCES) \ $(doxygen_examples_client_disconnect_SOURCES) \ $(doxygen_examples_client_thread_SOURCES) \ $(doxygen_examples_fetch_plugins_SOURCES) \ $(doxygen_examples_flags_SOURCES) \ $(doxygen_examples_legacy_callback_client_transmit_SOURCES) \ $(doxygen_examples_legacy_receiver_SOURCES) \ $(doxygen_examples_legacy_streaming_client_SOURCES) \ $(doxygen_examples_receiver_SOURCES) \ $(doxygen_examples_stdin_handler_SOURCES) \ $(doxygen_examples_streaming_client_SOURCES) \ $(doxygen_examples_streaming_client_plugin_SOURCES) \ $(doxygen_examples_udp_server_SOURCES) \ $(examples_ola_artnet_SOURCES) \ $(examples_ola_dev_info_SOURCES) \ $(examples_ola_dmxconsole_SOURCES) \ $(examples_ola_dmxmonitor_SOURCES) \ $(examples_ola_e131_SOURCES) $(examples_ola_latency_SOURCES) \ $(examples_ola_rdm_discover_SOURCES) \ $(examples_ola_rdm_get_SOURCES) \ $(examples_ola_recorder_SOURCES) \ $(examples_ola_streaming_client_SOURCES) \ $(examples_ola_throughput_SOURCES) \ $(examples_ola_timecode_SOURCES) \ $(examples_ola_uni_stats_SOURCES) \ $(examples_ola_usbpro_SOURCES) $(libs_acn_E131Tester_SOURCES) \ $(libs_acn_E133Tester_SOURCES) \ $(libs_acn_TransportTester_SOURCES) \ $(libs_acn_e131_loadtest_SOURCES) \ $(libs_acn_e131_transmit_test_SOURCES) \ $(libs_usb_LibUsbThreadTester_SOURCES) \ $(ola_OlaClientTester_SOURCES) $(olad_OlaTester_SOURCES) \ $(olad_olad_SOURCES) $(olad_plugin_api_ClientTester_SOURCES) \ $(olad_plugin_api_DeviceTester_SOURCES) \ $(olad_plugin_api_DmxSourceTester_SOURCES) \ $(olad_plugin_api_PortTester_SOURCES) \ $(olad_plugin_api_PreferencesTester_SOURCES) \ $(olad_plugin_api_UniverseTester_SOURCES) \ $(plugins_artnet_ArtNetTester_SOURCES) \ $(plugins_artnet_artnet_loadtest_SOURCES) \ $(plugins_dummy_DummyPluginTester_SOURCES) \ $(plugins_espnet_EspNetTester_SOURCES) \ $(plugins_kinet_KiNetTester_SOURCES) \ $(plugins_openpixelcontrol_OPCClientTester_SOURCES) \ $(plugins_openpixelcontrol_OPCServerTester_SOURCES) \ $(plugins_osc_OSCTester_SOURCES) \ $(plugins_shownet_ShowNetTester_SOURCES) \ $(plugins_spi_SPITester_SOURCES) \ $(plugins_usbpro_ArduinoWidgetTester_SOURCES) \ $(plugins_usbpro_BaseRobeWidgetTester_SOURCES) \ $(plugins_usbpro_BaseUsbProWidgetTester_SOURCES) \ $(plugins_usbpro_DmxTriWidgetTester_SOURCES) \ $(plugins_usbpro_DmxterWidgetTester_SOURCES) \ $(plugins_usbpro_EnttecUsbProWidgetTester_SOURCES) \ $(plugins_usbpro_RobeWidgetDetectorTester_SOURCES) \ $(plugins_usbpro_RobeWidgetTester_SOURCES) \ $(plugins_usbpro_UltraDMXProWidgetTester_SOURCES) \ $(plugins_usbpro_UsbProWidgetDetectorTester_SOURCES) \ $(plugins_usbpro_WidgetDetectorThreadTester_SOURCES) \ $(protoc_ola_protoc_plugin_SOURCES) \ $(tools_e133_basic_controller_SOURCES) \ $(tools_e133_basic_device_SOURCES) \ $(tools_e133_e133_controller_SOURCES) \ $(tools_e133_e133_monitor_SOURCES) \ $(tools_e133_e133_receiver_SOURCES) \ $(tools_ja_rule_ja_rule_SOURCES) \ $(tools_ja_rule_ja_rule_controller_SOURCES) \ $(tools_logic_logic_rdm_sniffer_SOURCES) \ $(tools_ola_trigger_ActionTester_SOURCES) \ $(tools_ola_trigger_ola_trigger_SOURCES) \ $(nodist_tools_ola_trigger_ola_trigger_SOURCES) \ $(tools_rdmpro_rdmpro_sniffer_SOURCES) \ $(tools_usbpro_usbpro_firmware_SOURCES) DIST_SOURCES = $(am__common_http_libolahttp_la_SOURCES_DIST) \ $(am__common_libolacommon_la_SOURCES_DIST) \ $(am__common_testing_libolatesting_la_SOURCES_DIST) \ $(am__common_testing_libtestmain_la_SOURCES_DIST) \ $(common_web_libolaweb_la_SOURCES) \ $(am__examples_libolaconfig_la_SOURCES_DIST) \ $(libs_acn_libolaacn_la_SOURCES) \ $(libs_acn_libolae131core_la_SOURCES) \ $(am__libs_usb_libolausb_la_SOURCES_DIST) \ $(ola_libola_la_SOURCES) \ $(am__olad_libolaserver_la_SOURCES_DIST) \ $(olad_plugin_api_libolaserverplugininterface_la_SOURCES) \ $(am__plugins_artnet_libolaartnet_la_SOURCES_DIST) \ $(am__plugins_artnet_libolaartnetnode_la_SOURCES_DIST) \ $(am__plugins_dmx4linux_liboladmx4linux_la_SOURCES_DIST) \ $(am__plugins_dummy_liboladummy_la_SOURCES_DIST) \ $(am__plugins_e131_libolae131_la_SOURCES_DIST) \ $(am__plugins_espnet_libolaespnet_la_SOURCES_DIST) \ $(am__plugins_ftdidmx_libolaftdidmx_la_SOURCES_DIST) \ $(am__plugins_gpio_libolagpio_la_SOURCES_DIST) \ $(am__plugins_gpio_libolagpiocore_la_SOURCES_DIST) \ $(am__plugins_karate_libolakarate_la_SOURCES_DIST) \ $(am__plugins_kinet_libolakinet_la_SOURCES_DIST) \ $(am__plugins_kinet_libolakinetnode_la_SOURCES_DIST) \ $(am__plugins_milinst_libolamilinst_la_SOURCES_DIST) \ $(am__plugins_opendmx_libolaopendmx_la_SOURCES_DIST) \ $(am__plugins_openpixelcontrol_libolaopc_la_SOURCES_DIST) \ $(am__plugins_openpixelcontrol_libolaopenpixelcontrol_la_SOURCES_DIST) \ $(am__plugins_osc_libolaosc_la_SOURCES_DIST) \ $(am__plugins_osc_libolaoscnode_la_SOURCES_DIST) \ $(am__plugins_pathport_libolapathport_la_SOURCES_DIST) \ $(am__plugins_renard_libolarenard_la_SOURCES_DIST) \ $(am__plugins_sandnet_libolasandnet_la_SOURCES_DIST) \ $(am__plugins_shownet_libolashownet_la_SOURCES_DIST) \ $(am__plugins_spi_libolaspi_la_SOURCES_DIST) \ $(am__plugins_spi_libolaspicore_la_SOURCES_DIST) \ $(am__plugins_stageprofi_libolastageprofi_la_SOURCES_DIST) \ $(am__plugins_uartdmx_libolauartdmx_la_SOURCES_DIST) \ $(am__plugins_usbdmx_libolausbdmx_la_SOURCES_DIST) \ $(am__plugins_usbdmx_libolausbdmxwidget_la_SOURCES_DIST) \ $(am__plugins_usbpro_libolausbpro_la_SOURCES_DIST) \ $(am__plugins_usbpro_libolausbprowidget_la_SOURCES_DIST) \ $(am__tools_e133_libolae133common_la_SOURCES_DIST) \ $(am__tools_e133_libolae133controller_la_SOURCES_DIST) \ $(am__tools_e133_libolae133device_la_SOURCES_DIST) \ $(tools_ola_trigger_libolatrigger_la_SOURCES) \ $(common_base_CredentialsTester_SOURCES) \ $(common_base_FlagsTester_SOURCES) \ $(common_base_LoggingTester_SOURCES) \ $(common_dmx_RunLengthEncoderTester_SOURCES) \ $(common_export_map_ExportMapTester_SOURCES) \ $(common_file_UtilTester_SOURCES) \ $(common_io_DescriptorTester_SOURCES) \ $(common_io_IOQueueTester_SOURCES) \ $(common_io_IOStackTester_SOURCES) \ $(common_io_MemoryBlockTester_SOURCES) \ $(common_io_SelectServerTester_SOURCES) \ $(common_io_StreamTester_SOURCES) \ $(common_io_TimeoutManagerTester_SOURCES) \ $(common_messaging_DescriptorTester_SOURCES) \ $(common_network_HealthCheckedConnectionTester_SOURCES) \ $(common_network_NetworkTester_SOURCES) \ $(common_network_TCPConnectorTester_SOURCES) \ $(common_rdm_DiscoveryAgentTester_SOURCES) \ $(common_rdm_PidStoreTester_SOURCES) \ $(common_rdm_QueueingRDMControllerTester_SOURCES) \ $(common_rdm_RDMAPITester_SOURCES) \ $(common_rdm_RDMCommandSerializerTester_SOURCES) \ $(common_rdm_RDMCommandTester_SOURCES) \ $(common_rdm_RDMFrameTester_SOURCES) \ $(common_rdm_RDMHelperTester_SOURCES) \ $(common_rdm_RDMMessageTester_SOURCES) \ $(common_rdm_RDMReplyTester_SOURCES) \ $(common_rdm_UIDAllocatorTester_SOURCES) \ $(common_rdm_UIDTester_SOURCES) \ $(common_rpc_RpcServerTester_SOURCES) \ $(common_rpc_RpcTester_SOURCES) \ $(common_strings_UtilsTester_SOURCES) \ $(common_thread_ExecutorThreadTester_SOURCES) \ $(common_thread_FutureTester_SOURCES) \ $(common_thread_ThreadTester_SOURCES) \ $(common_timecode_TimeCodeTester_SOURCES) \ $(common_utils_UtilsTester_SOURCES) \ $(common_web_JsonTester_SOURCES) \ $(common_web_ParserTester_SOURCES) \ $(common_web_PointerTester_SOURCES) \ $(common_web_PointerTrackerTester_SOURCES) \ $(common_web_PtchParserTester_SOURCES) \ $(common_web_PtchTester_SOURCES) \ $(common_web_SchemaParserTester_SOURCES) \ $(common_web_SchemaTester_SOURCES) \ $(common_web_SectionsTester_SOURCES) \ $(data_rdm_PidDataTester_SOURCES) \ $(doxygen_examples_callback_client_transmit_SOURCES) \ $(doxygen_examples_client_disconnect_SOURCES) \ $(doxygen_examples_client_thread_SOURCES) \ $(doxygen_examples_fetch_plugins_SOURCES) \ $(doxygen_examples_flags_SOURCES) \ $(doxygen_examples_legacy_callback_client_transmit_SOURCES) \ $(doxygen_examples_legacy_receiver_SOURCES) \ $(doxygen_examples_legacy_streaming_client_SOURCES) \ $(doxygen_examples_receiver_SOURCES) \ $(doxygen_examples_stdin_handler_SOURCES) \ $(doxygen_examples_streaming_client_SOURCES) \ $(doxygen_examples_streaming_client_plugin_SOURCES) \ $(doxygen_examples_udp_server_SOURCES) \ $(am__examples_ola_artnet_SOURCES_DIST) \ $(am__examples_ola_dev_info_SOURCES_DIST) \ $(am__examples_ola_dmxconsole_SOURCES_DIST) \ $(am__examples_ola_dmxmonitor_SOURCES_DIST) \ $(am__examples_ola_e131_SOURCES_DIST) \ $(am__examples_ola_latency_SOURCES_DIST) \ $(am__examples_ola_rdm_discover_SOURCES_DIST) \ $(am__examples_ola_rdm_get_SOURCES_DIST) \ $(am__examples_ola_recorder_SOURCES_DIST) \ $(am__examples_ola_streaming_client_SOURCES_DIST) \ $(am__examples_ola_throughput_SOURCES_DIST) \ $(am__examples_ola_timecode_SOURCES_DIST) \ $(am__examples_ola_uni_stats_SOURCES_DIST) \ $(am__examples_ola_usbpro_SOURCES_DIST) \ $(libs_acn_E131Tester_SOURCES) $(libs_acn_E133Tester_SOURCES) \ $(libs_acn_TransportTester_SOURCES) \ $(libs_acn_e131_loadtest_SOURCES) \ $(libs_acn_e131_transmit_test_SOURCES) \ $(am__libs_usb_LibUsbThreadTester_SOURCES_DIST) \ $(ola_OlaClientTester_SOURCES) $(olad_OlaTester_SOURCES) \ $(olad_olad_SOURCES) $(olad_plugin_api_ClientTester_SOURCES) \ $(olad_plugin_api_DeviceTester_SOURCES) \ $(olad_plugin_api_DmxSourceTester_SOURCES) \ $(olad_plugin_api_PortTester_SOURCES) \ $(olad_plugin_api_PreferencesTester_SOURCES) \ $(olad_plugin_api_UniverseTester_SOURCES) \ $(am__plugins_artnet_ArtNetTester_SOURCES_DIST) \ $(am__plugins_artnet_artnet_loadtest_SOURCES_DIST) \ $(am__plugins_dummy_DummyPluginTester_SOURCES_DIST) \ $(am__plugins_espnet_EspNetTester_SOURCES_DIST) \ $(am__plugins_kinet_KiNetTester_SOURCES_DIST) \ $(am__plugins_openpixelcontrol_OPCClientTester_SOURCES_DIST) \ $(am__plugins_openpixelcontrol_OPCServerTester_SOURCES_DIST) \ $(am__plugins_osc_OSCTester_SOURCES_DIST) \ $(am__plugins_shownet_ShowNetTester_SOURCES_DIST) \ $(am__plugins_spi_SPITester_SOURCES_DIST) \ $(am__plugins_usbpro_ArduinoWidgetTester_SOURCES_DIST) \ $(am__plugins_usbpro_BaseRobeWidgetTester_SOURCES_DIST) \ $(am__plugins_usbpro_BaseUsbProWidgetTester_SOURCES_DIST) \ $(am__plugins_usbpro_DmxTriWidgetTester_SOURCES_DIST) \ $(am__plugins_usbpro_DmxterWidgetTester_SOURCES_DIST) \ $(am__plugins_usbpro_EnttecUsbProWidgetTester_SOURCES_DIST) \ $(am__plugins_usbpro_RobeWidgetDetectorTester_SOURCES_DIST) \ $(am__plugins_usbpro_RobeWidgetTester_SOURCES_DIST) \ $(am__plugins_usbpro_UltraDMXProWidgetTester_SOURCES_DIST) \ $(am__plugins_usbpro_UsbProWidgetDetectorTester_SOURCES_DIST) \ $(am__plugins_usbpro_WidgetDetectorThreadTester_SOURCES_DIST) \ $(am__protoc_ola_protoc_plugin_SOURCES_DIST) \ $(am__tools_e133_basic_controller_SOURCES_DIST) \ $(am__tools_e133_basic_device_SOURCES_DIST) \ $(am__tools_e133_e133_controller_SOURCES_DIST) \ $(am__tools_e133_e133_monitor_SOURCES_DIST) \ $(am__tools_e133_e133_receiver_SOURCES_DIST) \ $(tools_ja_rule_ja_rule_SOURCES) \ $(tools_ja_rule_ja_rule_controller_SOURCES) \ $(tools_logic_logic_rdm_sniffer_SOURCES) \ $(tools_ola_trigger_ActionTester_SOURCES) \ $(tools_ola_trigger_ola_trigger_SOURCES) \ $(am__tools_rdmpro_rdmpro_sniffer_SOURCES_DIST) \ $(am__tools_usbpro_usbpro_firmware_SOURCES_DIST) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-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 \ tags-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__py_compile = PYTHON=$(PYTHON) $(SHELL) $(py_compile) am__pep3147_tweak = \ sed -e 's|\.py$$||' -e 's|[^/]*$$|__pycache__/&.*.py|' am__pkgpython_PYTHON_DIST = python/ola/ClientWrapper.py \ python/ola/DMXConstants.py python/ola/DUBDecoder.py \ python/ola/MACAddress.py python/ola/OlaClient.py \ python/ola/RDMAPI.py python/ola/RDMConstants.py \ python/ola/PidStore.py python/ola/UID.py \ python/ola/__init__.py am__rdminit_PYTHON_DIST = tools/rdm/__init__.py am__rdmtests_PYTHON_DIST = tools/rdm/DMXSender.py \ tools/rdm/ExpectedResults.py tools/rdm/ModelCollector.py \ tools/rdm/ResponderTest.py tools/rdm/TestCategory.py \ tools/rdm/TestDefinitions.py tools/rdm/TestHelpers.py \ tools/rdm/TestLogger.py tools/rdm/TestMixins.py \ tools/rdm/TestRunner.py tools/rdm/TimingStats.py \ tools/rdm/TestState.py tools/rdm/__init__.py am__rpcpython_PYTHON_DIST = python/ola/rpc/SimpleRpcController.py \ python/ola/rpc/StreamRpcChannel.py python/ola/rpc/__init__.py py_compile = $(top_srcdir)/config/py-compile man1dir = $(mandir)/man1 NROFF = nroff MANS = $(dist_man_MANS) am__dist_tools_rdm_testserver_images_DATA_DIST = \ tools/rdm/static/images/discovery.png \ tools/rdm/static/images/external.png \ tools/rdm/static/images/favicon.ico \ tools/rdm/static/images/loader.gif \ tools/rdm/static/images/logo.png \ tools/rdm/static/images/ui-bg_flat_0_aaaaaa_40x100.png \ tools/rdm/static/images/ui-bg_flat_0_eeeeee_40x100.png \ tools/rdm/static/images/ui-bg_flat_55_c0402a_40x100.png \ tools/rdm/static/images/ui-bg_flat_55_eeeeee_40x100.png \ tools/rdm/static/images/ui-bg_glass_100_f8f8f8_1x400.png \ tools/rdm/static/images/ui-bg_glass_35_dddddd_1x400.png \ tools/rdm/static/images/ui-bg_glass_60_eeeeee_1x400.png \ tools/rdm/static/images/ui-bg_inset-hard_75_999999_1x100.png \ tools/rdm/static/images/ui-bg_inset-soft_50_c9c9c9_1x100.png \ tools/rdm/static/images/ui-icons_3383bb_256x240.png \ tools/rdm/static/images/ui-icons_454545_256x240.png \ tools/rdm/static/images/ui-icons_70b2e1_256x240.png \ tools/rdm/static/images/ui-icons_999999_256x240.png \ tools/rdm/static/images/ui-icons_fbc856_256x240.png am__dist_tools_rdm_testserver_static_DATA_DIST = \ tools/rdm/static/MIT-LICENSE.txt tools/rdm/static/common.css \ tools/rdm/static/jquery-1.7.2.min.js \ tools/rdm/static/jquery-ui-1.8.21.custom.css \ tools/rdm/static/jquery-ui-1.8.21.custom.min.js \ tools/rdm/static/rdm_tests.js tools/rdm/static/rdmtests.html \ tools/rdm/static/ui.multiselect.css \ tools/rdm/static/ui.multiselect.js DATA = $(dist_angular_DATA) $(dist_angularroute_DATA) \ $(dist_bootcss_DATA) $(dist_bootfonts_DATA) \ $(dist_bootjs_DATA) $(dist_css_DATA) $(dist_img_DATA) \ $(dist_jquery_DATA) $(dist_js_DATA) $(dist_new_DATA) \ $(dist_noinst_DATA) $(dist_piddata_DATA) \ $(dist_tools_rdm_testserver_images_DATA) \ $(dist_tools_rdm_testserver_static_DATA) $(dist_views_DATA) \ $(dist_www_DATA) $(noinst_DATA) $(pkgconfig_DATA) am__olaacninclude_HEADERS_DIST = include/ola/acn/ACNPort.h \ include/ola/acn/ACNVectors.h include/ola/acn/CID.h am__olae133include_HEADERS_DIST = include/ola/e133/DeviceManager.h \ include/ola/e133/E133Enums.h include/ola/e133/E133Receiver.h \ include/ola/e133/E133StatusHelper.h \ include/ola/e133/E133URLParser.h \ include/ola/e133/MessageBuilder.h HEADERS = $(nodist_artnetinclude_HEADERS) \ $(nodist_e131include_HEADERS) $(nodist_olabaseinclude_HEADERS) \ $(nodist_olardminclude_HEADERS) \ $(nodist_olatimecodeinclude_HEADERS) \ $(nodist_pkginclude_HEADERS) $(nodist_usbproinclude_HEADERS) \ $(noinst_HEADERS) $(olaacninclude_HEADERS) \ $(olabaseinclude_HEADERS) $(olaclientinclude_HEADERS) \ $(oladinclude_HEADERS) $(oladmxinclude_HEADERS) \ $(olae133include_HEADERS) $(olafileinclude_HEADERS) \ $(olahttpinclude_HEADERS) $(olaioinclude_HEADERS) \ $(olamathinclude_HEADERS) $(olamessaginginclude_HEADERS) \ $(olanetworkinclude_HEADERS) $(olardminclude_HEADERS) \ $(olarpcinclude_HEADERS) $(olastlinclude_HEADERS) \ $(olastringsinclude_HEADERS) $(olasysteminclude_HEADERS) \ $(olathreadinclude_HEADERS) $(olatimecodeinclude_HEADERS) \ $(olautilinclude_HEADERS) $(olawebinclude_HEADERS) \ $(olawininclude_HEADERS) $(pkginclude_HEADERS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ cscope check recheck distdir dist dist-all distcheck am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ $(LISP)config.h.in # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags CSCOPE = cscope am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) TEST_SUITE_LOG = test-suite.log LOG_DRIVER = $(SHELL) $(top_srcdir)/config/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.py.log=.log) PY_LOG_DRIVER = $(SHELL) $(top_srcdir)/config/test-driver PY_LOG_COMPILE = $(PY_LOG_COMPILER) $(AM_PY_LOG_FLAGS) $(PY_LOG_FLAGS) DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(dist_man_MANS) $(srcdir)/Makefile.in \ $(srcdir)/aminclude.am $(srcdir)/common/Makefile.mk \ $(srcdir)/common/base/Makefile.mk \ $(srcdir)/common/dmx/Makefile.mk \ $(srcdir)/common/export_map/Makefile.mk \ $(srcdir)/common/file/Makefile.mk \ $(srcdir)/common/http/Makefile.mk \ $(srcdir)/common/io/Makefile.mk \ $(srcdir)/common/math/Makefile.mk \ $(srcdir)/common/messaging/Makefile.mk \ $(srcdir)/common/network/Makefile.mk \ $(srcdir)/common/protocol/Makefile.mk \ $(srcdir)/common/rdm/Makefile.mk \ $(srcdir)/common/rpc/Makefile.mk \ $(srcdir)/common/strings/Makefile.mk \ $(srcdir)/common/system/Makefile.mk \ $(srcdir)/common/testing/Makefile.mk \ $(srcdir)/common/thread/Makefile.mk \ $(srcdir)/common/timecode/Makefile.mk \ $(srcdir)/common/utils/Makefile.mk \ $(srcdir)/common/web/Makefile.mk $(srcdir)/config.h.in \ $(srcdir)/data/Makefile.mk $(srcdir)/data/rdm/Makefile.mk \ $(srcdir)/debian/Makefile.mk $(srcdir)/doxygen/Makefile.mk \ $(srcdir)/doxygen/examples/Makefile.mk \ $(srcdir)/examples/Makefile.mk $(srcdir)/include/Makefile.mk \ $(srcdir)/include/ola/Makefile.mk \ $(srcdir)/include/ola/acn/Makefile.mk \ $(srcdir)/include/ola/base/Makefile.mk \ $(srcdir)/include/ola/client/Makefile.mk \ $(srcdir)/include/ola/dmx/Makefile.mk \ $(srcdir)/include/ola/e133/Makefile.mk \ $(srcdir)/include/ola/file/Makefile.mk \ $(srcdir)/include/ola/http/Makefile.mk \ $(srcdir)/include/ola/io/Makefile.mk \ $(srcdir)/include/ola/math/Makefile.mk \ $(srcdir)/include/ola/messaging/Makefile.mk \ $(srcdir)/include/ola/network/Makefile.mk \ $(srcdir)/include/ola/rdm/Makefile.mk \ $(srcdir)/include/ola/rpc/Makefile.mk \ $(srcdir)/include/ola/stl/Makefile.mk \ $(srcdir)/include/ola/strings/Makefile.mk \ $(srcdir)/include/ola/system/Makefile.mk \ $(srcdir)/include/ola/testing/Makefile.mk \ $(srcdir)/include/ola/thread/Makefile.mk \ $(srcdir)/include/ola/timecode/Makefile.mk \ $(srcdir)/include/ola/util/Makefile.mk \ $(srcdir)/include/ola/web/Makefile.mk \ $(srcdir)/include/ola/win/Makefile.mk \ $(srcdir)/include/olad/Makefile.mk \ $(srcdir)/javascript/Makefile.mk $(srcdir)/libola.pc.in \ $(srcdir)/libolaserver.pc.in $(srcdir)/libs/Makefile.mk \ $(srcdir)/libs/acn/Makefile.mk $(srcdir)/libs/usb/Makefile.mk \ $(srcdir)/man/Makefile.mk $(srcdir)/ola.spec.in \ $(srcdir)/ola/Makefile.mk $(srcdir)/olad/Makefile.mk \ $(srcdir)/olad/plugin_api/Makefile.mk \ $(srcdir)/olad/www/Makefile.mk $(srcdir)/plugins/Makefile.mk \ $(srcdir)/plugins/artnet/Makefile.mk \ $(srcdir)/plugins/artnet/messages/Makefile.mk \ $(srcdir)/plugins/dmx4linux/Makefile.mk \ $(srcdir)/plugins/dummy/Makefile.mk \ $(srcdir)/plugins/e131/Makefile.mk \ $(srcdir)/plugins/e131/messages/Makefile.mk \ $(srcdir)/plugins/espnet/Makefile.mk \ $(srcdir)/plugins/ftdidmx/Makefile.mk \ $(srcdir)/plugins/gpio/Makefile.mk \ $(srcdir)/plugins/karate/Makefile.mk \ $(srcdir)/plugins/kinet/Makefile.mk \ $(srcdir)/plugins/milinst/Makefile.mk \ $(srcdir)/plugins/opendmx/Makefile.mk \ $(srcdir)/plugins/openpixelcontrol/Makefile.mk \ $(srcdir)/plugins/osc/Makefile.mk \ $(srcdir)/plugins/pathport/Makefile.mk \ $(srcdir)/plugins/renard/Makefile.mk \ $(srcdir)/plugins/sandnet/Makefile.mk \ $(srcdir)/plugins/shownet/Makefile.mk \ $(srcdir)/plugins/spi/Makefile.mk \ $(srcdir)/plugins/stageprofi/Makefile.mk \ $(srcdir)/plugins/uartdmx/Makefile.mk \ $(srcdir)/plugins/usbdmx/Makefile.mk \ $(srcdir)/plugins/usbpro/Makefile.mk \ $(srcdir)/plugins/usbpro/messages/Makefile.mk \ $(srcdir)/protoc/Makefile.mk $(srcdir)/python/Makefile.mk \ $(srcdir)/python/examples/Makefile.mk \ $(srcdir)/python/ola/Makefile.mk \ $(srcdir)/python/ola/rpc/Makefile.mk \ $(srcdir)/tools/Makefile.mk $(srcdir)/tools/e133/Makefile.mk \ $(srcdir)/tools/ja-rule/Makefile.mk \ $(srcdir)/tools/logic/Makefile.mk \ $(srcdir)/tools/ola_trigger/Makefile.mk \ $(srcdir)/tools/rdm/Makefile.mk \ $(srcdir)/tools/rdmpro/Makefile.mk \ $(srcdir)/tools/usbpro/Makefile.mk \ $(top_srcdir)/config/compile $(top_srcdir)/config/config.guess \ $(top_srcdir)/config/config.sub $(top_srcdir)/config/depcomp \ $(top_srcdir)/config/install-sh $(top_srcdir)/config/ltmain.sh \ $(top_srcdir)/config/missing $(top_srcdir)/config/py-compile \ $(top_srcdir)/config/test-driver \ $(top_srcdir)/include/ola/base/Version.h.in \ $(top_srcdir)/libs/acn/libolaacn.pc.in \ $(top_srcdir)/plugins/artnet/messages/libolaartnetconf.pc.in \ $(top_srcdir)/plugins/e131/messages/libolae131conf.pc.in \ $(top_srcdir)/plugins/usbpro/messages/libolausbproconf.pc.in \ $(top_srcdir)/python/ola/MACAddress.py \ $(top_srcdir)/python/ola/PidStore.py \ $(top_srcdir)/python/ola/RDMConstants.py \ $(top_srcdir)/python/ola/UID.py \ $(top_srcdir)/python/ola/__init__.py \ $(top_srcdir)/tools/e133/libolae133common.pc.in \ $(top_srcdir)/tools/e133/libolae133controller.pc.in AUTHORS \ COPYING ChangeLog INSTALL NEWS README TODO config/compile \ config/config.guess config/config.sub config/depcomp \ config/install-sh config/ltmain.sh config/missing \ config/py-compile 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__post_remove_distdir = $(am__remove_distdir) 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 DIST_TARGETS = dist-gzip distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print # As suggested by libtoolize ACLOCAL = aclocal -I $(auxdir) AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPUNIT1_CFLAGS = @CPPUNIT1_CFLAGS@ CPPUNIT1_LIBS = @CPPUNIT1_LIBS@ CPPUNIT2_CFLAGS = @CPPUNIT2_CFLAGS@ CPPUNIT2_LIBS = @CPPUNIT2_LIBS@ CPPUNIT_CFLAGS = @CPPUNIT_CFLAGS@ CPPUNIT_LIBS = @CPPUNIT_LIBS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN_PAPER_SIZE = @DOXYGEN_PAPER_SIZE@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ DX_CONFIG = @DX_CONFIG@ DX_DOCDIR = @DX_DOCDIR@ DX_DOT = @DX_DOT@ DX_DOXYGEN = @DX_DOXYGEN@ DX_DVIPS = @DX_DVIPS@ DX_EGREP = @DX_EGREP@ DX_ENV = @DX_ENV@ DX_FLAG_chi = @DX_FLAG_chi@ DX_FLAG_chm = @DX_FLAG_chm@ DX_FLAG_doc = @DX_FLAG_doc@ DX_FLAG_dot = @DX_FLAG_dot@ DX_FLAG_html = @DX_FLAG_html@ DX_FLAG_man = @DX_FLAG_man@ DX_FLAG_pdf = @DX_FLAG_pdf@ DX_FLAG_ps = @DX_FLAG_ps@ DX_FLAG_rtf = @DX_FLAG_rtf@ DX_FLAG_verbose = @DX_FLAG_verbose@ DX_FLAG_xml = @DX_FLAG_xml@ DX_HHC = @DX_HHC@ DX_LATEX = @DX_LATEX@ DX_MAKEINDEX = @DX_MAKEINDEX@ DX_PDFLATEX = @DX_PDFLATEX@ DX_PERL = @DX_PERL@ DX_PROJECT = @DX_PROJECT@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCJ_OPTS = @GCJ_OPTS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_CC = @JAVA_CC@ JAVA_CC_FLAGS = @JAVA_CC_FLAGS@ JAVA_CC_OPTS = @JAVA_CC_OPTS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAVEN = @MAVEN@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OLA_CLIENT_LIBS = @OLA_CLIENT_LIBS@ OLA_MAJOR_VERSION = @OLA_MAJOR_VERSION@ OLA_MINOR_VERSION = @OLA_MINOR_VERSION@ OLA_PROTOC = @OLA_PROTOC@ OLA_REVISION_VERSION = @OLA_REVISION_VERSION@ OLA_SERVER_LIBS = @OLA_SERVER_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ 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_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PLUGIN_LIBS = @PLUGIN_LIBS@ PROTOC = @PROTOC@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_CXX = @PTHREAD_CXX@ PTHREAD_CXXFLAGS = @PTHREAD_CXXFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RESOLV_LIBS = @RESOLV_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_aux_dir = @ac_aux_dir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ avahi_CFLAGS = @avahi_CFLAGS@ avahi_LIBS = @avahi_LIBS@ base_uuid_CFLAGS = @base_uuid_CFLAGS@ base_uuid_LIBS = @base_uuid_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libSaleaeDevice_LIBS = @libSaleaeDevice_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ libftdi_CFLAGS = @libftdi_CFLAGS@ libftdi_LIBS = @libftdi_LIBS@ liblo_CFLAGS = @liblo_CFLAGS@ liblo_LIBS = @liblo_LIBS@ libmicrohttpd_CFLAGS = @libmicrohttpd_CFLAGS@ libmicrohttpd_LIBS = @libmicrohttpd_LIBS@ libprotobuf2_CFLAGS = @libprotobuf2_CFLAGS@ libprotobuf2_LIBS = @libprotobuf2_LIBS@ libprotobuf_CFLAGS = @libprotobuf_CFLAGS@ libprotobuf_LIBS = @libprotobuf_LIBS@ libusb_CFLAGS = @libusb_CFLAGS@ libusb_LIBS = @libusb_LIBS@ libusb_error_name_CFLAGS = @libusb_error_name_CFLAGS@ libusb_error_name_LIBS = @libusb_error_name_LIBS@ libusb_hotplug_api_CFLAGS = @libusb_hotplug_api_CFLAGS@ libusb_hotplug_api_LIBS = @libusb_hotplug_api_LIBS@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ ola_major_version = @ola_major_version@ ola_minor_version = @ola_minor_version@ ola_revision_version = @ola_revision_version@ oldincludedir = @oldincludedir@ ossp_uuid_CFLAGS = @ossp_uuid_CFLAGS@ ossp_uuid_LIBS = @ossp_uuid_LIBS@ pdfdir = @pdfdir@ piddatadir = @piddatadir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ 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@ uuid_CFLAGS = @uuid_CFLAGS@ uuid_LIBS = @uuid_LIBS@ www_datadir = @www_datadir@ # This is a non-recursive Makefile, see # https://github.com/OpenLightingProject/ola/issues/397 for links to useful # documentation. # # Rather than defining everything in a single Makefile we include a Makefile.mk # from each directory. This gives the build rules a bit more structure. auxdir = @ac_aux_dir@ AUX_DIST = $(auxdir)/install-sh $(auxdir)/missing \ $(auxdir)/mkinstalldirs ACLOCAL_AMFLAGS = -I config @DX_COND_doc_TRUE@@DX_COND_html_TRUE@DX_CLEAN_HTML = @DX_DOCDIR@/html @DX_COND_chm_TRUE@@DX_COND_doc_TRUE@DX_CLEAN_CHM = @DX_DOCDIR@/chm @DX_COND_chi_TRUE@@DX_COND_chm_TRUE@@DX_COND_doc_TRUE@DX_CLEAN_CHI = @DX_DOCDIR@/@PACKAGE@.chi @DX_COND_doc_TRUE@@DX_COND_man_TRUE@DX_CLEAN_MAN = @DX_DOCDIR@/man @DX_COND_doc_TRUE@@DX_COND_rtf_TRUE@DX_CLEAN_RTF = @DX_DOCDIR@/rtf @DX_COND_doc_TRUE@@DX_COND_xml_TRUE@DX_CLEAN_XML = @DX_DOCDIR@/xml @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@DX_CLEAN_PS = @DX_DOCDIR@/@PACKAGE@.ps @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@DX_PS_GOAL = doxygen-ps @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@DX_CLEAN_PDF = @DX_DOCDIR@/@PACKAGE@.pdf @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@DX_PDF_GOAL = doxygen-pdf @DX_COND_doc_TRUE@@DX_COND_latex_TRUE@DX_CLEAN_LATEX = @DX_DOCDIR@/latex @DX_COND_doc_TRUE@DX_CLEANFILES = \ @DX_COND_doc_TRUE@ @DX_DOCDIR@/@PACKAGE@.tag \ @DX_COND_doc_TRUE@ -r \ @DX_COND_doc_TRUE@ $(DX_CLEAN_HTML) \ @DX_COND_doc_TRUE@ $(DX_CLEAN_CHM) \ @DX_COND_doc_TRUE@ $(DX_CLEAN_CHI) \ @DX_COND_doc_TRUE@ $(DX_CLEAN_MAN) \ @DX_COND_doc_TRUE@ $(DX_CLEAN_RTF) \ @DX_COND_doc_TRUE@ $(DX_CLEAN_XML) \ @DX_COND_doc_TRUE@ $(DX_CLEAN_PS) \ @DX_COND_doc_TRUE@ $(DX_CLEAN_PDF) \ @DX_COND_doc_TRUE@ $(DX_CLEAN_LATEX) # When running distcheck we want to enable the Python modules. AM_DISTCHECK_CONFIGURE_FLAGS = --enable-python-libs # C++ FLAGS variables # ------------------------------------------------------------------------------ # COMMON_CXXFLAGS # The common C++ flags. This may include -Werror if fatal-warning was enabled # in ./configure. AM_CXXFLAGS defaults to this, and it should be preferred. # # COMMON_PROTOBUF_CXXFLAGS # The common C++ flags with some warnings protobuf code throws disabled. Use # this for generated protobuf code that does not build correctly with # COMMON_CXXFLAGS. # # COMMON_CXXFLAGS_ONLY_WARNINGS # The common C++ flags with (non-fatal) warnings enabled. Use this for 3rd # party code that does not build correctly with COMMON_CXXFLAGS. # # COMMON_TESTING_FLAGS # The common C++ flags for testing. # # COMMON_TESTING_FLAGS_ONLY_WARNINGS # The common C++ flags for testing with (non-fatal) warnings enabled. Use this # for 3rd party code that does not build correctly with COMMON_TESTING_FLAGS. # # COMMON_TESTING_PROTOBUF_FLAGS # The common C++ flags for testing with some warnings protobuf code throws # disabled. COMMON_CXXFLAGS_ONLY_WARNINGS = \ -I$(top_srcdir)/include \ -I$(top_builddir)/include \ -Wall -Wformat -W -fvisibility-inlines-hidden \ $(libprotobuf_CFLAGS) COMMON_CXXFLAGS = $(COMMON_CXXFLAGS_ONLY_WARNINGS) $(am__append_1) COMMON_PROTOBUF_CXXFLAGS = $(COMMON_CXXFLAGS) $(am__append_2) COMMON_TESTING_FLAGS_ONLY_WARNINGS = $(COMMON_CXXFLAGS_ONLY_WARNINGS) \ $(CPPUNIT_CFLAGS) \ -DTEST_SRC_DIR=\"$(srcdir)\" \ -DTEST_BUILD_DIR=\"$(builddir)\" COMMON_TESTING_FLAGS = $(COMMON_TESTING_FLAGS_ONLY_WARNINGS) \ $(am__append_3) COMMON_TESTING_PROTOBUF_FLAGS = $(COMMON_TESTING_FLAGS) \ $(am__append_4) # AM_CXXFLAGS is used when target_CXXFLAGS isn't specified. AM_CXXFLAGS = $(COMMON_CXXFLAGS) # LIBS variables # ------------------------------------------------------------------------------ # # COMMON_TESTING_LIBS # The set of libraries used in the unittests. COMMON_TESTING_LIBS = $(CPPUNIT_LIBS) common/testing/libolatesting.la \ common/testing/libtestmain.la common/libolacommon.la \ $(am__append_5) # Setup pkgconfigdir, the path where .pc files are installed. pkgconfigdir = $(libdir)/pkgconfig oladincludedir = $(includedir)/olad # Define a custom runner for .py tests TESTS_ENVIRONMENT = PYTHONPATH=${top_srcdir}/python TEST_EXTENSIONS = .py PY_LOG_COMPILER = $(PYTHON) # Variables used by the included Makefile.mk(s) # ------------------------------------------------------------------------------ # Common automake variables. CLEANFILES = data/rdm/PidDataTest.sh $(am__append_29) \ olad/ola-output.conf python/examples/*.pyc \ python/ola/rpc/SimpleRpcControllerTest.sh python/ola/rpc/*.pyc \ python/ola/*.pyc tools/ola_trigger/FileValidateTest.sh \ tools/rdm/*.pyc $(built_sources) # The includes # ----------------------------------------------------------------------------- # Since `make install` relinks the libraries, this should be in the order in # which libraries depend on each other. e.g. common, plugin_api, plugins, server. # olad/plugin_api/Makefile.mk is included directly due to the order of # dependencies between them; we need to build olad/plugin_api, then the # plugins, then olad # ----------------------------------------------------------------------------- # Now some post-processing BUILT_SOURCES = $(built_sources) # TESTS_DATA ################################################## # Debian build files # The ArtNet plugin config messages. This needs to be available to client # programs. EXTRA_DIST = common/protocol/Ola.proto common/rdm/Pids.proto \ common/rdm/testdata/duplicate_manufacturer.proto \ common/rdm/testdata/duplicate_pid_name.proto \ common/rdm/testdata/duplicate_pid_value.proto \ common/rdm/testdata/inconsistent_pid.proto \ common/rdm/testdata/invalid_esta_pid.proto \ common/rdm/testdata/pids/overrides.proto \ common/rdm/testdata/pids/pids1.proto \ common/rdm/testdata/pids/pids2.proto \ common/rdm/testdata/test_pids.proto common/rpc/Rpc.proto \ common/rpc/TestService.proto debian/changelog debian/compat \ debian/control debian/copyright debian/libola-dev.dirs \ debian/libola-dev.install debian/libola1.install \ debian/ola-python.dirs debian/ola-python.install \ debian/ola-rdm-tests.bash-completion \ debian/ola-rdm-tests.config debian/ola-rdm-tests.dirs \ debian/ola-rdm-tests.install debian/ola-rdm-tests.postinst \ debian/ola-rdm-tests.rdm_test_server.init \ debian/ola-rdm-tests.templates debian/ola.bash-completion \ debian/ola.config debian/ola.dirs debian/ola.docs \ debian/ola.install debian/ola.olad.init debian/ola.postinst \ debian/ola.templates debian/ola.udev debian/rules \ debian/source/format debian/source/lintian-overrides \ debian/source/local-options doxygen/copy-doc.sh \ doxygen/cpp-client.dox doxygen/dmx-cpp-client.dox \ doxygen/event-driven.dox doxygen/http.dox doxygen/json.dox \ doxygen/namespaces.dox doxygen/olad.dox doxygen/OLALayout.xml \ doxygen/OLA.png doxygen/overview.dox doxygen/rdm.dox \ doxygen/rpc.dox doxygen/rpc-message.png doxygen/rpc.png \ $(am__append_27) javascript/README javascript/new-src/.jscsrc \ javascript/new-src/.jshintrc javascript/new-src/Gruntfile.js \ javascript/new-src/README.md javascript/new-src/bower.json \ javascript/new-src/package.json \ javascript/new-src/css/style.css \ javascript/new-src/src/controllers/menu.js \ javascript/new-src/src/controllers/patch_universe.js \ javascript/new-src/src/controllers/rdm_universe.js \ javascript/new-src/src/controllers/universe.js \ javascript/new-src/src/controllers/fader_universe.js \ javascript/new-src/src/controllers/keypad_universe.js \ javascript/new-src/src/controllers/plugins.js \ javascript/new-src/src/controllers/add_universe.js \ javascript/new-src/src/controllers/plugin_info.js \ javascript/new-src/src/controllers/setting_universe.js \ javascript/new-src/src/controllers/header.js \ javascript/new-src/src/controllers/overview.js \ javascript/new-src/src/constants.js \ javascript/new-src/src/factories/ola.js \ javascript/new-src/src/app.js \ javascript/new-src/src/filters/start_form.js \ javascript/ola/base_frame.js \ javascript/ola/common/dmx_constants.js \ javascript/ola/common/dmx_monitor.js \ javascript/ola/common/keypad_controller.js \ javascript/ola/common/keypad_parser.js \ javascript/ola/common/plugin_list.js \ javascript/ola/common/rdm_section_list.js \ javascript/ola/common/section_render.js \ javascript/ola/common/server.js \ javascript/ola/common/server_stats.js \ javascript/ola/common/sorted_list.js \ javascript/ola/common/uid_list.js javascript/ola/dialog.js \ javascript/ola/full/available_port_table.js \ javascript/ola/full/base_universe_tab.js \ javascript/ola/full/custom_dragger.js \ javascript/ola/full/custom_dragscrollsupport.js \ javascript/ola/full/dmx_console.js \ javascript/ola/full/dmx_console_tab.js \ javascript/ola/full/dmx_monitor_tab.js \ javascript/ola/full/plugin_frame.js \ javascript/ola/full/rdm_attributes_panel.js \ javascript/ola/full/rdm_patcher.js \ javascript/ola/full/rdm_patcher_tab.js \ javascript/ola/full/rdm_tab.js \ javascript/ola/full/universe_frame.js \ javascript/ola/full/universe_settings_tab.js \ javascript/ola/home_frame.js javascript/ola/logger.js \ javascript/ola/mobile.js \ javascript/ola/mobile/controller_tab.js \ javascript/ola/mobile/monitor_tab.js \ javascript/ola/mobile/plugin_tab.js \ javascript/ola/mobile/universe_tab.js \ javascript/ola/new_universe_frame.js javascript/ola/ola.js \ javascript/ola/port_table.js \ javascript/ola/universe_control.js \ javascript/ola/universe_item.js \ plugins/artnet/messages/ArtNetConfigMessages.proto \ plugins/karate/README.protocol plugins/osc/README \ plugins/usbdmx/README.md $(am__append_69) \ tools/logic/README.md tools/ola_trigger/config.lex \ tools/ola_trigger/config.ypp $(launcher_files) \ $(am__append_99) CONTRIBUTING Doxyfile GPL LGPL LICENCE \ README.debian README.developer README.mingw32 README.rpm \ config/ac_prog_java_cc.m4 config/ac_python_devel.m4 \ config/ac_saleae.m4 config/ax_python_module.m4 config/maven.m4 \ config/ola.m4 config/ola_version.m4 config/pkg.m4 \ config/resolv.m4 config/stl_hash.m4 mac_build.sh ola.spec # pkg-config ################################################## pkgconfig_DATA = $(am__append_31) \ plugins/artnet/messages/libolaartnetconf.pc $(am__append_70) \ $(am__append_92) libola.pc libolaserver.pc noinst_DATA = dist_noinst_DATA = common/web/testdata/allof.test \ common/web/testdata/anyof.test common/web/testdata/arrays.test \ common/web/testdata/basic-keywords.test \ common/web/testdata/definitions.test \ common/web/testdata/integers.test \ common/web/testdata/misc.test common/web/testdata/not.test \ common/web/testdata/objects.test \ common/web/testdata/oneof.test common/web/testdata/schema.json \ common/web/testdata/strings.test common/web/testdata/type.test \ olad/testdata/test_preferences.conf \ tools/ola_trigger/contrib/mac_itunes.conf \ tools/ola_trigger/contrib/mac_volume.conf \ tools/ola_trigger/contrib/philips_hue_osram_lightify.conf \ tools/ola_trigger/example.conf \ tools/ola_trigger/test_file.conf tools/ola_mon/index.html \ tools/ola_mon/ola_mon.conf tools/ola_mon/ola_mon.py # LIBRARIES ################################################## # LIBRARIES ################################################## # lib olaserverplugininterface # lib olaserver # LIBRARIES ################################################## lib_LTLIBRARIES = common/libolacommon.la $(am__append_32) \ ola/libola.la olad/plugin_api/libolaserverplugininterface.la \ $(am__append_36) $(am__append_41) $(am__append_43) \ $(am__append_45) $(am__append_46) $(am__append_47) \ $(am__append_49) $(am__append_51) $(am__append_52) \ $(am__append_54) $(am__append_57) $(am__append_59) \ $(am__append_60) $(am__append_61) $(am__append_62) \ $(am__append_64) $(am__append_66) $(am__append_68) \ $(am__append_71) $(am__append_74) $(am__append_76) \ $(am__append_77) $(am__append_79) olad/libolaserver.la \ tools/ola_trigger/libolatrigger.la $(am__append_93) # LIBRARIES ################################################## # We build the .cc files as a separate unit because they aren't warning-clean. # LIBRARIES ################################################ # libolae131core.la # This needs to be after libolaacn.la since it depends on it. Otherwise it # breaks the freeBSD build noinst_LTLIBRARIES = $(am__append_7) common/protocol/libolaproto.la \ $(am__append_14) common/web/libolaweb.la $(am__append_19) \ $(am__append_33) libs/acn/libolae131core.la $(am__append_34) \ $(am__append_38) $(am__append_48) $(am__append_53) \ $(am__append_56) $(am__append_67) $(am__append_73) \ $(am__append_94) check_SCRIPTS = # TESTS ################################################## dist_check_SCRIPTS = python/ola/rpc/SimpleRpcControllerTest.py \ python/ola/DUBDecoderTest.py python/ola/MACAddressTest.py \ python/ola/UIDTest.py # SCRIPTS ################################################ # example python scripts dist_noinst_SCRIPTS = data/rdm/download.sh data/rdm/PidDataTest.py \ include/ola/rdm/make_rdm_codes.sh \ include/ola/timecode/make_timecode.sh \ include/ola/gen_callbacks.py include/ola/make_plugin_id.sh \ python/examples/ola_artnet_params.py \ python/examples/ola_candidate_ports.py \ python/examples/ola_devices.py \ python/examples/ola_patch_unpatch.py \ python/examples/ola_plugin_info.py \ python/examples/ola_rdm_discover.py \ python/examples/ola_rdm_get.py python/examples/ola_recv_dmx.py \ python/examples/ola_send_dmx.py \ python/examples/ola_simple_fade.py \ python/examples/ola_universe_info.py \ python/examples/rdm_compare.py python/examples/rdm_snapshot.py \ $(am__append_97) dist_man_MANS = man/logic_rdm_sniffer.1 man/ola_artnet.1 \ man/ola_dev_info.1 man/ola_dmxconsole.1 man/ola_dmxmonitor.1 \ man/ola_e131.1 man/ola_patch.1 man/ola_plugin_info.1 \ man/ola_plugin_state.1 man/ola_rdm_discover.1 \ man/ola_rdm_get.1 man/ola_rdm_set.1 man/ola_recorder.1 \ man/ola_set_dmx.1 man/ola_set_priority.1 \ man/ola_streaming_client.1 man/ola_timecode.1 \ man/ola_trigger.1 man/ola_uni_info.1 man/ola_uni_merge.1 \ man/ola_uni_name.1 man/ola_uni_stats.1 man/ola_usbpro.1 \ man/olad.1 man/rdm_model_collector.py.1 \ man/rdm_responder_test.py.1 man/rdm_test_server.py.1 \ man/rdmpro_sniffer.1 man/usbpro_firmware.1 pkginclude_HEADERS = include/ola/ActionQueue.h include/ola/BaseTypes.h \ include/ola/Callback.h include/ola/CallbackRunner.h \ include/ola/Clock.h include/ola/Constants.h \ include/ola/DmxBuffer.h include/ola/ExportMap.h \ include/ola/Logging.h include/ola/MultiCallback.h \ include/ola/StringUtils.h ola/AutoStart.h \ ola/OlaClientWrapper.h $(DEPRECATED) # These aren't installed # HEADERS ################################################## noinst_HEADERS = include/ola/testing/MockUDPSocket.h \ include/ola/testing/TestUtils.h olad/plugin_api/TestCommon.h nodist_pkginclude_HEADERS = include/ola/plugin_id.h # Append to this to define an install-exec-hook. INSTALL_EXEC_HOOKS = $(am__append_26) # Test programs, these are added to check_PROGRAMS and TESTS if BUILD_TESTS is # true. # TESTS ################################################## # TESTS ################################################## # TESTS ################################################## # TESTS ################################################## # TESTS ################################################## # TESTS ################################################## # TESTS ################################################## # TESTS ################################################## # TESTS ################################################## # TESTS ################################################ # TESTS ################################################## # TESTS ################################################## # TESTS ################################################ # TESTS ################################################ # Patch test names are abbreviated to prevent Windows' UAC from blocking them. # TESTS ################################################## # TESTS ################################################## # TESTS ################################################## # TESTS ################################################## # TESTS ################################################## test_programs = common/base/CredentialsTester common/base/FlagsTester \ common/base/LoggingTester common/dmx/RunLengthEncoderTester \ common/export_map/ExportMapTester common/file/UtilTester \ common/io/DescriptorTester common/io/IOQueueTester \ common/io/IOStackTester common/io/MemoryBlockTester \ common/io/SelectServerTester common/io/StreamTester \ common/io/TimeoutManagerTester \ common/messaging/DescriptorTester \ common/network/HealthCheckedConnectionTester \ common/network/NetworkTester common/network/TCPConnectorTester \ common/rdm/DiscoveryAgentTester common/rdm/PidStoreTester \ common/rdm/QueueingRDMControllerTester common/rdm/RDMAPITester \ common/rdm/RDMCommandSerializerTester \ common/rdm/RDMCommandTester common/rdm/RDMFrameTester \ common/rdm/RDMHelperTester common/rdm/RDMMessageTester \ common/rdm/RDMReplyTester common/rdm/UIDAllocatorTester \ common/rdm/UIDTester common/rpc/RpcTester \ common/rpc/RpcServerTester common/strings/UtilsTester \ common/thread/ExecutorThreadTester common/thread/ThreadTester \ common/thread/FutureTester common/timecode/TimeCodeTester \ common/utils/UtilsTester common/web/JsonTester \ common/web/ParserTester common/web/PtchParserTester \ common/web/PtchTester common/web/PointerTester \ common/web/PointerTrackerTester common/web/SchemaParserTester \ common/web/SchemaTester common/web/SectionsTester \ $(am__append_15) libs/acn/E131Tester libs/acn/E133Tester \ libs/acn/TransportTester $(am__append_35) ola/OlaClientTester \ olad/plugin_api/ClientTester olad/plugin_api/DeviceTester \ olad/plugin_api/DmxSourceTester olad/plugin_api/PortTester \ olad/plugin_api/PreferencesTester \ olad/plugin_api/UniverseTester $(am__append_40) \ $(am__append_42) $(am__append_44) $(am__append_50) \ $(am__append_55) $(am__append_58) $(am__append_63) \ $(am__append_65) $(am__append_75) olad/OlaTester \ tools/ola_trigger/ActionTester # Files in built_sources are included in BUILT_SOURCES and CLEANFILES # The .h files are included elsewhere so we have to put them in BUILT_SOURCES # BUILT_SOURCES is our only option here since we can't override the generated # automake rules for common/libolacommon.la # BUILT_SOURCES is our only option here since we can't override the generated # automake rules for common/libolacommon.la # BUILT_SOURCES is our only option here since we can't override the generated # automake rules for common/libolacommon.la built_sources = common/protocol/Ola.pb.cc common/protocol/Ola.pb.h \ common/protocol/OlaService.pb.h \ common/protocol/OlaService.pb.cpp common/rdm/Pids.pb.cc \ common/rdm/Pids.pb.h common/rpc/Rpc.pb.cc common/rpc/Rpc.pb.h \ common/rpc/TestService.pb.cc common/rpc/TestService.pb.h \ common/rpc/TestServiceService.pb.cpp \ common/rpc/TestServiceService.pb.h \ include/ola/rdm/RDMResponseCodes.h \ include/ola/timecode/TimeCodeEnums.h include/ola/plugin_id.h \ $(am__append_37) $(am__append_72) $(am__append_78) \ $(am__append_87) tools/ola_trigger/lex.yy.cpp \ tools/ola_trigger/config.tab.cpp \ tools/ola_trigger/config.tab.h $(am__append_91) # Test scripts are run if BUILD_TESTS is true. test_scripts = $(am__append_16) $(am__append_28) $(am__append_88) \ tools/ola_trigger/FileValidateTest.sh # Variables the included files can append to # ------------------------------------------ common_libolacommon_la_CXXFLAGS = $(COMMON_PROTOBUF_CXXFLAGS) \ -DPID_DATA_DIR=\"${piddatadir}\" common_libolacommon_la_LIBADD = $(am__append_6) $(RESOLV_LIBS) \ common/protocol/libolaproto.la $(libprotobuf_LIBS) \ $(libprotobuf_LIBS) # LIBRARIES ################################################## # LIBRARIES ################################################## # LIBRARIES ################################################## # LIBRARIES ################################################## # LIBRARIES ################################################## # LIBRARIES ################################################## # LIBRARIES ################################################## # LIBRARIES ################################################## # LIBRARIES ################################################## # LIBRARIES ################################################## # LIBRARIES ################################################## # LIBRARIES ################################################## # LIBRARIES ################################################## # LIBRARIES ################################################## # LIBRARIES ################################################ common_libolacommon_la_SOURCES = common/base/Credentials.cpp \ common/base/Env.cpp common/base/Flags.cpp common/base/Init.cpp \ common/base/Logging.cpp common/base/SysExits.cpp \ common/base/Version.cpp common/dmx/RunLengthEncoder.cpp \ common/export_map/ExportMap.cpp common/file/Util.cpp \ common/io/Descriptor.cpp common/io/ExtendedSerial.cpp \ common/io/EPoller.h common/io/IOQueue.cpp \ common/io/IOStack.cpp common/io/IOUtils.cpp \ common/io/NonBlockingSender.cpp common/io/PollerInterface.cpp \ common/io/PollerInterface.h common/io/SelectServer.cpp \ common/io/Serial.cpp common/io/StdinHandler.cpp \ common/io/TimeoutManager.cpp common/io/TimeoutManager.h \ $(am__append_8) $(am__append_9) $(am__append_10) \ $(am__append_11) common/math/Random.cpp \ common/messaging/Descriptor.cpp common/messaging/Message.cpp \ common/messaging/MessagePrinter.cpp \ common/messaging/SchemaPrinter.cpp \ common/network/AdvancedTCPConnector.cpp \ common/network/FakeInterfacePicker.h \ common/network/HealthCheckedConnection.cpp \ common/network/IPV4Address.cpp common/network/Interface.cpp \ common/network/InterfacePicker.cpp \ common/network/MACAddress.cpp common/network/NetworkUtils.cpp \ common/network/NetworkUtilsInternal.h \ common/network/Socket.cpp common/network/SocketAddress.cpp \ common/network/SocketCloser.cpp \ common/network/SocketHelper.cpp common/network/SocketHelper.h \ common/network/TCPConnector.cpp common/network/TCPSocket.cpp \ $(am__append_12) $(am__append_13) \ common/rdm/AckTimerResponder.cpp \ common/rdm/AdvancedDimmerResponder.cpp \ common/rdm/CommandPrinter.cpp \ common/rdm/DescriptorConsistencyChecker.cpp \ common/rdm/DescriptorConsistencyChecker.h \ common/rdm/DimmerResponder.cpp common/rdm/DimmerRootDevice.cpp \ common/rdm/DimmerSubDevice.cpp common/rdm/DiscoveryAgent.cpp \ common/rdm/DiscoveryAgentTestHelper.h \ common/rdm/DummyResponder.cpp \ common/rdm/FakeNetworkManager.cpp \ common/rdm/FakeNetworkManager.h \ common/rdm/GroupSizeCalculator.cpp \ common/rdm/GroupSizeCalculator.h \ common/rdm/MessageDeserializer.cpp \ common/rdm/MessageSerializer.cpp \ common/rdm/MovingLightResponder.cpp \ common/rdm/NetworkManager.cpp common/rdm/NetworkManager.h \ common/rdm/NetworkResponder.cpp \ common/rdm/OpenLightingEnums.cpp common/rdm/PidStore.cpp \ common/rdm/PidStoreHelper.cpp common/rdm/PidStoreLoader.cpp \ common/rdm/PidStoreLoader.h \ common/rdm/QueueingRDMController.cpp common/rdm/RDMAPI.cpp \ common/rdm/RDMCommand.cpp common/rdm/RDMCommandSerializer.cpp \ common/rdm/RDMFrame.cpp common/rdm/RDMHelper.cpp \ common/rdm/RDMReply.cpp common/rdm/ResponderHelper.cpp \ common/rdm/ResponderLoadSensor.cpp \ common/rdm/ResponderPersonality.cpp \ common/rdm/ResponderSettings.cpp \ common/rdm/ResponderSlotData.cpp \ common/rdm/SensorResponder.cpp \ common/rdm/StringMessageBuilder.cpp \ common/rdm/SubDeviceDispatcher.cpp common/rdm/UID.cpp \ common/rdm/VariableFieldSizeCalculator.cpp \ common/rdm/VariableFieldSizeCalculator.h \ common/rpc/RpcChannel.cpp common/rpc/RpcChannel.h \ common/rpc/RpcSession.h common/rpc/RpcController.cpp \ common/rpc/RpcController.h common/rpc/RpcHeader.h \ common/rpc/RpcPeer.h common/rpc/RpcServer.cpp \ common/rpc/RpcServer.h common/rpc/RpcService.h \ common/strings/Format.cpp common/strings/Utils.cpp \ common/system/Limits.cpp common/system/SystemUtils.cpp \ common/thread/ConsumerThread.cpp \ common/thread/ExecutorThread.cpp common/thread/Mutex.cpp \ common/thread/PeriodicThread.cpp \ common/thread/SignalThread.cpp common/thread/Thread.cpp \ common/thread/ThreadPool.cpp common/thread/Utils.cpp \ common/timecode/TimeCode.cpp common/utils/ActionQueue.cpp \ common/utils/Clock.cpp common/utils/DmxBuffer.cpp \ common/utils/StringUtils.cpp common/utils/TokenBucket.cpp \ common/utils/Watchdog.cpp nodist_common_libolacommon_la_SOURCES = common/rdm/Pids.pb.cc \ common/rpc/Rpc.pb.cc common_base_CredentialsTester_SOURCES = common/base/CredentialsTest.cpp common_base_CredentialsTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_base_CredentialsTester_LDADD = $(COMMON_TESTING_LIBS) common_base_FlagsTester_SOURCES = common/base/FlagsTest.cpp common_base_FlagsTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_base_FlagsTester_LDADD = $(COMMON_TESTING_LIBS) common_base_LoggingTester_SOURCES = common/base/LoggingTest.cpp common_base_LoggingTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_base_LoggingTester_LDADD = $(COMMON_TESTING_LIBS) common_dmx_RunLengthEncoderTester_SOURCES = common/dmx/RunLengthEncoderTest.cpp common_dmx_RunLengthEncoderTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_dmx_RunLengthEncoderTester_LDADD = $(COMMON_TESTING_LIBS) common_export_map_ExportMapTester_SOURCES = common/export_map/ExportMapTest.cpp common_export_map_ExportMapTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_export_map_ExportMapTester_LDADD = $(COMMON_TESTING_LIBS) common_file_UtilTester_SOURCES = common/file/UtilTest.cpp common_file_UtilTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_file_UtilTester_LDADD = $(COMMON_TESTING_LIBS) @HAVE_LIBMICROHTTPD_TRUE@common_http_libolahttp_la_SOURCES = \ @HAVE_LIBMICROHTTPD_TRUE@ common/http/HTTPServer.cpp \ @HAVE_LIBMICROHTTPD_TRUE@ common/http/OlaHTTPServer.cpp @HAVE_LIBMICROHTTPD_TRUE@common_http_libolahttp_la_LIBADD = $(libmicrohttpd_LIBS) common_io_IOQueueTester_SOURCES = common/io/IOQueueTest.cpp common_io_IOQueueTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_io_IOQueueTester_LDADD = $(COMMON_TESTING_LIBS) common_io_IOStackTester_SOURCES = common/io/IOStackTest.cpp common_io_IOStackTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_io_IOStackTester_LDADD = $(COMMON_TESTING_LIBS) common_io_DescriptorTester_SOURCES = common/io/DescriptorTest.cpp common_io_DescriptorTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_io_DescriptorTester_LDADD = $(COMMON_TESTING_LIBS) common_io_MemoryBlockTester_SOURCES = common/io/MemoryBlockTest.cpp common_io_MemoryBlockTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_io_MemoryBlockTester_LDADD = $(COMMON_TESTING_LIBS) common_io_SelectServerTester_SOURCES = common/io/SelectServerTest.cpp \ common/io/SelectServerThreadTest.cpp common_io_SelectServerTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_io_SelectServerTester_LDADD = $(COMMON_TESTING_LIBS) common_io_TimeoutManagerTester_SOURCES = common/io/TimeoutManagerTest.cpp common_io_TimeoutManagerTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_io_TimeoutManagerTester_LDADD = $(COMMON_TESTING_LIBS) common_io_StreamTester_SOURCES = common/io/InputStreamTest.cpp \ common/io/OutputStreamTest.cpp common_io_StreamTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_io_StreamTester_LDADD = $(COMMON_TESTING_LIBS) common_messaging_DescriptorTester_SOURCES = \ common/messaging/DescriptorTest.cpp \ common/messaging/SchemaPrinterTest.cpp \ common/messaging/MessagePrinterTest.cpp common_messaging_DescriptorTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_messaging_DescriptorTester_LDADD = $(COMMON_TESTING_LIBS) common_network_HealthCheckedConnectionTester_SOURCES = \ common/network/HealthCheckedConnectionTest.cpp common_network_HealthCheckedConnectionTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_network_HealthCheckedConnectionTester_LDADD = $(COMMON_TESTING_LIBS) common_network_NetworkTester_SOURCES = \ common/network/IPV4AddressTest.cpp \ common/network/InterfacePickerTest.cpp \ common/network/InterfaceTest.cpp \ common/network/MACAddressTest.cpp \ common/network/NetworkUtilsTest.cpp \ common/network/SocketAddressTest.cpp \ common/network/SocketTest.cpp common_network_NetworkTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_network_NetworkTester_LDADD = $(COMMON_TESTING_LIBS) @USING_WIN32_TRUE@common_network_NetworkTester_LDFLAGS = -no-undefined -liphlpapi -lnetapi32 \ @USING_WIN32_TRUE@ -lcap -lws2_32 -ldpnet -lwsock32 common_network_TCPConnectorTester_SOURCES = \ common/network/AdvancedTCPConnectorTest.cpp \ common/network/TCPConnectorTest.cpp common_network_TCPConnectorTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_network_TCPConnectorTester_LDADD = $(COMMON_TESTING_LIBS) nodist_common_protocol_libolaproto_la_SOURCES = \ common/protocol/Ola.pb.cc \ common/protocol/OlaService.pb.cpp common_protocol_libolaproto_la_LIBADD = $(libprotobuf_LIBS) # required, otherwise we get build errors common_protocol_libolaproto_la_CXXFLAGS = $(COMMON_CXXFLAGS_ONLY_WARNINGS) common_rdm_DiscoveryAgentTester_SOURCES = common/rdm/DiscoveryAgentTest.cpp common_rdm_DiscoveryAgentTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_rdm_DiscoveryAgentTester_LDADD = $(COMMON_TESTING_LIBS) common_rdm_PidStoreTester_SOURCES = \ common/rdm/DescriptorConsistencyCheckerTest.cpp \ common/rdm/PidStoreTest.cpp common_rdm_PidStoreTester_CXXFLAGS = $(COMMON_TESTING_PROTOBUF_FLAGS) common_rdm_PidStoreTester_LDADD = $(COMMON_TESTING_LIBS) common_rdm_RDMHelperTester_SOURCES = common/rdm/RDMHelperTest.cpp common_rdm_RDMHelperTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_rdm_RDMHelperTester_LDADD = $(COMMON_TESTING_LIBS) common_rdm_RDMMessageTester_SOURCES = \ common/rdm/GroupSizeCalculatorTest.cpp \ common/rdm/MessageSerializerTest.cpp \ common/rdm/MessageDeserializerTest.cpp \ common/rdm/RDMMessageInterationTest.cpp \ common/rdm/StringMessageBuilderTest.cpp \ common/rdm/VariableFieldSizeCalculatorTest.cpp common_rdm_RDMMessageTester_CXXFLAGS = $(COMMON_TESTING_PROTOBUF_FLAGS) common_rdm_RDMMessageTester_LDADD = $(COMMON_TESTING_LIBS) common_rdm_RDMAPITester_SOURCES = \ common/rdm/RDMAPITest.cpp common_rdm_RDMAPITester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_rdm_RDMAPITester_LDADD = $(COMMON_TESTING_LIBS) common_rdm_RDMCommandTester_SOURCES = \ common/rdm/RDMCommandTest.cpp \ common/rdm/TestHelper.h common_rdm_RDMCommandTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_rdm_RDMCommandTester_LDADD = $(COMMON_TESTING_LIBS) common_rdm_RDMFrameTester_SOURCES = \ common/rdm/RDMFrameTest.cpp \ common/rdm/TestHelper.h common_rdm_RDMFrameTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_rdm_RDMFrameTester_LDADD = $(COMMON_TESTING_LIBS) common_rdm_RDMReplyTester_SOURCES = \ common/rdm/RDMReplyTest.cpp \ common/rdm/TestHelper.h common_rdm_RDMReplyTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_rdm_RDMReplyTester_LDADD = $(COMMON_TESTING_LIBS) common_rdm_RDMCommandSerializerTester_SOURCES = \ common/rdm/RDMCommandSerializerTest.cpp \ common/rdm/TestHelper.h common_rdm_RDMCommandSerializerTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_rdm_RDMCommandSerializerTester_LDADD = $(COMMON_TESTING_LIBS) common_rdm_QueueingRDMControllerTester_SOURCES = \ common/rdm/QueueingRDMControllerTest.cpp \ common/rdm/TestHelper.h common_rdm_QueueingRDMControllerTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_rdm_QueueingRDMControllerTester_LDADD = $(COMMON_TESTING_LIBS) common_rdm_UIDAllocatorTester_SOURCES = \ common/rdm/UIDAllocatorTest.cpp common_rdm_UIDAllocatorTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_rdm_UIDAllocatorTester_LDADD = $(COMMON_TESTING_LIBS) common_rdm_UIDTester_SOURCES = \ common/rdm/UIDTest.cpp common_rdm_UIDTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_rdm_UIDTester_LDADD = $(COMMON_TESTING_LIBS) common_rpc_TEST_SOURCES = \ common/rpc/TestService.h \ common/rpc/TestService.cpp common_rpc_RpcTester_SOURCES = \ common/rpc/RpcControllerTest.cpp \ common/rpc/RpcChannelTest.cpp \ common/rpc/RpcHeaderTest.cpp \ $(common_rpc_TEST_SOURCES) nodist_common_rpc_RpcTester_SOURCES = \ common/rpc/TestService.pb.cc \ common/rpc/TestServiceService.pb.cpp # required, otherwise we get build errors common_rpc_RpcTester_CXXFLAGS = $(COMMON_TESTING_FLAGS_ONLY_WARNINGS) common_rpc_RpcTester_LDADD = $(COMMON_TESTING_LIBS) \ $(libprotobuf_LIBS) common_rpc_RpcServerTester_SOURCES = \ common/rpc/RpcServerTest.cpp \ $(common_rpc_TEST_SOURCES) nodist_common_rpc_RpcServerTester_SOURCES = \ common/rpc/TestService.pb.cc \ common/rpc/TestServiceService.pb.cpp # required, otherwise we get build errors common_rpc_RpcServerTester_CXXFLAGS = $(COMMON_TESTING_FLAGS_ONLY_WARNINGS) common_rpc_RpcServerTester_LDADD = $(COMMON_TESTING_LIBS) \ $(libprotobuf_LIBS) common_strings_UtilsTester_SOURCES = \ common/strings/UtilsTest.cpp common_strings_UtilsTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_strings_UtilsTester_LDADD = $(COMMON_TESTING_LIBS) @BUILD_TESTS_TRUE@common_testing_libolatesting_la_SOURCES = \ @BUILD_TESTS_TRUE@ common/testing/MockUDPSocket.cpp \ @BUILD_TESTS_TRUE@ common/testing/TestUtils.cpp @BUILD_TESTS_TRUE@common_testing_libtestmain_la_SOURCES = common/testing/GenericTester.cpp common_thread_ThreadTester_SOURCES = \ common/thread/ThreadPoolTest.cpp \ common/thread/ThreadTest.cpp common_thread_ThreadTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_thread_ThreadTester_LDADD = $(COMMON_TESTING_LIBS) common_thread_FutureTester_SOURCES = common/thread/FutureTest.cpp common_thread_FutureTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_thread_FutureTester_LDADD = $(COMMON_TESTING_LIBS) common_thread_ExecutorThreadTester_SOURCES = \ common/thread/ExecutorThreadTest.cpp common_thread_ExecutorThreadTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_thread_ExecutorThreadTester_LDADD = $(COMMON_TESTING_LIBS) common_timecode_TimeCodeTester_SOURCES = common/timecode/TimeCodeTest.cpp common_timecode_TimeCodeTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_timecode_TimeCodeTester_LDADD = $(COMMON_TESTING_LIBS) common_utils_UtilsTester_SOURCES = \ common/utils/ActionQueueTest.cpp \ common/utils/BackoffTest.cpp \ common/utils/CallbackTest.cpp \ common/utils/ClockTest.cpp \ common/utils/DmxBufferTest.cpp \ common/utils/MultiCallbackTest.cpp \ common/utils/StringUtilsTest.cpp \ common/utils/TokenBucketTest.cpp \ common/utils/UtilsTest.cpp \ common/utils/WatchdogTest.cpp common_utils_UtilsTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_utils_UtilsTester_LDADD = $(COMMON_TESTING_LIBS) common_web_libolaweb_la_SOURCES = \ common/web/Json.cpp \ common/web/JsonData.cpp \ common/web/JsonLexer.cpp \ common/web/JsonParser.cpp \ common/web/JsonPatch.cpp \ common/web/JsonPatchParser.cpp \ common/web/JsonPointer.cpp \ common/web/JsonSchema.cpp \ common/web/JsonSections.cpp \ common/web/JsonTypes.cpp \ common/web/JsonWriter.cpp \ common/web/PointerTracker.cpp \ common/web/PointerTracker.h \ common/web/SchemaErrorLogger.cpp \ common/web/SchemaErrorLogger.h \ common/web/SchemaKeywords.cpp \ common/web/SchemaKeywords.h \ common/web/SchemaParseContext.cpp \ common/web/SchemaParseContext.h \ common/web/SchemaParser.cpp \ common/web/SchemaParser.h #Work around limitations with Windows library linking @USING_WIN32_TRUE@common_web_libolaweb_la_LIBADD = common/libolacommon.la COMMON_WEB_TEST_LDADD = $(COMMON_TESTING_LIBS) \ common/web/libolaweb.la common_web_JsonTester_SOURCES = common/web/JsonTest.cpp common_web_JsonTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_web_JsonTester_LDADD = $(COMMON_WEB_TEST_LDADD) common_web_ParserTester_SOURCES = common/web/ParserTest.cpp common_web_ParserTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_web_ParserTester_LDADD = $(COMMON_WEB_TEST_LDADD) common_web_PtchParserTester_SOURCES = common/web/PatchParserTest.cpp common_web_PtchParserTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_web_PtchParserTester_LDADD = $(COMMON_WEB_TEST_LDADD) common_web_PtchTester_SOURCES = common/web/PatchTest.cpp common_web_PtchTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_web_PtchTester_LDADD = $(COMMON_WEB_TEST_LDADD) common_web_PointerTester_SOURCES = common/web/PointerTest.cpp common_web_PointerTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_web_PointerTester_LDADD = $(COMMON_WEB_TEST_LDADD) common_web_PointerTrackerTester_SOURCES = common/web/PointerTrackerTest.cpp common_web_PointerTrackerTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_web_PointerTrackerTester_LDADD = $(COMMON_WEB_TEST_LDADD) common_web_SchemaParserTester_SOURCES = common/web/SchemaParserTest.cpp common_web_SchemaParserTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_web_SchemaParserTester_LDADD = $(COMMON_WEB_TEST_LDADD) common_web_SchemaTester_SOURCES = common/web/SchemaTest.cpp common_web_SchemaTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_web_SchemaTester_LDADD = $(COMMON_WEB_TEST_LDADD) common_web_SectionsTester_SOURCES = common/web/SectionsTest.cpp common_web_SectionsTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_web_SectionsTester_LDADD = $(COMMON_WEB_TEST_LDADD) # DATA ################################################ dist_piddata_DATA = \ data/rdm/draft_pids.proto \ data/rdm/pids.proto \ data/rdm/manufacturer_pids.proto data_rdm_PidDataTester_SOURCES = data/rdm/PidDataTest.cpp data_rdm_PidDataTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) -DDATADIR=\"$(srcdir)/data/rdm\" data_rdm_PidDataTester_LDADD = $(COMMON_TESTING_LIBS) # The following should match what pkg-config --libs libola returns DOXYGEN_EXAMPLES_LDADD = common/libolacommon.la \ ola/libola.la doxygen_examples_callback_client_transmit_SOURCES = \ doxygen/examples/callback_client_transmit.cpp doxygen_examples_callback_client_transmit_LDADD = $(DOXYGEN_EXAMPLES_LDADD) doxygen_examples_client_disconnect_SOURCES = \ doxygen/examples/client_disconnect.cpp doxygen_examples_client_disconnect_LDADD = $(DOXYGEN_EXAMPLES_LDADD) doxygen_examples_client_thread_SOURCES = \ doxygen/examples/client_thread.cpp doxygen_examples_client_thread_LDADD = $(DOXYGEN_EXAMPLES_LDADD) doxygen_examples_fetch_plugins_SOURCES = \ doxygen/examples/fetch_plugins.cpp doxygen_examples_fetch_plugins_LDADD = $(DOXYGEN_EXAMPLES_LDADD) doxygen_examples_legacy_callback_client_transmit_SOURCES = \ doxygen/examples/legacy_callback_client_transmit.cpp doxygen_examples_legacy_callback_client_transmit_LDADD = $(DOXYGEN_EXAMPLES_LDADD) doxygen_examples_flags_SOURCES = \ doxygen/examples/flags.cpp doxygen_examples_flags_LDADD = $(DOXYGEN_EXAMPLES_LDADD) doxygen_examples_streaming_client_SOURCES = \ doxygen/examples/streaming_client.cpp doxygen_examples_streaming_client_LDADD = $(DOXYGEN_EXAMPLES_LDADD) doxygen_examples_legacy_streaming_client_SOURCES = \ doxygen/examples/legacy_streaming_client.cpp doxygen_examples_legacy_streaming_client_LDADD = $(DOXYGEN_EXAMPLES_LDADD) doxygen_examples_streaming_client_plugin_SOURCES = \ doxygen/examples/streaming_client_plugin.cpp doxygen_examples_streaming_client_plugin_LDADD = $(DOXYGEN_EXAMPLES_LDADD) doxygen_examples_legacy_receiver_SOURCES = \ doxygen/examples/legacy_receiver.cpp doxygen_examples_legacy_receiver_LDADD = $(DOXYGEN_EXAMPLES_LDADD) doxygen_examples_receiver_SOURCES = \ doxygen/examples/receiver.cpp doxygen_examples_receiver_LDADD = $(DOXYGEN_EXAMPLES_LDADD) doxygen_examples_stdin_handler_SOURCES = \ doxygen/examples/stdin_handler.cpp doxygen_examples_stdin_handler_LDADD = $(DOXYGEN_EXAMPLES_LDADD) doxygen_examples_udp_server_SOURCES = \ doxygen/examples/udp_server.cpp doxygen_examples_udp_server_LDADD = $(DOXYGEN_EXAMPLES_LDADD) # The following should match what pkg-config --libs libola returns @BUILD_EXAMPLES_TRUE@EXAMPLE_COMMON_LIBS = common/libolacommon.la \ @BUILD_EXAMPLES_TRUE@ ola/libola.la @BUILD_EXAMPLES_TRUE@examples_libolaconfig_la_SOURCES = \ @BUILD_EXAMPLES_TRUE@ examples/OlaConfigurator.h \ @BUILD_EXAMPLES_TRUE@ examples/OlaConfigurator.cpp @BUILD_EXAMPLES_TRUE@examples_libolaconfig_la_CXXFLAGS = $(COMMON_PROTOBUF_CXXFLAGS) @BUILD_EXAMPLES_TRUE@@USE_E131_TRUE@examples_ola_e131_SOURCES = examples/ola-e131.cpp @BUILD_EXAMPLES_TRUE@@USE_E131_TRUE@examples_ola_e131_CXXFLAGS = $(COMMON_PROTOBUF_CXXFLAGS) @BUILD_EXAMPLES_TRUE@@USE_E131_TRUE@examples_ola_e131_LDADD = examples/libolaconfig.la \ @BUILD_EXAMPLES_TRUE@@USE_E131_TRUE@ $(EXAMPLE_COMMON_LIBS) \ @BUILD_EXAMPLES_TRUE@@USE_E131_TRUE@ plugins/e131/messages/libolae131conf.la \ @BUILD_EXAMPLES_TRUE@@USE_E131_TRUE@ $(libprotobuf_LIBS) @BUILD_EXAMPLES_TRUE@@USE_USBPRO_TRUE@examples_ola_usbpro_SOURCES = examples/ola-usbpro.cpp @BUILD_EXAMPLES_TRUE@@USE_USBPRO_TRUE@examples_ola_usbpro_CXXFLAGS = $(COMMON_PROTOBUF_CXXFLAGS) @BUILD_EXAMPLES_TRUE@@USE_USBPRO_TRUE@examples_ola_usbpro_LDADD = examples/libolaconfig.la \ @BUILD_EXAMPLES_TRUE@@USE_USBPRO_TRUE@ $(EXAMPLE_COMMON_LIBS) \ @BUILD_EXAMPLES_TRUE@@USE_USBPRO_TRUE@ plugins/usbpro/messages/libolausbproconf.la \ @BUILD_EXAMPLES_TRUE@@USE_USBPRO_TRUE@ $(libprotobuf_LIBS) @BUILD_EXAMPLES_TRUE@@USE_ARTNET_TRUE@examples_ola_artnet_SOURCES = examples/ola-artnet.cpp @BUILD_EXAMPLES_TRUE@@USE_ARTNET_TRUE@examples_ola_artnet_CXXFLAGS = $(COMMON_PROTOBUF_CXXFLAGS) @BUILD_EXAMPLES_TRUE@@USE_ARTNET_TRUE@examples_ola_artnet_LDADD = examples/libolaconfig.la \ @BUILD_EXAMPLES_TRUE@@USE_ARTNET_TRUE@ $(EXAMPLE_COMMON_LIBS) \ @BUILD_EXAMPLES_TRUE@@USE_ARTNET_TRUE@ plugins/artnet/messages/libolaartnetconf.la \ @BUILD_EXAMPLES_TRUE@@USE_ARTNET_TRUE@ $(libprotobuf_LIBS) @BUILD_EXAMPLES_TRUE@examples_ola_dev_info_SOURCES = examples/ola-client.cpp @BUILD_EXAMPLES_TRUE@examples_ola_dev_info_LDADD = $(EXAMPLE_COMMON_LIBS) @BUILD_EXAMPLES_TRUE@examples_ola_streaming_client_SOURCES = examples/ola-streaming-client.cpp @BUILD_EXAMPLES_TRUE@examples_ola_streaming_client_LDADD = $(EXAMPLE_COMMON_LIBS) @BUILD_EXAMPLES_TRUE@examples_ola_rdm_get_SOURCES = examples/ola-rdm.cpp @BUILD_EXAMPLES_TRUE@examples_ola_rdm_get_LDADD = $(EXAMPLE_COMMON_LIBS) @BUILD_EXAMPLES_TRUE@examples_ola_rdm_discover_SOURCES = examples/ola-rdm-discover.cpp @BUILD_EXAMPLES_TRUE@examples_ola_rdm_discover_LDADD = $(EXAMPLE_COMMON_LIBS) @BUILD_EXAMPLES_TRUE@examples_ola_recorder_SOURCES = \ @BUILD_EXAMPLES_TRUE@ examples/ola-recorder.cpp \ @BUILD_EXAMPLES_TRUE@ examples/ShowLoader.h \ @BUILD_EXAMPLES_TRUE@ examples/ShowLoader.cpp \ @BUILD_EXAMPLES_TRUE@ examples/ShowPlayer.h \ @BUILD_EXAMPLES_TRUE@ examples/ShowPlayer.cpp \ @BUILD_EXAMPLES_TRUE@ examples/ShowRecorder.h \ @BUILD_EXAMPLES_TRUE@ examples/ShowRecorder.cpp \ @BUILD_EXAMPLES_TRUE@ examples/ShowSaver.h \ @BUILD_EXAMPLES_TRUE@ examples/ShowSaver.cpp @BUILD_EXAMPLES_TRUE@examples_ola_recorder_LDADD = $(EXAMPLE_COMMON_LIBS) @BUILD_EXAMPLES_TRUE@examples_ola_timecode_SOURCES = examples/ola-timecode.cpp @BUILD_EXAMPLES_TRUE@examples_ola_timecode_LDADD = $(EXAMPLE_COMMON_LIBS) @BUILD_EXAMPLES_TRUE@examples_ola_uni_stats_SOURCES = examples/ola-uni-stats.cpp @BUILD_EXAMPLES_TRUE@examples_ola_uni_stats_LDADD = $(EXAMPLE_COMMON_LIBS) @BUILD_EXAMPLES_TRUE@@HAVE_NCURSES_TRUE@examples_ola_dmxconsole_SOURCES = examples/ola-dmxconsole.cpp @BUILD_EXAMPLES_TRUE@@HAVE_NCURSES_TRUE@examples_ola_dmxconsole_LDADD = $(EXAMPLE_COMMON_LIBS) -lncurses @BUILD_EXAMPLES_TRUE@@HAVE_NCURSES_TRUE@examples_ola_dmxmonitor_SOURCES = examples/ola-dmxmonitor.cpp @BUILD_EXAMPLES_TRUE@@HAVE_NCURSES_TRUE@examples_ola_dmxmonitor_LDADD = $(EXAMPLE_COMMON_LIBS) -lncurses @BUILD_EXAMPLES_TRUE@examples_ola_throughput_SOURCES = examples/ola-throughput.cpp @BUILD_EXAMPLES_TRUE@examples_ola_throughput_LDADD = $(EXAMPLE_COMMON_LIBS) @BUILD_EXAMPLES_TRUE@examples_ola_latency_SOURCES = examples/ola-latency.cpp @BUILD_EXAMPLES_TRUE@examples_ola_latency_LDADD = $(EXAMPLE_COMMON_LIBS) @BUILD_EXAMPLES_TRUE@@USING_WIN32_FALSE@OLA_PATCH_NAME = ola_patch # rename this program, otherwise UAC will block it @BUILD_EXAMPLES_TRUE@@USING_WIN32_TRUE@OLA_PATCH_NAME = ola_ptch olaacnincludedir = $(pkgincludedir)/acn/ olaacninclude_HEADERS = $(am__append_30) olabaseincludedir = $(pkgincludedir)/base/ olabaseinclude_HEADERS = \ include/ola/base/Array.h \ include/ola/base/Credentials.h \ include/ola/base/Env.h \ include/ola/base/Flags.h \ include/ola/base/FlagsPrivate.h \ include/ola/base/Init.h \ include/ola/base/Macro.h \ include/ola/base/SysExits.h nodist_olabaseinclude_HEADERS = \ include/ola/base/Version.h olaclientincludedir = $(pkgincludedir)/client/ olaclientinclude_HEADERS = \ include/ola/client/CallbackTypes.h \ include/ola/client/ClientArgs.h \ include/ola/client/ClientRDMAPIShim.h \ include/ola/client/ClientTypes.h \ include/ola/client/ClientWrapper.h \ include/ola/client/Module.h \ include/ola/client/OlaClient.h \ include/ola/client/Result.h \ include/ola/client/StreamingClient.h oladmxincludedir = $(pkgincludedir)/dmx/ oladmxinclude_HEADERS = \ include/ola/dmx/RunLengthEncoder.h \ include/ola/dmx/SourcePriorities.h olae133includedir = $(pkgincludedir)/e133/ @INSTALL_E133_TRUE@olae133include_HEADERS = \ @INSTALL_E133_TRUE@ include/ola/e133/DeviceManager.h \ @INSTALL_E133_TRUE@ include/ola/e133/E133Enums.h \ @INSTALL_E133_TRUE@ include/ola/e133/E133Receiver.h \ @INSTALL_E133_TRUE@ include/ola/e133/E133StatusHelper.h \ @INSTALL_E133_TRUE@ include/ola/e133/E133URLParser.h \ @INSTALL_E133_TRUE@ include/ola/e133/MessageBuilder.h olafileincludedir = $(pkgincludedir)/file/ olafileinclude_HEADERS = include/ola/file/Util.h olahttpincludedir = $(pkgincludedir)/http/ olahttpinclude_HEADERS = \ include/ola/http/HTTPServer.h \ include/ola/http/OlaHTTPServer.h olaioincludedir = $(pkgincludedir)/io/ olaioinclude_HEADERS = \ include/ola/io/BigEndianStream.h \ include/ola/io/ByteString.h \ include/ola/io/Descriptor.h \ include/ola/io/ExtendedSerial.h \ include/ola/io/IOQueue.h \ include/ola/io/IOStack.h \ include/ola/io/IOUtils.h \ include/ola/io/IOVecInterface.h \ include/ola/io/InputBuffer.h \ include/ola/io/InputStream.h \ include/ola/io/MemoryBlock.h \ include/ola/io/MemoryBlockPool.h \ include/ola/io/MemoryBuffer.h \ include/ola/io/NonBlockingSender.h \ include/ola/io/OutputBuffer.h \ include/ola/io/OutputStream.h \ include/ola/io/SelectServer.h \ include/ola/io/SelectServerInterface.h \ include/ola/io/Serial.h \ include/ola/io/StdinHandler.h olamathincludedir = $(pkgincludedir)/random/ olamathinclude_HEADERS = include/ola/math/Random.h olamessagingincludedir = $(pkgincludedir)/messaging/ olamessaginginclude_HEADERS = \ include/ola/messaging/Descriptor.h \ include/ola/messaging/DescriptorVisitor.h \ include/ola/messaging/Message.h \ include/ola/messaging/MessagePrinter.h \ include/ola/messaging/MessageVisitor.h \ include/ola/messaging/SchemaPrinter.h \ include/ola/messaging/StringMessageBuilder.h olanetworkincludedir = $(pkgincludedir)/network/ olanetworkinclude_HEADERS = \ include/ola/network/AdvancedTCPConnector.h\ include/ola/network/HealthCheckedConnection.h \ include/ola/network/IPV4Address.h \ include/ola/network/Interface.h \ include/ola/network/InterfacePicker.h \ include/ola/network/MACAddress.h \ include/ola/network/NetworkUtils.h \ include/ola/network/Socket.h \ include/ola/network/SocketAddress.h \ include/ola/network/SocketCloser.h \ include/ola/network/TCPConnector.h \ include/ola/network/TCPSocket.h \ include/ola/network/TCPSocketFactory.h olardmincludedir = $(pkgincludedir)/rdm/ olardminclude_HEADERS = \ include/ola/rdm/AckTimerResponder.h \ include/ola/rdm/AdvancedDimmerResponder.h \ include/ola/rdm/CommandPrinter.h \ include/ola/rdm/DimmerResponder.h \ include/ola/rdm/DimmerRootDevice.h \ include/ola/rdm/DimmerSubDevice.h \ include/ola/rdm/DiscoveryAgent.h \ include/ola/rdm/DummyResponder.h \ include/ola/rdm/MessageDeserializer.h \ include/ola/rdm/MessageSerializer.h \ include/ola/rdm/MovingLightResponder.h \ include/ola/rdm/NetworkManagerInterface.h \ include/ola/rdm/NetworkResponder.h \ include/ola/rdm/OpenLightingEnums.h \ include/ola/rdm/PidStore.h \ include/ola/rdm/PidStoreHelper.h \ include/ola/rdm/QueueingRDMController.h \ include/ola/rdm/RDMAPI.h \ include/ola/rdm/RDMAPIImplInterface.h \ include/ola/rdm/RDMCommand.h \ include/ola/rdm/RDMCommandSerializer.h \ include/ola/rdm/RDMControllerAdaptor.h \ include/ola/rdm/RDMControllerInterface.h \ include/ola/rdm/RDMEnums.h \ include/ola/rdm/RDMFrame.h \ include/ola/rdm/RDMHelper.h \ include/ola/rdm/RDMMessagePrinters.h \ include/ola/rdm/RDMPacket.h \ include/ola/rdm/RDMReply.h \ include/ola/rdm/ResponderHelper.h \ include/ola/rdm/ResponderLoadSensor.h \ include/ola/rdm/ResponderOps.h \ include/ola/rdm/ResponderOpsPrivate.h \ include/ola/rdm/ResponderPersonality.h \ include/ola/rdm/ResponderSensor.h \ include/ola/rdm/ResponderSettings.h \ include/ola/rdm/ResponderSlotData.h \ include/ola/rdm/SensorResponder.h \ include/ola/rdm/StringMessageBuilder.h \ include/ola/rdm/SubDeviceDispatcher.h \ include/ola/rdm/UID.h \ include/ola/rdm/UIDAllocator.h \ include/ola/rdm/UIDSet.h nodist_olardminclude_HEADERS = include/ola/rdm/RDMResponseCodes.h olarpcincludedir = $(pkgincludedir)/rpc/ olarpcinclude_HEADERS = \ include/ola/rpc/RpcSessionHandler.h olastlincludedir = $(pkgincludedir)/stl/ olastlinclude_HEADERS = include/ola/stl/STLUtils.h olastringsincludedir = $(pkgincludedir)/strings/ olastringsinclude_HEADERS = \ include/ola/strings/Format.h \ include/ola/strings/FormatPrivate.h \ include/ola/strings/Utils.h olasystemincludedir = $(pkgincludedir)/system/ olasysteminclude_HEADERS = \ include/ola/system/Limits.h \ include/ola/system/SystemUtils.h olathreadincludedir = $(pkgincludedir)/thread/ olathreadinclude_HEADERS = \ include/ola/thread/CallbackThread.h \ include/ola/thread/ConsumerThread.h \ include/ola/thread/ExecutorInterface.h \ include/ola/thread/ExecutorThread.h \ include/ola/thread/Future.h \ include/ola/thread/FuturePrivate.h \ include/ola/thread/Mutex.h \ include/ola/thread/PeriodicThread.h \ include/ola/thread/SchedulerInterface.h \ include/ola/thread/SchedulingExecutorInterface.h \ include/ola/thread/SignalThread.h \ include/ola/thread/Thread.h \ include/ola/thread/ThreadPool.h \ include/ola/thread/Utils.h olatimecodeincludedir = $(pkgincludedir)/timecode/ olatimecodeinclude_HEADERS = include/ola/timecode/TimeCode.h nodist_olatimecodeinclude_HEADERS = include/ola/timecode/TimeCodeEnums.h olautilincludedir = $(pkgincludedir)/util/ olautilinclude_HEADERS = \ include/ola/util/Backoff.h \ include/ola/util/Deleter.h \ include/ola/util/SequenceNumber.h \ include/ola/util/Utils.h \ include/ola/util/Watchdog.h olawebincludedir = $(pkgincludedir)/web/ olawebinclude_HEADERS = \ include/ola/web/Json.h \ include/ola/web/JsonData.h \ include/ola/web/JsonLexer.h \ include/ola/web/JsonParser.h \ include/ola/web/JsonPatch.h \ include/ola/web/JsonPatchParser.h \ include/ola/web/JsonPointer.h \ include/ola/web/JsonSchema.h \ include/ola/web/JsonSections.h \ include/ola/web/JsonTypes.h \ include/ola/web/JsonWriter.h \ include/ola/web/OptionalItem.h olawinincludedir = $(pkgincludedir)/win/ olawininclude_HEADERS = \ include/ola/win/CleanWinSock2.h \ include/ola/win/CleanWindows.h # HEADERS ################################################## oladinclude_HEADERS = include/olad/Device.h include/olad/DmxSource.h \ include/olad/Plugin.h include/olad/PluginAdaptor.h \ include/olad/Port.h include/olad/PortBroker.h \ include/olad/PortConstants.h include/olad/Preferences.h \ include/olad/TokenBucket.h include/olad/Universe.h \ olad/OlaDaemon.h olad/OlaServer.h COMMON_E131_CXXFLAGS = $(COMMON_CXXFLAGS) -Wconversion # libolaacn.la libs_acn_libolaacn_la_SOURCES = \ libs/acn/CID.cpp \ libs/acn/CIDImpl.cpp \ libs/acn/CIDImpl.h libs_acn_libolaacn_la_CXXFLAGS = $(COMMON_E131_CXXFLAGS) $(uuid_CFLAGS) libs_acn_libolaacn_la_LIBADD = $(uuid_LIBS) \ common/libolacommon.la libs_acn_libolae131core_la_SOURCES = \ libs/acn/BaseInflator.cpp \ libs/acn/BaseInflator.h \ libs/acn/DMPAddress.cpp \ libs/acn/DMPAddress.h \ libs/acn/DMPE131Inflator.cpp \ libs/acn/DMPE131Inflator.h \ libs/acn/DMPHeader.h \ libs/acn/DMPInflator.cpp \ libs/acn/DMPInflator.h \ libs/acn/DMPPDU.cpp \ libs/acn/DMPPDU.h \ libs/acn/E131DiscoveryInflator.cpp \ libs/acn/E131DiscoveryInflator.h \ libs/acn/E131Header.h \ libs/acn/E131Inflator.cpp \ libs/acn/E131Inflator.h \ libs/acn/E131Node.cpp \ libs/acn/E131Node.h \ libs/acn/E131PDU.cpp \ libs/acn/E131PDU.h \ libs/acn/E131Sender.cpp \ libs/acn/E131Sender.h \ libs/acn/E133Header.h \ libs/acn/E133Inflator.cpp \ libs/acn/E133Inflator.h \ libs/acn/E133PDU.cpp \ libs/acn/E133PDU.h \ libs/acn/E133StatusInflator.cpp \ libs/acn/E133StatusInflator.h \ libs/acn/E133StatusPDU.cpp \ libs/acn/E133StatusPDU.h \ libs/acn/HeaderSet.h \ libs/acn/PDU.cpp \ libs/acn/PDU.h \ libs/acn/PDUTestCommon.h \ libs/acn/PreamblePacker.cpp \ libs/acn/PreamblePacker.h \ libs/acn/RDMInflator.cpp \ libs/acn/RDMInflator.h \ libs/acn/RDMPDU.cpp \ libs/acn/RDMPDU.h \ libs/acn/RootHeader.h \ libs/acn/RootInflator.cpp \ libs/acn/RootInflator.h \ libs/acn/RootPDU.cpp \ libs/acn/RootPDU.h \ libs/acn/RootSender.cpp \ libs/acn/RootSender.h \ libs/acn/TCPTransport.cpp \ libs/acn/TCPTransport.h \ libs/acn/Transport.h \ libs/acn/TransportHeader.h \ libs/acn/UDPTransport.cpp \ libs/acn/UDPTransport.h libs_acn_libolae131core_la_CXXFLAGS = \ $(COMMON_E131_CXXFLAGS) $(uuid_CFLAGS) libs_acn_libolae131core_la_LIBADD = $(uuid_LIBS) \ common/libolacommon.la \ libs/acn/libolaacn.la libs_acn_e131_transmit_test_SOURCES = \ libs/acn/e131_transmit_test.cpp \ libs/acn/E131TestFramework.cpp \ libs/acn/E131TestFramework.h libs_acn_e131_transmit_test_LDADD = libs/acn/libolae131core.la libs_acn_e131_loadtest_SOURCES = libs/acn/e131_loadtest.cpp libs_acn_e131_loadtest_LDADD = libs/acn/libolae131core.la libs_acn_E131Tester_SOURCES = \ libs/acn/BaseInflatorTest.cpp \ libs/acn/CIDTest.cpp \ libs/acn/DMPAddressTest.cpp \ libs/acn/DMPInflatorTest.cpp \ libs/acn/DMPPDUTest.cpp \ libs/acn/E131InflatorTest.cpp \ libs/acn/E131PDUTest.cpp \ libs/acn/HeaderSetTest.cpp \ libs/acn/PDUTest.cpp \ libs/acn/RootInflatorTest.cpp \ libs/acn/RootPDUTest.cpp \ libs/acn/RootSenderTest.cpp libs_acn_E131Tester_CPPFLAGS = $(COMMON_TESTING_FLAGS) # For some completely messed up reason on mac CPPUNIT_LIBS has to come after # the ossp uuid library. # CPPUNIT_LIBS contains -ldl which causes the tests to fail in strange ways libs_acn_E131Tester_LDADD = \ libs/acn/libolae131core.la \ $(COMMON_TESTING_LIBS) libs_acn_E133Tester_SOURCES = \ libs/acn/E133InflatorTest.cpp \ libs/acn/E133PDUTest.cpp \ libs/acn/RDMPDUTest.cpp libs_acn_E133Tester_CPPFLAGS = $(COMMON_TESTING_FLAGS) libs_acn_E133Tester_LDADD = \ libs/acn/libolae131core.la \ $(COMMON_TESTING_LIBS) libs_acn_TransportTester_SOURCES = \ libs/acn/TCPTransportTest.cpp \ libs/acn/UDPTransportTest.cpp libs_acn_TransportTester_CPPFLAGS = $(COMMON_TESTING_FLAGS) libs_acn_TransportTester_LDADD = libs/acn/libolae131core.la \ $(COMMON_TESTING_LIBS) @USE_LIBUSB_TRUE@libs_usb_libolausb_la_SOURCES = \ @USE_LIBUSB_TRUE@ libs/usb/HotplugAgent.cpp \ @USE_LIBUSB_TRUE@ libs/usb/HotplugAgent.h \ @USE_LIBUSB_TRUE@ libs/usb/JaRuleConstants.h \ @USE_LIBUSB_TRUE@ libs/usb/JaRuleConstants.cpp \ @USE_LIBUSB_TRUE@ libs/usb/JaRulePortHandle.cpp \ @USE_LIBUSB_TRUE@ libs/usb/JaRulePortHandle.h \ @USE_LIBUSB_TRUE@ libs/usb/JaRulePortHandleImpl.cpp \ @USE_LIBUSB_TRUE@ libs/usb/JaRulePortHandleImpl.h \ @USE_LIBUSB_TRUE@ libs/usb/JaRuleWidget.cpp \ @USE_LIBUSB_TRUE@ libs/usb/JaRuleWidget.h \ @USE_LIBUSB_TRUE@ libs/usb/JaRuleWidgetPort.cpp \ @USE_LIBUSB_TRUE@ libs/usb/JaRuleWidgetPort.h \ @USE_LIBUSB_TRUE@ libs/usb/LibUsbAdaptor.cpp \ @USE_LIBUSB_TRUE@ libs/usb/LibUsbAdaptor.h \ @USE_LIBUSB_TRUE@ libs/usb/LibUsbThread.cpp \ @USE_LIBUSB_TRUE@ libs/usb/LibUsbThread.h \ @USE_LIBUSB_TRUE@ libs/usb/Types.cpp \ @USE_LIBUSB_TRUE@ libs/usb/Types.h @USE_LIBUSB_TRUE@libs_usb_libolausb_la_CXXFLAGS = $(COMMON_CXXFLAGS) \ @USE_LIBUSB_TRUE@ $(libusb_CFLAGS) @USE_LIBUSB_TRUE@libs_usb_libolausb_la_LIBADD = $(libusb_LIBS) \ @USE_LIBUSB_TRUE@ common/libolacommon.la @USE_LIBUSB_TRUE@LIBS_USB_TEST_LDADD = $(COMMON_TESTING_LIBS) \ @USE_LIBUSB_TRUE@ $(libusb_LIBS) \ @USE_LIBUSB_TRUE@ libs/usb/libolausb.la @USE_LIBUSB_TRUE@libs_usb_LibUsbThreadTester_SOURCES = \ @USE_LIBUSB_TRUE@ libs/usb/LibUsbThreadTest.cpp @USE_LIBUSB_TRUE@libs_usb_LibUsbThreadTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) \ @USE_LIBUSB_TRUE@ $(libusb_CFLAGS) @USE_LIBUSB_TRUE@libs_usb_LibUsbThreadTester_LDADD = $(LIBS_USB_TEST_LDADD) # HEADERS ################################################## # These headers are deprecated and will be removed 6 months after the 0.9.0 # release. DEPRECATED = \ ola/OlaCallbackClient.h \ ola/OlaDevice.h \ ola/StreamingClient.h ola_libola_la_SOURCES = \ ola/AutoStart.cpp \ ola/ClientRDMAPIShim.cpp \ ola/ClientTypesFactory.h \ ola/ClientTypesFactory.cpp \ ola/Module.cpp \ ola/OlaCallbackClient.cpp \ ola/OlaClient.cpp \ ola/OlaClientCore.h \ ola/OlaClientCore.cpp \ ola/OlaClientWrapper.cpp \ ola/StreamingClient.cpp ola_libola_la_CXXFLAGS = $(COMMON_PROTOBUF_CXXFLAGS) ola_libola_la_LDFLAGS = -version-info 1:1:0 ola_libola_la_LIBADD = common/libolacommon.la ola_OlaClientTester_SOURCES = ola/OlaClientWrapperTest.cpp \ ola/StreamingClientTest.cpp ola_OlaClientTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) ola_OlaClientTester_LDADD = $(COMMON_TESTING_LIBS) \ $(PLUGIN_LIBS) \ common/libolacommon.la \ olad/libolaserver.la \ ola/libola.la olad_plugin_api_libolaserverplugininterface_la_SOURCES = \ olad/plugin_api/Client.cpp \ olad/plugin_api/Client.h \ olad/plugin_api/Device.cpp \ olad/plugin_api/DeviceManager.cpp \ olad/plugin_api/DeviceManager.h \ olad/plugin_api/DmxSource.cpp \ olad/plugin_api/Plugin.cpp \ olad/plugin_api/PluginAdaptor.cpp \ olad/plugin_api/Port.cpp \ olad/plugin_api/PortBroker.cpp \ olad/plugin_api/PortManager.cpp \ olad/plugin_api/PortManager.h \ olad/plugin_api/Preferences.cpp \ olad/plugin_api/Universe.cpp \ olad/plugin_api/UniverseStore.cpp \ olad/plugin_api/UniverseStore.h olad_plugin_api_libolaserverplugininterface_la_CXXFLAGS = \ $(COMMON_PROTOBUF_CXXFLAGS) olad_plugin_api_libolaserverplugininterface_la_LIBADD = \ common/libolacommon.la \ common/web/libolaweb.la \ ola/libola.la COMMON_OLAD_PLUGIN_API_TEST_LDADD = \ $(COMMON_TESTING_LIBS) \ $(libprotobuf_LIBS) \ olad/plugin_api/libolaserverplugininterface.la \ common/libolacommon.la olad_plugin_api_ClientTester_SOURCES = olad/plugin_api/ClientTest.cpp olad_plugin_api_ClientTester_CXXFLAGS = $(COMMON_TESTING_PROTOBUF_FLAGS) olad_plugin_api_ClientTester_LDADD = $(COMMON_OLAD_PLUGIN_API_TEST_LDADD) olad_plugin_api_DeviceTester_SOURCES = olad/plugin_api/DeviceManagerTest.cpp \ olad/plugin_api/DeviceTest.cpp olad_plugin_api_DeviceTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) olad_plugin_api_DeviceTester_LDADD = $(COMMON_OLAD_PLUGIN_API_TEST_LDADD) olad_plugin_api_DmxSourceTester_SOURCES = olad/plugin_api/DmxSourceTest.cpp olad_plugin_api_DmxSourceTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) olad_plugin_api_DmxSourceTester_LDADD = $(COMMON_OLAD_PLUGIN_API_TEST_LDADD) olad_plugin_api_PortTester_SOURCES = olad/plugin_api/PortTest.cpp \ olad/plugin_api/PortManagerTest.cpp olad_plugin_api_PortTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) olad_plugin_api_PortTester_LDADD = $(COMMON_OLAD_PLUGIN_API_TEST_LDADD) olad_plugin_api_PreferencesTester_SOURCES = olad/plugin_api/PreferencesTest.cpp olad_plugin_api_PreferencesTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) olad_plugin_api_PreferencesTester_LDADD = $(COMMON_OLAD_PLUGIN_API_TEST_LDADD) olad_plugin_api_UniverseTester_SOURCES = olad/plugin_api/UniverseTest.cpp olad_plugin_api_UniverseTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) olad_plugin_api_UniverseTester_LDADD = $(COMMON_OLAD_PLUGIN_API_TEST_LDADD) @USE_ARTNET_TRUE@artnetincludedir = $(includedir)/ola/artnet @USE_ARTNET_TRUE@nodist_artnetinclude_HEADERS = \ @USE_ARTNET_TRUE@ plugins/artnet/messages/ArtNetConfigMessages.pb.h @USE_ARTNET_TRUE@nodist_plugins_artnet_messages_libolaartnetconf_la_SOURCES = \ @USE_ARTNET_TRUE@ plugins/artnet/messages/ArtNetConfigMessages.pb.cc @USE_ARTNET_TRUE@plugins_artnet_messages_libolaartnetconf_la_CXXFLAGS = $(COMMON_PROTOBUF_CXXFLAGS) @USE_ARTNET_TRUE@plugins_artnet_messages_libolaartnetconf_la_LIBADD = $(libprotobuf_LIBS) @USE_ARTNET_TRUE@plugins_artnet_libolaartnetnode_la_SOURCES = \ @USE_ARTNET_TRUE@ plugins/artnet/ArtNetPackets.h \ @USE_ARTNET_TRUE@ plugins/artnet/ArtNetNode.cpp \ @USE_ARTNET_TRUE@ plugins/artnet/ArtNetNode.h @USE_ARTNET_TRUE@plugins_artnet_libolaartnetnode_la_LIBADD = common/libolacommon.la @USE_ARTNET_TRUE@plugins_artnet_libolaartnet_la_SOURCES = \ @USE_ARTNET_TRUE@ plugins/artnet/ArtNetPlugin.cpp \ @USE_ARTNET_TRUE@ plugins/artnet/ArtNetPlugin.h \ @USE_ARTNET_TRUE@ plugins/artnet/ArtNetDevice.cpp \ @USE_ARTNET_TRUE@ plugins/artnet/ArtNetDevice.h \ @USE_ARTNET_TRUE@ plugins/artnet/ArtNetPort.cpp \ @USE_ARTNET_TRUE@ plugins/artnet/ArtNetPort.h @USE_ARTNET_TRUE@plugins_artnet_libolaartnet_la_CXXFLAGS = $(COMMON_PROTOBUF_CXXFLAGS) @USE_ARTNET_TRUE@plugins_artnet_libolaartnet_la_LIBADD = \ @USE_ARTNET_TRUE@ olad/plugin_api/libolaserverplugininterface.la \ @USE_ARTNET_TRUE@ plugins/artnet/libolaartnetnode.la \ @USE_ARTNET_TRUE@ plugins/artnet/messages/libolaartnetconf.la @USE_ARTNET_TRUE@plugins_artnet_artnet_loadtest_SOURCES = plugins/artnet/artnet_loadtest.cpp @USE_ARTNET_TRUE@plugins_artnet_artnet_loadtest_LDADD = plugins/artnet/libolaartnetnode.la @USE_ARTNET_TRUE@plugins_artnet_ArtNetTester_SOURCES = plugins/artnet/ArtNetNodeTest.cpp @USE_ARTNET_TRUE@plugins_artnet_ArtNetTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) @USE_ARTNET_TRUE@plugins_artnet_ArtNetTester_LDADD = $(COMMON_TESTING_LIBS) \ @USE_ARTNET_TRUE@ plugins/artnet/libolaartnetnode.la @USE_DUMMY_TRUE@plugins_dummy_liboladummy_la_SOURCES = \ @USE_DUMMY_TRUE@ plugins/dummy/DummyDevice.cpp \ @USE_DUMMY_TRUE@ plugins/dummy/DummyDevice.h \ @USE_DUMMY_TRUE@ plugins/dummy/DummyPlugin.cpp \ @USE_DUMMY_TRUE@ plugins/dummy/DummyPlugin.h \ @USE_DUMMY_TRUE@ plugins/dummy/DummyPort.cpp \ @USE_DUMMY_TRUE@ plugins/dummy/DummyPort.h @USE_DUMMY_TRUE@plugins_dummy_liboladummy_la_LIBADD = \ @USE_DUMMY_TRUE@ common/libolacommon.la \ @USE_DUMMY_TRUE@ olad/plugin_api/libolaserverplugininterface.la @USE_DUMMY_TRUE@plugins_dummy_DummyPluginTester_SOURCES = plugins/dummy/DummyPortTest.cpp @USE_DUMMY_TRUE@plugins_dummy_DummyPluginTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) # it's unclear to me why liboladummyresponder has to be included here # but if it isn't, the test breaks with gcc 4.6.1 @USE_DUMMY_TRUE@plugins_dummy_DummyPluginTester_LDADD = \ @USE_DUMMY_TRUE@ $(COMMON_TESTING_LIBS) \ @USE_DUMMY_TRUE@ $(top_builddir)/olad/plugin_api/libolaserverplugininterface.la \ @USE_DUMMY_TRUE@ $(top_builddir)/olad/libolaserver.la \ @USE_DUMMY_TRUE@ plugins/dummy/liboladummy.la \ @USE_DUMMY_TRUE@ common/libolacommon.la @USE_ESPNET_TRUE@plugins_espnet_libolaespnet_la_SOURCES = \ @USE_ESPNET_TRUE@ plugins/espnet/EspNetDevice.cpp \ @USE_ESPNET_TRUE@ plugins/espnet/EspNetDevice.h \ @USE_ESPNET_TRUE@ plugins/espnet/EspNetNode.cpp \ @USE_ESPNET_TRUE@ plugins/espnet/EspNetNode.h \ @USE_ESPNET_TRUE@ plugins/espnet/EspNetPackets.h \ @USE_ESPNET_TRUE@ plugins/espnet/EspNetPlugin.cpp \ @USE_ESPNET_TRUE@ plugins/espnet/EspNetPlugin.h \ @USE_ESPNET_TRUE@ plugins/espnet/EspNetPluginCommon.h \ @USE_ESPNET_TRUE@ plugins/espnet/EspNetPort.cpp \ @USE_ESPNET_TRUE@ plugins/espnet/EspNetPort.h \ @USE_ESPNET_TRUE@ plugins/espnet/RunLengthDecoder.cpp \ @USE_ESPNET_TRUE@ plugins/espnet/RunLengthDecoder.h @USE_ESPNET_TRUE@plugins_espnet_libolaespnet_la_LIBADD = \ @USE_ESPNET_TRUE@ common/libolacommon.la \ @USE_ESPNET_TRUE@ olad/plugin_api/libolaserverplugininterface.la @USE_ESPNET_TRUE@plugins_espnet_EspNetTester_SOURCES = \ @USE_ESPNET_TRUE@ plugins/espnet/RunLengthDecoderTest.cpp \ @USE_ESPNET_TRUE@ plugins/espnet/RunLengthDecoder.cpp @USE_ESPNET_TRUE@plugins_espnet_EspNetTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) @USE_ESPNET_TRUE@plugins_espnet_EspNetTester_LDADD = $(COMMON_TESTING_LIBS) \ @USE_ESPNET_TRUE@ common/libolacommon.la @USE_FTDI_TRUE@plugins_ftdidmx_libolaftdidmx_la_SOURCES = \ @USE_FTDI_TRUE@ plugins/ftdidmx/FtdiDmxDevice.cpp \ @USE_FTDI_TRUE@ plugins/ftdidmx/FtdiDmxDevice.h \ @USE_FTDI_TRUE@ plugins/ftdidmx/FtdiDmxPlugin.cpp \ @USE_FTDI_TRUE@ plugins/ftdidmx/FtdiDmxPlugin.h \ @USE_FTDI_TRUE@ plugins/ftdidmx/FtdiDmxPort.h \ @USE_FTDI_TRUE@ plugins/ftdidmx/FtdiDmxThread.cpp \ @USE_FTDI_TRUE@ plugins/ftdidmx/FtdiDmxThread.h \ @USE_FTDI_TRUE@ plugins/ftdidmx/FtdiWidget.cpp \ @USE_FTDI_TRUE@ plugins/ftdidmx/FtdiWidget.h @USE_FTDI_TRUE@plugins_ftdidmx_libolaftdidmx_la_LIBADD = \ @USE_FTDI_TRUE@ $(libftdi_LIBS) \ @USE_FTDI_TRUE@ common/libolacommon.la \ @USE_FTDI_TRUE@ olad/plugin_api/libolaserverplugininterface.la # This is a library which isn't coupled to olad @USE_GPIO_TRUE@plugins_gpio_libolagpiocore_la_SOURCES = \ @USE_GPIO_TRUE@ plugins/gpio/GPIODriver.cpp \ @USE_GPIO_TRUE@ plugins/gpio/GPIODriver.h @USE_GPIO_TRUE@plugins_gpio_libolagpiocore_la_LIBADD = common/libolacommon.la @USE_GPIO_TRUE@plugins_gpio_libolagpio_la_SOURCES = \ @USE_GPIO_TRUE@ plugins/gpio/GPIODevice.cpp \ @USE_GPIO_TRUE@ plugins/gpio/GPIODevice.h \ @USE_GPIO_TRUE@ plugins/gpio/GPIOPlugin.cpp \ @USE_GPIO_TRUE@ plugins/gpio/GPIOPlugin.h \ @USE_GPIO_TRUE@ plugins/gpio/GPIOPort.cpp \ @USE_GPIO_TRUE@ plugins/gpio/GPIOPort.h @USE_GPIO_TRUE@plugins_gpio_libolagpio_la_LIBADD = \ @USE_GPIO_TRUE@ common/libolacommon.la \ @USE_GPIO_TRUE@ olad/plugin_api/libolaserverplugininterface.la \ @USE_GPIO_TRUE@ plugins/gpio/libolagpiocore.la @USE_KARATE_TRUE@plugins_karate_libolakarate_la_SOURCES = \ @USE_KARATE_TRUE@ plugins/karate/KaratePlugin.cpp \ @USE_KARATE_TRUE@ plugins/karate/KarateDevice.cpp \ @USE_KARATE_TRUE@ plugins/karate/KarateThread.cpp \ @USE_KARATE_TRUE@ plugins/karate/KarateLight.cpp \ @USE_KARATE_TRUE@ plugins/karate/KaratePlugin.h \ @USE_KARATE_TRUE@ plugins/karate/KarateDevice.h \ @USE_KARATE_TRUE@ plugins/karate/KaratePort.h \ @USE_KARATE_TRUE@ plugins/karate/KarateThread.h \ @USE_KARATE_TRUE@ plugins/karate/KarateLight.h @USE_KARATE_TRUE@plugins_karate_libolakarate_la_LIBADD = \ @USE_KARATE_TRUE@ common/libolacommon.la \ @USE_KARATE_TRUE@ olad/plugin_api/libolaserverplugininterface.la @USE_KINET_TRUE@plugins_kinet_libolakinetnode_la_SOURCES = plugins/kinet/KiNetNode.cpp \ @USE_KINET_TRUE@ plugins/kinet/KiNetNode.h @USE_KINET_TRUE@plugins_kinet_libolakinetnode_la_LIBADD = common/libolacommon.la @USE_KINET_TRUE@plugins_kinet_libolakinet_la_SOURCES = \ @USE_KINET_TRUE@ plugins/kinet/KiNetPlugin.cpp \ @USE_KINET_TRUE@ plugins/kinet/KiNetPlugin.h \ @USE_KINET_TRUE@ plugins/kinet/KiNetDevice.cpp \ @USE_KINET_TRUE@ plugins/kinet/KiNetDevice.h \ @USE_KINET_TRUE@ plugins/kinet/KiNetPort.h @USE_KINET_TRUE@plugins_kinet_libolakinet_la_LIBADD = \ @USE_KINET_TRUE@ olad/plugin_api/libolaserverplugininterface.la \ @USE_KINET_TRUE@ plugins/kinet/libolakinetnode.la @USE_KINET_TRUE@plugins_kinet_KiNetTester_SOURCES = plugins/kinet/KiNetNodeTest.cpp @USE_KINET_TRUE@plugins_kinet_KiNetTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) @USE_KINET_TRUE@plugins_kinet_KiNetTester_LDADD = $(COMMON_TESTING_LIBS) \ @USE_KINET_TRUE@ plugins/kinet/libolakinetnode.la @USE_MILINST_TRUE@plugins_milinst_libolamilinst_la_SOURCES = \ @USE_MILINST_TRUE@ plugins/milinst/MilInstDevice.cpp \ @USE_MILINST_TRUE@ plugins/milinst/MilInstDevice.h \ @USE_MILINST_TRUE@ plugins/milinst/MilInstPlugin.cpp \ @USE_MILINST_TRUE@ plugins/milinst/MilInstPlugin.h \ @USE_MILINST_TRUE@ plugins/milinst/MilInstPort.cpp \ @USE_MILINST_TRUE@ plugins/milinst/MilInstPort.h \ @USE_MILINST_TRUE@ plugins/milinst/MilInstWidget.cpp \ @USE_MILINST_TRUE@ plugins/milinst/MilInstWidget.h \ @USE_MILINST_TRUE@ plugins/milinst/MilInstWidget1463.cpp \ @USE_MILINST_TRUE@ plugins/milinst/MilInstWidget1463.h \ @USE_MILINST_TRUE@ plugins/milinst/MilInstWidget1553.cpp \ @USE_MILINST_TRUE@ plugins/milinst/MilInstWidget1553.h @USE_MILINST_TRUE@plugins_milinst_libolamilinst_la_LIBADD = \ @USE_MILINST_TRUE@ common/libolacommon.la \ @USE_MILINST_TRUE@ olad/plugin_api/libolaserverplugininterface.la @USE_OPENDMX_TRUE@plugins_opendmx_libolaopendmx_la_SOURCES = \ @USE_OPENDMX_TRUE@ plugins/opendmx/OpenDmxDevice.cpp \ @USE_OPENDMX_TRUE@ plugins/opendmx/OpenDmxDevice.h \ @USE_OPENDMX_TRUE@ plugins/opendmx/OpenDmxPlugin.cpp \ @USE_OPENDMX_TRUE@ plugins/opendmx/OpenDmxPlugin.h \ @USE_OPENDMX_TRUE@ plugins/opendmx/OpenDmxPort.h \ @USE_OPENDMX_TRUE@ plugins/opendmx/OpenDmxThread.cpp \ @USE_OPENDMX_TRUE@ plugins/opendmx/OpenDmxThread.h @USE_OPENDMX_TRUE@plugins_opendmx_libolaopendmx_la_LIBADD = \ @USE_OPENDMX_TRUE@ common/libolacommon.la \ @USE_OPENDMX_TRUE@ olad/plugin_api/libolaserverplugininterface.la @USE_OPENPIXELCONTROL_TRUE@plugins_openpixelcontrol_libolaopc_la_SOURCES = \ @USE_OPENPIXELCONTROL_TRUE@ plugins/openpixelcontrol/OPCClient.cpp \ @USE_OPENPIXELCONTROL_TRUE@ plugins/openpixelcontrol/OPCClient.h \ @USE_OPENPIXELCONTROL_TRUE@ plugins/openpixelcontrol/OPCConstants.h \ @USE_OPENPIXELCONTROL_TRUE@ plugins/openpixelcontrol/OPCServer.cpp \ @USE_OPENPIXELCONTROL_TRUE@ plugins/openpixelcontrol/OPCServer.h @USE_OPENPIXELCONTROL_TRUE@plugins_openpixelcontrol_libolaopc_la_LIBADD = \ @USE_OPENPIXELCONTROL_TRUE@ common/libolacommon.la @USE_OPENPIXELCONTROL_TRUE@plugins_openpixelcontrol_libolaopenpixelcontrol_la_SOURCES = \ @USE_OPENPIXELCONTROL_TRUE@ plugins/openpixelcontrol/OPCDevice.cpp \ @USE_OPENPIXELCONTROL_TRUE@ plugins/openpixelcontrol/OPCDevice.h \ @USE_OPENPIXELCONTROL_TRUE@ plugins/openpixelcontrol/OPCPlugin.cpp \ @USE_OPENPIXELCONTROL_TRUE@ plugins/openpixelcontrol/OPCPlugin.h \ @USE_OPENPIXELCONTROL_TRUE@ plugins/openpixelcontrol/OPCPort.cpp \ @USE_OPENPIXELCONTROL_TRUE@ plugins/openpixelcontrol/OPCPort.h @USE_OPENPIXELCONTROL_TRUE@plugins_openpixelcontrol_libolaopenpixelcontrol_la_LIBADD = \ @USE_OPENPIXELCONTROL_TRUE@ common/libolacommon.la \ @USE_OPENPIXELCONTROL_TRUE@ olad/plugin_api/libolaserverplugininterface.la \ @USE_OPENPIXELCONTROL_TRUE@ plugins/openpixelcontrol/libolaopc.la @USE_OPENPIXELCONTROL_TRUE@plugins_openpixelcontrol_OPCClientTester_SOURCES = \ @USE_OPENPIXELCONTROL_TRUE@ plugins/openpixelcontrol/OPCClientTest.cpp @USE_OPENPIXELCONTROL_TRUE@plugins_openpixelcontrol_OPCClientTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) @USE_OPENPIXELCONTROL_TRUE@plugins_openpixelcontrol_OPCClientTester_LDADD = \ @USE_OPENPIXELCONTROL_TRUE@ $(COMMON_TESTING_LIBS) \ @USE_OPENPIXELCONTROL_TRUE@ plugins/openpixelcontrol/libolaopc.la @USE_OPENPIXELCONTROL_TRUE@plugins_openpixelcontrol_OPCServerTester_SOURCES = \ @USE_OPENPIXELCONTROL_TRUE@ plugins/openpixelcontrol/OPCServerTest.cpp @USE_OPENPIXELCONTROL_TRUE@plugins_openpixelcontrol_OPCServerTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) @USE_OPENPIXELCONTROL_TRUE@plugins_openpixelcontrol_OPCServerTester_LDADD = \ @USE_OPENPIXELCONTROL_TRUE@ $(COMMON_TESTING_LIBS) \ @USE_OPENPIXELCONTROL_TRUE@ plugins/openpixelcontrol/libolaopc.la @USE_OSC_TRUE@plugins_osc_libolaoscnode_la_SOURCES = \ @USE_OSC_TRUE@ plugins/osc/OSCAddressTemplate.cpp \ @USE_OSC_TRUE@ plugins/osc/OSCAddressTemplate.h \ @USE_OSC_TRUE@ plugins/osc/OSCNode.cpp \ @USE_OSC_TRUE@ plugins/osc/OSCNode.h \ @USE_OSC_TRUE@ plugins/osc/OSCTarget.h @USE_OSC_TRUE@plugins_osc_libolaoscnode_la_CXXFLAGS = $(COMMON_CXXFLAGS) $(liblo_CFLAGS) @USE_OSC_TRUE@plugins_osc_libolaoscnode_la_LIBADD = $(liblo_LIBS) @USE_OSC_TRUE@plugins_osc_libolaosc_la_SOURCES = \ @USE_OSC_TRUE@ plugins/osc/OSCDevice.cpp \ @USE_OSC_TRUE@ plugins/osc/OSCDevice.h \ @USE_OSC_TRUE@ plugins/osc/OSCPlugin.cpp \ @USE_OSC_TRUE@ plugins/osc/OSCPlugin.h \ @USE_OSC_TRUE@ plugins/osc/OSCPort.cpp \ @USE_OSC_TRUE@ plugins/osc/OSCPort.h @USE_OSC_TRUE@plugins_osc_libolaosc_la_CXXFLAGS = $(COMMON_CXXFLAGS) $(liblo_CFLAGS) @USE_OSC_TRUE@plugins_osc_libolaosc_la_LIBADD = \ @USE_OSC_TRUE@ olad/plugin_api/libolaserverplugininterface.la \ @USE_OSC_TRUE@ plugins/osc/libolaoscnode.la @USE_OSC_TRUE@plugins_osc_OSCTester_SOURCES = \ @USE_OSC_TRUE@ plugins/osc/OSCAddressTemplateTest.cpp \ @USE_OSC_TRUE@ plugins/osc/OSCNodeTest.cpp @USE_OSC_TRUE@plugins_osc_OSCTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) @USE_OSC_TRUE@plugins_osc_OSCTester_LDADD = $(COMMON_TESTING_LIBS) \ @USE_OSC_TRUE@ plugins/osc/libolaoscnode.la \ @USE_OSC_TRUE@ common/libolacommon.la @USE_PATHPORT_TRUE@plugins_pathport_libolapathport_la_SOURCES = \ @USE_PATHPORT_TRUE@ plugins/pathport/PathportDevice.cpp \ @USE_PATHPORT_TRUE@ plugins/pathport/PathportDevice.h \ @USE_PATHPORT_TRUE@ plugins/pathport/PathportNode.cpp \ @USE_PATHPORT_TRUE@ plugins/pathport/PathportNode.h \ @USE_PATHPORT_TRUE@ plugins/pathport/PathportPackets.h \ @USE_PATHPORT_TRUE@ plugins/pathport/PathportPlugin.cpp \ @USE_PATHPORT_TRUE@ plugins/pathport/PathportPlugin.h \ @USE_PATHPORT_TRUE@ plugins/pathport/PathportPort.cpp \ @USE_PATHPORT_TRUE@ plugins/pathport/PathportPort.h @USE_PATHPORT_TRUE@plugins_pathport_libolapathport_la_LIBADD = \ @USE_PATHPORT_TRUE@ common/libolacommon.la \ @USE_PATHPORT_TRUE@ olad/plugin_api/libolaserverplugininterface.la @USE_RENARD_TRUE@plugins_renard_libolarenard_la_SOURCES = \ @USE_RENARD_TRUE@ plugins/renard/RenardDevice.cpp \ @USE_RENARD_TRUE@ plugins/renard/RenardDevice.h \ @USE_RENARD_TRUE@ plugins/renard/RenardPlugin.cpp \ @USE_RENARD_TRUE@ plugins/renard/RenardPlugin.h \ @USE_RENARD_TRUE@ plugins/renard/RenardPort.cpp \ @USE_RENARD_TRUE@ plugins/renard/RenardPort.h \ @USE_RENARD_TRUE@ plugins/renard/RenardWidget.cpp \ @USE_RENARD_TRUE@ plugins/renard/RenardWidget.h @USE_RENARD_TRUE@plugins_renard_libolarenard_la_LIBADD = \ @USE_RENARD_TRUE@ common/libolacommon.la \ @USE_RENARD_TRUE@ olad/plugin_api/libolaserverplugininterface.la @USE_SANDNET_TRUE@plugins_sandnet_libolasandnet_la_SOURCES = \ @USE_SANDNET_TRUE@ plugins/sandnet/SandNetCommon.h \ @USE_SANDNET_TRUE@ plugins/sandnet/SandNetDevice.cpp \ @USE_SANDNET_TRUE@ plugins/sandnet/SandNetDevice.h \ @USE_SANDNET_TRUE@ plugins/sandnet/SandNetNode.cpp \ @USE_SANDNET_TRUE@ plugins/sandnet/SandNetNode.h \ @USE_SANDNET_TRUE@ plugins/sandnet/SandNetPackets.h \ @USE_SANDNET_TRUE@ plugins/sandnet/SandNetPlugin.cpp \ @USE_SANDNET_TRUE@ plugins/sandnet/SandNetPlugin.h \ @USE_SANDNET_TRUE@ plugins/sandnet/SandNetPort.cpp \ @USE_SANDNET_TRUE@ plugins/sandnet/SandNetPort.h @USE_SANDNET_TRUE@plugins_sandnet_libolasandnet_la_LIBADD = \ @USE_SANDNET_TRUE@ common/libolacommon.la \ @USE_SANDNET_TRUE@ olad/plugin_api/libolaserverplugininterface.la @USE_SHOWNET_TRUE@plugins_shownet_libolashownet_la_SOURCES = \ @USE_SHOWNET_TRUE@ plugins/shownet/ShowNetPlugin.cpp \ @USE_SHOWNET_TRUE@ plugins/shownet/ShowNetDevice.cpp \ @USE_SHOWNET_TRUE@ plugins/shownet/ShowNetPort.cpp \ @USE_SHOWNET_TRUE@ plugins/shownet/ShowNetNode.cpp \ @USE_SHOWNET_TRUE@ plugins/shownet/ShowNetPlugin.h \ @USE_SHOWNET_TRUE@ plugins/shownet/ShowNetDevice.h \ @USE_SHOWNET_TRUE@ plugins/shownet/ShowNetPort.h \ @USE_SHOWNET_TRUE@ plugins/shownet/ShowNetPackets.h \ @USE_SHOWNET_TRUE@ plugins/shownet/ShowNetNode.h @USE_SHOWNET_TRUE@plugins_shownet_libolashownet_la_LIBADD = \ @USE_SHOWNET_TRUE@ common/libolacommon.la \ @USE_SHOWNET_TRUE@ olad/plugin_api/libolaserverplugininterface.la @USE_SHOWNET_TRUE@plugins_shownet_ShowNetTester_SOURCES = \ @USE_SHOWNET_TRUE@ plugins/shownet/ShowNetNode.cpp \ @USE_SHOWNET_TRUE@ plugins/shownet/ShowNetNodeTest.cpp @USE_SHOWNET_TRUE@plugins_shownet_ShowNetTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) @USE_SHOWNET_TRUE@plugins_shownet_ShowNetTester_LDADD = $(COMMON_TESTING_LIBS) \ @USE_SHOWNET_TRUE@ common/libolacommon.la @USE_SPI_TRUE@plugins_spi_libolaspicore_la_SOURCES = \ @USE_SPI_TRUE@ plugins/spi/SPIBackend.cpp \ @USE_SPI_TRUE@ plugins/spi/SPIBackend.h \ @USE_SPI_TRUE@ plugins/spi/SPIOutput.cpp \ @USE_SPI_TRUE@ plugins/spi/SPIOutput.h \ @USE_SPI_TRUE@ plugins/spi/SPIWriter.cpp \ @USE_SPI_TRUE@ plugins/spi/SPIWriter.h @USE_SPI_TRUE@plugins_spi_libolaspicore_la_LIBADD = common/libolacommon.la @USE_SPI_TRUE@plugins_spi_libolaspi_la_SOURCES = \ @USE_SPI_TRUE@ plugins/spi/SPIDevice.cpp \ @USE_SPI_TRUE@ plugins/spi/SPIDevice.h \ @USE_SPI_TRUE@ plugins/spi/SPIPlugin.cpp \ @USE_SPI_TRUE@ plugins/spi/SPIPlugin.h \ @USE_SPI_TRUE@ plugins/spi/SPIPort.cpp \ @USE_SPI_TRUE@ plugins/spi/SPIPort.h @USE_SPI_TRUE@plugins_spi_libolaspi_la_LIBADD = \ @USE_SPI_TRUE@ common/libolacommon.la \ @USE_SPI_TRUE@ olad/plugin_api/libolaserverplugininterface.la \ @USE_SPI_TRUE@ plugins/spi/libolaspicore.la @USE_SPI_TRUE@plugins_spi_SPITester_SOURCES = \ @USE_SPI_TRUE@ plugins/spi/SPIBackendTest.cpp \ @USE_SPI_TRUE@ plugins/spi/SPIOutputTest.cpp \ @USE_SPI_TRUE@ plugins/spi/FakeSPIWriter.cpp \ @USE_SPI_TRUE@ plugins/spi/FakeSPIWriter.h @USE_SPI_TRUE@plugins_spi_SPITester_CXXFLAGS = $(COMMON_TESTING_FLAGS) @USE_SPI_TRUE@plugins_spi_SPITester_LDADD = $(COMMON_TESTING_LIBS) \ @USE_SPI_TRUE@ plugins/spi/libolaspicore.la \ @USE_SPI_TRUE@ common/libolacommon.la @USE_STAGEPROFI_TRUE@plugins_stageprofi_libolastageprofi_la_SOURCES = \ @USE_STAGEPROFI_TRUE@ plugins/stageprofi/StageProfiDetector.cpp \ @USE_STAGEPROFI_TRUE@ plugins/stageprofi/StageProfiDetector.h \ @USE_STAGEPROFI_TRUE@ plugins/stageprofi/StageProfiDevice.cpp \ @USE_STAGEPROFI_TRUE@ plugins/stageprofi/StageProfiDevice.h \ @USE_STAGEPROFI_TRUE@ plugins/stageprofi/StageProfiPlugin.cpp \ @USE_STAGEPROFI_TRUE@ plugins/stageprofi/StageProfiPlugin.h \ @USE_STAGEPROFI_TRUE@ plugins/stageprofi/StageProfiPort.cpp \ @USE_STAGEPROFI_TRUE@ plugins/stageprofi/StageProfiPort.h \ @USE_STAGEPROFI_TRUE@ plugins/stageprofi/StageProfiWidget.cpp \ @USE_STAGEPROFI_TRUE@ plugins/stageprofi/StageProfiWidget.h @USE_STAGEPROFI_TRUE@plugins_stageprofi_libolastageprofi_la_LIBADD = \ @USE_STAGEPROFI_TRUE@ common/libolacommon.la \ @USE_STAGEPROFI_TRUE@ olad/plugin_api/libolaserverplugininterface.la @USE_LIBUSB_TRUE@plugins_usbdmx_libolausbdmxwidget_la_SOURCES = \ @USE_LIBUSB_TRUE@ plugins/usbdmx/AnymauDMX.cpp \ @USE_LIBUSB_TRUE@ plugins/usbdmx/AnymauDMX.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/AnymauDMXFactory.cpp \ @USE_LIBUSB_TRUE@ plugins/usbdmx/AnymauDMXFactory.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/AsyncUsbReceiver.cpp \ @USE_LIBUSB_TRUE@ plugins/usbdmx/AsyncUsbReceiver.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/AsyncUsbSender.cpp \ @USE_LIBUSB_TRUE@ plugins/usbdmx/AsyncUsbSender.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/AsyncUsbTransceiverBase.cpp \ @USE_LIBUSB_TRUE@ plugins/usbdmx/AsyncUsbTransceiverBase.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/DMXCProjectsNodleU1.cpp \ @USE_LIBUSB_TRUE@ plugins/usbdmx/DMXCProjectsNodleU1.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/DMXCProjectsNodleU1Factory.cpp \ @USE_LIBUSB_TRUE@ plugins/usbdmx/DMXCProjectsNodleU1Factory.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/EurolitePro.cpp \ @USE_LIBUSB_TRUE@ plugins/usbdmx/EurolitePro.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/EuroliteProFactory.cpp \ @USE_LIBUSB_TRUE@ plugins/usbdmx/EuroliteProFactory.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/FirmwareLoader.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/Flags.cpp \ @USE_LIBUSB_TRUE@ plugins/usbdmx/JaRuleFactory.cpp \ @USE_LIBUSB_TRUE@ plugins/usbdmx/JaRuleFactory.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/ScanlimeFadecandy.cpp \ @USE_LIBUSB_TRUE@ plugins/usbdmx/ScanlimeFadecandy.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/ScanlimeFadecandyFactory.cpp \ @USE_LIBUSB_TRUE@ plugins/usbdmx/ScanlimeFadecandyFactory.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/Sunlite.cpp \ @USE_LIBUSB_TRUE@ plugins/usbdmx/Sunlite.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/SunliteFactory.cpp \ @USE_LIBUSB_TRUE@ plugins/usbdmx/SunliteFactory.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/SunliteFirmware.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/SunliteFirmwareLoader.cpp \ @USE_LIBUSB_TRUE@ plugins/usbdmx/SunliteFirmwareLoader.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/SyncronizedWidgetObserver.cpp \ @USE_LIBUSB_TRUE@ plugins/usbdmx/SyncronizedWidgetObserver.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/ThreadedUsbReceiver.cpp \ @USE_LIBUSB_TRUE@ plugins/usbdmx/ThreadedUsbReceiver.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/ThreadedUsbSender.cpp \ @USE_LIBUSB_TRUE@ plugins/usbdmx/ThreadedUsbSender.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/VellemanK8062.cpp \ @USE_LIBUSB_TRUE@ plugins/usbdmx/VellemanK8062.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/VellemanK8062Factory.cpp \ @USE_LIBUSB_TRUE@ plugins/usbdmx/VellemanK8062Factory.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/Widget.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/WidgetFactory.h @USE_LIBUSB_TRUE@plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS = \ @USE_LIBUSB_TRUE@ $(COMMON_CXXFLAGS) \ @USE_LIBUSB_TRUE@ $(libusb_CFLAGS) @USE_LIBUSB_TRUE@plugins_usbdmx_libolausbdmxwidget_la_LIBADD = \ @USE_LIBUSB_TRUE@ $(libusb_LIBS) \ @USE_LIBUSB_TRUE@ common/libolacommon.la \ @USE_LIBUSB_TRUE@ libs/usb/libolausb.la @USE_LIBUSB_TRUE@plugins_usbdmx_libolausbdmx_la_SOURCES = \ @USE_LIBUSB_TRUE@ plugins/usbdmx/AsyncPluginImpl.cpp \ @USE_LIBUSB_TRUE@ plugins/usbdmx/AsyncPluginImpl.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/DMXCProjectsNodleU1Device.cpp \ @USE_LIBUSB_TRUE@ plugins/usbdmx/DMXCProjectsNodleU1Device.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/DMXCProjectsNodleU1Port.cpp \ @USE_LIBUSB_TRUE@ plugins/usbdmx/DMXCProjectsNodleU1Port.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/GenericDevice.cpp \ @USE_LIBUSB_TRUE@ plugins/usbdmx/GenericDevice.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/GenericOutputPort.cpp \ @USE_LIBUSB_TRUE@ plugins/usbdmx/GenericOutputPort.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/JaRuleDevice.cpp \ @USE_LIBUSB_TRUE@ plugins/usbdmx/JaRuleDevice.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/JaRuleOutputPort.cpp \ @USE_LIBUSB_TRUE@ plugins/usbdmx/JaRuleOutputPort.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/PluginImplInterface.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/SyncPluginImpl.cpp \ @USE_LIBUSB_TRUE@ plugins/usbdmx/SyncPluginImpl.h \ @USE_LIBUSB_TRUE@ plugins/usbdmx/UsbDmxPlugin.cpp \ @USE_LIBUSB_TRUE@ plugins/usbdmx/UsbDmxPlugin.h @USE_LIBUSB_TRUE@plugins_usbdmx_libolausbdmx_la_CXXFLAGS = $(COMMON_CXXFLAGS) $(libusb_CFLAGS) @USE_LIBUSB_TRUE@plugins_usbdmx_libolausbdmx_la_LIBADD = \ @USE_LIBUSB_TRUE@ olad/plugin_api/libolaserverplugininterface.la \ @USE_LIBUSB_TRUE@ plugins/usbdmx/libolausbdmxwidget.la @USING_WIN32_FALSE@usbproincludedir = $(includedir)/ola/usbpro @USING_WIN32_FALSE@nodist_usbproinclude_HEADERS = \ @USING_WIN32_FALSE@ plugins/usbpro/messages/UsbProConfigMessages.pb.h @USING_WIN32_FALSE@nodist_plugins_usbpro_messages_libolausbproconf_la_SOURCES = \ @USING_WIN32_FALSE@ plugins/usbpro/messages/UsbProConfigMessages.pb.cc @USING_WIN32_FALSE@plugins_usbpro_messages_libolausbproconf_la_CXXFLAGS = $(COMMON_PROTOBUF_CXXFLAGS) @USING_WIN32_FALSE@plugins_usbpro_messages_libolausbproconf_la_LIBADD = $(libprotobuf_LIBS) @USING_WIN32_FALSE@plugins_usbpro_libolausbprowidget_la_SOURCES = \ @USING_WIN32_FALSE@ plugins/usbpro/ArduinoWidget.cpp \ @USING_WIN32_FALSE@ plugins/usbpro/ArduinoWidget.h \ @USING_WIN32_FALSE@ plugins/usbpro/BaseRobeWidget.cpp \ @USING_WIN32_FALSE@ plugins/usbpro/BaseRobeWidget.h \ @USING_WIN32_FALSE@ plugins/usbpro/BaseUsbProWidget.cpp \ @USING_WIN32_FALSE@ plugins/usbpro/BaseUsbProWidget.h \ @USING_WIN32_FALSE@ plugins/usbpro/DmxTriWidget.cpp \ @USING_WIN32_FALSE@ plugins/usbpro/DmxTriWidget.h \ @USING_WIN32_FALSE@ plugins/usbpro/DmxterWidget.cpp \ @USING_WIN32_FALSE@ plugins/usbpro/DmxterWidget.h \ @USING_WIN32_FALSE@ plugins/usbpro/EnttecUsbProWidget.cpp \ @USING_WIN32_FALSE@ plugins/usbpro/EnttecUsbProWidget.h \ @USING_WIN32_FALSE@ plugins/usbpro/EnttecUsbProWidgetImpl.h \ @USING_WIN32_FALSE@ plugins/usbpro/GenericUsbProWidget.cpp \ @USING_WIN32_FALSE@ plugins/usbpro/GenericUsbProWidget.h \ @USING_WIN32_FALSE@ plugins/usbpro/RobeWidget.cpp \ @USING_WIN32_FALSE@ plugins/usbpro/RobeWidget.h \ @USING_WIN32_FALSE@ plugins/usbpro/RobeWidgetDetector.cpp \ @USING_WIN32_FALSE@ plugins/usbpro/RobeWidgetDetector.h \ @USING_WIN32_FALSE@ plugins/usbpro/SerialWidgetInterface.h \ @USING_WIN32_FALSE@ plugins/usbpro/SerialWidgetInterface.h \ @USING_WIN32_FALSE@ plugins/usbpro/UltraDMXProWidget.cpp \ @USING_WIN32_FALSE@ plugins/usbpro/UltraDMXProWidget.h \ @USING_WIN32_FALSE@ plugins/usbpro/UsbProWidgetDetector.cpp \ @USING_WIN32_FALSE@ plugins/usbpro/UsbProWidgetDetector.h \ @USING_WIN32_FALSE@ plugins/usbpro/WidgetDetectorInterface.h \ @USING_WIN32_FALSE@ plugins/usbpro/WidgetDetectorThread.cpp \ @USING_WIN32_FALSE@ plugins/usbpro/WidgetDetectorThread.h @USING_WIN32_FALSE@plugins_usbpro_libolausbprowidget_la_LIBADD = common/libolacommon.la @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_libolausbpro_la_SOURCES = \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/ArduinoRGBDevice.cpp \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/ArduinoRGBDevice.h \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/DmxTriDevice.cpp \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/DmxTriDevice.h \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/DmxterDevice.cpp \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/DmxterDevice.h \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/RobeDevice.cpp \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/RobeDevice.h \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/UltraDMXProDevice.cpp \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/UltraDMXProDevice.h \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/UsbProDevice.cpp \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/UsbProDevice.h \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/UsbSerialDevice.h \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/UsbSerialPlugin.cpp \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/UsbSerialPlugin.h @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_libolausbpro_la_CXXFLAGS = $(COMMON_PROTOBUF_CXXFLAGS) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_libolausbpro_la_LIBADD = \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ olad/plugin_api/libolaserverplugininterface.la \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/libolausbprowidget.la \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/messages/libolausbproconf.la @USE_USBPRO_TRUE@@USING_WIN32_FALSE@COMMON_USBPRO_TEST_LDADD = $(COMMON_TESTING_LIBS) \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/libolausbprowidget.la @USE_USBPRO_TRUE@@USING_WIN32_FALSE@common_test_sources = \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/CommonWidgetTest.cpp \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/CommonWidgetTest.h \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/MockEndpoint.cpp \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/MockEndpoint.h @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_ArduinoWidgetTester_SOURCES = \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/ArduinoWidgetTest.cpp \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(common_test_sources) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_ArduinoWidgetTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_ArduinoWidgetTester_LDADD = $(COMMON_USBPRO_TEST_LDADD) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_BaseRobeWidgetTester_SOURCES = \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/BaseRobeWidgetTest.cpp \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(common_test_sources) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_BaseRobeWidgetTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_BaseRobeWidgetTester_LDADD = $(COMMON_USBPRO_TEST_LDADD) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_BaseUsbProWidgetTester_SOURCES = \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/BaseUsbProWidgetTest.cpp \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(common_test_sources) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_BaseUsbProWidgetTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_BaseUsbProWidgetTester_LDADD = $(COMMON_USBPRO_TEST_LDADD) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_DmxTriWidgetTester_SOURCES = \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/DmxTriWidgetTest.cpp \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(common_test_sources) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_DmxTriWidgetTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_DmxTriWidgetTester_LDADD = $(COMMON_USBPRO_TEST_LDADD) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_DmxterWidgetTester_SOURCES = \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/DmxterWidgetTest.cpp \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(common_test_sources) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_DmxterWidgetTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_DmxterWidgetTester_LDADD = $(COMMON_USBPRO_TEST_LDADD) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_EnttecUsbProWidgetTester_SOURCES = \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/EnttecUsbProWidgetTest.cpp \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(common_test_sources) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_EnttecUsbProWidgetTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_EnttecUsbProWidgetTester_LDADD = $(COMMON_USBPRO_TEST_LDADD) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_RobeWidgetDetectorTester_SOURCES = \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/RobeWidgetDetectorTest.cpp \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(common_test_sources) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_RobeWidgetDetectorTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_RobeWidgetDetectorTester_LDADD = $(COMMON_USBPRO_TEST_LDADD) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_RobeWidgetTester_SOURCES = \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/RobeWidgetTest.cpp \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(common_test_sources) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_RobeWidgetTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_RobeWidgetTester_LDADD = $(COMMON_USBPRO_TEST_LDADD) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_UltraDMXProWidgetTester_SOURCES = \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/UltraDMXProWidgetTest.cpp \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(common_test_sources) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_UltraDMXProWidgetTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_UltraDMXProWidgetTester_LDADD = $(COMMON_USBPRO_TEST_LDADD) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_UsbProWidgetDetectorTester_SOURCES = \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/UsbProWidgetDetectorTest.cpp \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(common_test_sources) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_UsbProWidgetDetectorTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_UsbProWidgetDetectorTester_LDADD = $(COMMON_USBPRO_TEST_LDADD) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_WidgetDetectorThreadTester_SOURCES = \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ plugins/usbpro/WidgetDetectorThreadTest.cpp \ @USE_USBPRO_TRUE@@USING_WIN32_FALSE@ $(common_test_sources) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_WidgetDetectorThreadTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) @USE_USBPRO_TRUE@@USING_WIN32_FALSE@plugins_usbpro_WidgetDetectorThreadTester_LDADD = $(COMMON_USBPRO_TEST_LDADD) @USE_DMX4LINUX_TRUE@@USING_WIN32_FALSE@plugins_dmx4linux_liboladmx4linux_la_SOURCES = \ @USE_DMX4LINUX_TRUE@@USING_WIN32_FALSE@ plugins/dmx4linux/Dmx4LinuxDevice.cpp \ @USE_DMX4LINUX_TRUE@@USING_WIN32_FALSE@ plugins/dmx4linux/Dmx4LinuxDevice.h \ @USE_DMX4LINUX_TRUE@@USING_WIN32_FALSE@ plugins/dmx4linux/Dmx4LinuxPlugin.cpp \ @USE_DMX4LINUX_TRUE@@USING_WIN32_FALSE@ plugins/dmx4linux/Dmx4LinuxPlugin.h \ @USE_DMX4LINUX_TRUE@@USING_WIN32_FALSE@ plugins/dmx4linux/Dmx4LinuxPort.cpp \ @USE_DMX4LINUX_TRUE@@USING_WIN32_FALSE@ plugins/dmx4linux/Dmx4LinuxPort.h \ @USE_DMX4LINUX_TRUE@@USING_WIN32_FALSE@ plugins/dmx4linux/Dmx4LinuxSocket.h @USE_DMX4LINUX_TRUE@@USING_WIN32_FALSE@plugins_dmx4linux_liboladmx4linux_la_LIBADD = \ @USE_DMX4LINUX_TRUE@@USING_WIN32_FALSE@ common/libolacommon.la \ @USE_DMX4LINUX_TRUE@@USING_WIN32_FALSE@ olad/plugin_api/libolaserverplugininterface.la @USE_E131_TRUE@@USING_WIN32_FALSE@e131includedir = $(includedir)/ola/e131 @USE_E131_TRUE@@USING_WIN32_FALSE@nodist_e131include_HEADERS = \ @USE_E131_TRUE@@USING_WIN32_FALSE@ plugins/e131/messages/E131ConfigMessages.pb.h @USE_E131_TRUE@@USING_WIN32_FALSE@nodist_plugins_e131_messages_libolae131conf_la_SOURCES = \ @USE_E131_TRUE@@USING_WIN32_FALSE@ plugins/e131/messages/E131ConfigMessages.pb.cc @USE_E131_TRUE@@USING_WIN32_FALSE@plugins_e131_messages_libolae131conf_la_CXXFLAGS = $(COMMON_PROTOBUF_CXXFLAGS) @USE_E131_TRUE@@USING_WIN32_FALSE@plugins_e131_messages_libolae131conf_la_LIBADD = $(libprotobuf_LIBS) @USE_E131_TRUE@@USING_WIN32_FALSE@plugins_e131_libolae131_la_SOURCES = \ @USE_E131_TRUE@@USING_WIN32_FALSE@ plugins/e131/E131Device.cpp \ @USE_E131_TRUE@@USING_WIN32_FALSE@ plugins/e131/E131Device.h \ @USE_E131_TRUE@@USING_WIN32_FALSE@ plugins/e131/E131Plugin.cpp \ @USE_E131_TRUE@@USING_WIN32_FALSE@ plugins/e131/E131Plugin.h \ @USE_E131_TRUE@@USING_WIN32_FALSE@ plugins/e131/E131Port.cpp \ @USE_E131_TRUE@@USING_WIN32_FALSE@ plugins/e131/E131Port.h @USE_E131_TRUE@@USING_WIN32_FALSE@plugins_e131_libolae131_la_CXXFLAGS = $(COMMON_PROTOBUF_CXXFLAGS) @USE_E131_TRUE@@USING_WIN32_FALSE@plugins_e131_libolae131_la_LIBADD = \ @USE_E131_TRUE@@USING_WIN32_FALSE@ olad/plugin_api/libolaserverplugininterface.la \ @USE_E131_TRUE@@USING_WIN32_FALSE@ plugins/e131/messages/libolae131conf.la \ @USE_E131_TRUE@@USING_WIN32_FALSE@ libs/acn/libolae131core.la @USE_UART_TRUE@@USING_WIN32_FALSE@plugins_uartdmx_libolauartdmx_la_SOURCES = \ @USE_UART_TRUE@@USING_WIN32_FALSE@ plugins/uartdmx/UartDmxDevice.cpp \ @USE_UART_TRUE@@USING_WIN32_FALSE@ plugins/uartdmx/UartDmxDevice.h \ @USE_UART_TRUE@@USING_WIN32_FALSE@ plugins/uartdmx/UartDmxPlugin.cpp \ @USE_UART_TRUE@@USING_WIN32_FALSE@ plugins/uartdmx/UartDmxPlugin.h \ @USE_UART_TRUE@@USING_WIN32_FALSE@ plugins/uartdmx/UartDmxPort.h \ @USE_UART_TRUE@@USING_WIN32_FALSE@ plugins/uartdmx/UartDmxThread.cpp \ @USE_UART_TRUE@@USING_WIN32_FALSE@ plugins/uartdmx/UartDmxThread.h \ @USE_UART_TRUE@@USING_WIN32_FALSE@ plugins/uartdmx/UartWidget.cpp \ @USE_UART_TRUE@@USING_WIN32_FALSE@ plugins/uartdmx/UartWidget.h @USE_UART_TRUE@@USING_WIN32_FALSE@plugins_uartdmx_libolauartdmx_la_LIBADD = \ @USE_UART_TRUE@@USING_WIN32_FALSE@ common/libolacommon.la \ @USE_UART_TRUE@@USING_WIN32_FALSE@ olad/plugin_api/libolaserverplugininterface.la wwwdir = $(www_datadir) newdir = $(www_datadir)/new viewsdir = $(www_datadir)/new/views jsdir = $(www_datadir)/new/js cssdir = $(www_datadir)/new/css imgdir = $(www_datadir)/new/img jquerydir = $(www_datadir)/new/libs/jquery/js angularroutedir = $(www_datadir)/new/libs/angular-route/js angulardir = $(www_datadir)/new/libs/angular/js bootcssdir = $(www_datadir)/new/libs/bootstrap/css bootjsdir = $(www_datadir)/new/libs/bootstrap/js bootfontsdir = $(www_datadir)/new/libs/bootstrap/fonts dist_www_DATA = \ olad/www/back.png \ olad/www/blank.gif \ olad/www/button-bg.png \ olad/www/console_values.html \ olad/www/custombutton.css \ olad/www/discovery.png \ olad/www/editortoolbar.png \ olad/www/expander.png \ olad/www/forward.png \ olad/www/handle.vertical.png \ olad/www/hide_sections.png \ olad/www/incremental-discovery.png \ olad/www/landing.html \ olad/www/light_bulb_off.png \ olad/www/light_bulb.png \ olad/www/loader-mini.gif \ olad/www/loader.gif \ olad/www/logo-mini.png \ olad/www/logo.png \ olad/www/mobile.html \ olad/www/mobile.js \ olad/www/ola.html \ olad/www/ola.js \ olad/www/refresh.png \ olad/www/show_sections.png \ olad/www/tick.gif \ olad/www/toolbar-bg.png \ olad/www/toolbar.css \ olad/www/toolbar_sprites.png \ olad/www/vertical.gif \ olad/www/wand.png \ olad/www/warning.png dist_new_DATA = \ olad/www/new/index.html dist_views_DATA = \ olad/www/new/views/overview.html \ olad/www/new/views/plugin-info.html \ olad/www/new/views/plugins.html \ olad/www/new/views/universe-add.html \ olad/www/new/views/universe-faders.html \ olad/www/new/views/universe-header.html \ olad/www/new/views/universe-keypad.html \ olad/www/new/views/universe-overview.html \ olad/www/new/views/universe-patch.html \ olad/www/new/views/universe-rdm.html \ olad/www/new/views/universe-settings.html \ olad/www/new/views/universes.html dist_js_DATA = \ olad/www/new/js/app.min.js \ olad/www/new/js/app.min.js.map dist_css_DATA = \ olad/www/new/css/style.min.css dist_img_DATA = \ olad/www/new/img/light_bulb_off.png \ olad/www/new/img/light_bulb.png \ olad/www/new/img/logo-mini.png \ olad/www/new/img/logo.png dist_jquery_DATA = \ olad/www/new/libs/jquery/js/jquery.min.js dist_angularroute_DATA = \ olad/www/new/libs/angular-route/js/angular-route.min.js dist_angular_DATA = \ olad/www/new/libs/angular/js/angular.min.js dist_bootjs_DATA = \ olad/www/new/libs/bootstrap/js/bootstrap.min.js dist_bootfonts_DATA = \ olad/www/new/libs/bootstrap/fonts/glyphicons-halflings-regular.eot \ olad/www/new/libs/bootstrap/fonts/glyphicons-halflings-regular.svg \ olad/www/new/libs/bootstrap/fonts/glyphicons-halflings-regular.ttf \ olad/www/new/libs/bootstrap/fonts/glyphicons-halflings-regular.woff \ olad/www/new/libs/bootstrap/fonts/glyphicons-halflings-regular.woff2 dist_bootcss_DATA = \ olad/www/new/libs/bootstrap/css/bootstrap.min.css # LIBRARIES ################################################## ola_server_sources = olad/ClientBroker.cpp olad/ClientBroker.h \ olad/DiscoveryAgent.cpp olad/DiscoveryAgent.h \ olad/DynamicPluginLoader.cpp olad/DynamicPluginLoader.h \ olad/HttpServerActions.h olad/OlaServerServiceImpl.cpp \ olad/OlaServerServiceImpl.h olad/OladHTTPServer.h \ olad/PluginLoader.h olad/PluginManager.cpp \ olad/PluginManager.h olad/RDMHTTPModule.h $(am__append_80) \ $(am__append_81) $(am__append_83) ola_server_additional_libs = $(am__append_82) $(am__append_84) olad_libolaserver_la_SOURCES = $(ola_server_sources) \ olad/OlaServer.cpp \ olad/OlaDaemon.cpp olad_libolaserver_la_CXXFLAGS = $(COMMON_PROTOBUF_CXXFLAGS) \ -DHTTP_DATA_DIR=\"${www_datadir}\" olad_libolaserver_la_LIBADD = $(PLUGIN_LIBS) \ common/libolacommon.la \ common/web/libolaweb.la \ ola/libola.la \ olad/plugin_api/libolaserverplugininterface.la \ $(ola_server_additional_libs) # Simon: I'm not too sure about this but it seems that because PLUGIN_LIBS is # determined at configure time, we need to add them here. EXTRA_olad_libolaserver_la_DEPENDENCIES = $(PLUGIN_LIBS) olad_olad_SOURCES = olad/Olad.cpp @SUPPORTS_RDYNAMIC_TRUE@olad_olad_LDFLAGS = -rdynamic olad_olad_LDADD = olad/libolaserver.la common/libolacommon.la \ ola/libola.la $(am__append_85) COMMON_OLAD_TEST_LDADD = $(COMMON_TESTING_LIBS) $(libprotobuf_LIBS) \ olad/plugin_api/libolaserverplugininterface.la \ olad/libolaserver.la \ common/libolacommon.la olad_OlaTester_SOURCES = \ olad/PluginManagerTest.cpp \ olad/OlaServerServiceImplTest.cpp olad_OlaTester_CXXFLAGS = $(COMMON_TESTING_PROTOBUF_FLAGS) olad_OlaTester_LDADD = $(COMMON_OLAD_TEST_LDADD) @BUILD_OLA_PROTOC_PLUGIN_TRUE@protoc_ola_protoc_plugin_SOURCES = \ @BUILD_OLA_PROTOC_PLUGIN_TRUE@ protoc/CppFileGenerator.cpp \ @BUILD_OLA_PROTOC_PLUGIN_TRUE@ protoc/CppFileGenerator.h \ @BUILD_OLA_PROTOC_PLUGIN_TRUE@ protoc/CppGenerator.cpp \ @BUILD_OLA_PROTOC_PLUGIN_TRUE@ protoc/CppGenerator.h \ @BUILD_OLA_PROTOC_PLUGIN_TRUE@ protoc/GeneratorHelpers.cpp \ @BUILD_OLA_PROTOC_PLUGIN_TRUE@ protoc/GeneratorHelpers.h \ @BUILD_OLA_PROTOC_PLUGIN_TRUE@ protoc/ServiceGenerator.cpp \ @BUILD_OLA_PROTOC_PLUGIN_TRUE@ protoc/ServiceGenerator.h \ @BUILD_OLA_PROTOC_PLUGIN_TRUE@ protoc/StrUtil.cpp \ @BUILD_OLA_PROTOC_PLUGIN_TRUE@ protoc/StrUtil.h \ @BUILD_OLA_PROTOC_PLUGIN_TRUE@ protoc/ola-protoc-generator-plugin.cpp @BUILD_OLA_PROTOC_PLUGIN_TRUE@protoc_ola_protoc_plugin_CXXFLAGS = $(COMMON_PROTOBUF_CXXFLAGS) @BUILD_OLA_PROTOC_PLUGIN_TRUE@protoc_ola_protoc_plugin_LDADD = $(libprotobuf_LIBS) -lprotoc # Python modules. ################################################## @BUILD_PYTHON_LIBS_TRUE@rpcpythondir = $(pkgpythondir)/rpc @BUILD_PYTHON_LIBS_TRUE@nodist_rpcpython_PYTHON = python/ola/rpc/Rpc_pb2.py @BUILD_PYTHON_LIBS_TRUE@rpcpython_PYTHON = python/ola/rpc/SimpleRpcController.py \ @BUILD_PYTHON_LIBS_TRUE@ python/ola/rpc/StreamRpcChannel.py \ @BUILD_PYTHON_LIBS_TRUE@ python/ola/rpc/__init__.py # Python modules. ################################################## artnet_path = ${top_srcdir}/plugins/artnet/messages artnet_proto = $(artnet_path)/ArtNetConfigMessages.proto ola_path = ${top_srcdir}/common/protocol ola_proto = $(ola_path)/Ola.proto pids_path = ${top_srcdir}/common/rdm pids_proto = $(pids_path)/Pids.proto usbpro_path = ${top_srcdir}/plugins/usbpro/messages usbpro_proto = $(usbpro_path)/UsbProConfigMessages.proto @BUILD_PYTHON_LIBS_TRUE@output_files = \ @BUILD_PYTHON_LIBS_TRUE@ python/ola/ArtNetConfigMessages_pb2.py \ @BUILD_PYTHON_LIBS_TRUE@ python/ola/Ola_pb2.py \ @BUILD_PYTHON_LIBS_TRUE@ python/ola/UsbProConfigMessages_pb2.py \ @BUILD_PYTHON_LIBS_TRUE@ python/ola/Pids_pb2.py \ @BUILD_PYTHON_LIBS_TRUE@ python/ola/PidStoreLocation.py \ @BUILD_PYTHON_LIBS_TRUE@ python/ola/Version.py @BUILD_PYTHON_LIBS_TRUE@nodist_pkgpython_PYTHON = $(output_files) @BUILD_PYTHON_LIBS_TRUE@pkgpython_PYTHON = \ @BUILD_PYTHON_LIBS_TRUE@ python/ola/ClientWrapper.py \ @BUILD_PYTHON_LIBS_TRUE@ python/ola/DMXConstants.py \ @BUILD_PYTHON_LIBS_TRUE@ python/ola/DUBDecoder.py \ @BUILD_PYTHON_LIBS_TRUE@ python/ola/MACAddress.py \ @BUILD_PYTHON_LIBS_TRUE@ python/ola/OlaClient.py \ @BUILD_PYTHON_LIBS_TRUE@ python/ola/RDMAPI.py \ @BUILD_PYTHON_LIBS_TRUE@ python/ola/RDMConstants.py \ @BUILD_PYTHON_LIBS_TRUE@ python/ola/PidStore.py \ @BUILD_PYTHON_LIBS_TRUE@ python/ola/UID.py \ @BUILD_PYTHON_LIBS_TRUE@ python/ola/__init__.py tools_ja_rule_ja_rule_SOURCES = \ tools/ja-rule/USBDeviceManager.cpp \ tools/ja-rule/USBDeviceManager.h \ tools/ja-rule/ja-rule.cpp tools_ja_rule_ja_rule_CXXFLAGS = $(COMMON_CXXFLAGS) $(libusb_CFLAGS) tools_ja_rule_ja_rule_LDADD = $(libusb_LIBS) \ common/libolacommon.la \ plugins/usbdmx/libolausbdmxwidget.la \ libs/usb/libolausb.la tools_ja_rule_ja_rule_controller_SOURCES = \ tools/ja-rule/USBDeviceManager.cpp \ tools/ja-rule/USBDeviceManager.h \ tools/ja-rule/ja-rule-controller.cpp tools_ja_rule_ja_rule_controller_CXXFLAGS = $(COMMON_CXXFLAGS) $(libusb_CFLAGS) tools_ja_rule_ja_rule_controller_LDADD = $(libusb_LIBS) \ common/libolacommon.la \ plugins/usbdmx/libolausbdmxwidget.la \ libs/usb/libolausb.la tools_logic_logic_rdm_sniffer_SOURCES = \ tools/logic/DMXSignalProcessor.cpp \ tools/logic/DMXSignalProcessor.h \ tools/logic/logic-rdm-sniffer.cpp tools_logic_logic_rdm_sniffer_LDADD = common/libolacommon.la \ $(libSaleaeDevice_LIBS) tools_ola_trigger_libolatrigger_la_SOURCES = \ tools/ola_trigger/Action.cpp \ tools/ola_trigger/Action.h \ tools/ola_trigger/Context.cpp \ tools/ola_trigger/Context.h \ tools/ola_trigger/DMXTrigger.cpp \ tools/ola_trigger/DMXTrigger.h \ tools/ola_trigger/VariableInterpolator.h \ tools/ola_trigger/VariableInterpolator.cpp tools_ola_trigger_libolatrigger_la_LIBADD = common/libolacommon.la tools_ola_trigger_ola_trigger_SOURCES = \ tools/ola_trigger/ConfigCommon.h \ tools/ola_trigger/ParserActions.cpp \ tools/ola_trigger/ParserActions.h \ tools/ola_trigger/ParserGlobals.h \ tools/ola_trigger/ola-trigger.cpp nodist_tools_ola_trigger_ola_trigger_SOURCES = \ tools/ola_trigger/config.tab.cpp \ tools/ola_trigger/lex.yy.cpp # required, otherwise we get build errors from the flex output tools_ola_trigger_ola_trigger_CXXFLAGS = $(COMMON_CXXFLAGS_ONLY_WARNINGS) tools_ola_trigger_ola_trigger_LDADD = common/libolacommon.la \ ola/libola.la \ tools/ola_trigger/libolatrigger.la \ $(LEXLIB) tools_ola_trigger_ActionTester_SOURCES = \ tools/ola_trigger/ActionTest.cpp \ tools/ola_trigger/ContextTest.cpp \ tools/ola_trigger/DMXTriggerTest.cpp \ tools/ola_trigger/IntervalTest.cpp \ tools/ola_trigger/MockAction.h \ tools/ola_trigger/SlotTest.cpp \ tools/ola_trigger/VariableInterpolatorTest.cpp tools_ola_trigger_ActionTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) tools_ola_trigger_ActionTester_LDADD = $(COMMON_TESTING_LIBS) \ tools/ola_trigger/libolatrigger.la module_files = \ tools/rdm/DMXSender.py \ tools/rdm/ExpectedResults.py \ tools/rdm/ModelCollector.py \ tools/rdm/ResponderTest.py \ tools/rdm/TestCategory.py \ tools/rdm/TestDefinitions.py \ tools/rdm/TestHelpers.py \ tools/rdm/TestLogger.py \ tools/rdm/TestMixins.py \ tools/rdm/TestRunner.py \ tools/rdm/TimingStats.py \ tools/rdm/TestState.py \ tools/rdm/__init__.py # These files are installed to the directory from DataLocation.py testserver_static_files = \ tools/rdm/static/MIT-LICENSE.txt \ tools/rdm/static/common.css \ tools/rdm/static/jquery-1.7.2.min.js \ tools/rdm/static/jquery-ui-1.8.21.custom.css \ tools/rdm/static/jquery-ui-1.8.21.custom.min.js \ tools/rdm/static/rdm_tests.js \ tools/rdm/static/rdmtests.html \ tools/rdm/static/ui.multiselect.css \ tools/rdm/static/ui.multiselect.js # These files are installed to the images directory under the directory from # DataLocation.py testserver_image_files = \ tools/rdm/static/images/discovery.png \ tools/rdm/static/images/external.png \ tools/rdm/static/images/favicon.ico \ tools/rdm/static/images/loader.gif \ tools/rdm/static/images/logo.png \ tools/rdm/static/images/ui-bg_flat_0_aaaaaa_40x100.png \ tools/rdm/static/images/ui-bg_flat_0_eeeeee_40x100.png \ tools/rdm/static/images/ui-bg_flat_55_c0402a_40x100.png \ tools/rdm/static/images/ui-bg_flat_55_eeeeee_40x100.png \ tools/rdm/static/images/ui-bg_glass_100_f8f8f8_1x400.png \ tools/rdm/static/images/ui-bg_glass_35_dddddd_1x400.png \ tools/rdm/static/images/ui-bg_glass_60_eeeeee_1x400.png \ tools/rdm/static/images/ui-bg_inset-hard_75_999999_1x100.png \ tools/rdm/static/images/ui-bg_inset-soft_50_c9c9c9_1x100.png \ tools/rdm/static/images/ui-icons_3383bb_256x240.png \ tools/rdm/static/images/ui-icons_454545_256x240.png \ tools/rdm/static/images/ui-icons_70b2e1_256x240.png \ tools/rdm/static/images/ui-icons_999999_256x240.png \ tools/rdm/static/images/ui-icons_fbc856_256x240.png launcher_files = \ tools/rdm/launch_tests.py \ tools/rdm/setup_patch.py \ tools/rdm/skel_config/ola-usbserial.conf # RDM Test modules @INSTALL_RDM_TESTS_TRUE@rdmtestsdir = $(pkgpythondir)/testing/rdm @INSTALL_RDM_TESTS_TRUE@rdmtests_PYTHON = $(module_files) @INSTALL_RDM_TESTS_TRUE@nodist_rdmtests_PYTHON = tools/rdm/DataLocation.py # Hack to put the top level __init__.py file in place @INSTALL_RDM_TESTS_TRUE@rdminitdir = $(pkgpythondir)/testing @INSTALL_RDM_TESTS_TRUE@rdminit_PYTHON = tools/rdm/__init__.py # RDM Test Scripts @INSTALL_RDM_TESTS_TRUE@rdmtestsexecdir = $(bindir) @INSTALL_RDM_TESTS_TRUE@dist_rdmtestsexec_SCRIPTS = \ @INSTALL_RDM_TESTS_TRUE@ tools/rdm/rdm_model_collector.py \ @INSTALL_RDM_TESTS_TRUE@ tools/rdm/rdm_responder_test.py \ @INSTALL_RDM_TESTS_TRUE@ tools/rdm/rdm_test_server.py # Data files for the RDM Test Server @INSTALL_RDM_TESTS_TRUE@tools_rdm_testserver_staticdir = $(datadir)/ola/rdm-server @INSTALL_RDM_TESTS_TRUE@dist_tools_rdm_testserver_static_DATA = $(testserver_static_files) @INSTALL_RDM_TESTS_TRUE@tools_rdm_testserver_imagesdir = $(datadir)/ola/rdm-server/images @INSTALL_RDM_TESTS_TRUE@dist_tools_rdm_testserver_images_DATA = $(testserver_image_files) # LIBRARIES ################################################## @USING_WIN32_FALSE@E133_LIBS = \ @USING_WIN32_FALSE@ tools/e133/libolae133common.la \ @USING_WIN32_FALSE@ tools/e133/libolae133controller.la \ @USING_WIN32_FALSE@ tools/e133/libolae133device.la # libolae133common # Code required by both the controller and device. @USING_WIN32_FALSE@tools_e133_libolae133common_la_SOURCES = \ @USING_WIN32_FALSE@ tools/e133/E133HealthCheckedConnection.cpp \ @USING_WIN32_FALSE@ tools/e133/E133HealthCheckedConnection.h \ @USING_WIN32_FALSE@ tools/e133/E133Receiver.cpp \ @USING_WIN32_FALSE@ tools/e133/E133StatusHelper.cpp \ @USING_WIN32_FALSE@ tools/e133/MessageBuilder.cpp @USING_WIN32_FALSE@tools_e133_libolae133common_la_LIBADD = libs/acn/libolae131core.la # libolae133controller # Controller side. @USING_WIN32_FALSE@tools_e133_libolae133controller_la_SOURCES = \ @USING_WIN32_FALSE@ tools/e133/DeviceManager.cpp \ @USING_WIN32_FALSE@ tools/e133/DeviceManagerImpl.cpp \ @USING_WIN32_FALSE@ tools/e133/DeviceManagerImpl.h @USING_WIN32_FALSE@tools_e133_libolae133controller_la_LIBADD = \ @USING_WIN32_FALSE@ common/libolacommon.la \ @USING_WIN32_FALSE@ libs/acn/libolae131core.la \ @USING_WIN32_FALSE@ tools/e133/libolae133common.la # libolae133device # Device side. @USING_WIN32_FALSE@tools_e133_libolae133device_la_SOURCES = \ @USING_WIN32_FALSE@ tools/e133/DesignatedControllerConnection.cpp \ @USING_WIN32_FALSE@ tools/e133/DesignatedControllerConnection.h \ @USING_WIN32_FALSE@ tools/e133/E133Device.cpp \ @USING_WIN32_FALSE@ tools/e133/E133Device.h \ @USING_WIN32_FALSE@ tools/e133/E133Endpoint.cpp \ @USING_WIN32_FALSE@ tools/e133/E133Endpoint.h \ @USING_WIN32_FALSE@ tools/e133/EndpointManager.cpp \ @USING_WIN32_FALSE@ tools/e133/EndpointManager.h \ @USING_WIN32_FALSE@ tools/e133/ManagementEndpoint.cpp \ @USING_WIN32_FALSE@ tools/e133/ManagementEndpoint.h \ @USING_WIN32_FALSE@ tools/e133/SimpleE133Node.cpp \ @USING_WIN32_FALSE@ tools/e133/SimpleE133Node.h \ @USING_WIN32_FALSE@ tools/e133/TCPConnectionStats.h @USING_WIN32_FALSE@tools_e133_libolae133device_la_LIBADD = \ @USING_WIN32_FALSE@ common/libolacommon.la \ @USING_WIN32_FALSE@ libs/acn/libolae131core.la \ @USING_WIN32_FALSE@ tools/e133/libolae133common.la @USING_WIN32_FALSE@tools_e133_e133_receiver_SOURCES = tools/e133/e133-receiver.cpp @USING_WIN32_FALSE@tools_e133_e133_receiver_LDADD = \ @USING_WIN32_FALSE@ common/libolacommon.la \ @USING_WIN32_FALSE@ libs/acn/libolaacn.la \ @USING_WIN32_FALSE@ plugins/usbpro/libolausbprowidget.la \ @USING_WIN32_FALSE@ tools/e133/libolae133device.la \ @USING_WIN32_FALSE@ $(am__append_96) @USING_WIN32_FALSE@tools_e133_e133_monitor_SOURCES = tools/e133/e133-monitor.cpp @USING_WIN32_FALSE@tools_e133_e133_monitor_LDADD = common/libolacommon.la \ @USING_WIN32_FALSE@ libs/acn/libolaacn.la \ @USING_WIN32_FALSE@ tools/e133/libolae133common.la \ @USING_WIN32_FALSE@ tools/e133/libolae133controller.la @USING_WIN32_FALSE@tools_e133_e133_controller_SOURCES = tools/e133/e133-controller.cpp # required for PID_DATA_FILE @USING_WIN32_FALSE@tools_e133_e133_controller_LDADD = common/libolacommon.la \ @USING_WIN32_FALSE@ libs/acn/libolae131core.la \ @USING_WIN32_FALSE@ tools/e133/libolae133common.la \ @USING_WIN32_FALSE@ tools/e133/libolae133controller.la @USING_WIN32_FALSE@tools_e133_basic_controller_SOURCES = tools/e133/basic-controller.cpp @USING_WIN32_FALSE@tools_e133_basic_controller_LDADD = common/libolacommon.la \ @USING_WIN32_FALSE@ libs/acn/libolaacn.la \ @USING_WIN32_FALSE@ tools/e133/libolae133common.la @USING_WIN32_FALSE@tools_e133_basic_device_SOURCES = tools/e133/basic-device.cpp @USING_WIN32_FALSE@tools_e133_basic_device_LDADD = common/libolacommon.la \ @USING_WIN32_FALSE@ libs/acn/libolaacn.la \ @USING_WIN32_FALSE@ tools/e133/libolae133common.la @USING_WIN32_FALSE@tools_usbpro_usbpro_firmware_SOURCES = tools/usbpro/usbpro-firmware.cpp @USING_WIN32_FALSE@tools_usbpro_usbpro_firmware_LDADD = common/libolacommon.la \ @USING_WIN32_FALSE@ plugins/usbpro/libolausbprowidget.la @USING_WIN32_FALSE@tools_rdmpro_rdmpro_sniffer_SOURCES = tools/rdmpro/rdm-sniffer.cpp @USING_WIN32_FALSE@tools_rdmpro_rdmpro_sniffer_LDADD = common/libolacommon.la \ @USING_WIN32_FALSE@ plugins/usbpro/libolausbprowidget.la # I can't figure out how to safely execute a command (mvn) in a subdirectory, # so this is recursive for now. SUBDIRS = java all: $(BUILT_SOURCES) config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: .SUFFIXES: .cc .cpp .lo .log .o .obj .py .py$(EXEEXT) .trs am--refresh: Makefile @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/aminclude.am $(srcdir)/common/Makefile.mk $(srcdir)/common/base/Makefile.mk $(srcdir)/common/dmx/Makefile.mk $(srcdir)/common/export_map/Makefile.mk $(srcdir)/common/file/Makefile.mk $(srcdir)/common/http/Makefile.mk $(srcdir)/common/io/Makefile.mk $(srcdir)/common/math/Makefile.mk $(srcdir)/common/messaging/Makefile.mk $(srcdir)/common/network/Makefile.mk $(srcdir)/common/protocol/Makefile.mk $(srcdir)/common/rdm/Makefile.mk $(srcdir)/common/rpc/Makefile.mk $(srcdir)/common/strings/Makefile.mk $(srcdir)/common/system/Makefile.mk $(srcdir)/common/testing/Makefile.mk $(srcdir)/common/thread/Makefile.mk $(srcdir)/common/timecode/Makefile.mk $(srcdir)/common/utils/Makefile.mk $(srcdir)/common/web/Makefile.mk $(srcdir)/data/Makefile.mk $(srcdir)/data/rdm/Makefile.mk $(srcdir)/debian/Makefile.mk $(srcdir)/doxygen/Makefile.mk $(srcdir)/doxygen/examples/Makefile.mk $(srcdir)/examples/Makefile.mk $(srcdir)/include/Makefile.mk $(srcdir)/include/ola/Makefile.mk $(srcdir)/include/ola/acn/Makefile.mk $(srcdir)/include/ola/base/Makefile.mk $(srcdir)/include/ola/client/Makefile.mk $(srcdir)/include/ola/dmx/Makefile.mk $(srcdir)/include/ola/e133/Makefile.mk $(srcdir)/include/ola/file/Makefile.mk $(srcdir)/include/ola/http/Makefile.mk $(srcdir)/include/ola/io/Makefile.mk $(srcdir)/include/ola/math/Makefile.mk $(srcdir)/include/ola/messaging/Makefile.mk $(srcdir)/include/ola/network/Makefile.mk $(srcdir)/include/ola/rdm/Makefile.mk $(srcdir)/include/ola/rpc/Makefile.mk $(srcdir)/include/ola/stl/Makefile.mk $(srcdir)/include/ola/strings/Makefile.mk $(srcdir)/include/ola/system/Makefile.mk $(srcdir)/include/ola/testing/Makefile.mk $(srcdir)/include/ola/thread/Makefile.mk $(srcdir)/include/ola/timecode/Makefile.mk $(srcdir)/include/ola/util/Makefile.mk $(srcdir)/include/ola/web/Makefile.mk $(srcdir)/include/ola/win/Makefile.mk $(srcdir)/include/olad/Makefile.mk $(srcdir)/javascript/Makefile.mk $(srcdir)/man/Makefile.mk $(srcdir)/libs/Makefile.mk $(srcdir)/libs/acn/Makefile.mk $(srcdir)/libs/usb/Makefile.mk $(srcdir)/ola/Makefile.mk $(srcdir)/olad/plugin_api/Makefile.mk $(srcdir)/plugins/Makefile.mk $(srcdir)/plugins/artnet/Makefile.mk $(srcdir)/plugins/artnet/messages/Makefile.mk $(srcdir)/plugins/dummy/Makefile.mk $(srcdir)/plugins/espnet/Makefile.mk $(srcdir)/plugins/ftdidmx/Makefile.mk $(srcdir)/plugins/gpio/Makefile.mk $(srcdir)/plugins/karate/Makefile.mk $(srcdir)/plugins/kinet/Makefile.mk $(srcdir)/plugins/milinst/Makefile.mk $(srcdir)/plugins/opendmx/Makefile.mk $(srcdir)/plugins/openpixelcontrol/Makefile.mk $(srcdir)/plugins/osc/Makefile.mk $(srcdir)/plugins/pathport/Makefile.mk $(srcdir)/plugins/renard/Makefile.mk $(srcdir)/plugins/sandnet/Makefile.mk $(srcdir)/plugins/shownet/Makefile.mk $(srcdir)/plugins/spi/Makefile.mk $(srcdir)/plugins/stageprofi/Makefile.mk $(srcdir)/plugins/usbdmx/Makefile.mk $(srcdir)/plugins/usbpro/Makefile.mk $(srcdir)/plugins/usbpro/messages/Makefile.mk $(srcdir)/plugins/dmx4linux/Makefile.mk $(srcdir)/plugins/e131/Makefile.mk $(srcdir)/plugins/e131/messages/Makefile.mk $(srcdir)/plugins/uartdmx/Makefile.mk $(srcdir)/olad/Makefile.mk $(srcdir)/olad/www/Makefile.mk $(srcdir)/protoc/Makefile.mk $(srcdir)/python/Makefile.mk $(srcdir)/python/examples/Makefile.mk $(srcdir)/python/ola/Makefile.mk $(srcdir)/python/ola/rpc/Makefile.mk $(srcdir)/tools/Makefile.mk $(srcdir)/tools/ja-rule/Makefile.mk $(srcdir)/tools/logic/Makefile.mk $(srcdir)/tools/ola_trigger/Makefile.mk $(srcdir)/tools/rdm/Makefile.mk $(srcdir)/tools/e133/Makefile.mk $(srcdir)/tools/usbpro/Makefile.mk $(srcdir)/tools/rdmpro/Makefile.mk $(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 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; $(srcdir)/aminclude.am $(srcdir)/common/Makefile.mk $(srcdir)/common/base/Makefile.mk $(srcdir)/common/dmx/Makefile.mk $(srcdir)/common/export_map/Makefile.mk $(srcdir)/common/file/Makefile.mk $(srcdir)/common/http/Makefile.mk $(srcdir)/common/io/Makefile.mk $(srcdir)/common/math/Makefile.mk $(srcdir)/common/messaging/Makefile.mk $(srcdir)/common/network/Makefile.mk $(srcdir)/common/protocol/Makefile.mk $(srcdir)/common/rdm/Makefile.mk $(srcdir)/common/rpc/Makefile.mk $(srcdir)/common/strings/Makefile.mk $(srcdir)/common/system/Makefile.mk $(srcdir)/common/testing/Makefile.mk $(srcdir)/common/thread/Makefile.mk $(srcdir)/common/timecode/Makefile.mk $(srcdir)/common/utils/Makefile.mk $(srcdir)/common/web/Makefile.mk $(srcdir)/data/Makefile.mk $(srcdir)/data/rdm/Makefile.mk $(srcdir)/debian/Makefile.mk $(srcdir)/doxygen/Makefile.mk $(srcdir)/doxygen/examples/Makefile.mk $(srcdir)/examples/Makefile.mk $(srcdir)/include/Makefile.mk $(srcdir)/include/ola/Makefile.mk $(srcdir)/include/ola/acn/Makefile.mk $(srcdir)/include/ola/base/Makefile.mk $(srcdir)/include/ola/client/Makefile.mk $(srcdir)/include/ola/dmx/Makefile.mk $(srcdir)/include/ola/e133/Makefile.mk $(srcdir)/include/ola/file/Makefile.mk $(srcdir)/include/ola/http/Makefile.mk $(srcdir)/include/ola/io/Makefile.mk $(srcdir)/include/ola/math/Makefile.mk $(srcdir)/include/ola/messaging/Makefile.mk $(srcdir)/include/ola/network/Makefile.mk $(srcdir)/include/ola/rdm/Makefile.mk $(srcdir)/include/ola/rpc/Makefile.mk $(srcdir)/include/ola/stl/Makefile.mk $(srcdir)/include/ola/strings/Makefile.mk $(srcdir)/include/ola/system/Makefile.mk $(srcdir)/include/ola/testing/Makefile.mk $(srcdir)/include/ola/thread/Makefile.mk $(srcdir)/include/ola/timecode/Makefile.mk $(srcdir)/include/ola/util/Makefile.mk $(srcdir)/include/ola/web/Makefile.mk $(srcdir)/include/ola/win/Makefile.mk $(srcdir)/include/olad/Makefile.mk $(srcdir)/javascript/Makefile.mk $(srcdir)/man/Makefile.mk $(srcdir)/libs/Makefile.mk $(srcdir)/libs/acn/Makefile.mk $(srcdir)/libs/usb/Makefile.mk $(srcdir)/ola/Makefile.mk $(srcdir)/olad/plugin_api/Makefile.mk $(srcdir)/plugins/Makefile.mk $(srcdir)/plugins/artnet/Makefile.mk $(srcdir)/plugins/artnet/messages/Makefile.mk $(srcdir)/plugins/dummy/Makefile.mk $(srcdir)/plugins/espnet/Makefile.mk $(srcdir)/plugins/ftdidmx/Makefile.mk $(srcdir)/plugins/gpio/Makefile.mk $(srcdir)/plugins/karate/Makefile.mk $(srcdir)/plugins/kinet/Makefile.mk $(srcdir)/plugins/milinst/Makefile.mk $(srcdir)/plugins/opendmx/Makefile.mk $(srcdir)/plugins/openpixelcontrol/Makefile.mk $(srcdir)/plugins/osc/Makefile.mk $(srcdir)/plugins/pathport/Makefile.mk $(srcdir)/plugins/renard/Makefile.mk $(srcdir)/plugins/sandnet/Makefile.mk $(srcdir)/plugins/shownet/Makefile.mk $(srcdir)/plugins/spi/Makefile.mk $(srcdir)/plugins/stageprofi/Makefile.mk $(srcdir)/plugins/usbdmx/Makefile.mk $(srcdir)/plugins/usbpro/Makefile.mk $(srcdir)/plugins/usbpro/messages/Makefile.mk $(srcdir)/plugins/dmx4linux/Makefile.mk $(srcdir)/plugins/e131/Makefile.mk $(srcdir)/plugins/e131/messages/Makefile.mk $(srcdir)/plugins/uartdmx/Makefile.mk $(srcdir)/olad/Makefile.mk $(srcdir)/olad/www/Makefile.mk $(srcdir)/protoc/Makefile.mk $(srcdir)/python/Makefile.mk $(srcdir)/python/examples/Makefile.mk $(srcdir)/python/ola/Makefile.mk $(srcdir)/python/ola/rpc/Makefile.mk $(srcdir)/tools/Makefile.mk $(srcdir)/tools/ja-rule/Makefile.mk $(srcdir)/tools/logic/Makefile.mk $(srcdir)/tools/ola_trigger/Makefile.mk $(srcdir)/tools/rdm/Makefile.mk $(srcdir)/tools/e133/Makefile.mk $(srcdir)/tools/usbpro/Makefile.mk $(srcdir)/tools/rdmpro/Makefile.mk $(am__empty): $(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 @test -f $@ || rm -f stamp-h1 @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 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 include/ola/base/Version.h: $(top_builddir)/config.status $(top_srcdir)/include/ola/base/Version.h.in cd $(top_builddir) && $(SHELL) ./config.status $@ libola.pc: $(top_builddir)/config.status $(srcdir)/libola.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ libolaserver.pc: $(top_builddir)/config.status $(srcdir)/libolaserver.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ libs/acn/libolaacn.pc: $(top_builddir)/config.status $(top_srcdir)/libs/acn/libolaacn.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ ola.spec: $(top_builddir)/config.status $(srcdir)/ola.spec.in cd $(top_builddir) && $(SHELL) ./config.status $@ plugins/artnet/messages/libolaartnetconf.pc: $(top_builddir)/config.status $(top_srcdir)/plugins/artnet/messages/libolaartnetconf.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ plugins/e131/messages/libolae131conf.pc: $(top_builddir)/config.status $(top_srcdir)/plugins/e131/messages/libolae131conf.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ plugins/usbpro/messages/libolausbproconf.pc: $(top_builddir)/config.status $(top_srcdir)/plugins/usbpro/messages/libolausbproconf.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ tools/e133/libolae133common.pc: $(top_builddir)/config.status $(top_srcdir)/tools/e133/libolae133common.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ tools/e133/libolae133controller.pc: $(top_builddir)/config.status $(top_srcdir)/tools/e133/libolae133controller.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } common/http/$(am__dirstamp): @$(MKDIR_P) common/http @: > common/http/$(am__dirstamp) common/http/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) common/http/$(DEPDIR) @: > common/http/$(DEPDIR)/$(am__dirstamp) common/http/HTTPServer.lo: common/http/$(am__dirstamp) \ common/http/$(DEPDIR)/$(am__dirstamp) common/http/OlaHTTPServer.lo: common/http/$(am__dirstamp) \ common/http/$(DEPDIR)/$(am__dirstamp) common/http/libolahttp.la: $(common_http_libolahttp_la_OBJECTS) $(common_http_libolahttp_la_DEPENDENCIES) $(EXTRA_common_http_libolahttp_la_DEPENDENCIES) common/http/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) $(am_common_http_libolahttp_la_rpath) $(common_http_libolahttp_la_OBJECTS) $(common_http_libolahttp_la_LIBADD) $(LIBS) common/base/$(am__dirstamp): @$(MKDIR_P) common/base @: > common/base/$(am__dirstamp) common/base/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) common/base/$(DEPDIR) @: > common/base/$(DEPDIR)/$(am__dirstamp) common/base/common_libolacommon_la-Credentials.lo: \ common/base/$(am__dirstamp) \ common/base/$(DEPDIR)/$(am__dirstamp) common/base/common_libolacommon_la-Env.lo: \ common/base/$(am__dirstamp) \ common/base/$(DEPDIR)/$(am__dirstamp) common/base/common_libolacommon_la-Flags.lo: \ common/base/$(am__dirstamp) \ common/base/$(DEPDIR)/$(am__dirstamp) common/base/common_libolacommon_la-Init.lo: \ common/base/$(am__dirstamp) \ common/base/$(DEPDIR)/$(am__dirstamp) common/base/common_libolacommon_la-Logging.lo: \ common/base/$(am__dirstamp) \ common/base/$(DEPDIR)/$(am__dirstamp) common/base/common_libolacommon_la-SysExits.lo: \ common/base/$(am__dirstamp) \ common/base/$(DEPDIR)/$(am__dirstamp) common/base/common_libolacommon_la-Version.lo: \ common/base/$(am__dirstamp) \ common/base/$(DEPDIR)/$(am__dirstamp) common/dmx/$(am__dirstamp): @$(MKDIR_P) common/dmx @: > common/dmx/$(am__dirstamp) common/dmx/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) common/dmx/$(DEPDIR) @: > common/dmx/$(DEPDIR)/$(am__dirstamp) common/dmx/common_libolacommon_la-RunLengthEncoder.lo: \ common/dmx/$(am__dirstamp) \ common/dmx/$(DEPDIR)/$(am__dirstamp) common/export_map/$(am__dirstamp): @$(MKDIR_P) common/export_map @: > common/export_map/$(am__dirstamp) common/export_map/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) common/export_map/$(DEPDIR) @: > common/export_map/$(DEPDIR)/$(am__dirstamp) common/export_map/common_libolacommon_la-ExportMap.lo: \ common/export_map/$(am__dirstamp) \ common/export_map/$(DEPDIR)/$(am__dirstamp) common/file/$(am__dirstamp): @$(MKDIR_P) common/file @: > common/file/$(am__dirstamp) common/file/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) common/file/$(DEPDIR) @: > common/file/$(DEPDIR)/$(am__dirstamp) common/file/common_libolacommon_la-Util.lo: \ common/file/$(am__dirstamp) \ common/file/$(DEPDIR)/$(am__dirstamp) common/io/$(am__dirstamp): @$(MKDIR_P) common/io @: > common/io/$(am__dirstamp) common/io/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) common/io/$(DEPDIR) @: > common/io/$(DEPDIR)/$(am__dirstamp) common/io/common_libolacommon_la-Descriptor.lo: \ common/io/$(am__dirstamp) common/io/$(DEPDIR)/$(am__dirstamp) common/io/common_libolacommon_la-ExtendedSerial.lo: \ common/io/$(am__dirstamp) common/io/$(DEPDIR)/$(am__dirstamp) common/io/common_libolacommon_la-IOQueue.lo: \ common/io/$(am__dirstamp) common/io/$(DEPDIR)/$(am__dirstamp) common/io/common_libolacommon_la-IOStack.lo: \ common/io/$(am__dirstamp) common/io/$(DEPDIR)/$(am__dirstamp) common/io/common_libolacommon_la-IOUtils.lo: \ common/io/$(am__dirstamp) common/io/$(DEPDIR)/$(am__dirstamp) common/io/common_libolacommon_la-NonBlockingSender.lo: \ common/io/$(am__dirstamp) common/io/$(DEPDIR)/$(am__dirstamp) common/io/common_libolacommon_la-PollerInterface.lo: \ common/io/$(am__dirstamp) common/io/$(DEPDIR)/$(am__dirstamp) common/io/common_libolacommon_la-SelectServer.lo: \ common/io/$(am__dirstamp) common/io/$(DEPDIR)/$(am__dirstamp) common/io/common_libolacommon_la-Serial.lo: common/io/$(am__dirstamp) \ common/io/$(DEPDIR)/$(am__dirstamp) common/io/common_libolacommon_la-StdinHandler.lo: \ common/io/$(am__dirstamp) common/io/$(DEPDIR)/$(am__dirstamp) common/io/common_libolacommon_la-TimeoutManager.lo: \ common/io/$(am__dirstamp) common/io/$(DEPDIR)/$(am__dirstamp) common/io/common_libolacommon_la-WindowsPoller.lo: \ common/io/$(am__dirstamp) common/io/$(DEPDIR)/$(am__dirstamp) common/io/common_libolacommon_la-SelectPoller.lo: \ common/io/$(am__dirstamp) common/io/$(DEPDIR)/$(am__dirstamp) common/io/common_libolacommon_la-EPoller.lo: \ common/io/$(am__dirstamp) common/io/$(DEPDIR)/$(am__dirstamp) common/io/common_libolacommon_la-KQueuePoller.lo: \ common/io/$(am__dirstamp) common/io/$(DEPDIR)/$(am__dirstamp) common/math/$(am__dirstamp): @$(MKDIR_P) common/math @: > common/math/$(am__dirstamp) common/math/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) common/math/$(DEPDIR) @: > common/math/$(DEPDIR)/$(am__dirstamp) common/math/common_libolacommon_la-Random.lo: \ common/math/$(am__dirstamp) \ common/math/$(DEPDIR)/$(am__dirstamp) common/messaging/$(am__dirstamp): @$(MKDIR_P) common/messaging @: > common/messaging/$(am__dirstamp) common/messaging/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) common/messaging/$(DEPDIR) @: > common/messaging/$(DEPDIR)/$(am__dirstamp) common/messaging/common_libolacommon_la-Descriptor.lo: \ common/messaging/$(am__dirstamp) \ common/messaging/$(DEPDIR)/$(am__dirstamp) common/messaging/common_libolacommon_la-Message.lo: \ common/messaging/$(am__dirstamp) \ common/messaging/$(DEPDIR)/$(am__dirstamp) common/messaging/common_libolacommon_la-MessagePrinter.lo: \ common/messaging/$(am__dirstamp) \ common/messaging/$(DEPDIR)/$(am__dirstamp) common/messaging/common_libolacommon_la-SchemaPrinter.lo: \ common/messaging/$(am__dirstamp) \ common/messaging/$(DEPDIR)/$(am__dirstamp) common/network/$(am__dirstamp): @$(MKDIR_P) common/network @: > common/network/$(am__dirstamp) common/network/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) common/network/$(DEPDIR) @: > common/network/$(DEPDIR)/$(am__dirstamp) common/network/common_libolacommon_la-AdvancedTCPConnector.lo: \ common/network/$(am__dirstamp) \ common/network/$(DEPDIR)/$(am__dirstamp) common/network/common_libolacommon_la-HealthCheckedConnection.lo: \ common/network/$(am__dirstamp) \ common/network/$(DEPDIR)/$(am__dirstamp) common/network/common_libolacommon_la-IPV4Address.lo: \ common/network/$(am__dirstamp) \ common/network/$(DEPDIR)/$(am__dirstamp) common/network/common_libolacommon_la-Interface.lo: \ common/network/$(am__dirstamp) \ common/network/$(DEPDIR)/$(am__dirstamp) common/network/common_libolacommon_la-InterfacePicker.lo: \ common/network/$(am__dirstamp) \ common/network/$(DEPDIR)/$(am__dirstamp) common/network/common_libolacommon_la-MACAddress.lo: \ common/network/$(am__dirstamp) \ common/network/$(DEPDIR)/$(am__dirstamp) common/network/common_libolacommon_la-NetworkUtils.lo: \ common/network/$(am__dirstamp) \ common/network/$(DEPDIR)/$(am__dirstamp) common/network/common_libolacommon_la-Socket.lo: \ common/network/$(am__dirstamp) \ common/network/$(DEPDIR)/$(am__dirstamp) common/network/common_libolacommon_la-SocketAddress.lo: \ common/network/$(am__dirstamp) \ common/network/$(DEPDIR)/$(am__dirstamp) common/network/common_libolacommon_la-SocketCloser.lo: \ common/network/$(am__dirstamp) \ common/network/$(DEPDIR)/$(am__dirstamp) common/network/common_libolacommon_la-SocketHelper.lo: \ common/network/$(am__dirstamp) \ common/network/$(DEPDIR)/$(am__dirstamp) common/network/common_libolacommon_la-TCPConnector.lo: \ common/network/$(am__dirstamp) \ common/network/$(DEPDIR)/$(am__dirstamp) common/network/common_libolacommon_la-TCPSocket.lo: \ common/network/$(am__dirstamp) \ common/network/$(DEPDIR)/$(am__dirstamp) common/network/common_libolacommon_la-WindowsInterfacePicker.lo: \ common/network/$(am__dirstamp) \ common/network/$(DEPDIR)/$(am__dirstamp) common/network/common_libolacommon_la-PosixInterfacePicker.lo: \ common/network/$(am__dirstamp) \ common/network/$(DEPDIR)/$(am__dirstamp) common/rdm/$(am__dirstamp): @$(MKDIR_P) common/rdm @: > common/rdm/$(am__dirstamp) common/rdm/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) common/rdm/$(DEPDIR) @: > common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-AckTimerResponder.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-AdvancedDimmerResponder.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-CommandPrinter.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-DescriptorConsistencyChecker.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-DimmerResponder.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-DimmerRootDevice.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-DimmerSubDevice.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-DiscoveryAgent.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-DummyResponder.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-FakeNetworkManager.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-GroupSizeCalculator.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-MessageDeserializer.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-MessageSerializer.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-MovingLightResponder.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-NetworkManager.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-NetworkResponder.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-OpenLightingEnums.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-PidStore.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-PidStoreHelper.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-PidStoreLoader.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-QueueingRDMController.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-RDMAPI.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-RDMCommand.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-RDMCommandSerializer.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-RDMFrame.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-RDMHelper.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-RDMReply.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-ResponderHelper.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-ResponderLoadSensor.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-ResponderPersonality.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-ResponderSettings.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-ResponderSlotData.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-SensorResponder.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-StringMessageBuilder.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-SubDeviceDispatcher.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-UID.lo: common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-VariableFieldSizeCalculator.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rpc/$(am__dirstamp): @$(MKDIR_P) common/rpc @: > common/rpc/$(am__dirstamp) common/rpc/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) common/rpc/$(DEPDIR) @: > common/rpc/$(DEPDIR)/$(am__dirstamp) common/rpc/common_libolacommon_la-RpcChannel.lo: \ common/rpc/$(am__dirstamp) \ common/rpc/$(DEPDIR)/$(am__dirstamp) common/rpc/common_libolacommon_la-RpcController.lo: \ common/rpc/$(am__dirstamp) \ common/rpc/$(DEPDIR)/$(am__dirstamp) common/rpc/common_libolacommon_la-RpcServer.lo: \ common/rpc/$(am__dirstamp) \ common/rpc/$(DEPDIR)/$(am__dirstamp) common/strings/$(am__dirstamp): @$(MKDIR_P) common/strings @: > common/strings/$(am__dirstamp) common/strings/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) common/strings/$(DEPDIR) @: > common/strings/$(DEPDIR)/$(am__dirstamp) common/strings/common_libolacommon_la-Format.lo: \ common/strings/$(am__dirstamp) \ common/strings/$(DEPDIR)/$(am__dirstamp) common/strings/common_libolacommon_la-Utils.lo: \ common/strings/$(am__dirstamp) \ common/strings/$(DEPDIR)/$(am__dirstamp) common/system/$(am__dirstamp): @$(MKDIR_P) common/system @: > common/system/$(am__dirstamp) common/system/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) common/system/$(DEPDIR) @: > common/system/$(DEPDIR)/$(am__dirstamp) common/system/common_libolacommon_la-Limits.lo: \ common/system/$(am__dirstamp) \ common/system/$(DEPDIR)/$(am__dirstamp) common/system/common_libolacommon_la-SystemUtils.lo: \ common/system/$(am__dirstamp) \ common/system/$(DEPDIR)/$(am__dirstamp) common/thread/$(am__dirstamp): @$(MKDIR_P) common/thread @: > common/thread/$(am__dirstamp) common/thread/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) common/thread/$(DEPDIR) @: > common/thread/$(DEPDIR)/$(am__dirstamp) common/thread/common_libolacommon_la-ConsumerThread.lo: \ common/thread/$(am__dirstamp) \ common/thread/$(DEPDIR)/$(am__dirstamp) common/thread/common_libolacommon_la-ExecutorThread.lo: \ common/thread/$(am__dirstamp) \ common/thread/$(DEPDIR)/$(am__dirstamp) common/thread/common_libolacommon_la-Mutex.lo: \ common/thread/$(am__dirstamp) \ common/thread/$(DEPDIR)/$(am__dirstamp) common/thread/common_libolacommon_la-PeriodicThread.lo: \ common/thread/$(am__dirstamp) \ common/thread/$(DEPDIR)/$(am__dirstamp) common/thread/common_libolacommon_la-SignalThread.lo: \ common/thread/$(am__dirstamp) \ common/thread/$(DEPDIR)/$(am__dirstamp) common/thread/common_libolacommon_la-Thread.lo: \ common/thread/$(am__dirstamp) \ common/thread/$(DEPDIR)/$(am__dirstamp) common/thread/common_libolacommon_la-ThreadPool.lo: \ common/thread/$(am__dirstamp) \ common/thread/$(DEPDIR)/$(am__dirstamp) common/thread/common_libolacommon_la-Utils.lo: \ common/thread/$(am__dirstamp) \ common/thread/$(DEPDIR)/$(am__dirstamp) common/timecode/$(am__dirstamp): @$(MKDIR_P) common/timecode @: > common/timecode/$(am__dirstamp) common/timecode/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) common/timecode/$(DEPDIR) @: > common/timecode/$(DEPDIR)/$(am__dirstamp) common/timecode/common_libolacommon_la-TimeCode.lo: \ common/timecode/$(am__dirstamp) \ common/timecode/$(DEPDIR)/$(am__dirstamp) common/utils/$(am__dirstamp): @$(MKDIR_P) common/utils @: > common/utils/$(am__dirstamp) common/utils/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) common/utils/$(DEPDIR) @: > common/utils/$(DEPDIR)/$(am__dirstamp) common/utils/common_libolacommon_la-ActionQueue.lo: \ common/utils/$(am__dirstamp) \ common/utils/$(DEPDIR)/$(am__dirstamp) common/utils/common_libolacommon_la-Clock.lo: \ common/utils/$(am__dirstamp) \ common/utils/$(DEPDIR)/$(am__dirstamp) common/utils/common_libolacommon_la-DmxBuffer.lo: \ common/utils/$(am__dirstamp) \ common/utils/$(DEPDIR)/$(am__dirstamp) common/utils/common_libolacommon_la-StringUtils.lo: \ common/utils/$(am__dirstamp) \ common/utils/$(DEPDIR)/$(am__dirstamp) common/utils/common_libolacommon_la-TokenBucket.lo: \ common/utils/$(am__dirstamp) \ common/utils/$(DEPDIR)/$(am__dirstamp) common/utils/common_libolacommon_la-Watchdog.lo: \ common/utils/$(am__dirstamp) \ common/utils/$(DEPDIR)/$(am__dirstamp) common/rdm/common_libolacommon_la-Pids.pb.lo: \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rpc/common_libolacommon_la-Rpc.pb.lo: \ common/rpc/$(am__dirstamp) \ common/rpc/$(DEPDIR)/$(am__dirstamp) common/$(am__dirstamp): @$(MKDIR_P) common @: > common/$(am__dirstamp) common/libolacommon.la: $(common_libolacommon_la_OBJECTS) $(common_libolacommon_la_DEPENDENCIES) $(EXTRA_common_libolacommon_la_DEPENDENCIES) common/$(am__dirstamp) $(AM_V_CXXLD)$(common_libolacommon_la_LINK) -rpath $(libdir) $(common_libolacommon_la_OBJECTS) $(common_libolacommon_la_LIBADD) $(LIBS) common/protocol/$(am__dirstamp): @$(MKDIR_P) common/protocol @: > common/protocol/$(am__dirstamp) common/protocol/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) common/protocol/$(DEPDIR) @: > common/protocol/$(DEPDIR)/$(am__dirstamp) common/protocol/common_protocol_libolaproto_la-Ola.pb.lo: \ common/protocol/$(am__dirstamp) \ common/protocol/$(DEPDIR)/$(am__dirstamp) common/protocol/common_protocol_libolaproto_la-OlaService.pb.lo: \ common/protocol/$(am__dirstamp) \ common/protocol/$(DEPDIR)/$(am__dirstamp) common/protocol/libolaproto.la: $(common_protocol_libolaproto_la_OBJECTS) $(common_protocol_libolaproto_la_DEPENDENCIES) $(EXTRA_common_protocol_libolaproto_la_DEPENDENCIES) common/protocol/$(am__dirstamp) $(AM_V_CXXLD)$(common_protocol_libolaproto_la_LINK) $(common_protocol_libolaproto_la_OBJECTS) $(common_protocol_libolaproto_la_LIBADD) $(LIBS) common/testing/$(am__dirstamp): @$(MKDIR_P) common/testing @: > common/testing/$(am__dirstamp) common/testing/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) common/testing/$(DEPDIR) @: > common/testing/$(DEPDIR)/$(am__dirstamp) common/testing/MockUDPSocket.lo: common/testing/$(am__dirstamp) \ common/testing/$(DEPDIR)/$(am__dirstamp) common/testing/TestUtils.lo: common/testing/$(am__dirstamp) \ common/testing/$(DEPDIR)/$(am__dirstamp) common/testing/libolatesting.la: $(common_testing_libolatesting_la_OBJECTS) $(common_testing_libolatesting_la_DEPENDENCIES) $(EXTRA_common_testing_libolatesting_la_DEPENDENCIES) common/testing/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) $(am_common_testing_libolatesting_la_rpath) $(common_testing_libolatesting_la_OBJECTS) $(common_testing_libolatesting_la_LIBADD) $(LIBS) common/testing/GenericTester.lo: common/testing/$(am__dirstamp) \ common/testing/$(DEPDIR)/$(am__dirstamp) common/testing/libtestmain.la: $(common_testing_libtestmain_la_OBJECTS) $(common_testing_libtestmain_la_DEPENDENCIES) $(EXTRA_common_testing_libtestmain_la_DEPENDENCIES) common/testing/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) $(am_common_testing_libtestmain_la_rpath) $(common_testing_libtestmain_la_OBJECTS) $(common_testing_libtestmain_la_LIBADD) $(LIBS) common/web/$(am__dirstamp): @$(MKDIR_P) common/web @: > common/web/$(am__dirstamp) common/web/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) common/web/$(DEPDIR) @: > common/web/$(DEPDIR)/$(am__dirstamp) common/web/Json.lo: common/web/$(am__dirstamp) \ common/web/$(DEPDIR)/$(am__dirstamp) common/web/JsonData.lo: common/web/$(am__dirstamp) \ common/web/$(DEPDIR)/$(am__dirstamp) common/web/JsonLexer.lo: common/web/$(am__dirstamp) \ common/web/$(DEPDIR)/$(am__dirstamp) common/web/JsonParser.lo: common/web/$(am__dirstamp) \ common/web/$(DEPDIR)/$(am__dirstamp) common/web/JsonPatch.lo: common/web/$(am__dirstamp) \ common/web/$(DEPDIR)/$(am__dirstamp) common/web/JsonPatchParser.lo: common/web/$(am__dirstamp) \ common/web/$(DEPDIR)/$(am__dirstamp) common/web/JsonPointer.lo: common/web/$(am__dirstamp) \ common/web/$(DEPDIR)/$(am__dirstamp) common/web/JsonSchema.lo: common/web/$(am__dirstamp) \ common/web/$(DEPDIR)/$(am__dirstamp) common/web/JsonSections.lo: common/web/$(am__dirstamp) \ common/web/$(DEPDIR)/$(am__dirstamp) common/web/JsonTypes.lo: common/web/$(am__dirstamp) \ common/web/$(DEPDIR)/$(am__dirstamp) common/web/JsonWriter.lo: common/web/$(am__dirstamp) \ common/web/$(DEPDIR)/$(am__dirstamp) common/web/PointerTracker.lo: common/web/$(am__dirstamp) \ common/web/$(DEPDIR)/$(am__dirstamp) common/web/SchemaErrorLogger.lo: common/web/$(am__dirstamp) \ common/web/$(DEPDIR)/$(am__dirstamp) common/web/SchemaKeywords.lo: common/web/$(am__dirstamp) \ common/web/$(DEPDIR)/$(am__dirstamp) common/web/SchemaParseContext.lo: common/web/$(am__dirstamp) \ common/web/$(DEPDIR)/$(am__dirstamp) common/web/SchemaParser.lo: common/web/$(am__dirstamp) \ common/web/$(DEPDIR)/$(am__dirstamp) common/web/libolaweb.la: $(common_web_libolaweb_la_OBJECTS) $(common_web_libolaweb_la_DEPENDENCIES) $(EXTRA_common_web_libolaweb_la_DEPENDENCIES) common/web/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) $(common_web_libolaweb_la_OBJECTS) $(common_web_libolaweb_la_LIBADD) $(LIBS) examples/$(am__dirstamp): @$(MKDIR_P) examples @: > examples/$(am__dirstamp) examples/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) examples/$(DEPDIR) @: > examples/$(DEPDIR)/$(am__dirstamp) examples/examples_libolaconfig_la-OlaConfigurator.lo: \ examples/$(am__dirstamp) examples/$(DEPDIR)/$(am__dirstamp) examples/libolaconfig.la: $(examples_libolaconfig_la_OBJECTS) $(examples_libolaconfig_la_DEPENDENCIES) $(EXTRA_examples_libolaconfig_la_DEPENDENCIES) examples/$(am__dirstamp) $(AM_V_CXXLD)$(examples_libolaconfig_la_LINK) $(am_examples_libolaconfig_la_rpath) $(examples_libolaconfig_la_OBJECTS) $(examples_libolaconfig_la_LIBADD) $(LIBS) libs/acn/$(am__dirstamp): @$(MKDIR_P) libs/acn @: > libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) libs/acn/$(DEPDIR) @: > libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_libolaacn_la-CID.lo: libs/acn/$(am__dirstamp) \ libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_libolaacn_la-CIDImpl.lo: libs/acn/$(am__dirstamp) \ libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libolaacn.la: $(libs_acn_libolaacn_la_OBJECTS) $(libs_acn_libolaacn_la_DEPENDENCIES) $(EXTRA_libs_acn_libolaacn_la_DEPENDENCIES) libs/acn/$(am__dirstamp) $(AM_V_CXXLD)$(libs_acn_libolaacn_la_LINK) $(am_libs_acn_libolaacn_la_rpath) $(libs_acn_libolaacn_la_OBJECTS) $(libs_acn_libolaacn_la_LIBADD) $(LIBS) libs/acn/libs_acn_libolae131core_la-BaseInflator.lo: \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_libolae131core_la-DMPAddress.lo: \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_libolae131core_la-DMPE131Inflator.lo: \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_libolae131core_la-DMPInflator.lo: \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_libolae131core_la-DMPPDU.lo: \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_libolae131core_la-E131DiscoveryInflator.lo: \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_libolae131core_la-E131Inflator.lo: \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_libolae131core_la-E131Node.lo: \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_libolae131core_la-E131PDU.lo: \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_libolae131core_la-E131Sender.lo: \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_libolae131core_la-E133Inflator.lo: \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_libolae131core_la-E133PDU.lo: \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_libolae131core_la-E133StatusInflator.lo: \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_libolae131core_la-E133StatusPDU.lo: \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_libolae131core_la-PDU.lo: libs/acn/$(am__dirstamp) \ libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_libolae131core_la-PreamblePacker.lo: \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_libolae131core_la-RDMInflator.lo: \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_libolae131core_la-RDMPDU.lo: \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_libolae131core_la-RootInflator.lo: \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_libolae131core_la-RootPDU.lo: \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_libolae131core_la-RootSender.lo: \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_libolae131core_la-TCPTransport.lo: \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_libolae131core_la-UDPTransport.lo: \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libolae131core.la: $(libs_acn_libolae131core_la_OBJECTS) $(libs_acn_libolae131core_la_DEPENDENCIES) $(EXTRA_libs_acn_libolae131core_la_DEPENDENCIES) libs/acn/$(am__dirstamp) $(AM_V_CXXLD)$(libs_acn_libolae131core_la_LINK) $(libs_acn_libolae131core_la_OBJECTS) $(libs_acn_libolae131core_la_LIBADD) $(LIBS) libs/usb/$(am__dirstamp): @$(MKDIR_P) libs/usb @: > libs/usb/$(am__dirstamp) libs/usb/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) libs/usb/$(DEPDIR) @: > libs/usb/$(DEPDIR)/$(am__dirstamp) libs/usb/libs_usb_libolausb_la-HotplugAgent.lo: \ libs/usb/$(am__dirstamp) libs/usb/$(DEPDIR)/$(am__dirstamp) libs/usb/libs_usb_libolausb_la-JaRuleConstants.lo: \ libs/usb/$(am__dirstamp) libs/usb/$(DEPDIR)/$(am__dirstamp) libs/usb/libs_usb_libolausb_la-JaRulePortHandle.lo: \ libs/usb/$(am__dirstamp) libs/usb/$(DEPDIR)/$(am__dirstamp) libs/usb/libs_usb_libolausb_la-JaRulePortHandleImpl.lo: \ libs/usb/$(am__dirstamp) libs/usb/$(DEPDIR)/$(am__dirstamp) libs/usb/libs_usb_libolausb_la-JaRuleWidget.lo: \ libs/usb/$(am__dirstamp) libs/usb/$(DEPDIR)/$(am__dirstamp) libs/usb/libs_usb_libolausb_la-JaRuleWidgetPort.lo: \ libs/usb/$(am__dirstamp) libs/usb/$(DEPDIR)/$(am__dirstamp) libs/usb/libs_usb_libolausb_la-LibUsbAdaptor.lo: \ libs/usb/$(am__dirstamp) libs/usb/$(DEPDIR)/$(am__dirstamp) libs/usb/libs_usb_libolausb_la-LibUsbThread.lo: \ libs/usb/$(am__dirstamp) libs/usb/$(DEPDIR)/$(am__dirstamp) libs/usb/libs_usb_libolausb_la-Types.lo: libs/usb/$(am__dirstamp) \ libs/usb/$(DEPDIR)/$(am__dirstamp) libs/usb/libolausb.la: $(libs_usb_libolausb_la_OBJECTS) $(libs_usb_libolausb_la_DEPENDENCIES) $(EXTRA_libs_usb_libolausb_la_DEPENDENCIES) libs/usb/$(am__dirstamp) $(AM_V_CXXLD)$(libs_usb_libolausb_la_LINK) $(am_libs_usb_libolausb_la_rpath) $(libs_usb_libolausb_la_OBJECTS) $(libs_usb_libolausb_la_LIBADD) $(LIBS) ola/$(am__dirstamp): @$(MKDIR_P) ola @: > ola/$(am__dirstamp) ola/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) ola/$(DEPDIR) @: > ola/$(DEPDIR)/$(am__dirstamp) ola/ola_libola_la-AutoStart.lo: ola/$(am__dirstamp) \ ola/$(DEPDIR)/$(am__dirstamp) ola/ola_libola_la-ClientRDMAPIShim.lo: ola/$(am__dirstamp) \ ola/$(DEPDIR)/$(am__dirstamp) ola/ola_libola_la-ClientTypesFactory.lo: ola/$(am__dirstamp) \ ola/$(DEPDIR)/$(am__dirstamp) ola/ola_libola_la-Module.lo: ola/$(am__dirstamp) \ ola/$(DEPDIR)/$(am__dirstamp) ola/ola_libola_la-OlaCallbackClient.lo: ola/$(am__dirstamp) \ ola/$(DEPDIR)/$(am__dirstamp) ola/ola_libola_la-OlaClient.lo: ola/$(am__dirstamp) \ ola/$(DEPDIR)/$(am__dirstamp) ola/ola_libola_la-OlaClientCore.lo: ola/$(am__dirstamp) \ ola/$(DEPDIR)/$(am__dirstamp) ola/ola_libola_la-OlaClientWrapper.lo: ola/$(am__dirstamp) \ ola/$(DEPDIR)/$(am__dirstamp) ola/ola_libola_la-StreamingClient.lo: ola/$(am__dirstamp) \ ola/$(DEPDIR)/$(am__dirstamp) ola/libola.la: $(ola_libola_la_OBJECTS) $(ola_libola_la_DEPENDENCIES) $(EXTRA_ola_libola_la_DEPENDENCIES) ola/$(am__dirstamp) $(AM_V_CXXLD)$(ola_libola_la_LINK) -rpath $(libdir) $(ola_libola_la_OBJECTS) $(ola_libola_la_LIBADD) $(LIBS) olad/$(am__dirstamp): @$(MKDIR_P) olad @: > olad/$(am__dirstamp) olad/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) olad/$(DEPDIR) @: > olad/$(DEPDIR)/$(am__dirstamp) olad/olad_libolaserver_la-ClientBroker.lo: olad/$(am__dirstamp) \ olad/$(DEPDIR)/$(am__dirstamp) olad/olad_libolaserver_la-DiscoveryAgent.lo: olad/$(am__dirstamp) \ olad/$(DEPDIR)/$(am__dirstamp) olad/olad_libolaserver_la-DynamicPluginLoader.lo: \ olad/$(am__dirstamp) olad/$(DEPDIR)/$(am__dirstamp) olad/olad_libolaserver_la-OlaServerServiceImpl.lo: \ olad/$(am__dirstamp) olad/$(DEPDIR)/$(am__dirstamp) olad/olad_libolaserver_la-PluginManager.lo: olad/$(am__dirstamp) \ olad/$(DEPDIR)/$(am__dirstamp) olad/olad_libolaserver_la-BonjourDiscoveryAgent.lo: \ olad/$(am__dirstamp) olad/$(DEPDIR)/$(am__dirstamp) olad/olad_libolaserver_la-AvahiDiscoveryAgent.lo: \ olad/$(am__dirstamp) olad/$(DEPDIR)/$(am__dirstamp) olad/olad_libolaserver_la-HttpServerActions.lo: olad/$(am__dirstamp) \ olad/$(DEPDIR)/$(am__dirstamp) olad/olad_libolaserver_la-OladHTTPServer.lo: olad/$(am__dirstamp) \ olad/$(DEPDIR)/$(am__dirstamp) olad/olad_libolaserver_la-RDMHTTPModule.lo: olad/$(am__dirstamp) \ olad/$(DEPDIR)/$(am__dirstamp) olad/olad_libolaserver_la-OlaServer.lo: olad/$(am__dirstamp) \ olad/$(DEPDIR)/$(am__dirstamp) olad/olad_libolaserver_la-OlaDaemon.lo: olad/$(am__dirstamp) \ olad/$(DEPDIR)/$(am__dirstamp) olad/libolaserver.la: $(olad_libolaserver_la_OBJECTS) $(olad_libolaserver_la_DEPENDENCIES) $(EXTRA_olad_libolaserver_la_DEPENDENCIES) olad/$(am__dirstamp) $(AM_V_CXXLD)$(olad_libolaserver_la_LINK) -rpath $(libdir) $(olad_libolaserver_la_OBJECTS) $(olad_libolaserver_la_LIBADD) $(LIBS) olad/plugin_api/$(am__dirstamp): @$(MKDIR_P) olad/plugin_api @: > olad/plugin_api/$(am__dirstamp) olad/plugin_api/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) olad/plugin_api/$(DEPDIR) @: > olad/plugin_api/$(DEPDIR)/$(am__dirstamp) olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Client.lo: \ olad/plugin_api/$(am__dirstamp) \ olad/plugin_api/$(DEPDIR)/$(am__dirstamp) olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Device.lo: \ olad/plugin_api/$(am__dirstamp) \ olad/plugin_api/$(DEPDIR)/$(am__dirstamp) olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-DeviceManager.lo: \ olad/plugin_api/$(am__dirstamp) \ olad/plugin_api/$(DEPDIR)/$(am__dirstamp) olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-DmxSource.lo: \ olad/plugin_api/$(am__dirstamp) \ olad/plugin_api/$(DEPDIR)/$(am__dirstamp) olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Plugin.lo: \ olad/plugin_api/$(am__dirstamp) \ olad/plugin_api/$(DEPDIR)/$(am__dirstamp) olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-PluginAdaptor.lo: \ olad/plugin_api/$(am__dirstamp) \ olad/plugin_api/$(DEPDIR)/$(am__dirstamp) olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Port.lo: \ olad/plugin_api/$(am__dirstamp) \ olad/plugin_api/$(DEPDIR)/$(am__dirstamp) olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-PortBroker.lo: \ olad/plugin_api/$(am__dirstamp) \ olad/plugin_api/$(DEPDIR)/$(am__dirstamp) olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-PortManager.lo: \ olad/plugin_api/$(am__dirstamp) \ olad/plugin_api/$(DEPDIR)/$(am__dirstamp) olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Preferences.lo: \ olad/plugin_api/$(am__dirstamp) \ olad/plugin_api/$(DEPDIR)/$(am__dirstamp) olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Universe.lo: \ olad/plugin_api/$(am__dirstamp) \ olad/plugin_api/$(DEPDIR)/$(am__dirstamp) olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-UniverseStore.lo: \ olad/plugin_api/$(am__dirstamp) \ olad/plugin_api/$(DEPDIR)/$(am__dirstamp) olad/plugin_api/libolaserverplugininterface.la: $(olad_plugin_api_libolaserverplugininterface_la_OBJECTS) $(olad_plugin_api_libolaserverplugininterface_la_DEPENDENCIES) $(EXTRA_olad_plugin_api_libolaserverplugininterface_la_DEPENDENCIES) olad/plugin_api/$(am__dirstamp) $(AM_V_CXXLD)$(olad_plugin_api_libolaserverplugininterface_la_LINK) -rpath $(libdir) $(olad_plugin_api_libolaserverplugininterface_la_OBJECTS) $(olad_plugin_api_libolaserverplugininterface_la_LIBADD) $(LIBS) plugins/artnet/$(am__dirstamp): @$(MKDIR_P) plugins/artnet @: > plugins/artnet/$(am__dirstamp) plugins/artnet/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) plugins/artnet/$(DEPDIR) @: > plugins/artnet/$(DEPDIR)/$(am__dirstamp) plugins/artnet/plugins_artnet_libolaartnet_la-ArtNetPlugin.lo: \ plugins/artnet/$(am__dirstamp) \ plugins/artnet/$(DEPDIR)/$(am__dirstamp) plugins/artnet/plugins_artnet_libolaartnet_la-ArtNetDevice.lo: \ plugins/artnet/$(am__dirstamp) \ plugins/artnet/$(DEPDIR)/$(am__dirstamp) plugins/artnet/plugins_artnet_libolaartnet_la-ArtNetPort.lo: \ plugins/artnet/$(am__dirstamp) \ plugins/artnet/$(DEPDIR)/$(am__dirstamp) plugins/artnet/libolaartnet.la: $(plugins_artnet_libolaartnet_la_OBJECTS) $(plugins_artnet_libolaartnet_la_DEPENDENCIES) $(EXTRA_plugins_artnet_libolaartnet_la_DEPENDENCIES) plugins/artnet/$(am__dirstamp) $(AM_V_CXXLD)$(plugins_artnet_libolaartnet_la_LINK) $(am_plugins_artnet_libolaartnet_la_rpath) $(plugins_artnet_libolaartnet_la_OBJECTS) $(plugins_artnet_libolaartnet_la_LIBADD) $(LIBS) plugins/artnet/ArtNetNode.lo: plugins/artnet/$(am__dirstamp) \ plugins/artnet/$(DEPDIR)/$(am__dirstamp) plugins/artnet/libolaartnetnode.la: $(plugins_artnet_libolaartnetnode_la_OBJECTS) $(plugins_artnet_libolaartnetnode_la_DEPENDENCIES) $(EXTRA_plugins_artnet_libolaartnetnode_la_DEPENDENCIES) plugins/artnet/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) $(am_plugins_artnet_libolaartnetnode_la_rpath) $(plugins_artnet_libolaartnetnode_la_OBJECTS) $(plugins_artnet_libolaartnetnode_la_LIBADD) $(LIBS) plugins/artnet/messages/$(am__dirstamp): @$(MKDIR_P) plugins/artnet/messages @: > plugins/artnet/messages/$(am__dirstamp) plugins/artnet/messages/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) plugins/artnet/messages/$(DEPDIR) @: > plugins/artnet/messages/$(DEPDIR)/$(am__dirstamp) plugins/artnet/messages/plugins_artnet_messages_libolaartnetconf_la-ArtNetConfigMessages.pb.lo: \ plugins/artnet/messages/$(am__dirstamp) \ plugins/artnet/messages/$(DEPDIR)/$(am__dirstamp) plugins/artnet/messages/libolaartnetconf.la: $(plugins_artnet_messages_libolaartnetconf_la_OBJECTS) $(plugins_artnet_messages_libolaartnetconf_la_DEPENDENCIES) $(EXTRA_plugins_artnet_messages_libolaartnetconf_la_DEPENDENCIES) plugins/artnet/messages/$(am__dirstamp) $(AM_V_CXXLD)$(plugins_artnet_messages_libolaartnetconf_la_LINK) $(am_plugins_artnet_messages_libolaartnetconf_la_rpath) $(plugins_artnet_messages_libolaartnetconf_la_OBJECTS) $(plugins_artnet_messages_libolaartnetconf_la_LIBADD) $(LIBS) plugins/dmx4linux/$(am__dirstamp): @$(MKDIR_P) plugins/dmx4linux @: > plugins/dmx4linux/$(am__dirstamp) plugins/dmx4linux/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) plugins/dmx4linux/$(DEPDIR) @: > plugins/dmx4linux/$(DEPDIR)/$(am__dirstamp) plugins/dmx4linux/Dmx4LinuxDevice.lo: \ plugins/dmx4linux/$(am__dirstamp) \ plugins/dmx4linux/$(DEPDIR)/$(am__dirstamp) plugins/dmx4linux/Dmx4LinuxPlugin.lo: \ plugins/dmx4linux/$(am__dirstamp) \ plugins/dmx4linux/$(DEPDIR)/$(am__dirstamp) plugins/dmx4linux/Dmx4LinuxPort.lo: plugins/dmx4linux/$(am__dirstamp) \ plugins/dmx4linux/$(DEPDIR)/$(am__dirstamp) plugins/dmx4linux/liboladmx4linux.la: $(plugins_dmx4linux_liboladmx4linux_la_OBJECTS) $(plugins_dmx4linux_liboladmx4linux_la_DEPENDENCIES) $(EXTRA_plugins_dmx4linux_liboladmx4linux_la_DEPENDENCIES) plugins/dmx4linux/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) $(am_plugins_dmx4linux_liboladmx4linux_la_rpath) $(plugins_dmx4linux_liboladmx4linux_la_OBJECTS) $(plugins_dmx4linux_liboladmx4linux_la_LIBADD) $(LIBS) plugins/dummy/$(am__dirstamp): @$(MKDIR_P) plugins/dummy @: > plugins/dummy/$(am__dirstamp) plugins/dummy/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) plugins/dummy/$(DEPDIR) @: > plugins/dummy/$(DEPDIR)/$(am__dirstamp) plugins/dummy/DummyDevice.lo: plugins/dummy/$(am__dirstamp) \ plugins/dummy/$(DEPDIR)/$(am__dirstamp) plugins/dummy/DummyPlugin.lo: plugins/dummy/$(am__dirstamp) \ plugins/dummy/$(DEPDIR)/$(am__dirstamp) plugins/dummy/DummyPort.lo: plugins/dummy/$(am__dirstamp) \ plugins/dummy/$(DEPDIR)/$(am__dirstamp) plugins/dummy/liboladummy.la: $(plugins_dummy_liboladummy_la_OBJECTS) $(plugins_dummy_liboladummy_la_DEPENDENCIES) $(EXTRA_plugins_dummy_liboladummy_la_DEPENDENCIES) plugins/dummy/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) $(am_plugins_dummy_liboladummy_la_rpath) $(plugins_dummy_liboladummy_la_OBJECTS) $(plugins_dummy_liboladummy_la_LIBADD) $(LIBS) plugins/e131/$(am__dirstamp): @$(MKDIR_P) plugins/e131 @: > plugins/e131/$(am__dirstamp) plugins/e131/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) plugins/e131/$(DEPDIR) @: > plugins/e131/$(DEPDIR)/$(am__dirstamp) plugins/e131/plugins_e131_libolae131_la-E131Device.lo: \ plugins/e131/$(am__dirstamp) \ plugins/e131/$(DEPDIR)/$(am__dirstamp) plugins/e131/plugins_e131_libolae131_la-E131Plugin.lo: \ plugins/e131/$(am__dirstamp) \ plugins/e131/$(DEPDIR)/$(am__dirstamp) plugins/e131/plugins_e131_libolae131_la-E131Port.lo: \ plugins/e131/$(am__dirstamp) \ plugins/e131/$(DEPDIR)/$(am__dirstamp) plugins/e131/libolae131.la: $(plugins_e131_libolae131_la_OBJECTS) $(plugins_e131_libolae131_la_DEPENDENCIES) $(EXTRA_plugins_e131_libolae131_la_DEPENDENCIES) plugins/e131/$(am__dirstamp) $(AM_V_CXXLD)$(plugins_e131_libolae131_la_LINK) $(am_plugins_e131_libolae131_la_rpath) $(plugins_e131_libolae131_la_OBJECTS) $(plugins_e131_libolae131_la_LIBADD) $(LIBS) plugins/e131/messages/$(am__dirstamp): @$(MKDIR_P) plugins/e131/messages @: > plugins/e131/messages/$(am__dirstamp) plugins/e131/messages/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) plugins/e131/messages/$(DEPDIR) @: > plugins/e131/messages/$(DEPDIR)/$(am__dirstamp) plugins/e131/messages/plugins_e131_messages_libolae131conf_la-E131ConfigMessages.pb.lo: \ plugins/e131/messages/$(am__dirstamp) \ plugins/e131/messages/$(DEPDIR)/$(am__dirstamp) plugins/e131/messages/libolae131conf.la: $(plugins_e131_messages_libolae131conf_la_OBJECTS) $(plugins_e131_messages_libolae131conf_la_DEPENDENCIES) $(EXTRA_plugins_e131_messages_libolae131conf_la_DEPENDENCIES) plugins/e131/messages/$(am__dirstamp) $(AM_V_CXXLD)$(plugins_e131_messages_libolae131conf_la_LINK) $(am_plugins_e131_messages_libolae131conf_la_rpath) $(plugins_e131_messages_libolae131conf_la_OBJECTS) $(plugins_e131_messages_libolae131conf_la_LIBADD) $(LIBS) plugins/espnet/$(am__dirstamp): @$(MKDIR_P) plugins/espnet @: > plugins/espnet/$(am__dirstamp) plugins/espnet/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) plugins/espnet/$(DEPDIR) @: > plugins/espnet/$(DEPDIR)/$(am__dirstamp) plugins/espnet/EspNetDevice.lo: plugins/espnet/$(am__dirstamp) \ plugins/espnet/$(DEPDIR)/$(am__dirstamp) plugins/espnet/EspNetNode.lo: plugins/espnet/$(am__dirstamp) \ plugins/espnet/$(DEPDIR)/$(am__dirstamp) plugins/espnet/EspNetPlugin.lo: plugins/espnet/$(am__dirstamp) \ plugins/espnet/$(DEPDIR)/$(am__dirstamp) plugins/espnet/EspNetPort.lo: plugins/espnet/$(am__dirstamp) \ plugins/espnet/$(DEPDIR)/$(am__dirstamp) plugins/espnet/RunLengthDecoder.lo: plugins/espnet/$(am__dirstamp) \ plugins/espnet/$(DEPDIR)/$(am__dirstamp) plugins/espnet/libolaespnet.la: $(plugins_espnet_libolaespnet_la_OBJECTS) $(plugins_espnet_libolaespnet_la_DEPENDENCIES) $(EXTRA_plugins_espnet_libolaespnet_la_DEPENDENCIES) plugins/espnet/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) $(am_plugins_espnet_libolaespnet_la_rpath) $(plugins_espnet_libolaespnet_la_OBJECTS) $(plugins_espnet_libolaespnet_la_LIBADD) $(LIBS) plugins/ftdidmx/$(am__dirstamp): @$(MKDIR_P) plugins/ftdidmx @: > plugins/ftdidmx/$(am__dirstamp) plugins/ftdidmx/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) plugins/ftdidmx/$(DEPDIR) @: > plugins/ftdidmx/$(DEPDIR)/$(am__dirstamp) plugins/ftdidmx/FtdiDmxDevice.lo: plugins/ftdidmx/$(am__dirstamp) \ plugins/ftdidmx/$(DEPDIR)/$(am__dirstamp) plugins/ftdidmx/FtdiDmxPlugin.lo: plugins/ftdidmx/$(am__dirstamp) \ plugins/ftdidmx/$(DEPDIR)/$(am__dirstamp) plugins/ftdidmx/FtdiDmxThread.lo: plugins/ftdidmx/$(am__dirstamp) \ plugins/ftdidmx/$(DEPDIR)/$(am__dirstamp) plugins/ftdidmx/FtdiWidget.lo: plugins/ftdidmx/$(am__dirstamp) \ plugins/ftdidmx/$(DEPDIR)/$(am__dirstamp) plugins/ftdidmx/libolaftdidmx.la: $(plugins_ftdidmx_libolaftdidmx_la_OBJECTS) $(plugins_ftdidmx_libolaftdidmx_la_DEPENDENCIES) $(EXTRA_plugins_ftdidmx_libolaftdidmx_la_DEPENDENCIES) plugins/ftdidmx/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) $(am_plugins_ftdidmx_libolaftdidmx_la_rpath) $(plugins_ftdidmx_libolaftdidmx_la_OBJECTS) $(plugins_ftdidmx_libolaftdidmx_la_LIBADD) $(LIBS) plugins/gpio/$(am__dirstamp): @$(MKDIR_P) plugins/gpio @: > plugins/gpio/$(am__dirstamp) plugins/gpio/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) plugins/gpio/$(DEPDIR) @: > plugins/gpio/$(DEPDIR)/$(am__dirstamp) plugins/gpio/GPIODevice.lo: plugins/gpio/$(am__dirstamp) \ plugins/gpio/$(DEPDIR)/$(am__dirstamp) plugins/gpio/GPIOPlugin.lo: plugins/gpio/$(am__dirstamp) \ plugins/gpio/$(DEPDIR)/$(am__dirstamp) plugins/gpio/GPIOPort.lo: plugins/gpio/$(am__dirstamp) \ plugins/gpio/$(DEPDIR)/$(am__dirstamp) plugins/gpio/libolagpio.la: $(plugins_gpio_libolagpio_la_OBJECTS) $(plugins_gpio_libolagpio_la_DEPENDENCIES) $(EXTRA_plugins_gpio_libolagpio_la_DEPENDENCIES) plugins/gpio/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) $(am_plugins_gpio_libolagpio_la_rpath) $(plugins_gpio_libolagpio_la_OBJECTS) $(plugins_gpio_libolagpio_la_LIBADD) $(LIBS) plugins/gpio/GPIODriver.lo: plugins/gpio/$(am__dirstamp) \ plugins/gpio/$(DEPDIR)/$(am__dirstamp) plugins/gpio/libolagpiocore.la: $(plugins_gpio_libolagpiocore_la_OBJECTS) $(plugins_gpio_libolagpiocore_la_DEPENDENCIES) $(EXTRA_plugins_gpio_libolagpiocore_la_DEPENDENCIES) plugins/gpio/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) $(am_plugins_gpio_libolagpiocore_la_rpath) $(plugins_gpio_libolagpiocore_la_OBJECTS) $(plugins_gpio_libolagpiocore_la_LIBADD) $(LIBS) plugins/karate/$(am__dirstamp): @$(MKDIR_P) plugins/karate @: > plugins/karate/$(am__dirstamp) plugins/karate/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) plugins/karate/$(DEPDIR) @: > plugins/karate/$(DEPDIR)/$(am__dirstamp) plugins/karate/KaratePlugin.lo: plugins/karate/$(am__dirstamp) \ plugins/karate/$(DEPDIR)/$(am__dirstamp) plugins/karate/KarateDevice.lo: plugins/karate/$(am__dirstamp) \ plugins/karate/$(DEPDIR)/$(am__dirstamp) plugins/karate/KarateThread.lo: plugins/karate/$(am__dirstamp) \ plugins/karate/$(DEPDIR)/$(am__dirstamp) plugins/karate/KarateLight.lo: plugins/karate/$(am__dirstamp) \ plugins/karate/$(DEPDIR)/$(am__dirstamp) plugins/karate/libolakarate.la: $(plugins_karate_libolakarate_la_OBJECTS) $(plugins_karate_libolakarate_la_DEPENDENCIES) $(EXTRA_plugins_karate_libolakarate_la_DEPENDENCIES) plugins/karate/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) $(am_plugins_karate_libolakarate_la_rpath) $(plugins_karate_libolakarate_la_OBJECTS) $(plugins_karate_libolakarate_la_LIBADD) $(LIBS) plugins/kinet/$(am__dirstamp): @$(MKDIR_P) plugins/kinet @: > plugins/kinet/$(am__dirstamp) plugins/kinet/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) plugins/kinet/$(DEPDIR) @: > plugins/kinet/$(DEPDIR)/$(am__dirstamp) plugins/kinet/KiNetPlugin.lo: plugins/kinet/$(am__dirstamp) \ plugins/kinet/$(DEPDIR)/$(am__dirstamp) plugins/kinet/KiNetDevice.lo: plugins/kinet/$(am__dirstamp) \ plugins/kinet/$(DEPDIR)/$(am__dirstamp) plugins/kinet/libolakinet.la: $(plugins_kinet_libolakinet_la_OBJECTS) $(plugins_kinet_libolakinet_la_DEPENDENCIES) $(EXTRA_plugins_kinet_libolakinet_la_DEPENDENCIES) plugins/kinet/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) $(am_plugins_kinet_libolakinet_la_rpath) $(plugins_kinet_libolakinet_la_OBJECTS) $(plugins_kinet_libolakinet_la_LIBADD) $(LIBS) plugins/kinet/KiNetNode.lo: plugins/kinet/$(am__dirstamp) \ plugins/kinet/$(DEPDIR)/$(am__dirstamp) plugins/kinet/libolakinetnode.la: $(plugins_kinet_libolakinetnode_la_OBJECTS) $(plugins_kinet_libolakinetnode_la_DEPENDENCIES) $(EXTRA_plugins_kinet_libolakinetnode_la_DEPENDENCIES) plugins/kinet/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) $(am_plugins_kinet_libolakinetnode_la_rpath) $(plugins_kinet_libolakinetnode_la_OBJECTS) $(plugins_kinet_libolakinetnode_la_LIBADD) $(LIBS) plugins/milinst/$(am__dirstamp): @$(MKDIR_P) plugins/milinst @: > plugins/milinst/$(am__dirstamp) plugins/milinst/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) plugins/milinst/$(DEPDIR) @: > plugins/milinst/$(DEPDIR)/$(am__dirstamp) plugins/milinst/MilInstDevice.lo: plugins/milinst/$(am__dirstamp) \ plugins/milinst/$(DEPDIR)/$(am__dirstamp) plugins/milinst/MilInstPlugin.lo: plugins/milinst/$(am__dirstamp) \ plugins/milinst/$(DEPDIR)/$(am__dirstamp) plugins/milinst/MilInstPort.lo: plugins/milinst/$(am__dirstamp) \ plugins/milinst/$(DEPDIR)/$(am__dirstamp) plugins/milinst/MilInstWidget.lo: plugins/milinst/$(am__dirstamp) \ plugins/milinst/$(DEPDIR)/$(am__dirstamp) plugins/milinst/MilInstWidget1463.lo: plugins/milinst/$(am__dirstamp) \ plugins/milinst/$(DEPDIR)/$(am__dirstamp) plugins/milinst/MilInstWidget1553.lo: plugins/milinst/$(am__dirstamp) \ plugins/milinst/$(DEPDIR)/$(am__dirstamp) plugins/milinst/libolamilinst.la: $(plugins_milinst_libolamilinst_la_OBJECTS) $(plugins_milinst_libolamilinst_la_DEPENDENCIES) $(EXTRA_plugins_milinst_libolamilinst_la_DEPENDENCIES) plugins/milinst/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) $(am_plugins_milinst_libolamilinst_la_rpath) $(plugins_milinst_libolamilinst_la_OBJECTS) $(plugins_milinst_libolamilinst_la_LIBADD) $(LIBS) plugins/opendmx/$(am__dirstamp): @$(MKDIR_P) plugins/opendmx @: > plugins/opendmx/$(am__dirstamp) plugins/opendmx/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) plugins/opendmx/$(DEPDIR) @: > plugins/opendmx/$(DEPDIR)/$(am__dirstamp) plugins/opendmx/OpenDmxDevice.lo: plugins/opendmx/$(am__dirstamp) \ plugins/opendmx/$(DEPDIR)/$(am__dirstamp) plugins/opendmx/OpenDmxPlugin.lo: plugins/opendmx/$(am__dirstamp) \ plugins/opendmx/$(DEPDIR)/$(am__dirstamp) plugins/opendmx/OpenDmxThread.lo: plugins/opendmx/$(am__dirstamp) \ plugins/opendmx/$(DEPDIR)/$(am__dirstamp) plugins/opendmx/libolaopendmx.la: $(plugins_opendmx_libolaopendmx_la_OBJECTS) $(plugins_opendmx_libolaopendmx_la_DEPENDENCIES) $(EXTRA_plugins_opendmx_libolaopendmx_la_DEPENDENCIES) plugins/opendmx/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) $(am_plugins_opendmx_libolaopendmx_la_rpath) $(plugins_opendmx_libolaopendmx_la_OBJECTS) $(plugins_opendmx_libolaopendmx_la_LIBADD) $(LIBS) plugins/openpixelcontrol/$(am__dirstamp): @$(MKDIR_P) plugins/openpixelcontrol @: > plugins/openpixelcontrol/$(am__dirstamp) plugins/openpixelcontrol/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) plugins/openpixelcontrol/$(DEPDIR) @: > plugins/openpixelcontrol/$(DEPDIR)/$(am__dirstamp) plugins/openpixelcontrol/OPCClient.lo: \ plugins/openpixelcontrol/$(am__dirstamp) \ plugins/openpixelcontrol/$(DEPDIR)/$(am__dirstamp) plugins/openpixelcontrol/OPCServer.lo: \ plugins/openpixelcontrol/$(am__dirstamp) \ plugins/openpixelcontrol/$(DEPDIR)/$(am__dirstamp) plugins/openpixelcontrol/libolaopc.la: $(plugins_openpixelcontrol_libolaopc_la_OBJECTS) $(plugins_openpixelcontrol_libolaopc_la_DEPENDENCIES) $(EXTRA_plugins_openpixelcontrol_libolaopc_la_DEPENDENCIES) plugins/openpixelcontrol/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) $(am_plugins_openpixelcontrol_libolaopc_la_rpath) $(plugins_openpixelcontrol_libolaopc_la_OBJECTS) $(plugins_openpixelcontrol_libolaopc_la_LIBADD) $(LIBS) plugins/openpixelcontrol/OPCDevice.lo: \ plugins/openpixelcontrol/$(am__dirstamp) \ plugins/openpixelcontrol/$(DEPDIR)/$(am__dirstamp) plugins/openpixelcontrol/OPCPlugin.lo: \ plugins/openpixelcontrol/$(am__dirstamp) \ plugins/openpixelcontrol/$(DEPDIR)/$(am__dirstamp) plugins/openpixelcontrol/OPCPort.lo: \ plugins/openpixelcontrol/$(am__dirstamp) \ plugins/openpixelcontrol/$(DEPDIR)/$(am__dirstamp) plugins/openpixelcontrol/libolaopenpixelcontrol.la: $(plugins_openpixelcontrol_libolaopenpixelcontrol_la_OBJECTS) $(plugins_openpixelcontrol_libolaopenpixelcontrol_la_DEPENDENCIES) $(EXTRA_plugins_openpixelcontrol_libolaopenpixelcontrol_la_DEPENDENCIES) plugins/openpixelcontrol/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) $(am_plugins_openpixelcontrol_libolaopenpixelcontrol_la_rpath) $(plugins_openpixelcontrol_libolaopenpixelcontrol_la_OBJECTS) $(plugins_openpixelcontrol_libolaopenpixelcontrol_la_LIBADD) $(LIBS) plugins/osc/$(am__dirstamp): @$(MKDIR_P) plugins/osc @: > plugins/osc/$(am__dirstamp) plugins/osc/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) plugins/osc/$(DEPDIR) @: > plugins/osc/$(DEPDIR)/$(am__dirstamp) plugins/osc/plugins_osc_libolaosc_la-OSCDevice.lo: \ plugins/osc/$(am__dirstamp) \ plugins/osc/$(DEPDIR)/$(am__dirstamp) plugins/osc/plugins_osc_libolaosc_la-OSCPlugin.lo: \ plugins/osc/$(am__dirstamp) \ plugins/osc/$(DEPDIR)/$(am__dirstamp) plugins/osc/plugins_osc_libolaosc_la-OSCPort.lo: \ plugins/osc/$(am__dirstamp) \ plugins/osc/$(DEPDIR)/$(am__dirstamp) plugins/osc/libolaosc.la: $(plugins_osc_libolaosc_la_OBJECTS) $(plugins_osc_libolaosc_la_DEPENDENCIES) $(EXTRA_plugins_osc_libolaosc_la_DEPENDENCIES) plugins/osc/$(am__dirstamp) $(AM_V_CXXLD)$(plugins_osc_libolaosc_la_LINK) $(am_plugins_osc_libolaosc_la_rpath) $(plugins_osc_libolaosc_la_OBJECTS) $(plugins_osc_libolaosc_la_LIBADD) $(LIBS) plugins/osc/plugins_osc_libolaoscnode_la-OSCAddressTemplate.lo: \ plugins/osc/$(am__dirstamp) \ plugins/osc/$(DEPDIR)/$(am__dirstamp) plugins/osc/plugins_osc_libolaoscnode_la-OSCNode.lo: \ plugins/osc/$(am__dirstamp) \ plugins/osc/$(DEPDIR)/$(am__dirstamp) plugins/osc/libolaoscnode.la: $(plugins_osc_libolaoscnode_la_OBJECTS) $(plugins_osc_libolaoscnode_la_DEPENDENCIES) $(EXTRA_plugins_osc_libolaoscnode_la_DEPENDENCIES) plugins/osc/$(am__dirstamp) $(AM_V_CXXLD)$(plugins_osc_libolaoscnode_la_LINK) $(am_plugins_osc_libolaoscnode_la_rpath) $(plugins_osc_libolaoscnode_la_OBJECTS) $(plugins_osc_libolaoscnode_la_LIBADD) $(LIBS) plugins/pathport/$(am__dirstamp): @$(MKDIR_P) plugins/pathport @: > plugins/pathport/$(am__dirstamp) plugins/pathport/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) plugins/pathport/$(DEPDIR) @: > plugins/pathport/$(DEPDIR)/$(am__dirstamp) plugins/pathport/PathportDevice.lo: plugins/pathport/$(am__dirstamp) \ plugins/pathport/$(DEPDIR)/$(am__dirstamp) plugins/pathport/PathportNode.lo: plugins/pathport/$(am__dirstamp) \ plugins/pathport/$(DEPDIR)/$(am__dirstamp) plugins/pathport/PathportPlugin.lo: plugins/pathport/$(am__dirstamp) \ plugins/pathport/$(DEPDIR)/$(am__dirstamp) plugins/pathport/PathportPort.lo: plugins/pathport/$(am__dirstamp) \ plugins/pathport/$(DEPDIR)/$(am__dirstamp) plugins/pathport/libolapathport.la: $(plugins_pathport_libolapathport_la_OBJECTS) $(plugins_pathport_libolapathport_la_DEPENDENCIES) $(EXTRA_plugins_pathport_libolapathport_la_DEPENDENCIES) plugins/pathport/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) $(am_plugins_pathport_libolapathport_la_rpath) $(plugins_pathport_libolapathport_la_OBJECTS) $(plugins_pathport_libolapathport_la_LIBADD) $(LIBS) plugins/renard/$(am__dirstamp): @$(MKDIR_P) plugins/renard @: > plugins/renard/$(am__dirstamp) plugins/renard/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) plugins/renard/$(DEPDIR) @: > plugins/renard/$(DEPDIR)/$(am__dirstamp) plugins/renard/RenardDevice.lo: plugins/renard/$(am__dirstamp) \ plugins/renard/$(DEPDIR)/$(am__dirstamp) plugins/renard/RenardPlugin.lo: plugins/renard/$(am__dirstamp) \ plugins/renard/$(DEPDIR)/$(am__dirstamp) plugins/renard/RenardPort.lo: plugins/renard/$(am__dirstamp) \ plugins/renard/$(DEPDIR)/$(am__dirstamp) plugins/renard/RenardWidget.lo: plugins/renard/$(am__dirstamp) \ plugins/renard/$(DEPDIR)/$(am__dirstamp) plugins/renard/libolarenard.la: $(plugins_renard_libolarenard_la_OBJECTS) $(plugins_renard_libolarenard_la_DEPENDENCIES) $(EXTRA_plugins_renard_libolarenard_la_DEPENDENCIES) plugins/renard/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) $(am_plugins_renard_libolarenard_la_rpath) $(plugins_renard_libolarenard_la_OBJECTS) $(plugins_renard_libolarenard_la_LIBADD) $(LIBS) plugins/sandnet/$(am__dirstamp): @$(MKDIR_P) plugins/sandnet @: > plugins/sandnet/$(am__dirstamp) plugins/sandnet/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) plugins/sandnet/$(DEPDIR) @: > plugins/sandnet/$(DEPDIR)/$(am__dirstamp) plugins/sandnet/SandNetDevice.lo: plugins/sandnet/$(am__dirstamp) \ plugins/sandnet/$(DEPDIR)/$(am__dirstamp) plugins/sandnet/SandNetNode.lo: plugins/sandnet/$(am__dirstamp) \ plugins/sandnet/$(DEPDIR)/$(am__dirstamp) plugins/sandnet/SandNetPlugin.lo: plugins/sandnet/$(am__dirstamp) \ plugins/sandnet/$(DEPDIR)/$(am__dirstamp) plugins/sandnet/SandNetPort.lo: plugins/sandnet/$(am__dirstamp) \ plugins/sandnet/$(DEPDIR)/$(am__dirstamp) plugins/sandnet/libolasandnet.la: $(plugins_sandnet_libolasandnet_la_OBJECTS) $(plugins_sandnet_libolasandnet_la_DEPENDENCIES) $(EXTRA_plugins_sandnet_libolasandnet_la_DEPENDENCIES) plugins/sandnet/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) $(am_plugins_sandnet_libolasandnet_la_rpath) $(plugins_sandnet_libolasandnet_la_OBJECTS) $(plugins_sandnet_libolasandnet_la_LIBADD) $(LIBS) plugins/shownet/$(am__dirstamp): @$(MKDIR_P) plugins/shownet @: > plugins/shownet/$(am__dirstamp) plugins/shownet/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) plugins/shownet/$(DEPDIR) @: > plugins/shownet/$(DEPDIR)/$(am__dirstamp) plugins/shownet/ShowNetPlugin.lo: plugins/shownet/$(am__dirstamp) \ plugins/shownet/$(DEPDIR)/$(am__dirstamp) plugins/shownet/ShowNetDevice.lo: plugins/shownet/$(am__dirstamp) \ plugins/shownet/$(DEPDIR)/$(am__dirstamp) plugins/shownet/ShowNetPort.lo: plugins/shownet/$(am__dirstamp) \ plugins/shownet/$(DEPDIR)/$(am__dirstamp) plugins/shownet/ShowNetNode.lo: plugins/shownet/$(am__dirstamp) \ plugins/shownet/$(DEPDIR)/$(am__dirstamp) plugins/shownet/libolashownet.la: $(plugins_shownet_libolashownet_la_OBJECTS) $(plugins_shownet_libolashownet_la_DEPENDENCIES) $(EXTRA_plugins_shownet_libolashownet_la_DEPENDENCIES) plugins/shownet/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) $(am_plugins_shownet_libolashownet_la_rpath) $(plugins_shownet_libolashownet_la_OBJECTS) $(plugins_shownet_libolashownet_la_LIBADD) $(LIBS) plugins/spi/$(am__dirstamp): @$(MKDIR_P) plugins/spi @: > plugins/spi/$(am__dirstamp) plugins/spi/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) plugins/spi/$(DEPDIR) @: > plugins/spi/$(DEPDIR)/$(am__dirstamp) plugins/spi/SPIDevice.lo: plugins/spi/$(am__dirstamp) \ plugins/spi/$(DEPDIR)/$(am__dirstamp) plugins/spi/SPIPlugin.lo: plugins/spi/$(am__dirstamp) \ plugins/spi/$(DEPDIR)/$(am__dirstamp) plugins/spi/SPIPort.lo: plugins/spi/$(am__dirstamp) \ plugins/spi/$(DEPDIR)/$(am__dirstamp) plugins/spi/libolaspi.la: $(plugins_spi_libolaspi_la_OBJECTS) $(plugins_spi_libolaspi_la_DEPENDENCIES) $(EXTRA_plugins_spi_libolaspi_la_DEPENDENCIES) plugins/spi/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) $(am_plugins_spi_libolaspi_la_rpath) $(plugins_spi_libolaspi_la_OBJECTS) $(plugins_spi_libolaspi_la_LIBADD) $(LIBS) plugins/spi/SPIBackend.lo: plugins/spi/$(am__dirstamp) \ plugins/spi/$(DEPDIR)/$(am__dirstamp) plugins/spi/SPIOutput.lo: plugins/spi/$(am__dirstamp) \ plugins/spi/$(DEPDIR)/$(am__dirstamp) plugins/spi/SPIWriter.lo: plugins/spi/$(am__dirstamp) \ plugins/spi/$(DEPDIR)/$(am__dirstamp) plugins/spi/libolaspicore.la: $(plugins_spi_libolaspicore_la_OBJECTS) $(plugins_spi_libolaspicore_la_DEPENDENCIES) $(EXTRA_plugins_spi_libolaspicore_la_DEPENDENCIES) plugins/spi/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) $(am_plugins_spi_libolaspicore_la_rpath) $(plugins_spi_libolaspicore_la_OBJECTS) $(plugins_spi_libolaspicore_la_LIBADD) $(LIBS) plugins/stageprofi/$(am__dirstamp): @$(MKDIR_P) plugins/stageprofi @: > plugins/stageprofi/$(am__dirstamp) plugins/stageprofi/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) plugins/stageprofi/$(DEPDIR) @: > plugins/stageprofi/$(DEPDIR)/$(am__dirstamp) plugins/stageprofi/StageProfiDetector.lo: \ plugins/stageprofi/$(am__dirstamp) \ plugins/stageprofi/$(DEPDIR)/$(am__dirstamp) plugins/stageprofi/StageProfiDevice.lo: \ plugins/stageprofi/$(am__dirstamp) \ plugins/stageprofi/$(DEPDIR)/$(am__dirstamp) plugins/stageprofi/StageProfiPlugin.lo: \ plugins/stageprofi/$(am__dirstamp) \ plugins/stageprofi/$(DEPDIR)/$(am__dirstamp) plugins/stageprofi/StageProfiPort.lo: \ plugins/stageprofi/$(am__dirstamp) \ plugins/stageprofi/$(DEPDIR)/$(am__dirstamp) plugins/stageprofi/StageProfiWidget.lo: \ plugins/stageprofi/$(am__dirstamp) \ plugins/stageprofi/$(DEPDIR)/$(am__dirstamp) plugins/stageprofi/libolastageprofi.la: $(plugins_stageprofi_libolastageprofi_la_OBJECTS) $(plugins_stageprofi_libolastageprofi_la_DEPENDENCIES) $(EXTRA_plugins_stageprofi_libolastageprofi_la_DEPENDENCIES) plugins/stageprofi/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) $(am_plugins_stageprofi_libolastageprofi_la_rpath) $(plugins_stageprofi_libolastageprofi_la_OBJECTS) $(plugins_stageprofi_libolastageprofi_la_LIBADD) $(LIBS) plugins/uartdmx/$(am__dirstamp): @$(MKDIR_P) plugins/uartdmx @: > plugins/uartdmx/$(am__dirstamp) plugins/uartdmx/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) plugins/uartdmx/$(DEPDIR) @: > plugins/uartdmx/$(DEPDIR)/$(am__dirstamp) plugins/uartdmx/UartDmxDevice.lo: plugins/uartdmx/$(am__dirstamp) \ plugins/uartdmx/$(DEPDIR)/$(am__dirstamp) plugins/uartdmx/UartDmxPlugin.lo: plugins/uartdmx/$(am__dirstamp) \ plugins/uartdmx/$(DEPDIR)/$(am__dirstamp) plugins/uartdmx/UartDmxThread.lo: plugins/uartdmx/$(am__dirstamp) \ plugins/uartdmx/$(DEPDIR)/$(am__dirstamp) plugins/uartdmx/UartWidget.lo: plugins/uartdmx/$(am__dirstamp) \ plugins/uartdmx/$(DEPDIR)/$(am__dirstamp) plugins/uartdmx/libolauartdmx.la: $(plugins_uartdmx_libolauartdmx_la_OBJECTS) $(plugins_uartdmx_libolauartdmx_la_DEPENDENCIES) $(EXTRA_plugins_uartdmx_libolauartdmx_la_DEPENDENCIES) plugins/uartdmx/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) $(am_plugins_uartdmx_libolauartdmx_la_rpath) $(plugins_uartdmx_libolauartdmx_la_OBJECTS) $(plugins_uartdmx_libolauartdmx_la_LIBADD) $(LIBS) plugins/usbdmx/$(am__dirstamp): @$(MKDIR_P) plugins/usbdmx @: > plugins/usbdmx/$(am__dirstamp) plugins/usbdmx/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) plugins/usbdmx/$(DEPDIR) @: > plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-AsyncPluginImpl.lo: \ plugins/usbdmx/$(am__dirstamp) \ plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-DMXCProjectsNodleU1Device.lo: \ plugins/usbdmx/$(am__dirstamp) \ plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-DMXCProjectsNodleU1Port.lo: \ plugins/usbdmx/$(am__dirstamp) \ plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-GenericDevice.lo: \ plugins/usbdmx/$(am__dirstamp) \ plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-GenericOutputPort.lo: \ plugins/usbdmx/$(am__dirstamp) \ plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-JaRuleDevice.lo: \ plugins/usbdmx/$(am__dirstamp) \ plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-JaRuleOutputPort.lo: \ plugins/usbdmx/$(am__dirstamp) \ plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-SyncPluginImpl.lo: \ plugins/usbdmx/$(am__dirstamp) \ plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-UsbDmxPlugin.lo: \ plugins/usbdmx/$(am__dirstamp) \ plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) plugins/usbdmx/libolausbdmx.la: $(plugins_usbdmx_libolausbdmx_la_OBJECTS) $(plugins_usbdmx_libolausbdmx_la_DEPENDENCIES) $(EXTRA_plugins_usbdmx_libolausbdmx_la_DEPENDENCIES) plugins/usbdmx/$(am__dirstamp) $(AM_V_CXXLD)$(plugins_usbdmx_libolausbdmx_la_LINK) $(am_plugins_usbdmx_libolausbdmx_la_rpath) $(plugins_usbdmx_libolausbdmx_la_OBJECTS) $(plugins_usbdmx_libolausbdmx_la_LIBADD) $(LIBS) plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AnymauDMX.lo: \ plugins/usbdmx/$(am__dirstamp) \ plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AnymauDMXFactory.lo: \ plugins/usbdmx/$(am__dirstamp) \ plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbReceiver.lo: \ plugins/usbdmx/$(am__dirstamp) \ plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbSender.lo: \ plugins/usbdmx/$(am__dirstamp) \ plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbTransceiverBase.lo: \ plugins/usbdmx/$(am__dirstamp) \ plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-DMXCProjectsNodleU1.lo: \ plugins/usbdmx/$(am__dirstamp) \ plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-DMXCProjectsNodleU1Factory.lo: \ plugins/usbdmx/$(am__dirstamp) \ plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-EurolitePro.lo: \ plugins/usbdmx/$(am__dirstamp) \ plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-EuroliteProFactory.lo: \ plugins/usbdmx/$(am__dirstamp) \ plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-Flags.lo: \ plugins/usbdmx/$(am__dirstamp) \ plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-JaRuleFactory.lo: \ plugins/usbdmx/$(am__dirstamp) \ plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-ScanlimeFadecandy.lo: \ plugins/usbdmx/$(am__dirstamp) \ plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-ScanlimeFadecandyFactory.lo: \ plugins/usbdmx/$(am__dirstamp) \ plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-Sunlite.lo: \ plugins/usbdmx/$(am__dirstamp) \ plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-SunliteFactory.lo: \ plugins/usbdmx/$(am__dirstamp) \ plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-SunliteFirmwareLoader.lo: \ plugins/usbdmx/$(am__dirstamp) \ plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-SyncronizedWidgetObserver.lo: \ plugins/usbdmx/$(am__dirstamp) \ plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-ThreadedUsbReceiver.lo: \ plugins/usbdmx/$(am__dirstamp) \ plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-ThreadedUsbSender.lo: \ plugins/usbdmx/$(am__dirstamp) \ plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-VellemanK8062.lo: \ plugins/usbdmx/$(am__dirstamp) \ plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-VellemanK8062Factory.lo: \ plugins/usbdmx/$(am__dirstamp) \ plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) plugins/usbdmx/libolausbdmxwidget.la: $(plugins_usbdmx_libolausbdmxwidget_la_OBJECTS) $(plugins_usbdmx_libolausbdmxwidget_la_DEPENDENCIES) $(EXTRA_plugins_usbdmx_libolausbdmxwidget_la_DEPENDENCIES) plugins/usbdmx/$(am__dirstamp) $(AM_V_CXXLD)$(plugins_usbdmx_libolausbdmxwidget_la_LINK) $(am_plugins_usbdmx_libolausbdmxwidget_la_rpath) $(plugins_usbdmx_libolausbdmxwidget_la_OBJECTS) $(plugins_usbdmx_libolausbdmxwidget_la_LIBADD) $(LIBS) plugins/usbpro/$(am__dirstamp): @$(MKDIR_P) plugins/usbpro @: > plugins/usbpro/$(am__dirstamp) plugins/usbpro/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) plugins/usbpro/$(DEPDIR) @: > plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/plugins_usbpro_libolausbpro_la-ArduinoRGBDevice.lo: \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/plugins_usbpro_libolausbpro_la-DmxTriDevice.lo: \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/plugins_usbpro_libolausbpro_la-DmxterDevice.lo: \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/plugins_usbpro_libolausbpro_la-RobeDevice.lo: \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/plugins_usbpro_libolausbpro_la-UltraDMXProDevice.lo: \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/plugins_usbpro_libolausbpro_la-UsbProDevice.lo: \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/plugins_usbpro_libolausbpro_la-UsbSerialPlugin.lo: \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/libolausbpro.la: $(plugins_usbpro_libolausbpro_la_OBJECTS) $(plugins_usbpro_libolausbpro_la_DEPENDENCIES) $(EXTRA_plugins_usbpro_libolausbpro_la_DEPENDENCIES) plugins/usbpro/$(am__dirstamp) $(AM_V_CXXLD)$(plugins_usbpro_libolausbpro_la_LINK) $(am_plugins_usbpro_libolausbpro_la_rpath) $(plugins_usbpro_libolausbpro_la_OBJECTS) $(plugins_usbpro_libolausbpro_la_LIBADD) $(LIBS) plugins/usbpro/ArduinoWidget.lo: plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/BaseRobeWidget.lo: plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/BaseUsbProWidget.lo: plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/DmxTriWidget.lo: plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/DmxterWidget.lo: plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/EnttecUsbProWidget.lo: plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/GenericUsbProWidget.lo: plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/RobeWidget.lo: plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/RobeWidgetDetector.lo: plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/UltraDMXProWidget.lo: plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/UsbProWidgetDetector.lo: \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/WidgetDetectorThread.lo: \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/libolausbprowidget.la: $(plugins_usbpro_libolausbprowidget_la_OBJECTS) $(plugins_usbpro_libolausbprowidget_la_DEPENDENCIES) $(EXTRA_plugins_usbpro_libolausbprowidget_la_DEPENDENCIES) plugins/usbpro/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) $(am_plugins_usbpro_libolausbprowidget_la_rpath) $(plugins_usbpro_libolausbprowidget_la_OBJECTS) $(plugins_usbpro_libolausbprowidget_la_LIBADD) $(LIBS) plugins/usbpro/messages/$(am__dirstamp): @$(MKDIR_P) plugins/usbpro/messages @: > plugins/usbpro/messages/$(am__dirstamp) plugins/usbpro/messages/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) plugins/usbpro/messages/$(DEPDIR) @: > plugins/usbpro/messages/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/messages/plugins_usbpro_messages_libolausbproconf_la-UsbProConfigMessages.pb.lo: \ plugins/usbpro/messages/$(am__dirstamp) \ plugins/usbpro/messages/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/messages/libolausbproconf.la: $(plugins_usbpro_messages_libolausbproconf_la_OBJECTS) $(plugins_usbpro_messages_libolausbproconf_la_DEPENDENCIES) $(EXTRA_plugins_usbpro_messages_libolausbproconf_la_DEPENDENCIES) plugins/usbpro/messages/$(am__dirstamp) $(AM_V_CXXLD)$(plugins_usbpro_messages_libolausbproconf_la_LINK) $(am_plugins_usbpro_messages_libolausbproconf_la_rpath) $(plugins_usbpro_messages_libolausbproconf_la_OBJECTS) $(plugins_usbpro_messages_libolausbproconf_la_LIBADD) $(LIBS) tools/e133/$(am__dirstamp): @$(MKDIR_P) tools/e133 @: > tools/e133/$(am__dirstamp) tools/e133/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) tools/e133/$(DEPDIR) @: > tools/e133/$(DEPDIR)/$(am__dirstamp) tools/e133/E133HealthCheckedConnection.lo: tools/e133/$(am__dirstamp) \ tools/e133/$(DEPDIR)/$(am__dirstamp) tools/e133/E133Receiver.lo: tools/e133/$(am__dirstamp) \ tools/e133/$(DEPDIR)/$(am__dirstamp) tools/e133/E133StatusHelper.lo: tools/e133/$(am__dirstamp) \ tools/e133/$(DEPDIR)/$(am__dirstamp) tools/e133/MessageBuilder.lo: tools/e133/$(am__dirstamp) \ tools/e133/$(DEPDIR)/$(am__dirstamp) tools/e133/libolae133common.la: $(tools_e133_libolae133common_la_OBJECTS) $(tools_e133_libolae133common_la_DEPENDENCIES) $(EXTRA_tools_e133_libolae133common_la_DEPENDENCIES) tools/e133/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) $(am_tools_e133_libolae133common_la_rpath) $(tools_e133_libolae133common_la_OBJECTS) $(tools_e133_libolae133common_la_LIBADD) $(LIBS) tools/e133/DeviceManager.lo: tools/e133/$(am__dirstamp) \ tools/e133/$(DEPDIR)/$(am__dirstamp) tools/e133/DeviceManagerImpl.lo: tools/e133/$(am__dirstamp) \ tools/e133/$(DEPDIR)/$(am__dirstamp) tools/e133/libolae133controller.la: $(tools_e133_libolae133controller_la_OBJECTS) $(tools_e133_libolae133controller_la_DEPENDENCIES) $(EXTRA_tools_e133_libolae133controller_la_DEPENDENCIES) tools/e133/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) $(am_tools_e133_libolae133controller_la_rpath) $(tools_e133_libolae133controller_la_OBJECTS) $(tools_e133_libolae133controller_la_LIBADD) $(LIBS) tools/e133/DesignatedControllerConnection.lo: \ tools/e133/$(am__dirstamp) \ tools/e133/$(DEPDIR)/$(am__dirstamp) tools/e133/E133Device.lo: tools/e133/$(am__dirstamp) \ tools/e133/$(DEPDIR)/$(am__dirstamp) tools/e133/E133Endpoint.lo: tools/e133/$(am__dirstamp) \ tools/e133/$(DEPDIR)/$(am__dirstamp) tools/e133/EndpointManager.lo: tools/e133/$(am__dirstamp) \ tools/e133/$(DEPDIR)/$(am__dirstamp) tools/e133/ManagementEndpoint.lo: tools/e133/$(am__dirstamp) \ tools/e133/$(DEPDIR)/$(am__dirstamp) tools/e133/SimpleE133Node.lo: tools/e133/$(am__dirstamp) \ tools/e133/$(DEPDIR)/$(am__dirstamp) tools/e133/libolae133device.la: $(tools_e133_libolae133device_la_OBJECTS) $(tools_e133_libolae133device_la_DEPENDENCIES) $(EXTRA_tools_e133_libolae133device_la_DEPENDENCIES) tools/e133/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) $(am_tools_e133_libolae133device_la_rpath) $(tools_e133_libolae133device_la_OBJECTS) $(tools_e133_libolae133device_la_LIBADD) $(LIBS) tools/ola_trigger/$(am__dirstamp): @$(MKDIR_P) tools/ola_trigger @: > tools/ola_trigger/$(am__dirstamp) tools/ola_trigger/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) tools/ola_trigger/$(DEPDIR) @: > tools/ola_trigger/$(DEPDIR)/$(am__dirstamp) tools/ola_trigger/Action.lo: tools/ola_trigger/$(am__dirstamp) \ tools/ola_trigger/$(DEPDIR)/$(am__dirstamp) tools/ola_trigger/Context.lo: tools/ola_trigger/$(am__dirstamp) \ tools/ola_trigger/$(DEPDIR)/$(am__dirstamp) tools/ola_trigger/DMXTrigger.lo: tools/ola_trigger/$(am__dirstamp) \ tools/ola_trigger/$(DEPDIR)/$(am__dirstamp) tools/ola_trigger/VariableInterpolator.lo: \ tools/ola_trigger/$(am__dirstamp) \ tools/ola_trigger/$(DEPDIR)/$(am__dirstamp) tools/ola_trigger/libolatrigger.la: $(tools_ola_trigger_libolatrigger_la_OBJECTS) $(tools_ola_trigger_libolatrigger_la_DEPENDENCIES) $(EXTRA_tools_ola_trigger_libolatrigger_la_DEPENDENCIES) tools/ola_trigger/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) -rpath $(libdir) $(tools_ola_trigger_libolatrigger_la_OBJECTS) $(tools_ola_trigger_libolatrigger_la_LIBADD) $(LIBS) 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 \ || test -f $$p1 \ ; 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) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(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: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list common/base/common_base_CredentialsTester-CredentialsTest.$(OBJEXT): \ common/base/$(am__dirstamp) \ common/base/$(DEPDIR)/$(am__dirstamp) common/base/CredentialsTester$(EXEEXT): $(common_base_CredentialsTester_OBJECTS) $(common_base_CredentialsTester_DEPENDENCIES) $(EXTRA_common_base_CredentialsTester_DEPENDENCIES) common/base/$(am__dirstamp) @rm -f common/base/CredentialsTester$(EXEEXT) $(AM_V_CXXLD)$(common_base_CredentialsTester_LINK) $(common_base_CredentialsTester_OBJECTS) $(common_base_CredentialsTester_LDADD) $(LIBS) common/base/common_base_FlagsTester-FlagsTest.$(OBJEXT): \ common/base/$(am__dirstamp) \ common/base/$(DEPDIR)/$(am__dirstamp) common/base/FlagsTester$(EXEEXT): $(common_base_FlagsTester_OBJECTS) $(common_base_FlagsTester_DEPENDENCIES) $(EXTRA_common_base_FlagsTester_DEPENDENCIES) common/base/$(am__dirstamp) @rm -f common/base/FlagsTester$(EXEEXT) $(AM_V_CXXLD)$(common_base_FlagsTester_LINK) $(common_base_FlagsTester_OBJECTS) $(common_base_FlagsTester_LDADD) $(LIBS) common/base/common_base_LoggingTester-LoggingTest.$(OBJEXT): \ common/base/$(am__dirstamp) \ common/base/$(DEPDIR)/$(am__dirstamp) common/base/LoggingTester$(EXEEXT): $(common_base_LoggingTester_OBJECTS) $(common_base_LoggingTester_DEPENDENCIES) $(EXTRA_common_base_LoggingTester_DEPENDENCIES) common/base/$(am__dirstamp) @rm -f common/base/LoggingTester$(EXEEXT) $(AM_V_CXXLD)$(common_base_LoggingTester_LINK) $(common_base_LoggingTester_OBJECTS) $(common_base_LoggingTester_LDADD) $(LIBS) common/dmx/common_dmx_RunLengthEncoderTester-RunLengthEncoderTest.$(OBJEXT): \ common/dmx/$(am__dirstamp) \ common/dmx/$(DEPDIR)/$(am__dirstamp) common/dmx/RunLengthEncoderTester$(EXEEXT): $(common_dmx_RunLengthEncoderTester_OBJECTS) $(common_dmx_RunLengthEncoderTester_DEPENDENCIES) $(EXTRA_common_dmx_RunLengthEncoderTester_DEPENDENCIES) common/dmx/$(am__dirstamp) @rm -f common/dmx/RunLengthEncoderTester$(EXEEXT) $(AM_V_CXXLD)$(common_dmx_RunLengthEncoderTester_LINK) $(common_dmx_RunLengthEncoderTester_OBJECTS) $(common_dmx_RunLengthEncoderTester_LDADD) $(LIBS) common/export_map/common_export_map_ExportMapTester-ExportMapTest.$(OBJEXT): \ common/export_map/$(am__dirstamp) \ common/export_map/$(DEPDIR)/$(am__dirstamp) common/export_map/ExportMapTester$(EXEEXT): $(common_export_map_ExportMapTester_OBJECTS) $(common_export_map_ExportMapTester_DEPENDENCIES) $(EXTRA_common_export_map_ExportMapTester_DEPENDENCIES) common/export_map/$(am__dirstamp) @rm -f common/export_map/ExportMapTester$(EXEEXT) $(AM_V_CXXLD)$(common_export_map_ExportMapTester_LINK) $(common_export_map_ExportMapTester_OBJECTS) $(common_export_map_ExportMapTester_LDADD) $(LIBS) common/file/common_file_UtilTester-UtilTest.$(OBJEXT): \ common/file/$(am__dirstamp) \ common/file/$(DEPDIR)/$(am__dirstamp) common/file/UtilTester$(EXEEXT): $(common_file_UtilTester_OBJECTS) $(common_file_UtilTester_DEPENDENCIES) $(EXTRA_common_file_UtilTester_DEPENDENCIES) common/file/$(am__dirstamp) @rm -f common/file/UtilTester$(EXEEXT) $(AM_V_CXXLD)$(common_file_UtilTester_LINK) $(common_file_UtilTester_OBJECTS) $(common_file_UtilTester_LDADD) $(LIBS) common/io/common_io_DescriptorTester-DescriptorTest.$(OBJEXT): \ common/io/$(am__dirstamp) common/io/$(DEPDIR)/$(am__dirstamp) common/io/DescriptorTester$(EXEEXT): $(common_io_DescriptorTester_OBJECTS) $(common_io_DescriptorTester_DEPENDENCIES) $(EXTRA_common_io_DescriptorTester_DEPENDENCIES) common/io/$(am__dirstamp) @rm -f common/io/DescriptorTester$(EXEEXT) $(AM_V_CXXLD)$(common_io_DescriptorTester_LINK) $(common_io_DescriptorTester_OBJECTS) $(common_io_DescriptorTester_LDADD) $(LIBS) common/io/common_io_IOQueueTester-IOQueueTest.$(OBJEXT): \ common/io/$(am__dirstamp) common/io/$(DEPDIR)/$(am__dirstamp) common/io/IOQueueTester$(EXEEXT): $(common_io_IOQueueTester_OBJECTS) $(common_io_IOQueueTester_DEPENDENCIES) $(EXTRA_common_io_IOQueueTester_DEPENDENCIES) common/io/$(am__dirstamp) @rm -f common/io/IOQueueTester$(EXEEXT) $(AM_V_CXXLD)$(common_io_IOQueueTester_LINK) $(common_io_IOQueueTester_OBJECTS) $(common_io_IOQueueTester_LDADD) $(LIBS) common/io/common_io_IOStackTester-IOStackTest.$(OBJEXT): \ common/io/$(am__dirstamp) common/io/$(DEPDIR)/$(am__dirstamp) common/io/IOStackTester$(EXEEXT): $(common_io_IOStackTester_OBJECTS) $(common_io_IOStackTester_DEPENDENCIES) $(EXTRA_common_io_IOStackTester_DEPENDENCIES) common/io/$(am__dirstamp) @rm -f common/io/IOStackTester$(EXEEXT) $(AM_V_CXXLD)$(common_io_IOStackTester_LINK) $(common_io_IOStackTester_OBJECTS) $(common_io_IOStackTester_LDADD) $(LIBS) common/io/common_io_MemoryBlockTester-MemoryBlockTest.$(OBJEXT): \ common/io/$(am__dirstamp) common/io/$(DEPDIR)/$(am__dirstamp) common/io/MemoryBlockTester$(EXEEXT): $(common_io_MemoryBlockTester_OBJECTS) $(common_io_MemoryBlockTester_DEPENDENCIES) $(EXTRA_common_io_MemoryBlockTester_DEPENDENCIES) common/io/$(am__dirstamp) @rm -f common/io/MemoryBlockTester$(EXEEXT) $(AM_V_CXXLD)$(common_io_MemoryBlockTester_LINK) $(common_io_MemoryBlockTester_OBJECTS) $(common_io_MemoryBlockTester_LDADD) $(LIBS) common/io/common_io_SelectServerTester-SelectServerTest.$(OBJEXT): \ common/io/$(am__dirstamp) common/io/$(DEPDIR)/$(am__dirstamp) common/io/common_io_SelectServerTester-SelectServerThreadTest.$(OBJEXT): \ common/io/$(am__dirstamp) common/io/$(DEPDIR)/$(am__dirstamp) common/io/SelectServerTester$(EXEEXT): $(common_io_SelectServerTester_OBJECTS) $(common_io_SelectServerTester_DEPENDENCIES) $(EXTRA_common_io_SelectServerTester_DEPENDENCIES) common/io/$(am__dirstamp) @rm -f common/io/SelectServerTester$(EXEEXT) $(AM_V_CXXLD)$(common_io_SelectServerTester_LINK) $(common_io_SelectServerTester_OBJECTS) $(common_io_SelectServerTester_LDADD) $(LIBS) common/io/common_io_StreamTester-InputStreamTest.$(OBJEXT): \ common/io/$(am__dirstamp) common/io/$(DEPDIR)/$(am__dirstamp) common/io/common_io_StreamTester-OutputStreamTest.$(OBJEXT): \ common/io/$(am__dirstamp) common/io/$(DEPDIR)/$(am__dirstamp) common/io/StreamTester$(EXEEXT): $(common_io_StreamTester_OBJECTS) $(common_io_StreamTester_DEPENDENCIES) $(EXTRA_common_io_StreamTester_DEPENDENCIES) common/io/$(am__dirstamp) @rm -f common/io/StreamTester$(EXEEXT) $(AM_V_CXXLD)$(common_io_StreamTester_LINK) $(common_io_StreamTester_OBJECTS) $(common_io_StreamTester_LDADD) $(LIBS) common/io/common_io_TimeoutManagerTester-TimeoutManagerTest.$(OBJEXT): \ common/io/$(am__dirstamp) common/io/$(DEPDIR)/$(am__dirstamp) common/io/TimeoutManagerTester$(EXEEXT): $(common_io_TimeoutManagerTester_OBJECTS) $(common_io_TimeoutManagerTester_DEPENDENCIES) $(EXTRA_common_io_TimeoutManagerTester_DEPENDENCIES) common/io/$(am__dirstamp) @rm -f common/io/TimeoutManagerTester$(EXEEXT) $(AM_V_CXXLD)$(common_io_TimeoutManagerTester_LINK) $(common_io_TimeoutManagerTester_OBJECTS) $(common_io_TimeoutManagerTester_LDADD) $(LIBS) common/messaging/common_messaging_DescriptorTester-DescriptorTest.$(OBJEXT): \ common/messaging/$(am__dirstamp) \ common/messaging/$(DEPDIR)/$(am__dirstamp) common/messaging/common_messaging_DescriptorTester-SchemaPrinterTest.$(OBJEXT): \ common/messaging/$(am__dirstamp) \ common/messaging/$(DEPDIR)/$(am__dirstamp) common/messaging/common_messaging_DescriptorTester-MessagePrinterTest.$(OBJEXT): \ common/messaging/$(am__dirstamp) \ common/messaging/$(DEPDIR)/$(am__dirstamp) common/messaging/DescriptorTester$(EXEEXT): $(common_messaging_DescriptorTester_OBJECTS) $(common_messaging_DescriptorTester_DEPENDENCIES) $(EXTRA_common_messaging_DescriptorTester_DEPENDENCIES) common/messaging/$(am__dirstamp) @rm -f common/messaging/DescriptorTester$(EXEEXT) $(AM_V_CXXLD)$(common_messaging_DescriptorTester_LINK) $(common_messaging_DescriptorTester_OBJECTS) $(common_messaging_DescriptorTester_LDADD) $(LIBS) common/network/common_network_HealthCheckedConnectionTester-HealthCheckedConnectionTest.$(OBJEXT): \ common/network/$(am__dirstamp) \ common/network/$(DEPDIR)/$(am__dirstamp) common/network/HealthCheckedConnectionTester$(EXEEXT): $(common_network_HealthCheckedConnectionTester_OBJECTS) $(common_network_HealthCheckedConnectionTester_DEPENDENCIES) $(EXTRA_common_network_HealthCheckedConnectionTester_DEPENDENCIES) common/network/$(am__dirstamp) @rm -f common/network/HealthCheckedConnectionTester$(EXEEXT) $(AM_V_CXXLD)$(common_network_HealthCheckedConnectionTester_LINK) $(common_network_HealthCheckedConnectionTester_OBJECTS) $(common_network_HealthCheckedConnectionTester_LDADD) $(LIBS) common/network/common_network_NetworkTester-IPV4AddressTest.$(OBJEXT): \ common/network/$(am__dirstamp) \ common/network/$(DEPDIR)/$(am__dirstamp) common/network/common_network_NetworkTester-InterfacePickerTest.$(OBJEXT): \ common/network/$(am__dirstamp) \ common/network/$(DEPDIR)/$(am__dirstamp) common/network/common_network_NetworkTester-InterfaceTest.$(OBJEXT): \ common/network/$(am__dirstamp) \ common/network/$(DEPDIR)/$(am__dirstamp) common/network/common_network_NetworkTester-MACAddressTest.$(OBJEXT): \ common/network/$(am__dirstamp) \ common/network/$(DEPDIR)/$(am__dirstamp) common/network/common_network_NetworkTester-NetworkUtilsTest.$(OBJEXT): \ common/network/$(am__dirstamp) \ common/network/$(DEPDIR)/$(am__dirstamp) common/network/common_network_NetworkTester-SocketAddressTest.$(OBJEXT): \ common/network/$(am__dirstamp) \ common/network/$(DEPDIR)/$(am__dirstamp) common/network/common_network_NetworkTester-SocketTest.$(OBJEXT): \ common/network/$(am__dirstamp) \ common/network/$(DEPDIR)/$(am__dirstamp) common/network/NetworkTester$(EXEEXT): $(common_network_NetworkTester_OBJECTS) $(common_network_NetworkTester_DEPENDENCIES) $(EXTRA_common_network_NetworkTester_DEPENDENCIES) common/network/$(am__dirstamp) @rm -f common/network/NetworkTester$(EXEEXT) $(AM_V_CXXLD)$(common_network_NetworkTester_LINK) $(common_network_NetworkTester_OBJECTS) $(common_network_NetworkTester_LDADD) $(LIBS) common/network/common_network_TCPConnectorTester-AdvancedTCPConnectorTest.$(OBJEXT): \ common/network/$(am__dirstamp) \ common/network/$(DEPDIR)/$(am__dirstamp) common/network/common_network_TCPConnectorTester-TCPConnectorTest.$(OBJEXT): \ common/network/$(am__dirstamp) \ common/network/$(DEPDIR)/$(am__dirstamp) common/network/TCPConnectorTester$(EXEEXT): $(common_network_TCPConnectorTester_OBJECTS) $(common_network_TCPConnectorTester_DEPENDENCIES) $(EXTRA_common_network_TCPConnectorTester_DEPENDENCIES) common/network/$(am__dirstamp) @rm -f common/network/TCPConnectorTester$(EXEEXT) $(AM_V_CXXLD)$(common_network_TCPConnectorTester_LINK) $(common_network_TCPConnectorTester_OBJECTS) $(common_network_TCPConnectorTester_LDADD) $(LIBS) common/rdm/common_rdm_DiscoveryAgentTester-DiscoveryAgentTest.$(OBJEXT): \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/DiscoveryAgentTester$(EXEEXT): $(common_rdm_DiscoveryAgentTester_OBJECTS) $(common_rdm_DiscoveryAgentTester_DEPENDENCIES) $(EXTRA_common_rdm_DiscoveryAgentTester_DEPENDENCIES) common/rdm/$(am__dirstamp) @rm -f common/rdm/DiscoveryAgentTester$(EXEEXT) $(AM_V_CXXLD)$(common_rdm_DiscoveryAgentTester_LINK) $(common_rdm_DiscoveryAgentTester_OBJECTS) $(common_rdm_DiscoveryAgentTester_LDADD) $(LIBS) common/rdm/common_rdm_PidStoreTester-DescriptorConsistencyCheckerTest.$(OBJEXT): \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_rdm_PidStoreTester-PidStoreTest.$(OBJEXT): \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/PidStoreTester$(EXEEXT): $(common_rdm_PidStoreTester_OBJECTS) $(common_rdm_PidStoreTester_DEPENDENCIES) $(EXTRA_common_rdm_PidStoreTester_DEPENDENCIES) common/rdm/$(am__dirstamp) @rm -f common/rdm/PidStoreTester$(EXEEXT) $(AM_V_CXXLD)$(common_rdm_PidStoreTester_LINK) $(common_rdm_PidStoreTester_OBJECTS) $(common_rdm_PidStoreTester_LDADD) $(LIBS) common/rdm/common_rdm_QueueingRDMControllerTester-QueueingRDMControllerTest.$(OBJEXT): \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/QueueingRDMControllerTester$(EXEEXT): $(common_rdm_QueueingRDMControllerTester_OBJECTS) $(common_rdm_QueueingRDMControllerTester_DEPENDENCIES) $(EXTRA_common_rdm_QueueingRDMControllerTester_DEPENDENCIES) common/rdm/$(am__dirstamp) @rm -f common/rdm/QueueingRDMControllerTester$(EXEEXT) $(AM_V_CXXLD)$(common_rdm_QueueingRDMControllerTester_LINK) $(common_rdm_QueueingRDMControllerTester_OBJECTS) $(common_rdm_QueueingRDMControllerTester_LDADD) $(LIBS) common/rdm/common_rdm_RDMAPITester-RDMAPITest.$(OBJEXT): \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/RDMAPITester$(EXEEXT): $(common_rdm_RDMAPITester_OBJECTS) $(common_rdm_RDMAPITester_DEPENDENCIES) $(EXTRA_common_rdm_RDMAPITester_DEPENDENCIES) common/rdm/$(am__dirstamp) @rm -f common/rdm/RDMAPITester$(EXEEXT) $(AM_V_CXXLD)$(common_rdm_RDMAPITester_LINK) $(common_rdm_RDMAPITester_OBJECTS) $(common_rdm_RDMAPITester_LDADD) $(LIBS) common/rdm/common_rdm_RDMCommandSerializerTester-RDMCommandSerializerTest.$(OBJEXT): \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/RDMCommandSerializerTester$(EXEEXT): $(common_rdm_RDMCommandSerializerTester_OBJECTS) $(common_rdm_RDMCommandSerializerTester_DEPENDENCIES) $(EXTRA_common_rdm_RDMCommandSerializerTester_DEPENDENCIES) common/rdm/$(am__dirstamp) @rm -f common/rdm/RDMCommandSerializerTester$(EXEEXT) $(AM_V_CXXLD)$(common_rdm_RDMCommandSerializerTester_LINK) $(common_rdm_RDMCommandSerializerTester_OBJECTS) $(common_rdm_RDMCommandSerializerTester_LDADD) $(LIBS) common/rdm/common_rdm_RDMCommandTester-RDMCommandTest.$(OBJEXT): \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/RDMCommandTester$(EXEEXT): $(common_rdm_RDMCommandTester_OBJECTS) $(common_rdm_RDMCommandTester_DEPENDENCIES) $(EXTRA_common_rdm_RDMCommandTester_DEPENDENCIES) common/rdm/$(am__dirstamp) @rm -f common/rdm/RDMCommandTester$(EXEEXT) $(AM_V_CXXLD)$(common_rdm_RDMCommandTester_LINK) $(common_rdm_RDMCommandTester_OBJECTS) $(common_rdm_RDMCommandTester_LDADD) $(LIBS) common/rdm/common_rdm_RDMFrameTester-RDMFrameTest.$(OBJEXT): \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/RDMFrameTester$(EXEEXT): $(common_rdm_RDMFrameTester_OBJECTS) $(common_rdm_RDMFrameTester_DEPENDENCIES) $(EXTRA_common_rdm_RDMFrameTester_DEPENDENCIES) common/rdm/$(am__dirstamp) @rm -f common/rdm/RDMFrameTester$(EXEEXT) $(AM_V_CXXLD)$(common_rdm_RDMFrameTester_LINK) $(common_rdm_RDMFrameTester_OBJECTS) $(common_rdm_RDMFrameTester_LDADD) $(LIBS) common/rdm/common_rdm_RDMHelperTester-RDMHelperTest.$(OBJEXT): \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/RDMHelperTester$(EXEEXT): $(common_rdm_RDMHelperTester_OBJECTS) $(common_rdm_RDMHelperTester_DEPENDENCIES) $(EXTRA_common_rdm_RDMHelperTester_DEPENDENCIES) common/rdm/$(am__dirstamp) @rm -f common/rdm/RDMHelperTester$(EXEEXT) $(AM_V_CXXLD)$(common_rdm_RDMHelperTester_LINK) $(common_rdm_RDMHelperTester_OBJECTS) $(common_rdm_RDMHelperTester_LDADD) $(LIBS) common/rdm/common_rdm_RDMMessageTester-GroupSizeCalculatorTest.$(OBJEXT): \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_rdm_RDMMessageTester-MessageSerializerTest.$(OBJEXT): \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_rdm_RDMMessageTester-MessageDeserializerTest.$(OBJEXT): \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_rdm_RDMMessageTester-RDMMessageInterationTest.$(OBJEXT): \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_rdm_RDMMessageTester-StringMessageBuilderTest.$(OBJEXT): \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/common_rdm_RDMMessageTester-VariableFieldSizeCalculatorTest.$(OBJEXT): \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/RDMMessageTester$(EXEEXT): $(common_rdm_RDMMessageTester_OBJECTS) $(common_rdm_RDMMessageTester_DEPENDENCIES) $(EXTRA_common_rdm_RDMMessageTester_DEPENDENCIES) common/rdm/$(am__dirstamp) @rm -f common/rdm/RDMMessageTester$(EXEEXT) $(AM_V_CXXLD)$(common_rdm_RDMMessageTester_LINK) $(common_rdm_RDMMessageTester_OBJECTS) $(common_rdm_RDMMessageTester_LDADD) $(LIBS) common/rdm/common_rdm_RDMReplyTester-RDMReplyTest.$(OBJEXT): \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/RDMReplyTester$(EXEEXT): $(common_rdm_RDMReplyTester_OBJECTS) $(common_rdm_RDMReplyTester_DEPENDENCIES) $(EXTRA_common_rdm_RDMReplyTester_DEPENDENCIES) common/rdm/$(am__dirstamp) @rm -f common/rdm/RDMReplyTester$(EXEEXT) $(AM_V_CXXLD)$(common_rdm_RDMReplyTester_LINK) $(common_rdm_RDMReplyTester_OBJECTS) $(common_rdm_RDMReplyTester_LDADD) $(LIBS) common/rdm/common_rdm_UIDAllocatorTester-UIDAllocatorTest.$(OBJEXT): \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/UIDAllocatorTester$(EXEEXT): $(common_rdm_UIDAllocatorTester_OBJECTS) $(common_rdm_UIDAllocatorTester_DEPENDENCIES) $(EXTRA_common_rdm_UIDAllocatorTester_DEPENDENCIES) common/rdm/$(am__dirstamp) @rm -f common/rdm/UIDAllocatorTester$(EXEEXT) $(AM_V_CXXLD)$(common_rdm_UIDAllocatorTester_LINK) $(common_rdm_UIDAllocatorTester_OBJECTS) $(common_rdm_UIDAllocatorTester_LDADD) $(LIBS) common/rdm/common_rdm_UIDTester-UIDTest.$(OBJEXT): \ common/rdm/$(am__dirstamp) \ common/rdm/$(DEPDIR)/$(am__dirstamp) common/rdm/UIDTester$(EXEEXT): $(common_rdm_UIDTester_OBJECTS) $(common_rdm_UIDTester_DEPENDENCIES) $(EXTRA_common_rdm_UIDTester_DEPENDENCIES) common/rdm/$(am__dirstamp) @rm -f common/rdm/UIDTester$(EXEEXT) $(AM_V_CXXLD)$(common_rdm_UIDTester_LINK) $(common_rdm_UIDTester_OBJECTS) $(common_rdm_UIDTester_LDADD) $(LIBS) common/rpc/common_rpc_RpcServerTester-RpcServerTest.$(OBJEXT): \ common/rpc/$(am__dirstamp) \ common/rpc/$(DEPDIR)/$(am__dirstamp) common/rpc/common_rpc_RpcServerTester-TestService.$(OBJEXT): \ common/rpc/$(am__dirstamp) \ common/rpc/$(DEPDIR)/$(am__dirstamp) common/rpc/common_rpc_RpcServerTester-TestService.pb.$(OBJEXT): \ common/rpc/$(am__dirstamp) \ common/rpc/$(DEPDIR)/$(am__dirstamp) common/rpc/common_rpc_RpcServerTester-TestServiceService.pb.$(OBJEXT): \ common/rpc/$(am__dirstamp) \ common/rpc/$(DEPDIR)/$(am__dirstamp) common/rpc/RpcServerTester$(EXEEXT): $(common_rpc_RpcServerTester_OBJECTS) $(common_rpc_RpcServerTester_DEPENDENCIES) $(EXTRA_common_rpc_RpcServerTester_DEPENDENCIES) common/rpc/$(am__dirstamp) @rm -f common/rpc/RpcServerTester$(EXEEXT) $(AM_V_CXXLD)$(common_rpc_RpcServerTester_LINK) $(common_rpc_RpcServerTester_OBJECTS) $(common_rpc_RpcServerTester_LDADD) $(LIBS) common/rpc/common_rpc_RpcTester-RpcControllerTest.$(OBJEXT): \ common/rpc/$(am__dirstamp) \ common/rpc/$(DEPDIR)/$(am__dirstamp) common/rpc/common_rpc_RpcTester-RpcChannelTest.$(OBJEXT): \ common/rpc/$(am__dirstamp) \ common/rpc/$(DEPDIR)/$(am__dirstamp) common/rpc/common_rpc_RpcTester-RpcHeaderTest.$(OBJEXT): \ common/rpc/$(am__dirstamp) \ common/rpc/$(DEPDIR)/$(am__dirstamp) common/rpc/common_rpc_RpcTester-TestService.$(OBJEXT): \ common/rpc/$(am__dirstamp) \ common/rpc/$(DEPDIR)/$(am__dirstamp) common/rpc/common_rpc_RpcTester-TestService.pb.$(OBJEXT): \ common/rpc/$(am__dirstamp) \ common/rpc/$(DEPDIR)/$(am__dirstamp) common/rpc/common_rpc_RpcTester-TestServiceService.pb.$(OBJEXT): \ common/rpc/$(am__dirstamp) \ common/rpc/$(DEPDIR)/$(am__dirstamp) common/rpc/RpcTester$(EXEEXT): $(common_rpc_RpcTester_OBJECTS) $(common_rpc_RpcTester_DEPENDENCIES) $(EXTRA_common_rpc_RpcTester_DEPENDENCIES) common/rpc/$(am__dirstamp) @rm -f common/rpc/RpcTester$(EXEEXT) $(AM_V_CXXLD)$(common_rpc_RpcTester_LINK) $(common_rpc_RpcTester_OBJECTS) $(common_rpc_RpcTester_LDADD) $(LIBS) common/strings/common_strings_UtilsTester-UtilsTest.$(OBJEXT): \ common/strings/$(am__dirstamp) \ common/strings/$(DEPDIR)/$(am__dirstamp) common/strings/UtilsTester$(EXEEXT): $(common_strings_UtilsTester_OBJECTS) $(common_strings_UtilsTester_DEPENDENCIES) $(EXTRA_common_strings_UtilsTester_DEPENDENCIES) common/strings/$(am__dirstamp) @rm -f common/strings/UtilsTester$(EXEEXT) $(AM_V_CXXLD)$(common_strings_UtilsTester_LINK) $(common_strings_UtilsTester_OBJECTS) $(common_strings_UtilsTester_LDADD) $(LIBS) common/thread/common_thread_ExecutorThreadTester-ExecutorThreadTest.$(OBJEXT): \ common/thread/$(am__dirstamp) \ common/thread/$(DEPDIR)/$(am__dirstamp) common/thread/ExecutorThreadTester$(EXEEXT): $(common_thread_ExecutorThreadTester_OBJECTS) $(common_thread_ExecutorThreadTester_DEPENDENCIES) $(EXTRA_common_thread_ExecutorThreadTester_DEPENDENCIES) common/thread/$(am__dirstamp) @rm -f common/thread/ExecutorThreadTester$(EXEEXT) $(AM_V_CXXLD)$(common_thread_ExecutorThreadTester_LINK) $(common_thread_ExecutorThreadTester_OBJECTS) $(common_thread_ExecutorThreadTester_LDADD) $(LIBS) common/thread/common_thread_FutureTester-FutureTest.$(OBJEXT): \ common/thread/$(am__dirstamp) \ common/thread/$(DEPDIR)/$(am__dirstamp) common/thread/FutureTester$(EXEEXT): $(common_thread_FutureTester_OBJECTS) $(common_thread_FutureTester_DEPENDENCIES) $(EXTRA_common_thread_FutureTester_DEPENDENCIES) common/thread/$(am__dirstamp) @rm -f common/thread/FutureTester$(EXEEXT) $(AM_V_CXXLD)$(common_thread_FutureTester_LINK) $(common_thread_FutureTester_OBJECTS) $(common_thread_FutureTester_LDADD) $(LIBS) common/thread/common_thread_ThreadTester-ThreadPoolTest.$(OBJEXT): \ common/thread/$(am__dirstamp) \ common/thread/$(DEPDIR)/$(am__dirstamp) common/thread/common_thread_ThreadTester-ThreadTest.$(OBJEXT): \ common/thread/$(am__dirstamp) \ common/thread/$(DEPDIR)/$(am__dirstamp) common/thread/ThreadTester$(EXEEXT): $(common_thread_ThreadTester_OBJECTS) $(common_thread_ThreadTester_DEPENDENCIES) $(EXTRA_common_thread_ThreadTester_DEPENDENCIES) common/thread/$(am__dirstamp) @rm -f common/thread/ThreadTester$(EXEEXT) $(AM_V_CXXLD)$(common_thread_ThreadTester_LINK) $(common_thread_ThreadTester_OBJECTS) $(common_thread_ThreadTester_LDADD) $(LIBS) common/timecode/common_timecode_TimeCodeTester-TimeCodeTest.$(OBJEXT): \ common/timecode/$(am__dirstamp) \ common/timecode/$(DEPDIR)/$(am__dirstamp) common/timecode/TimeCodeTester$(EXEEXT): $(common_timecode_TimeCodeTester_OBJECTS) $(common_timecode_TimeCodeTester_DEPENDENCIES) $(EXTRA_common_timecode_TimeCodeTester_DEPENDENCIES) common/timecode/$(am__dirstamp) @rm -f common/timecode/TimeCodeTester$(EXEEXT) $(AM_V_CXXLD)$(common_timecode_TimeCodeTester_LINK) $(common_timecode_TimeCodeTester_OBJECTS) $(common_timecode_TimeCodeTester_LDADD) $(LIBS) common/utils/common_utils_UtilsTester-ActionQueueTest.$(OBJEXT): \ common/utils/$(am__dirstamp) \ common/utils/$(DEPDIR)/$(am__dirstamp) common/utils/common_utils_UtilsTester-BackoffTest.$(OBJEXT): \ common/utils/$(am__dirstamp) \ common/utils/$(DEPDIR)/$(am__dirstamp) common/utils/common_utils_UtilsTester-CallbackTest.$(OBJEXT): \ common/utils/$(am__dirstamp) \ common/utils/$(DEPDIR)/$(am__dirstamp) common/utils/common_utils_UtilsTester-ClockTest.$(OBJEXT): \ common/utils/$(am__dirstamp) \ common/utils/$(DEPDIR)/$(am__dirstamp) common/utils/common_utils_UtilsTester-DmxBufferTest.$(OBJEXT): \ common/utils/$(am__dirstamp) \ common/utils/$(DEPDIR)/$(am__dirstamp) common/utils/common_utils_UtilsTester-MultiCallbackTest.$(OBJEXT): \ common/utils/$(am__dirstamp) \ common/utils/$(DEPDIR)/$(am__dirstamp) common/utils/common_utils_UtilsTester-StringUtilsTest.$(OBJEXT): \ common/utils/$(am__dirstamp) \ common/utils/$(DEPDIR)/$(am__dirstamp) common/utils/common_utils_UtilsTester-TokenBucketTest.$(OBJEXT): \ common/utils/$(am__dirstamp) \ common/utils/$(DEPDIR)/$(am__dirstamp) common/utils/common_utils_UtilsTester-UtilsTest.$(OBJEXT): \ common/utils/$(am__dirstamp) \ common/utils/$(DEPDIR)/$(am__dirstamp) common/utils/common_utils_UtilsTester-WatchdogTest.$(OBJEXT): \ common/utils/$(am__dirstamp) \ common/utils/$(DEPDIR)/$(am__dirstamp) common/utils/UtilsTester$(EXEEXT): $(common_utils_UtilsTester_OBJECTS) $(common_utils_UtilsTester_DEPENDENCIES) $(EXTRA_common_utils_UtilsTester_DEPENDENCIES) common/utils/$(am__dirstamp) @rm -f common/utils/UtilsTester$(EXEEXT) $(AM_V_CXXLD)$(common_utils_UtilsTester_LINK) $(common_utils_UtilsTester_OBJECTS) $(common_utils_UtilsTester_LDADD) $(LIBS) common/web/common_web_JsonTester-JsonTest.$(OBJEXT): \ common/web/$(am__dirstamp) \ common/web/$(DEPDIR)/$(am__dirstamp) common/web/JsonTester$(EXEEXT): $(common_web_JsonTester_OBJECTS) $(common_web_JsonTester_DEPENDENCIES) $(EXTRA_common_web_JsonTester_DEPENDENCIES) common/web/$(am__dirstamp) @rm -f common/web/JsonTester$(EXEEXT) $(AM_V_CXXLD)$(common_web_JsonTester_LINK) $(common_web_JsonTester_OBJECTS) $(common_web_JsonTester_LDADD) $(LIBS) common/web/common_web_ParserTester-ParserTest.$(OBJEXT): \ common/web/$(am__dirstamp) \ common/web/$(DEPDIR)/$(am__dirstamp) common/web/ParserTester$(EXEEXT): $(common_web_ParserTester_OBJECTS) $(common_web_ParserTester_DEPENDENCIES) $(EXTRA_common_web_ParserTester_DEPENDENCIES) common/web/$(am__dirstamp) @rm -f common/web/ParserTester$(EXEEXT) $(AM_V_CXXLD)$(common_web_ParserTester_LINK) $(common_web_ParserTester_OBJECTS) $(common_web_ParserTester_LDADD) $(LIBS) common/web/common_web_PointerTester-PointerTest.$(OBJEXT): \ common/web/$(am__dirstamp) \ common/web/$(DEPDIR)/$(am__dirstamp) common/web/PointerTester$(EXEEXT): $(common_web_PointerTester_OBJECTS) $(common_web_PointerTester_DEPENDENCIES) $(EXTRA_common_web_PointerTester_DEPENDENCIES) common/web/$(am__dirstamp) @rm -f common/web/PointerTester$(EXEEXT) $(AM_V_CXXLD)$(common_web_PointerTester_LINK) $(common_web_PointerTester_OBJECTS) $(common_web_PointerTester_LDADD) $(LIBS) common/web/common_web_PointerTrackerTester-PointerTrackerTest.$(OBJEXT): \ common/web/$(am__dirstamp) \ common/web/$(DEPDIR)/$(am__dirstamp) common/web/PointerTrackerTester$(EXEEXT): $(common_web_PointerTrackerTester_OBJECTS) $(common_web_PointerTrackerTester_DEPENDENCIES) $(EXTRA_common_web_PointerTrackerTester_DEPENDENCIES) common/web/$(am__dirstamp) @rm -f common/web/PointerTrackerTester$(EXEEXT) $(AM_V_CXXLD)$(common_web_PointerTrackerTester_LINK) $(common_web_PointerTrackerTester_OBJECTS) $(common_web_PointerTrackerTester_LDADD) $(LIBS) common/web/common_web_PtchParserTester-PatchParserTest.$(OBJEXT): \ common/web/$(am__dirstamp) \ common/web/$(DEPDIR)/$(am__dirstamp) common/web/PtchParserTester$(EXEEXT): $(common_web_PtchParserTester_OBJECTS) $(common_web_PtchParserTester_DEPENDENCIES) $(EXTRA_common_web_PtchParserTester_DEPENDENCIES) common/web/$(am__dirstamp) @rm -f common/web/PtchParserTester$(EXEEXT) $(AM_V_CXXLD)$(common_web_PtchParserTester_LINK) $(common_web_PtchParserTester_OBJECTS) $(common_web_PtchParserTester_LDADD) $(LIBS) common/web/common_web_PtchTester-PatchTest.$(OBJEXT): \ common/web/$(am__dirstamp) \ common/web/$(DEPDIR)/$(am__dirstamp) common/web/PtchTester$(EXEEXT): $(common_web_PtchTester_OBJECTS) $(common_web_PtchTester_DEPENDENCIES) $(EXTRA_common_web_PtchTester_DEPENDENCIES) common/web/$(am__dirstamp) @rm -f common/web/PtchTester$(EXEEXT) $(AM_V_CXXLD)$(common_web_PtchTester_LINK) $(common_web_PtchTester_OBJECTS) $(common_web_PtchTester_LDADD) $(LIBS) common/web/common_web_SchemaParserTester-SchemaParserTest.$(OBJEXT): \ common/web/$(am__dirstamp) \ common/web/$(DEPDIR)/$(am__dirstamp) common/web/SchemaParserTester$(EXEEXT): $(common_web_SchemaParserTester_OBJECTS) $(common_web_SchemaParserTester_DEPENDENCIES) $(EXTRA_common_web_SchemaParserTester_DEPENDENCIES) common/web/$(am__dirstamp) @rm -f common/web/SchemaParserTester$(EXEEXT) $(AM_V_CXXLD)$(common_web_SchemaParserTester_LINK) $(common_web_SchemaParserTester_OBJECTS) $(common_web_SchemaParserTester_LDADD) $(LIBS) common/web/common_web_SchemaTester-SchemaTest.$(OBJEXT): \ common/web/$(am__dirstamp) \ common/web/$(DEPDIR)/$(am__dirstamp) common/web/SchemaTester$(EXEEXT): $(common_web_SchemaTester_OBJECTS) $(common_web_SchemaTester_DEPENDENCIES) $(EXTRA_common_web_SchemaTester_DEPENDENCIES) common/web/$(am__dirstamp) @rm -f common/web/SchemaTester$(EXEEXT) $(AM_V_CXXLD)$(common_web_SchemaTester_LINK) $(common_web_SchemaTester_OBJECTS) $(common_web_SchemaTester_LDADD) $(LIBS) common/web/common_web_SectionsTester-SectionsTest.$(OBJEXT): \ common/web/$(am__dirstamp) \ common/web/$(DEPDIR)/$(am__dirstamp) common/web/SectionsTester$(EXEEXT): $(common_web_SectionsTester_OBJECTS) $(common_web_SectionsTester_DEPENDENCIES) $(EXTRA_common_web_SectionsTester_DEPENDENCIES) common/web/$(am__dirstamp) @rm -f common/web/SectionsTester$(EXEEXT) $(AM_V_CXXLD)$(common_web_SectionsTester_LINK) $(common_web_SectionsTester_OBJECTS) $(common_web_SectionsTester_LDADD) $(LIBS) data/rdm/$(am__dirstamp): @$(MKDIR_P) data/rdm @: > data/rdm/$(am__dirstamp) data/rdm/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) data/rdm/$(DEPDIR) @: > data/rdm/$(DEPDIR)/$(am__dirstamp) data/rdm/data_rdm_PidDataTester-PidDataTest.$(OBJEXT): \ data/rdm/$(am__dirstamp) data/rdm/$(DEPDIR)/$(am__dirstamp) data/rdm/PidDataTester$(EXEEXT): $(data_rdm_PidDataTester_OBJECTS) $(data_rdm_PidDataTester_DEPENDENCIES) $(EXTRA_data_rdm_PidDataTester_DEPENDENCIES) data/rdm/$(am__dirstamp) @rm -f data/rdm/PidDataTester$(EXEEXT) $(AM_V_CXXLD)$(data_rdm_PidDataTester_LINK) $(data_rdm_PidDataTester_OBJECTS) $(data_rdm_PidDataTester_LDADD) $(LIBS) doxygen/examples/$(am__dirstamp): @$(MKDIR_P) doxygen/examples @: > doxygen/examples/$(am__dirstamp) doxygen/examples/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) doxygen/examples/$(DEPDIR) @: > doxygen/examples/$(DEPDIR)/$(am__dirstamp) doxygen/examples/callback_client_transmit.$(OBJEXT): \ doxygen/examples/$(am__dirstamp) \ doxygen/examples/$(DEPDIR)/$(am__dirstamp) doxygen/examples/callback_client_transmit$(EXEEXT): $(doxygen_examples_callback_client_transmit_OBJECTS) $(doxygen_examples_callback_client_transmit_DEPENDENCIES) $(EXTRA_doxygen_examples_callback_client_transmit_DEPENDENCIES) doxygen/examples/$(am__dirstamp) @rm -f doxygen/examples/callback_client_transmit$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(doxygen_examples_callback_client_transmit_OBJECTS) $(doxygen_examples_callback_client_transmit_LDADD) $(LIBS) doxygen/examples/client_disconnect.$(OBJEXT): \ doxygen/examples/$(am__dirstamp) \ doxygen/examples/$(DEPDIR)/$(am__dirstamp) doxygen/examples/client_disconnect$(EXEEXT): $(doxygen_examples_client_disconnect_OBJECTS) $(doxygen_examples_client_disconnect_DEPENDENCIES) $(EXTRA_doxygen_examples_client_disconnect_DEPENDENCIES) doxygen/examples/$(am__dirstamp) @rm -f doxygen/examples/client_disconnect$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(doxygen_examples_client_disconnect_OBJECTS) $(doxygen_examples_client_disconnect_LDADD) $(LIBS) doxygen/examples/client_thread.$(OBJEXT): \ doxygen/examples/$(am__dirstamp) \ doxygen/examples/$(DEPDIR)/$(am__dirstamp) doxygen/examples/client_thread$(EXEEXT): $(doxygen_examples_client_thread_OBJECTS) $(doxygen_examples_client_thread_DEPENDENCIES) $(EXTRA_doxygen_examples_client_thread_DEPENDENCIES) doxygen/examples/$(am__dirstamp) @rm -f doxygen/examples/client_thread$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(doxygen_examples_client_thread_OBJECTS) $(doxygen_examples_client_thread_LDADD) $(LIBS) doxygen/examples/fetch_plugins.$(OBJEXT): \ doxygen/examples/$(am__dirstamp) \ doxygen/examples/$(DEPDIR)/$(am__dirstamp) doxygen/examples/fetch_plugins$(EXEEXT): $(doxygen_examples_fetch_plugins_OBJECTS) $(doxygen_examples_fetch_plugins_DEPENDENCIES) $(EXTRA_doxygen_examples_fetch_plugins_DEPENDENCIES) doxygen/examples/$(am__dirstamp) @rm -f doxygen/examples/fetch_plugins$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(doxygen_examples_fetch_plugins_OBJECTS) $(doxygen_examples_fetch_plugins_LDADD) $(LIBS) doxygen/examples/flags.$(OBJEXT): doxygen/examples/$(am__dirstamp) \ doxygen/examples/$(DEPDIR)/$(am__dirstamp) doxygen/examples/flags$(EXEEXT): $(doxygen_examples_flags_OBJECTS) $(doxygen_examples_flags_DEPENDENCIES) $(EXTRA_doxygen_examples_flags_DEPENDENCIES) doxygen/examples/$(am__dirstamp) @rm -f doxygen/examples/flags$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(doxygen_examples_flags_OBJECTS) $(doxygen_examples_flags_LDADD) $(LIBS) doxygen/examples/legacy_callback_client_transmit.$(OBJEXT): \ doxygen/examples/$(am__dirstamp) \ doxygen/examples/$(DEPDIR)/$(am__dirstamp) doxygen/examples/legacy_callback_client_transmit$(EXEEXT): $(doxygen_examples_legacy_callback_client_transmit_OBJECTS) $(doxygen_examples_legacy_callback_client_transmit_DEPENDENCIES) $(EXTRA_doxygen_examples_legacy_callback_client_transmit_DEPENDENCIES) doxygen/examples/$(am__dirstamp) @rm -f doxygen/examples/legacy_callback_client_transmit$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(doxygen_examples_legacy_callback_client_transmit_OBJECTS) $(doxygen_examples_legacy_callback_client_transmit_LDADD) $(LIBS) doxygen/examples/legacy_receiver.$(OBJEXT): \ doxygen/examples/$(am__dirstamp) \ doxygen/examples/$(DEPDIR)/$(am__dirstamp) doxygen/examples/legacy_receiver$(EXEEXT): $(doxygen_examples_legacy_receiver_OBJECTS) $(doxygen_examples_legacy_receiver_DEPENDENCIES) $(EXTRA_doxygen_examples_legacy_receiver_DEPENDENCIES) doxygen/examples/$(am__dirstamp) @rm -f doxygen/examples/legacy_receiver$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(doxygen_examples_legacy_receiver_OBJECTS) $(doxygen_examples_legacy_receiver_LDADD) $(LIBS) doxygen/examples/legacy_streaming_client.$(OBJEXT): \ doxygen/examples/$(am__dirstamp) \ doxygen/examples/$(DEPDIR)/$(am__dirstamp) doxygen/examples/legacy_streaming_client$(EXEEXT): $(doxygen_examples_legacy_streaming_client_OBJECTS) $(doxygen_examples_legacy_streaming_client_DEPENDENCIES) $(EXTRA_doxygen_examples_legacy_streaming_client_DEPENDENCIES) doxygen/examples/$(am__dirstamp) @rm -f doxygen/examples/legacy_streaming_client$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(doxygen_examples_legacy_streaming_client_OBJECTS) $(doxygen_examples_legacy_streaming_client_LDADD) $(LIBS) doxygen/examples/receiver.$(OBJEXT): doxygen/examples/$(am__dirstamp) \ doxygen/examples/$(DEPDIR)/$(am__dirstamp) doxygen/examples/receiver$(EXEEXT): $(doxygen_examples_receiver_OBJECTS) $(doxygen_examples_receiver_DEPENDENCIES) $(EXTRA_doxygen_examples_receiver_DEPENDENCIES) doxygen/examples/$(am__dirstamp) @rm -f doxygen/examples/receiver$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(doxygen_examples_receiver_OBJECTS) $(doxygen_examples_receiver_LDADD) $(LIBS) doxygen/examples/stdin_handler.$(OBJEXT): \ doxygen/examples/$(am__dirstamp) \ doxygen/examples/$(DEPDIR)/$(am__dirstamp) doxygen/examples/stdin_handler$(EXEEXT): $(doxygen_examples_stdin_handler_OBJECTS) $(doxygen_examples_stdin_handler_DEPENDENCIES) $(EXTRA_doxygen_examples_stdin_handler_DEPENDENCIES) doxygen/examples/$(am__dirstamp) @rm -f doxygen/examples/stdin_handler$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(doxygen_examples_stdin_handler_OBJECTS) $(doxygen_examples_stdin_handler_LDADD) $(LIBS) doxygen/examples/streaming_client.$(OBJEXT): \ doxygen/examples/$(am__dirstamp) \ doxygen/examples/$(DEPDIR)/$(am__dirstamp) doxygen/examples/streaming_client$(EXEEXT): $(doxygen_examples_streaming_client_OBJECTS) $(doxygen_examples_streaming_client_DEPENDENCIES) $(EXTRA_doxygen_examples_streaming_client_DEPENDENCIES) doxygen/examples/$(am__dirstamp) @rm -f doxygen/examples/streaming_client$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(doxygen_examples_streaming_client_OBJECTS) $(doxygen_examples_streaming_client_LDADD) $(LIBS) doxygen/examples/streaming_client_plugin.$(OBJEXT): \ doxygen/examples/$(am__dirstamp) \ doxygen/examples/$(DEPDIR)/$(am__dirstamp) doxygen/examples/streaming_client_plugin$(EXEEXT): $(doxygen_examples_streaming_client_plugin_OBJECTS) $(doxygen_examples_streaming_client_plugin_DEPENDENCIES) $(EXTRA_doxygen_examples_streaming_client_plugin_DEPENDENCIES) doxygen/examples/$(am__dirstamp) @rm -f doxygen/examples/streaming_client_plugin$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(doxygen_examples_streaming_client_plugin_OBJECTS) $(doxygen_examples_streaming_client_plugin_LDADD) $(LIBS) doxygen/examples/udp_server.$(OBJEXT): \ doxygen/examples/$(am__dirstamp) \ doxygen/examples/$(DEPDIR)/$(am__dirstamp) doxygen/examples/udp_server$(EXEEXT): $(doxygen_examples_udp_server_OBJECTS) $(doxygen_examples_udp_server_DEPENDENCIES) $(EXTRA_doxygen_examples_udp_server_DEPENDENCIES) doxygen/examples/$(am__dirstamp) @rm -f doxygen/examples/udp_server$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(doxygen_examples_udp_server_OBJECTS) $(doxygen_examples_udp_server_LDADD) $(LIBS) examples/examples_ola_artnet-ola-artnet.$(OBJEXT): \ examples/$(am__dirstamp) examples/$(DEPDIR)/$(am__dirstamp) examples/ola_artnet$(EXEEXT): $(examples_ola_artnet_OBJECTS) $(examples_ola_artnet_DEPENDENCIES) $(EXTRA_examples_ola_artnet_DEPENDENCIES) examples/$(am__dirstamp) @rm -f examples/ola_artnet$(EXEEXT) $(AM_V_CXXLD)$(examples_ola_artnet_LINK) $(examples_ola_artnet_OBJECTS) $(examples_ola_artnet_LDADD) $(LIBS) examples/ola-client.$(OBJEXT): examples/$(am__dirstamp) \ examples/$(DEPDIR)/$(am__dirstamp) examples/ola_dev_info$(EXEEXT): $(examples_ola_dev_info_OBJECTS) $(examples_ola_dev_info_DEPENDENCIES) $(EXTRA_examples_ola_dev_info_DEPENDENCIES) examples/$(am__dirstamp) @rm -f examples/ola_dev_info$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(examples_ola_dev_info_OBJECTS) $(examples_ola_dev_info_LDADD) $(LIBS) examples/ola-dmxconsole.$(OBJEXT): examples/$(am__dirstamp) \ examples/$(DEPDIR)/$(am__dirstamp) examples/ola_dmxconsole$(EXEEXT): $(examples_ola_dmxconsole_OBJECTS) $(examples_ola_dmxconsole_DEPENDENCIES) $(EXTRA_examples_ola_dmxconsole_DEPENDENCIES) examples/$(am__dirstamp) @rm -f examples/ola_dmxconsole$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(examples_ola_dmxconsole_OBJECTS) $(examples_ola_dmxconsole_LDADD) $(LIBS) examples/ola-dmxmonitor.$(OBJEXT): examples/$(am__dirstamp) \ examples/$(DEPDIR)/$(am__dirstamp) examples/ola_dmxmonitor$(EXEEXT): $(examples_ola_dmxmonitor_OBJECTS) $(examples_ola_dmxmonitor_DEPENDENCIES) $(EXTRA_examples_ola_dmxmonitor_DEPENDENCIES) examples/$(am__dirstamp) @rm -f examples/ola_dmxmonitor$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(examples_ola_dmxmonitor_OBJECTS) $(examples_ola_dmxmonitor_LDADD) $(LIBS) examples/examples_ola_e131-ola-e131.$(OBJEXT): \ examples/$(am__dirstamp) examples/$(DEPDIR)/$(am__dirstamp) examples/ola_e131$(EXEEXT): $(examples_ola_e131_OBJECTS) $(examples_ola_e131_DEPENDENCIES) $(EXTRA_examples_ola_e131_DEPENDENCIES) examples/$(am__dirstamp) @rm -f examples/ola_e131$(EXEEXT) $(AM_V_CXXLD)$(examples_ola_e131_LINK) $(examples_ola_e131_OBJECTS) $(examples_ola_e131_LDADD) $(LIBS) examples/ola-latency.$(OBJEXT): examples/$(am__dirstamp) \ examples/$(DEPDIR)/$(am__dirstamp) examples/ola_latency$(EXEEXT): $(examples_ola_latency_OBJECTS) $(examples_ola_latency_DEPENDENCIES) $(EXTRA_examples_ola_latency_DEPENDENCIES) examples/$(am__dirstamp) @rm -f examples/ola_latency$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(examples_ola_latency_OBJECTS) $(examples_ola_latency_LDADD) $(LIBS) examples/ola-rdm-discover.$(OBJEXT): examples/$(am__dirstamp) \ examples/$(DEPDIR)/$(am__dirstamp) examples/ola_rdm_discover$(EXEEXT): $(examples_ola_rdm_discover_OBJECTS) $(examples_ola_rdm_discover_DEPENDENCIES) $(EXTRA_examples_ola_rdm_discover_DEPENDENCIES) examples/$(am__dirstamp) @rm -f examples/ola_rdm_discover$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(examples_ola_rdm_discover_OBJECTS) $(examples_ola_rdm_discover_LDADD) $(LIBS) examples/ola-rdm.$(OBJEXT): examples/$(am__dirstamp) \ examples/$(DEPDIR)/$(am__dirstamp) examples/ola_rdm_get$(EXEEXT): $(examples_ola_rdm_get_OBJECTS) $(examples_ola_rdm_get_DEPENDENCIES) $(EXTRA_examples_ola_rdm_get_DEPENDENCIES) examples/$(am__dirstamp) @rm -f examples/ola_rdm_get$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(examples_ola_rdm_get_OBJECTS) $(examples_ola_rdm_get_LDADD) $(LIBS) examples/ola-recorder.$(OBJEXT): examples/$(am__dirstamp) \ examples/$(DEPDIR)/$(am__dirstamp) examples/ShowLoader.$(OBJEXT): examples/$(am__dirstamp) \ examples/$(DEPDIR)/$(am__dirstamp) examples/ShowPlayer.$(OBJEXT): examples/$(am__dirstamp) \ examples/$(DEPDIR)/$(am__dirstamp) examples/ShowRecorder.$(OBJEXT): examples/$(am__dirstamp) \ examples/$(DEPDIR)/$(am__dirstamp) examples/ShowSaver.$(OBJEXT): examples/$(am__dirstamp) \ examples/$(DEPDIR)/$(am__dirstamp) examples/ola_recorder$(EXEEXT): $(examples_ola_recorder_OBJECTS) $(examples_ola_recorder_DEPENDENCIES) $(EXTRA_examples_ola_recorder_DEPENDENCIES) examples/$(am__dirstamp) @rm -f examples/ola_recorder$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(examples_ola_recorder_OBJECTS) $(examples_ola_recorder_LDADD) $(LIBS) examples/ola-streaming-client.$(OBJEXT): examples/$(am__dirstamp) \ examples/$(DEPDIR)/$(am__dirstamp) examples/ola_streaming_client$(EXEEXT): $(examples_ola_streaming_client_OBJECTS) $(examples_ola_streaming_client_DEPENDENCIES) $(EXTRA_examples_ola_streaming_client_DEPENDENCIES) examples/$(am__dirstamp) @rm -f examples/ola_streaming_client$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(examples_ola_streaming_client_OBJECTS) $(examples_ola_streaming_client_LDADD) $(LIBS) examples/ola-throughput.$(OBJEXT): examples/$(am__dirstamp) \ examples/$(DEPDIR)/$(am__dirstamp) examples/ola_throughput$(EXEEXT): $(examples_ola_throughput_OBJECTS) $(examples_ola_throughput_DEPENDENCIES) $(EXTRA_examples_ola_throughput_DEPENDENCIES) examples/$(am__dirstamp) @rm -f examples/ola_throughput$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(examples_ola_throughput_OBJECTS) $(examples_ola_throughput_LDADD) $(LIBS) examples/ola-timecode.$(OBJEXT): examples/$(am__dirstamp) \ examples/$(DEPDIR)/$(am__dirstamp) examples/ola_timecode$(EXEEXT): $(examples_ola_timecode_OBJECTS) $(examples_ola_timecode_DEPENDENCIES) $(EXTRA_examples_ola_timecode_DEPENDENCIES) examples/$(am__dirstamp) @rm -f examples/ola_timecode$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(examples_ola_timecode_OBJECTS) $(examples_ola_timecode_LDADD) $(LIBS) examples/ola-uni-stats.$(OBJEXT): examples/$(am__dirstamp) \ examples/$(DEPDIR)/$(am__dirstamp) examples/ola_uni_stats$(EXEEXT): $(examples_ola_uni_stats_OBJECTS) $(examples_ola_uni_stats_DEPENDENCIES) $(EXTRA_examples_ola_uni_stats_DEPENDENCIES) examples/$(am__dirstamp) @rm -f examples/ola_uni_stats$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(examples_ola_uni_stats_OBJECTS) $(examples_ola_uni_stats_LDADD) $(LIBS) examples/examples_ola_usbpro-ola-usbpro.$(OBJEXT): \ examples/$(am__dirstamp) examples/$(DEPDIR)/$(am__dirstamp) examples/ola_usbpro$(EXEEXT): $(examples_ola_usbpro_OBJECTS) $(examples_ola_usbpro_DEPENDENCIES) $(EXTRA_examples_ola_usbpro_DEPENDENCIES) examples/$(am__dirstamp) @rm -f examples/ola_usbpro$(EXEEXT) $(AM_V_CXXLD)$(examples_ola_usbpro_LINK) $(examples_ola_usbpro_OBJECTS) $(examples_ola_usbpro_LDADD) $(LIBS) libs/acn/libs_acn_E131Tester-BaseInflatorTest.$(OBJEXT): \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_E131Tester-CIDTest.$(OBJEXT): \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_E131Tester-DMPAddressTest.$(OBJEXT): \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_E131Tester-DMPInflatorTest.$(OBJEXT): \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_E131Tester-DMPPDUTest.$(OBJEXT): \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_E131Tester-E131InflatorTest.$(OBJEXT): \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_E131Tester-E131PDUTest.$(OBJEXT): \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_E131Tester-HeaderSetTest.$(OBJEXT): \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_E131Tester-PDUTest.$(OBJEXT): \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_E131Tester-RootInflatorTest.$(OBJEXT): \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_E131Tester-RootPDUTest.$(OBJEXT): \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_E131Tester-RootSenderTest.$(OBJEXT): \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/E131Tester$(EXEEXT): $(libs_acn_E131Tester_OBJECTS) $(libs_acn_E131Tester_DEPENDENCIES) $(EXTRA_libs_acn_E131Tester_DEPENDENCIES) libs/acn/$(am__dirstamp) @rm -f libs/acn/E131Tester$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(libs_acn_E131Tester_OBJECTS) $(libs_acn_E131Tester_LDADD) $(LIBS) libs/acn/libs_acn_E133Tester-E133InflatorTest.$(OBJEXT): \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_E133Tester-E133PDUTest.$(OBJEXT): \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_E133Tester-RDMPDUTest.$(OBJEXT): \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/E133Tester$(EXEEXT): $(libs_acn_E133Tester_OBJECTS) $(libs_acn_E133Tester_DEPENDENCIES) $(EXTRA_libs_acn_E133Tester_DEPENDENCIES) libs/acn/$(am__dirstamp) @rm -f libs/acn/E133Tester$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(libs_acn_E133Tester_OBJECTS) $(libs_acn_E133Tester_LDADD) $(LIBS) libs/acn/libs_acn_TransportTester-TCPTransportTest.$(OBJEXT): \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/libs_acn_TransportTester-UDPTransportTest.$(OBJEXT): \ libs/acn/$(am__dirstamp) libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/TransportTester$(EXEEXT): $(libs_acn_TransportTester_OBJECTS) $(libs_acn_TransportTester_DEPENDENCIES) $(EXTRA_libs_acn_TransportTester_DEPENDENCIES) libs/acn/$(am__dirstamp) @rm -f libs/acn/TransportTester$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(libs_acn_TransportTester_OBJECTS) $(libs_acn_TransportTester_LDADD) $(LIBS) libs/acn/e131_loadtest.$(OBJEXT): libs/acn/$(am__dirstamp) \ libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/e131_loadtest$(EXEEXT): $(libs_acn_e131_loadtest_OBJECTS) $(libs_acn_e131_loadtest_DEPENDENCIES) $(EXTRA_libs_acn_e131_loadtest_DEPENDENCIES) libs/acn/$(am__dirstamp) @rm -f libs/acn/e131_loadtest$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(libs_acn_e131_loadtest_OBJECTS) $(libs_acn_e131_loadtest_LDADD) $(LIBS) libs/acn/e131_transmit_test.$(OBJEXT): libs/acn/$(am__dirstamp) \ libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/E131TestFramework.$(OBJEXT): libs/acn/$(am__dirstamp) \ libs/acn/$(DEPDIR)/$(am__dirstamp) libs/acn/e131_transmit_test$(EXEEXT): $(libs_acn_e131_transmit_test_OBJECTS) $(libs_acn_e131_transmit_test_DEPENDENCIES) $(EXTRA_libs_acn_e131_transmit_test_DEPENDENCIES) libs/acn/$(am__dirstamp) @rm -f libs/acn/e131_transmit_test$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(libs_acn_e131_transmit_test_OBJECTS) $(libs_acn_e131_transmit_test_LDADD) $(LIBS) libs/usb/libs_usb_LibUsbThreadTester-LibUsbThreadTest.$(OBJEXT): \ libs/usb/$(am__dirstamp) libs/usb/$(DEPDIR)/$(am__dirstamp) libs/usb/LibUsbThreadTester$(EXEEXT): $(libs_usb_LibUsbThreadTester_OBJECTS) $(libs_usb_LibUsbThreadTester_DEPENDENCIES) $(EXTRA_libs_usb_LibUsbThreadTester_DEPENDENCIES) libs/usb/$(am__dirstamp) @rm -f libs/usb/LibUsbThreadTester$(EXEEXT) $(AM_V_CXXLD)$(libs_usb_LibUsbThreadTester_LINK) $(libs_usb_LibUsbThreadTester_OBJECTS) $(libs_usb_LibUsbThreadTester_LDADD) $(LIBS) ola/ola_OlaClientTester-OlaClientWrapperTest.$(OBJEXT): \ ola/$(am__dirstamp) ola/$(DEPDIR)/$(am__dirstamp) ola/ola_OlaClientTester-StreamingClientTest.$(OBJEXT): \ ola/$(am__dirstamp) ola/$(DEPDIR)/$(am__dirstamp) ola/OlaClientTester$(EXEEXT): $(ola_OlaClientTester_OBJECTS) $(ola_OlaClientTester_DEPENDENCIES) $(EXTRA_ola_OlaClientTester_DEPENDENCIES) ola/$(am__dirstamp) @rm -f ola/OlaClientTester$(EXEEXT) $(AM_V_CXXLD)$(ola_OlaClientTester_LINK) $(ola_OlaClientTester_OBJECTS) $(ola_OlaClientTester_LDADD) $(LIBS) olad/olad_OlaTester-PluginManagerTest.$(OBJEXT): olad/$(am__dirstamp) \ olad/$(DEPDIR)/$(am__dirstamp) olad/olad_OlaTester-OlaServerServiceImplTest.$(OBJEXT): \ olad/$(am__dirstamp) olad/$(DEPDIR)/$(am__dirstamp) olad/OlaTester$(EXEEXT): $(olad_OlaTester_OBJECTS) $(olad_OlaTester_DEPENDENCIES) $(EXTRA_olad_OlaTester_DEPENDENCIES) olad/$(am__dirstamp) @rm -f olad/OlaTester$(EXEEXT) $(AM_V_CXXLD)$(olad_OlaTester_LINK) $(olad_OlaTester_OBJECTS) $(olad_OlaTester_LDADD) $(LIBS) olad/Olad.$(OBJEXT): olad/$(am__dirstamp) \ olad/$(DEPDIR)/$(am__dirstamp) olad/olad$(EXEEXT): $(olad_olad_OBJECTS) $(olad_olad_DEPENDENCIES) $(EXTRA_olad_olad_DEPENDENCIES) olad/$(am__dirstamp) @rm -f olad/olad$(EXEEXT) $(AM_V_CXXLD)$(olad_olad_LINK) $(olad_olad_OBJECTS) $(olad_olad_LDADD) $(LIBS) olad/plugin_api/olad_plugin_api_ClientTester-ClientTest.$(OBJEXT): \ olad/plugin_api/$(am__dirstamp) \ olad/plugin_api/$(DEPDIR)/$(am__dirstamp) olad/plugin_api/ClientTester$(EXEEXT): $(olad_plugin_api_ClientTester_OBJECTS) $(olad_plugin_api_ClientTester_DEPENDENCIES) $(EXTRA_olad_plugin_api_ClientTester_DEPENDENCIES) olad/plugin_api/$(am__dirstamp) @rm -f olad/plugin_api/ClientTester$(EXEEXT) $(AM_V_CXXLD)$(olad_plugin_api_ClientTester_LINK) $(olad_plugin_api_ClientTester_OBJECTS) $(olad_plugin_api_ClientTester_LDADD) $(LIBS) olad/plugin_api/olad_plugin_api_DeviceTester-DeviceManagerTest.$(OBJEXT): \ olad/plugin_api/$(am__dirstamp) \ olad/plugin_api/$(DEPDIR)/$(am__dirstamp) olad/plugin_api/olad_plugin_api_DeviceTester-DeviceTest.$(OBJEXT): \ olad/plugin_api/$(am__dirstamp) \ olad/plugin_api/$(DEPDIR)/$(am__dirstamp) olad/plugin_api/DeviceTester$(EXEEXT): $(olad_plugin_api_DeviceTester_OBJECTS) $(olad_plugin_api_DeviceTester_DEPENDENCIES) $(EXTRA_olad_plugin_api_DeviceTester_DEPENDENCIES) olad/plugin_api/$(am__dirstamp) @rm -f olad/plugin_api/DeviceTester$(EXEEXT) $(AM_V_CXXLD)$(olad_plugin_api_DeviceTester_LINK) $(olad_plugin_api_DeviceTester_OBJECTS) $(olad_plugin_api_DeviceTester_LDADD) $(LIBS) olad/plugin_api/olad_plugin_api_DmxSourceTester-DmxSourceTest.$(OBJEXT): \ olad/plugin_api/$(am__dirstamp) \ olad/plugin_api/$(DEPDIR)/$(am__dirstamp) olad/plugin_api/DmxSourceTester$(EXEEXT): $(olad_plugin_api_DmxSourceTester_OBJECTS) $(olad_plugin_api_DmxSourceTester_DEPENDENCIES) $(EXTRA_olad_plugin_api_DmxSourceTester_DEPENDENCIES) olad/plugin_api/$(am__dirstamp) @rm -f olad/plugin_api/DmxSourceTester$(EXEEXT) $(AM_V_CXXLD)$(olad_plugin_api_DmxSourceTester_LINK) $(olad_plugin_api_DmxSourceTester_OBJECTS) $(olad_plugin_api_DmxSourceTester_LDADD) $(LIBS) olad/plugin_api/olad_plugin_api_PortTester-PortTest.$(OBJEXT): \ olad/plugin_api/$(am__dirstamp) \ olad/plugin_api/$(DEPDIR)/$(am__dirstamp) olad/plugin_api/olad_plugin_api_PortTester-PortManagerTest.$(OBJEXT): \ olad/plugin_api/$(am__dirstamp) \ olad/plugin_api/$(DEPDIR)/$(am__dirstamp) olad/plugin_api/PortTester$(EXEEXT): $(olad_plugin_api_PortTester_OBJECTS) $(olad_plugin_api_PortTester_DEPENDENCIES) $(EXTRA_olad_plugin_api_PortTester_DEPENDENCIES) olad/plugin_api/$(am__dirstamp) @rm -f olad/plugin_api/PortTester$(EXEEXT) $(AM_V_CXXLD)$(olad_plugin_api_PortTester_LINK) $(olad_plugin_api_PortTester_OBJECTS) $(olad_plugin_api_PortTester_LDADD) $(LIBS) olad/plugin_api/olad_plugin_api_PreferencesTester-PreferencesTest.$(OBJEXT): \ olad/plugin_api/$(am__dirstamp) \ olad/plugin_api/$(DEPDIR)/$(am__dirstamp) olad/plugin_api/PreferencesTester$(EXEEXT): $(olad_plugin_api_PreferencesTester_OBJECTS) $(olad_plugin_api_PreferencesTester_DEPENDENCIES) $(EXTRA_olad_plugin_api_PreferencesTester_DEPENDENCIES) olad/plugin_api/$(am__dirstamp) @rm -f olad/plugin_api/PreferencesTester$(EXEEXT) $(AM_V_CXXLD)$(olad_plugin_api_PreferencesTester_LINK) $(olad_plugin_api_PreferencesTester_OBJECTS) $(olad_plugin_api_PreferencesTester_LDADD) $(LIBS) olad/plugin_api/olad_plugin_api_UniverseTester-UniverseTest.$(OBJEXT): \ olad/plugin_api/$(am__dirstamp) \ olad/plugin_api/$(DEPDIR)/$(am__dirstamp) olad/plugin_api/UniverseTester$(EXEEXT): $(olad_plugin_api_UniverseTester_OBJECTS) $(olad_plugin_api_UniverseTester_DEPENDENCIES) $(EXTRA_olad_plugin_api_UniverseTester_DEPENDENCIES) olad/plugin_api/$(am__dirstamp) @rm -f olad/plugin_api/UniverseTester$(EXEEXT) $(AM_V_CXXLD)$(olad_plugin_api_UniverseTester_LINK) $(olad_plugin_api_UniverseTester_OBJECTS) $(olad_plugin_api_UniverseTester_LDADD) $(LIBS) plugins/artnet/plugins_artnet_ArtNetTester-ArtNetNodeTest.$(OBJEXT): \ plugins/artnet/$(am__dirstamp) \ plugins/artnet/$(DEPDIR)/$(am__dirstamp) plugins/artnet/ArtNetTester$(EXEEXT): $(plugins_artnet_ArtNetTester_OBJECTS) $(plugins_artnet_ArtNetTester_DEPENDENCIES) $(EXTRA_plugins_artnet_ArtNetTester_DEPENDENCIES) plugins/artnet/$(am__dirstamp) @rm -f plugins/artnet/ArtNetTester$(EXEEXT) $(AM_V_CXXLD)$(plugins_artnet_ArtNetTester_LINK) $(plugins_artnet_ArtNetTester_OBJECTS) $(plugins_artnet_ArtNetTester_LDADD) $(LIBS) plugins/artnet/artnet_loadtest.$(OBJEXT): \ plugins/artnet/$(am__dirstamp) \ plugins/artnet/$(DEPDIR)/$(am__dirstamp) plugins/artnet/artnet_loadtest$(EXEEXT): $(plugins_artnet_artnet_loadtest_OBJECTS) $(plugins_artnet_artnet_loadtest_DEPENDENCIES) $(EXTRA_plugins_artnet_artnet_loadtest_DEPENDENCIES) plugins/artnet/$(am__dirstamp) @rm -f plugins/artnet/artnet_loadtest$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(plugins_artnet_artnet_loadtest_OBJECTS) $(plugins_artnet_artnet_loadtest_LDADD) $(LIBS) plugins/dummy/plugins_dummy_DummyPluginTester-DummyPortTest.$(OBJEXT): \ plugins/dummy/$(am__dirstamp) \ plugins/dummy/$(DEPDIR)/$(am__dirstamp) plugins/dummy/DummyPluginTester$(EXEEXT): $(plugins_dummy_DummyPluginTester_OBJECTS) $(plugins_dummy_DummyPluginTester_DEPENDENCIES) $(EXTRA_plugins_dummy_DummyPluginTester_DEPENDENCIES) plugins/dummy/$(am__dirstamp) @rm -f plugins/dummy/DummyPluginTester$(EXEEXT) $(AM_V_CXXLD)$(plugins_dummy_DummyPluginTester_LINK) $(plugins_dummy_DummyPluginTester_OBJECTS) $(plugins_dummy_DummyPluginTester_LDADD) $(LIBS) plugins/espnet/plugins_espnet_EspNetTester-RunLengthDecoderTest.$(OBJEXT): \ plugins/espnet/$(am__dirstamp) \ plugins/espnet/$(DEPDIR)/$(am__dirstamp) plugins/espnet/plugins_espnet_EspNetTester-RunLengthDecoder.$(OBJEXT): \ plugins/espnet/$(am__dirstamp) \ plugins/espnet/$(DEPDIR)/$(am__dirstamp) plugins/espnet/EspNetTester$(EXEEXT): $(plugins_espnet_EspNetTester_OBJECTS) $(plugins_espnet_EspNetTester_DEPENDENCIES) $(EXTRA_plugins_espnet_EspNetTester_DEPENDENCIES) plugins/espnet/$(am__dirstamp) @rm -f plugins/espnet/EspNetTester$(EXEEXT) $(AM_V_CXXLD)$(plugins_espnet_EspNetTester_LINK) $(plugins_espnet_EspNetTester_OBJECTS) $(plugins_espnet_EspNetTester_LDADD) $(LIBS) plugins/kinet/plugins_kinet_KiNetTester-KiNetNodeTest.$(OBJEXT): \ plugins/kinet/$(am__dirstamp) \ plugins/kinet/$(DEPDIR)/$(am__dirstamp) plugins/kinet/KiNetTester$(EXEEXT): $(plugins_kinet_KiNetTester_OBJECTS) $(plugins_kinet_KiNetTester_DEPENDENCIES) $(EXTRA_plugins_kinet_KiNetTester_DEPENDENCIES) plugins/kinet/$(am__dirstamp) @rm -f plugins/kinet/KiNetTester$(EXEEXT) $(AM_V_CXXLD)$(plugins_kinet_KiNetTester_LINK) $(plugins_kinet_KiNetTester_OBJECTS) $(plugins_kinet_KiNetTester_LDADD) $(LIBS) plugins/openpixelcontrol/plugins_openpixelcontrol_OPCClientTester-OPCClientTest.$(OBJEXT): \ plugins/openpixelcontrol/$(am__dirstamp) \ plugins/openpixelcontrol/$(DEPDIR)/$(am__dirstamp) plugins/openpixelcontrol/OPCClientTester$(EXEEXT): $(plugins_openpixelcontrol_OPCClientTester_OBJECTS) $(plugins_openpixelcontrol_OPCClientTester_DEPENDENCIES) $(EXTRA_plugins_openpixelcontrol_OPCClientTester_DEPENDENCIES) plugins/openpixelcontrol/$(am__dirstamp) @rm -f plugins/openpixelcontrol/OPCClientTester$(EXEEXT) $(AM_V_CXXLD)$(plugins_openpixelcontrol_OPCClientTester_LINK) $(plugins_openpixelcontrol_OPCClientTester_OBJECTS) $(plugins_openpixelcontrol_OPCClientTester_LDADD) $(LIBS) plugins/openpixelcontrol/plugins_openpixelcontrol_OPCServerTester-OPCServerTest.$(OBJEXT): \ plugins/openpixelcontrol/$(am__dirstamp) \ plugins/openpixelcontrol/$(DEPDIR)/$(am__dirstamp) plugins/openpixelcontrol/OPCServerTester$(EXEEXT): $(plugins_openpixelcontrol_OPCServerTester_OBJECTS) $(plugins_openpixelcontrol_OPCServerTester_DEPENDENCIES) $(EXTRA_plugins_openpixelcontrol_OPCServerTester_DEPENDENCIES) plugins/openpixelcontrol/$(am__dirstamp) @rm -f plugins/openpixelcontrol/OPCServerTester$(EXEEXT) $(AM_V_CXXLD)$(plugins_openpixelcontrol_OPCServerTester_LINK) $(plugins_openpixelcontrol_OPCServerTester_OBJECTS) $(plugins_openpixelcontrol_OPCServerTester_LDADD) $(LIBS) plugins/osc/plugins_osc_OSCTester-OSCAddressTemplateTest.$(OBJEXT): \ plugins/osc/$(am__dirstamp) \ plugins/osc/$(DEPDIR)/$(am__dirstamp) plugins/osc/plugins_osc_OSCTester-OSCNodeTest.$(OBJEXT): \ plugins/osc/$(am__dirstamp) \ plugins/osc/$(DEPDIR)/$(am__dirstamp) plugins/osc/OSCTester$(EXEEXT): $(plugins_osc_OSCTester_OBJECTS) $(plugins_osc_OSCTester_DEPENDENCIES) $(EXTRA_plugins_osc_OSCTester_DEPENDENCIES) plugins/osc/$(am__dirstamp) @rm -f plugins/osc/OSCTester$(EXEEXT) $(AM_V_CXXLD)$(plugins_osc_OSCTester_LINK) $(plugins_osc_OSCTester_OBJECTS) $(plugins_osc_OSCTester_LDADD) $(LIBS) plugins/shownet/plugins_shownet_ShowNetTester-ShowNetNode.$(OBJEXT): \ plugins/shownet/$(am__dirstamp) \ plugins/shownet/$(DEPDIR)/$(am__dirstamp) plugins/shownet/plugins_shownet_ShowNetTester-ShowNetNodeTest.$(OBJEXT): \ plugins/shownet/$(am__dirstamp) \ plugins/shownet/$(DEPDIR)/$(am__dirstamp) plugins/shownet/ShowNetTester$(EXEEXT): $(plugins_shownet_ShowNetTester_OBJECTS) $(plugins_shownet_ShowNetTester_DEPENDENCIES) $(EXTRA_plugins_shownet_ShowNetTester_DEPENDENCIES) plugins/shownet/$(am__dirstamp) @rm -f plugins/shownet/ShowNetTester$(EXEEXT) $(AM_V_CXXLD)$(plugins_shownet_ShowNetTester_LINK) $(plugins_shownet_ShowNetTester_OBJECTS) $(plugins_shownet_ShowNetTester_LDADD) $(LIBS) plugins/spi/plugins_spi_SPITester-SPIBackendTest.$(OBJEXT): \ plugins/spi/$(am__dirstamp) \ plugins/spi/$(DEPDIR)/$(am__dirstamp) plugins/spi/plugins_spi_SPITester-SPIOutputTest.$(OBJEXT): \ plugins/spi/$(am__dirstamp) \ plugins/spi/$(DEPDIR)/$(am__dirstamp) plugins/spi/plugins_spi_SPITester-FakeSPIWriter.$(OBJEXT): \ plugins/spi/$(am__dirstamp) \ plugins/spi/$(DEPDIR)/$(am__dirstamp) plugins/spi/SPITester$(EXEEXT): $(plugins_spi_SPITester_OBJECTS) $(plugins_spi_SPITester_DEPENDENCIES) $(EXTRA_plugins_spi_SPITester_DEPENDENCIES) plugins/spi/$(am__dirstamp) @rm -f plugins/spi/SPITester$(EXEEXT) $(AM_V_CXXLD)$(plugins_spi_SPITester_LINK) $(plugins_spi_SPITester_OBJECTS) $(plugins_spi_SPITester_LDADD) $(LIBS) plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-ArduinoWidgetTest.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-CommonWidgetTest.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-MockEndpoint.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/ArduinoWidgetTester$(EXEEXT): $(plugins_usbpro_ArduinoWidgetTester_OBJECTS) $(plugins_usbpro_ArduinoWidgetTester_DEPENDENCIES) $(EXTRA_plugins_usbpro_ArduinoWidgetTester_DEPENDENCIES) plugins/usbpro/$(am__dirstamp) @rm -f plugins/usbpro/ArduinoWidgetTester$(EXEEXT) $(AM_V_CXXLD)$(plugins_usbpro_ArduinoWidgetTester_LINK) $(plugins_usbpro_ArduinoWidgetTester_OBJECTS) $(plugins_usbpro_ArduinoWidgetTester_LDADD) $(LIBS) plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-BaseRobeWidgetTest.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-CommonWidgetTest.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-MockEndpoint.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/BaseRobeWidgetTester$(EXEEXT): $(plugins_usbpro_BaseRobeWidgetTester_OBJECTS) $(plugins_usbpro_BaseRobeWidgetTester_DEPENDENCIES) $(EXTRA_plugins_usbpro_BaseRobeWidgetTester_DEPENDENCIES) plugins/usbpro/$(am__dirstamp) @rm -f plugins/usbpro/BaseRobeWidgetTester$(EXEEXT) $(AM_V_CXXLD)$(plugins_usbpro_BaseRobeWidgetTester_LINK) $(plugins_usbpro_BaseRobeWidgetTester_OBJECTS) $(plugins_usbpro_BaseRobeWidgetTester_LDADD) $(LIBS) plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-BaseUsbProWidgetTest.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-CommonWidgetTest.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-MockEndpoint.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/BaseUsbProWidgetTester$(EXEEXT): $(plugins_usbpro_BaseUsbProWidgetTester_OBJECTS) $(plugins_usbpro_BaseUsbProWidgetTester_DEPENDENCIES) $(EXTRA_plugins_usbpro_BaseUsbProWidgetTester_DEPENDENCIES) plugins/usbpro/$(am__dirstamp) @rm -f plugins/usbpro/BaseUsbProWidgetTester$(EXEEXT) $(AM_V_CXXLD)$(plugins_usbpro_BaseUsbProWidgetTester_LINK) $(plugins_usbpro_BaseUsbProWidgetTester_OBJECTS) $(plugins_usbpro_BaseUsbProWidgetTester_LDADD) $(LIBS) plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-DmxTriWidgetTest.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-CommonWidgetTest.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-MockEndpoint.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/DmxTriWidgetTester$(EXEEXT): $(plugins_usbpro_DmxTriWidgetTester_OBJECTS) $(plugins_usbpro_DmxTriWidgetTester_DEPENDENCIES) $(EXTRA_plugins_usbpro_DmxTriWidgetTester_DEPENDENCIES) plugins/usbpro/$(am__dirstamp) @rm -f plugins/usbpro/DmxTriWidgetTester$(EXEEXT) $(AM_V_CXXLD)$(plugins_usbpro_DmxTriWidgetTester_LINK) $(plugins_usbpro_DmxTriWidgetTester_OBJECTS) $(plugins_usbpro_DmxTriWidgetTester_LDADD) $(LIBS) plugins/usbpro/plugins_usbpro_DmxterWidgetTester-DmxterWidgetTest.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/plugins_usbpro_DmxterWidgetTester-CommonWidgetTest.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/plugins_usbpro_DmxterWidgetTester-MockEndpoint.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/DmxterWidgetTester$(EXEEXT): $(plugins_usbpro_DmxterWidgetTester_OBJECTS) $(plugins_usbpro_DmxterWidgetTester_DEPENDENCIES) $(EXTRA_plugins_usbpro_DmxterWidgetTester_DEPENDENCIES) plugins/usbpro/$(am__dirstamp) @rm -f plugins/usbpro/DmxterWidgetTester$(EXEEXT) $(AM_V_CXXLD)$(plugins_usbpro_DmxterWidgetTester_LINK) $(plugins_usbpro_DmxterWidgetTester_OBJECTS) $(plugins_usbpro_DmxterWidgetTester_LDADD) $(LIBS) plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-EnttecUsbProWidgetTest.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-CommonWidgetTest.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-MockEndpoint.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/EnttecUsbProWidgetTester$(EXEEXT): $(plugins_usbpro_EnttecUsbProWidgetTester_OBJECTS) $(plugins_usbpro_EnttecUsbProWidgetTester_DEPENDENCIES) $(EXTRA_plugins_usbpro_EnttecUsbProWidgetTester_DEPENDENCIES) plugins/usbpro/$(am__dirstamp) @rm -f plugins/usbpro/EnttecUsbProWidgetTester$(EXEEXT) $(AM_V_CXXLD)$(plugins_usbpro_EnttecUsbProWidgetTester_LINK) $(plugins_usbpro_EnttecUsbProWidgetTester_OBJECTS) $(plugins_usbpro_EnttecUsbProWidgetTester_LDADD) $(LIBS) plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-RobeWidgetDetectorTest.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-CommonWidgetTest.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-MockEndpoint.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/RobeWidgetDetectorTester$(EXEEXT): $(plugins_usbpro_RobeWidgetDetectorTester_OBJECTS) $(plugins_usbpro_RobeWidgetDetectorTester_DEPENDENCIES) $(EXTRA_plugins_usbpro_RobeWidgetDetectorTester_DEPENDENCIES) plugins/usbpro/$(am__dirstamp) @rm -f plugins/usbpro/RobeWidgetDetectorTester$(EXEEXT) $(AM_V_CXXLD)$(plugins_usbpro_RobeWidgetDetectorTester_LINK) $(plugins_usbpro_RobeWidgetDetectorTester_OBJECTS) $(plugins_usbpro_RobeWidgetDetectorTester_LDADD) $(LIBS) plugins/usbpro/plugins_usbpro_RobeWidgetTester-RobeWidgetTest.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/plugins_usbpro_RobeWidgetTester-CommonWidgetTest.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/plugins_usbpro_RobeWidgetTester-MockEndpoint.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/RobeWidgetTester$(EXEEXT): $(plugins_usbpro_RobeWidgetTester_OBJECTS) $(plugins_usbpro_RobeWidgetTester_DEPENDENCIES) $(EXTRA_plugins_usbpro_RobeWidgetTester_DEPENDENCIES) plugins/usbpro/$(am__dirstamp) @rm -f plugins/usbpro/RobeWidgetTester$(EXEEXT) $(AM_V_CXXLD)$(plugins_usbpro_RobeWidgetTester_LINK) $(plugins_usbpro_RobeWidgetTester_OBJECTS) $(plugins_usbpro_RobeWidgetTester_LDADD) $(LIBS) plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-UltraDMXProWidgetTest.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-CommonWidgetTest.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-MockEndpoint.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/UltraDMXProWidgetTester$(EXEEXT): $(plugins_usbpro_UltraDMXProWidgetTester_OBJECTS) $(plugins_usbpro_UltraDMXProWidgetTester_DEPENDENCIES) $(EXTRA_plugins_usbpro_UltraDMXProWidgetTester_DEPENDENCIES) plugins/usbpro/$(am__dirstamp) @rm -f plugins/usbpro/UltraDMXProWidgetTester$(EXEEXT) $(AM_V_CXXLD)$(plugins_usbpro_UltraDMXProWidgetTester_LINK) $(plugins_usbpro_UltraDMXProWidgetTester_OBJECTS) $(plugins_usbpro_UltraDMXProWidgetTester_LDADD) $(LIBS) plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-UsbProWidgetDetectorTest.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-CommonWidgetTest.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-MockEndpoint.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/UsbProWidgetDetectorTester$(EXEEXT): $(plugins_usbpro_UsbProWidgetDetectorTester_OBJECTS) $(plugins_usbpro_UsbProWidgetDetectorTester_DEPENDENCIES) $(EXTRA_plugins_usbpro_UsbProWidgetDetectorTester_DEPENDENCIES) plugins/usbpro/$(am__dirstamp) @rm -f plugins/usbpro/UsbProWidgetDetectorTester$(EXEEXT) $(AM_V_CXXLD)$(plugins_usbpro_UsbProWidgetDetectorTester_LINK) $(plugins_usbpro_UsbProWidgetDetectorTester_OBJECTS) $(plugins_usbpro_UsbProWidgetDetectorTester_LDADD) $(LIBS) plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-WidgetDetectorThreadTest.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-CommonWidgetTest.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-MockEndpoint.$(OBJEXT): \ plugins/usbpro/$(am__dirstamp) \ plugins/usbpro/$(DEPDIR)/$(am__dirstamp) plugins/usbpro/WidgetDetectorThreadTester$(EXEEXT): $(plugins_usbpro_WidgetDetectorThreadTester_OBJECTS) $(plugins_usbpro_WidgetDetectorThreadTester_DEPENDENCIES) $(EXTRA_plugins_usbpro_WidgetDetectorThreadTester_DEPENDENCIES) plugins/usbpro/$(am__dirstamp) @rm -f plugins/usbpro/WidgetDetectorThreadTester$(EXEEXT) $(AM_V_CXXLD)$(plugins_usbpro_WidgetDetectorThreadTester_LINK) $(plugins_usbpro_WidgetDetectorThreadTester_OBJECTS) $(plugins_usbpro_WidgetDetectorThreadTester_LDADD) $(LIBS) protoc/$(am__dirstamp): @$(MKDIR_P) protoc @: > protoc/$(am__dirstamp) protoc/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) protoc/$(DEPDIR) @: > protoc/$(DEPDIR)/$(am__dirstamp) protoc/protoc_ola_protoc_plugin-CppFileGenerator.$(OBJEXT): \ protoc/$(am__dirstamp) protoc/$(DEPDIR)/$(am__dirstamp) protoc/protoc_ola_protoc_plugin-CppGenerator.$(OBJEXT): \ protoc/$(am__dirstamp) protoc/$(DEPDIR)/$(am__dirstamp) protoc/protoc_ola_protoc_plugin-GeneratorHelpers.$(OBJEXT): \ protoc/$(am__dirstamp) protoc/$(DEPDIR)/$(am__dirstamp) protoc/protoc_ola_protoc_plugin-ServiceGenerator.$(OBJEXT): \ protoc/$(am__dirstamp) protoc/$(DEPDIR)/$(am__dirstamp) protoc/protoc_ola_protoc_plugin-StrUtil.$(OBJEXT): \ protoc/$(am__dirstamp) protoc/$(DEPDIR)/$(am__dirstamp) protoc/protoc_ola_protoc_plugin-ola-protoc-generator-plugin.$(OBJEXT): \ protoc/$(am__dirstamp) protoc/$(DEPDIR)/$(am__dirstamp) @BUILD_OLA_PROTOC_PLUGIN_TRUE@protoc/ola_protoc_plugin$(EXEEXT): $(protoc_ola_protoc_plugin_OBJECTS) $(protoc_ola_protoc_plugin_DEPENDENCIES) $(EXTRA_protoc_ola_protoc_plugin_DEPENDENCIES) protoc/$(am__dirstamp) @BUILD_OLA_PROTOC_PLUGIN_TRUE@ @rm -f protoc/ola_protoc_plugin$(EXEEXT) @BUILD_OLA_PROTOC_PLUGIN_TRUE@ $(AM_V_CXXLD)$(protoc_ola_protoc_plugin_LINK) $(protoc_ola_protoc_plugin_OBJECTS) $(protoc_ola_protoc_plugin_LDADD) $(LIBS) tools/e133/basic-controller.$(OBJEXT): tools/e133/$(am__dirstamp) \ tools/e133/$(DEPDIR)/$(am__dirstamp) tools/e133/basic_controller$(EXEEXT): $(tools_e133_basic_controller_OBJECTS) $(tools_e133_basic_controller_DEPENDENCIES) $(EXTRA_tools_e133_basic_controller_DEPENDENCIES) tools/e133/$(am__dirstamp) @rm -f tools/e133/basic_controller$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(tools_e133_basic_controller_OBJECTS) $(tools_e133_basic_controller_LDADD) $(LIBS) tools/e133/basic-device.$(OBJEXT): tools/e133/$(am__dirstamp) \ tools/e133/$(DEPDIR)/$(am__dirstamp) tools/e133/basic_device$(EXEEXT): $(tools_e133_basic_device_OBJECTS) $(tools_e133_basic_device_DEPENDENCIES) $(EXTRA_tools_e133_basic_device_DEPENDENCIES) tools/e133/$(am__dirstamp) @rm -f tools/e133/basic_device$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(tools_e133_basic_device_OBJECTS) $(tools_e133_basic_device_LDADD) $(LIBS) tools/e133/e133-controller.$(OBJEXT): tools/e133/$(am__dirstamp) \ tools/e133/$(DEPDIR)/$(am__dirstamp) tools/e133/e133_controller$(EXEEXT): $(tools_e133_e133_controller_OBJECTS) $(tools_e133_e133_controller_DEPENDENCIES) $(EXTRA_tools_e133_e133_controller_DEPENDENCIES) tools/e133/$(am__dirstamp) @rm -f tools/e133/e133_controller$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(tools_e133_e133_controller_OBJECTS) $(tools_e133_e133_controller_LDADD) $(LIBS) tools/e133/e133-monitor.$(OBJEXT): tools/e133/$(am__dirstamp) \ tools/e133/$(DEPDIR)/$(am__dirstamp) tools/e133/e133_monitor$(EXEEXT): $(tools_e133_e133_monitor_OBJECTS) $(tools_e133_e133_monitor_DEPENDENCIES) $(EXTRA_tools_e133_e133_monitor_DEPENDENCIES) tools/e133/$(am__dirstamp) @rm -f tools/e133/e133_monitor$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(tools_e133_e133_monitor_OBJECTS) $(tools_e133_e133_monitor_LDADD) $(LIBS) tools/e133/e133-receiver.$(OBJEXT): tools/e133/$(am__dirstamp) \ tools/e133/$(DEPDIR)/$(am__dirstamp) tools/e133/e133_receiver$(EXEEXT): $(tools_e133_e133_receiver_OBJECTS) $(tools_e133_e133_receiver_DEPENDENCIES) $(EXTRA_tools_e133_e133_receiver_DEPENDENCIES) tools/e133/$(am__dirstamp) @rm -f tools/e133/e133_receiver$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(tools_e133_e133_receiver_OBJECTS) $(tools_e133_e133_receiver_LDADD) $(LIBS) tools/ja-rule/$(am__dirstamp): @$(MKDIR_P) tools/ja-rule @: > tools/ja-rule/$(am__dirstamp) tools/ja-rule/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) tools/ja-rule/$(DEPDIR) @: > tools/ja-rule/$(DEPDIR)/$(am__dirstamp) tools/ja-rule/tools_ja_rule_ja_rule-USBDeviceManager.$(OBJEXT): \ tools/ja-rule/$(am__dirstamp) \ tools/ja-rule/$(DEPDIR)/$(am__dirstamp) tools/ja-rule/tools_ja_rule_ja_rule-ja-rule.$(OBJEXT): \ tools/ja-rule/$(am__dirstamp) \ tools/ja-rule/$(DEPDIR)/$(am__dirstamp) tools/ja-rule/ja-rule$(EXEEXT): $(tools_ja_rule_ja_rule_OBJECTS) $(tools_ja_rule_ja_rule_DEPENDENCIES) $(EXTRA_tools_ja_rule_ja_rule_DEPENDENCIES) tools/ja-rule/$(am__dirstamp) @rm -f tools/ja-rule/ja-rule$(EXEEXT) $(AM_V_CXXLD)$(tools_ja_rule_ja_rule_LINK) $(tools_ja_rule_ja_rule_OBJECTS) $(tools_ja_rule_ja_rule_LDADD) $(LIBS) tools/ja-rule/tools_ja_rule_ja_rule_controller-USBDeviceManager.$(OBJEXT): \ tools/ja-rule/$(am__dirstamp) \ tools/ja-rule/$(DEPDIR)/$(am__dirstamp) tools/ja-rule/tools_ja_rule_ja_rule_controller-ja-rule-controller.$(OBJEXT): \ tools/ja-rule/$(am__dirstamp) \ tools/ja-rule/$(DEPDIR)/$(am__dirstamp) tools/ja-rule/ja-rule-controller$(EXEEXT): $(tools_ja_rule_ja_rule_controller_OBJECTS) $(tools_ja_rule_ja_rule_controller_DEPENDENCIES) $(EXTRA_tools_ja_rule_ja_rule_controller_DEPENDENCIES) tools/ja-rule/$(am__dirstamp) @rm -f tools/ja-rule/ja-rule-controller$(EXEEXT) $(AM_V_CXXLD)$(tools_ja_rule_ja_rule_controller_LINK) $(tools_ja_rule_ja_rule_controller_OBJECTS) $(tools_ja_rule_ja_rule_controller_LDADD) $(LIBS) tools/logic/$(am__dirstamp): @$(MKDIR_P) tools/logic @: > tools/logic/$(am__dirstamp) tools/logic/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) tools/logic/$(DEPDIR) @: > tools/logic/$(DEPDIR)/$(am__dirstamp) tools/logic/DMXSignalProcessor.$(OBJEXT): tools/logic/$(am__dirstamp) \ tools/logic/$(DEPDIR)/$(am__dirstamp) tools/logic/logic-rdm-sniffer.$(OBJEXT): tools/logic/$(am__dirstamp) \ tools/logic/$(DEPDIR)/$(am__dirstamp) tools/logic/logic_rdm_sniffer$(EXEEXT): $(tools_logic_logic_rdm_sniffer_OBJECTS) $(tools_logic_logic_rdm_sniffer_DEPENDENCIES) $(EXTRA_tools_logic_logic_rdm_sniffer_DEPENDENCIES) tools/logic/$(am__dirstamp) @rm -f tools/logic/logic_rdm_sniffer$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(tools_logic_logic_rdm_sniffer_OBJECTS) $(tools_logic_logic_rdm_sniffer_LDADD) $(LIBS) tools/ola_trigger/tools_ola_trigger_ActionTester-ActionTest.$(OBJEXT): \ tools/ola_trigger/$(am__dirstamp) \ tools/ola_trigger/$(DEPDIR)/$(am__dirstamp) tools/ola_trigger/tools_ola_trigger_ActionTester-ContextTest.$(OBJEXT): \ tools/ola_trigger/$(am__dirstamp) \ tools/ola_trigger/$(DEPDIR)/$(am__dirstamp) tools/ola_trigger/tools_ola_trigger_ActionTester-DMXTriggerTest.$(OBJEXT): \ tools/ola_trigger/$(am__dirstamp) \ tools/ola_trigger/$(DEPDIR)/$(am__dirstamp) tools/ola_trigger/tools_ola_trigger_ActionTester-IntervalTest.$(OBJEXT): \ tools/ola_trigger/$(am__dirstamp) \ tools/ola_trigger/$(DEPDIR)/$(am__dirstamp) tools/ola_trigger/tools_ola_trigger_ActionTester-SlotTest.$(OBJEXT): \ tools/ola_trigger/$(am__dirstamp) \ tools/ola_trigger/$(DEPDIR)/$(am__dirstamp) tools/ola_trigger/tools_ola_trigger_ActionTester-VariableInterpolatorTest.$(OBJEXT): \ tools/ola_trigger/$(am__dirstamp) \ tools/ola_trigger/$(DEPDIR)/$(am__dirstamp) tools/ola_trigger/ActionTester$(EXEEXT): $(tools_ola_trigger_ActionTester_OBJECTS) $(tools_ola_trigger_ActionTester_DEPENDENCIES) $(EXTRA_tools_ola_trigger_ActionTester_DEPENDENCIES) tools/ola_trigger/$(am__dirstamp) @rm -f tools/ola_trigger/ActionTester$(EXEEXT) $(AM_V_CXXLD)$(tools_ola_trigger_ActionTester_LINK) $(tools_ola_trigger_ActionTester_OBJECTS) $(tools_ola_trigger_ActionTester_LDADD) $(LIBS) tools/ola_trigger/tools_ola_trigger_ola_trigger-ParserActions.$(OBJEXT): \ tools/ola_trigger/$(am__dirstamp) \ tools/ola_trigger/$(DEPDIR)/$(am__dirstamp) tools/ola_trigger/tools_ola_trigger_ola_trigger-ola-trigger.$(OBJEXT): \ tools/ola_trigger/$(am__dirstamp) \ tools/ola_trigger/$(DEPDIR)/$(am__dirstamp) tools/ola_trigger/tools_ola_trigger_ola_trigger-config.tab.$(OBJEXT): \ tools/ola_trigger/$(am__dirstamp) \ tools/ola_trigger/$(DEPDIR)/$(am__dirstamp) tools/ola_trigger/tools_ola_trigger_ola_trigger-lex.yy.$(OBJEXT): \ tools/ola_trigger/$(am__dirstamp) \ tools/ola_trigger/$(DEPDIR)/$(am__dirstamp) tools/ola_trigger/ola_trigger$(EXEEXT): $(tools_ola_trigger_ola_trigger_OBJECTS) $(tools_ola_trigger_ola_trigger_DEPENDENCIES) $(EXTRA_tools_ola_trigger_ola_trigger_DEPENDENCIES) tools/ola_trigger/$(am__dirstamp) @rm -f tools/ola_trigger/ola_trigger$(EXEEXT) $(AM_V_CXXLD)$(tools_ola_trigger_ola_trigger_LINK) $(tools_ola_trigger_ola_trigger_OBJECTS) $(tools_ola_trigger_ola_trigger_LDADD) $(LIBS) tools/rdmpro/$(am__dirstamp): @$(MKDIR_P) tools/rdmpro @: > tools/rdmpro/$(am__dirstamp) tools/rdmpro/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) tools/rdmpro/$(DEPDIR) @: > tools/rdmpro/$(DEPDIR)/$(am__dirstamp) tools/rdmpro/rdm-sniffer.$(OBJEXT): tools/rdmpro/$(am__dirstamp) \ tools/rdmpro/$(DEPDIR)/$(am__dirstamp) tools/rdmpro/rdmpro_sniffer$(EXEEXT): $(tools_rdmpro_rdmpro_sniffer_OBJECTS) $(tools_rdmpro_rdmpro_sniffer_DEPENDENCIES) $(EXTRA_tools_rdmpro_rdmpro_sniffer_DEPENDENCIES) tools/rdmpro/$(am__dirstamp) @rm -f tools/rdmpro/rdmpro_sniffer$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(tools_rdmpro_rdmpro_sniffer_OBJECTS) $(tools_rdmpro_rdmpro_sniffer_LDADD) $(LIBS) tools/usbpro/$(am__dirstamp): @$(MKDIR_P) tools/usbpro @: > tools/usbpro/$(am__dirstamp) tools/usbpro/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) tools/usbpro/$(DEPDIR) @: > tools/usbpro/$(DEPDIR)/$(am__dirstamp) tools/usbpro/usbpro-firmware.$(OBJEXT): tools/usbpro/$(am__dirstamp) \ tools/usbpro/$(DEPDIR)/$(am__dirstamp) tools/usbpro/usbpro_firmware$(EXEEXT): $(tools_usbpro_usbpro_firmware_OBJECTS) $(tools_usbpro_usbpro_firmware_DEPENDENCIES) $(EXTRA_tools_usbpro_usbpro_firmware_DEPENDENCIES) tools/usbpro/$(am__dirstamp) @rm -f tools/usbpro/usbpro_firmware$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(tools_usbpro_usbpro_firmware_OBJECTS) $(tools_usbpro_usbpro_firmware_LDADD) $(LIBS) install-dist_rdmtestsexecSCRIPTS: $(dist_rdmtestsexec_SCRIPTS) @$(NORMAL_INSTALL) @list='$(dist_rdmtestsexec_SCRIPTS)'; test -n "$(rdmtestsexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(rdmtestsexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(rdmtestsexecdir)" || 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)$(rdmtestsexecdir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(rdmtestsexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-dist_rdmtestsexecSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(dist_rdmtestsexec_SCRIPTS)'; test -n "$(rdmtestsexecdir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(rdmtestsexecdir)'; $(am__uninstall_files_from_dir) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f common/base/*.$(OBJEXT) -rm -f common/base/*.lo -rm -f common/dmx/*.$(OBJEXT) -rm -f common/dmx/*.lo -rm -f common/export_map/*.$(OBJEXT) -rm -f common/export_map/*.lo -rm -f common/file/*.$(OBJEXT) -rm -f common/file/*.lo -rm -f common/http/*.$(OBJEXT) -rm -f common/http/*.lo -rm -f common/io/*.$(OBJEXT) -rm -f common/io/*.lo -rm -f common/math/*.$(OBJEXT) -rm -f common/math/*.lo -rm -f common/messaging/*.$(OBJEXT) -rm -f common/messaging/*.lo -rm -f common/network/*.$(OBJEXT) -rm -f common/network/*.lo -rm -f common/protocol/*.$(OBJEXT) -rm -f common/protocol/*.lo -rm -f common/rdm/*.$(OBJEXT) -rm -f common/rdm/*.lo -rm -f common/rpc/*.$(OBJEXT) -rm -f common/rpc/*.lo -rm -f common/strings/*.$(OBJEXT) -rm -f common/strings/*.lo -rm -f common/system/*.$(OBJEXT) -rm -f common/system/*.lo -rm -f common/testing/*.$(OBJEXT) -rm -f common/testing/*.lo -rm -f common/thread/*.$(OBJEXT) -rm -f common/thread/*.lo -rm -f common/timecode/*.$(OBJEXT) -rm -f common/timecode/*.lo -rm -f common/utils/*.$(OBJEXT) -rm -f common/utils/*.lo -rm -f common/web/*.$(OBJEXT) -rm -f common/web/*.lo -rm -f data/rdm/*.$(OBJEXT) -rm -f doxygen/examples/*.$(OBJEXT) -rm -f examples/*.$(OBJEXT) -rm -f examples/*.lo -rm -f libs/acn/*.$(OBJEXT) -rm -f libs/acn/*.lo -rm -f libs/usb/*.$(OBJEXT) -rm -f libs/usb/*.lo -rm -f ola/*.$(OBJEXT) -rm -f ola/*.lo -rm -f olad/*.$(OBJEXT) -rm -f olad/*.lo -rm -f olad/plugin_api/*.$(OBJEXT) -rm -f olad/plugin_api/*.lo -rm -f plugins/artnet/*.$(OBJEXT) -rm -f plugins/artnet/*.lo -rm -f plugins/artnet/messages/*.$(OBJEXT) -rm -f plugins/artnet/messages/*.lo -rm -f plugins/dmx4linux/*.$(OBJEXT) -rm -f plugins/dmx4linux/*.lo -rm -f plugins/dummy/*.$(OBJEXT) -rm -f plugins/dummy/*.lo -rm -f plugins/e131/*.$(OBJEXT) -rm -f plugins/e131/*.lo -rm -f plugins/e131/messages/*.$(OBJEXT) -rm -f plugins/e131/messages/*.lo -rm -f plugins/espnet/*.$(OBJEXT) -rm -f plugins/espnet/*.lo -rm -f plugins/ftdidmx/*.$(OBJEXT) -rm -f plugins/ftdidmx/*.lo -rm -f plugins/gpio/*.$(OBJEXT) -rm -f plugins/gpio/*.lo -rm -f plugins/karate/*.$(OBJEXT) -rm -f plugins/karate/*.lo -rm -f plugins/kinet/*.$(OBJEXT) -rm -f plugins/kinet/*.lo -rm -f plugins/milinst/*.$(OBJEXT) -rm -f plugins/milinst/*.lo -rm -f plugins/opendmx/*.$(OBJEXT) -rm -f plugins/opendmx/*.lo -rm -f plugins/openpixelcontrol/*.$(OBJEXT) -rm -f plugins/openpixelcontrol/*.lo -rm -f plugins/osc/*.$(OBJEXT) -rm -f plugins/osc/*.lo -rm -f plugins/pathport/*.$(OBJEXT) -rm -f plugins/pathport/*.lo -rm -f plugins/renard/*.$(OBJEXT) -rm -f plugins/renard/*.lo -rm -f plugins/sandnet/*.$(OBJEXT) -rm -f plugins/sandnet/*.lo -rm -f plugins/shownet/*.$(OBJEXT) -rm -f plugins/shownet/*.lo -rm -f plugins/spi/*.$(OBJEXT) -rm -f plugins/spi/*.lo -rm -f plugins/stageprofi/*.$(OBJEXT) -rm -f plugins/stageprofi/*.lo -rm -f plugins/uartdmx/*.$(OBJEXT) -rm -f plugins/uartdmx/*.lo -rm -f plugins/usbdmx/*.$(OBJEXT) -rm -f plugins/usbdmx/*.lo -rm -f plugins/usbpro/*.$(OBJEXT) -rm -f plugins/usbpro/*.lo -rm -f plugins/usbpro/messages/*.$(OBJEXT) -rm -f plugins/usbpro/messages/*.lo -rm -f protoc/*.$(OBJEXT) -rm -f tools/e133/*.$(OBJEXT) -rm -f tools/e133/*.lo -rm -f tools/ja-rule/*.$(OBJEXT) -rm -f tools/logic/*.$(OBJEXT) -rm -f tools/ola_trigger/*.$(OBJEXT) -rm -f tools/ola_trigger/*.lo -rm -f tools/rdmpro/*.$(OBJEXT) -rm -f tools/usbpro/*.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@common/base/$(DEPDIR)/common_base_CredentialsTester-CredentialsTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/base/$(DEPDIR)/common_base_FlagsTester-FlagsTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/base/$(DEPDIR)/common_base_LoggingTester-LoggingTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/base/$(DEPDIR)/common_libolacommon_la-Credentials.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/base/$(DEPDIR)/common_libolacommon_la-Env.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/base/$(DEPDIR)/common_libolacommon_la-Flags.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/base/$(DEPDIR)/common_libolacommon_la-Init.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/base/$(DEPDIR)/common_libolacommon_la-Logging.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/base/$(DEPDIR)/common_libolacommon_la-SysExits.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/base/$(DEPDIR)/common_libolacommon_la-Version.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/dmx/$(DEPDIR)/common_dmx_RunLengthEncoderTester-RunLengthEncoderTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/dmx/$(DEPDIR)/common_libolacommon_la-RunLengthEncoder.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/export_map/$(DEPDIR)/common_export_map_ExportMapTester-ExportMapTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/export_map/$(DEPDIR)/common_libolacommon_la-ExportMap.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/file/$(DEPDIR)/common_file_UtilTester-UtilTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/file/$(DEPDIR)/common_libolacommon_la-Util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/http/$(DEPDIR)/HTTPServer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/http/$(DEPDIR)/OlaHTTPServer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/io/$(DEPDIR)/common_io_DescriptorTester-DescriptorTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/io/$(DEPDIR)/common_io_IOQueueTester-IOQueueTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/io/$(DEPDIR)/common_io_IOStackTester-IOStackTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/io/$(DEPDIR)/common_io_MemoryBlockTester-MemoryBlockTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/io/$(DEPDIR)/common_io_SelectServerTester-SelectServerTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/io/$(DEPDIR)/common_io_SelectServerTester-SelectServerThreadTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/io/$(DEPDIR)/common_io_StreamTester-InputStreamTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/io/$(DEPDIR)/common_io_StreamTester-OutputStreamTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/io/$(DEPDIR)/common_io_TimeoutManagerTester-TimeoutManagerTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/io/$(DEPDIR)/common_libolacommon_la-Descriptor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/io/$(DEPDIR)/common_libolacommon_la-EPoller.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/io/$(DEPDIR)/common_libolacommon_la-ExtendedSerial.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/io/$(DEPDIR)/common_libolacommon_la-IOQueue.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/io/$(DEPDIR)/common_libolacommon_la-IOStack.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/io/$(DEPDIR)/common_libolacommon_la-IOUtils.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/io/$(DEPDIR)/common_libolacommon_la-KQueuePoller.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/io/$(DEPDIR)/common_libolacommon_la-NonBlockingSender.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/io/$(DEPDIR)/common_libolacommon_la-PollerInterface.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/io/$(DEPDIR)/common_libolacommon_la-SelectPoller.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/io/$(DEPDIR)/common_libolacommon_la-SelectServer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/io/$(DEPDIR)/common_libolacommon_la-Serial.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/io/$(DEPDIR)/common_libolacommon_la-StdinHandler.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/io/$(DEPDIR)/common_libolacommon_la-TimeoutManager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/io/$(DEPDIR)/common_libolacommon_la-WindowsPoller.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/math/$(DEPDIR)/common_libolacommon_la-Random.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/messaging/$(DEPDIR)/common_libolacommon_la-Descriptor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/messaging/$(DEPDIR)/common_libolacommon_la-Message.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/messaging/$(DEPDIR)/common_libolacommon_la-MessagePrinter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/messaging/$(DEPDIR)/common_libolacommon_la-SchemaPrinter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/messaging/$(DEPDIR)/common_messaging_DescriptorTester-DescriptorTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/messaging/$(DEPDIR)/common_messaging_DescriptorTester-MessagePrinterTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/messaging/$(DEPDIR)/common_messaging_DescriptorTester-SchemaPrinterTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/network/$(DEPDIR)/common_libolacommon_la-AdvancedTCPConnector.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/network/$(DEPDIR)/common_libolacommon_la-HealthCheckedConnection.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/network/$(DEPDIR)/common_libolacommon_la-IPV4Address.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/network/$(DEPDIR)/common_libolacommon_la-Interface.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/network/$(DEPDIR)/common_libolacommon_la-InterfacePicker.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/network/$(DEPDIR)/common_libolacommon_la-MACAddress.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/network/$(DEPDIR)/common_libolacommon_la-NetworkUtils.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/network/$(DEPDIR)/common_libolacommon_la-PosixInterfacePicker.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/network/$(DEPDIR)/common_libolacommon_la-Socket.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/network/$(DEPDIR)/common_libolacommon_la-SocketAddress.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/network/$(DEPDIR)/common_libolacommon_la-SocketCloser.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/network/$(DEPDIR)/common_libolacommon_la-SocketHelper.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/network/$(DEPDIR)/common_libolacommon_la-TCPConnector.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/network/$(DEPDIR)/common_libolacommon_la-TCPSocket.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/network/$(DEPDIR)/common_libolacommon_la-WindowsInterfacePicker.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/network/$(DEPDIR)/common_network_HealthCheckedConnectionTester-HealthCheckedConnectionTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/network/$(DEPDIR)/common_network_NetworkTester-IPV4AddressTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/network/$(DEPDIR)/common_network_NetworkTester-InterfacePickerTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/network/$(DEPDIR)/common_network_NetworkTester-InterfaceTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/network/$(DEPDIR)/common_network_NetworkTester-MACAddressTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/network/$(DEPDIR)/common_network_NetworkTester-NetworkUtilsTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/network/$(DEPDIR)/common_network_NetworkTester-SocketAddressTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/network/$(DEPDIR)/common_network_NetworkTester-SocketTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/network/$(DEPDIR)/common_network_TCPConnectorTester-AdvancedTCPConnectorTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/network/$(DEPDIR)/common_network_TCPConnectorTester-TCPConnectorTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/protocol/$(DEPDIR)/common_protocol_libolaproto_la-Ola.pb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/protocol/$(DEPDIR)/common_protocol_libolaproto_la-OlaService.pb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-AckTimerResponder.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-AdvancedDimmerResponder.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-CommandPrinter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-DescriptorConsistencyChecker.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-DimmerResponder.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-DimmerRootDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-DimmerSubDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-DiscoveryAgent.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-DummyResponder.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-FakeNetworkManager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-GroupSizeCalculator.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-MessageDeserializer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-MessageSerializer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-MovingLightResponder.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-NetworkManager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-NetworkResponder.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-OpenLightingEnums.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-PidStore.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-PidStoreHelper.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-PidStoreLoader.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-Pids.pb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-QueueingRDMController.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-RDMAPI.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-RDMCommand.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-RDMCommandSerializer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-RDMFrame.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-RDMHelper.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-RDMReply.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-ResponderHelper.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-ResponderLoadSensor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-ResponderPersonality.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-ResponderSettings.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-ResponderSlotData.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-SensorResponder.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-StringMessageBuilder.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-SubDeviceDispatcher.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-UID.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_libolacommon_la-VariableFieldSizeCalculator.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_rdm_DiscoveryAgentTester-DiscoveryAgentTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_rdm_PidStoreTester-DescriptorConsistencyCheckerTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_rdm_PidStoreTester-PidStoreTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_rdm_QueueingRDMControllerTester-QueueingRDMControllerTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_rdm_RDMAPITester-RDMAPITest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_rdm_RDMCommandSerializerTester-RDMCommandSerializerTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_rdm_RDMCommandTester-RDMCommandTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_rdm_RDMFrameTester-RDMFrameTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_rdm_RDMHelperTester-RDMHelperTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-GroupSizeCalculatorTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-MessageDeserializerTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-MessageSerializerTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-RDMMessageInterationTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-StringMessageBuilderTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-VariableFieldSizeCalculatorTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_rdm_RDMReplyTester-RDMReplyTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_rdm_UIDAllocatorTester-UIDAllocatorTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rdm/$(DEPDIR)/common_rdm_UIDTester-UIDTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rpc/$(DEPDIR)/common_libolacommon_la-Rpc.pb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rpc/$(DEPDIR)/common_libolacommon_la-RpcChannel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rpc/$(DEPDIR)/common_libolacommon_la-RpcController.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rpc/$(DEPDIR)/common_libolacommon_la-RpcServer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rpc/$(DEPDIR)/common_rpc_RpcServerTester-RpcServerTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rpc/$(DEPDIR)/common_rpc_RpcServerTester-TestService.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rpc/$(DEPDIR)/common_rpc_RpcServerTester-TestService.pb.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rpc/$(DEPDIR)/common_rpc_RpcServerTester-TestServiceService.pb.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rpc/$(DEPDIR)/common_rpc_RpcTester-RpcChannelTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rpc/$(DEPDIR)/common_rpc_RpcTester-RpcControllerTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rpc/$(DEPDIR)/common_rpc_RpcTester-RpcHeaderTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rpc/$(DEPDIR)/common_rpc_RpcTester-TestService.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rpc/$(DEPDIR)/common_rpc_RpcTester-TestService.pb.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/rpc/$(DEPDIR)/common_rpc_RpcTester-TestServiceService.pb.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/strings/$(DEPDIR)/common_libolacommon_la-Format.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/strings/$(DEPDIR)/common_libolacommon_la-Utils.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/strings/$(DEPDIR)/common_strings_UtilsTester-UtilsTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/system/$(DEPDIR)/common_libolacommon_la-Limits.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/system/$(DEPDIR)/common_libolacommon_la-SystemUtils.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/testing/$(DEPDIR)/GenericTester.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/testing/$(DEPDIR)/MockUDPSocket.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/testing/$(DEPDIR)/TestUtils.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/thread/$(DEPDIR)/common_libolacommon_la-ConsumerThread.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/thread/$(DEPDIR)/common_libolacommon_la-ExecutorThread.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/thread/$(DEPDIR)/common_libolacommon_la-Mutex.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/thread/$(DEPDIR)/common_libolacommon_la-PeriodicThread.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/thread/$(DEPDIR)/common_libolacommon_la-SignalThread.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/thread/$(DEPDIR)/common_libolacommon_la-Thread.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/thread/$(DEPDIR)/common_libolacommon_la-ThreadPool.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/thread/$(DEPDIR)/common_libolacommon_la-Utils.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/thread/$(DEPDIR)/common_thread_ExecutorThreadTester-ExecutorThreadTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/thread/$(DEPDIR)/common_thread_FutureTester-FutureTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/thread/$(DEPDIR)/common_thread_ThreadTester-ThreadPoolTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/thread/$(DEPDIR)/common_thread_ThreadTester-ThreadTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/timecode/$(DEPDIR)/common_libolacommon_la-TimeCode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/timecode/$(DEPDIR)/common_timecode_TimeCodeTester-TimeCodeTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/utils/$(DEPDIR)/common_libolacommon_la-ActionQueue.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/utils/$(DEPDIR)/common_libolacommon_la-Clock.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/utils/$(DEPDIR)/common_libolacommon_la-DmxBuffer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/utils/$(DEPDIR)/common_libolacommon_la-StringUtils.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/utils/$(DEPDIR)/common_libolacommon_la-TokenBucket.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/utils/$(DEPDIR)/common_libolacommon_la-Watchdog.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/utils/$(DEPDIR)/common_utils_UtilsTester-ActionQueueTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/utils/$(DEPDIR)/common_utils_UtilsTester-BackoffTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/utils/$(DEPDIR)/common_utils_UtilsTester-CallbackTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/utils/$(DEPDIR)/common_utils_UtilsTester-ClockTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/utils/$(DEPDIR)/common_utils_UtilsTester-DmxBufferTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/utils/$(DEPDIR)/common_utils_UtilsTester-MultiCallbackTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/utils/$(DEPDIR)/common_utils_UtilsTester-StringUtilsTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/utils/$(DEPDIR)/common_utils_UtilsTester-TokenBucketTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/utils/$(DEPDIR)/common_utils_UtilsTester-UtilsTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/utils/$(DEPDIR)/common_utils_UtilsTester-WatchdogTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/web/$(DEPDIR)/Json.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/web/$(DEPDIR)/JsonData.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/web/$(DEPDIR)/JsonLexer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/web/$(DEPDIR)/JsonParser.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/web/$(DEPDIR)/JsonPatch.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/web/$(DEPDIR)/JsonPatchParser.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/web/$(DEPDIR)/JsonPointer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/web/$(DEPDIR)/JsonSchema.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/web/$(DEPDIR)/JsonSections.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/web/$(DEPDIR)/JsonTypes.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/web/$(DEPDIR)/JsonWriter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/web/$(DEPDIR)/PointerTracker.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/web/$(DEPDIR)/SchemaErrorLogger.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/web/$(DEPDIR)/SchemaKeywords.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/web/$(DEPDIR)/SchemaParseContext.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/web/$(DEPDIR)/SchemaParser.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/web/$(DEPDIR)/common_web_JsonTester-JsonTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/web/$(DEPDIR)/common_web_ParserTester-ParserTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/web/$(DEPDIR)/common_web_PointerTester-PointerTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/web/$(DEPDIR)/common_web_PointerTrackerTester-PointerTrackerTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/web/$(DEPDIR)/common_web_PtchParserTester-PatchParserTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/web/$(DEPDIR)/common_web_PtchTester-PatchTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/web/$(DEPDIR)/common_web_SchemaParserTester-SchemaParserTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/web/$(DEPDIR)/common_web_SchemaTester-SchemaTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/web/$(DEPDIR)/common_web_SectionsTester-SectionsTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@data/rdm/$(DEPDIR)/data_rdm_PidDataTester-PidDataTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@doxygen/examples/$(DEPDIR)/callback_client_transmit.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@doxygen/examples/$(DEPDIR)/client_disconnect.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@doxygen/examples/$(DEPDIR)/client_thread.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@doxygen/examples/$(DEPDIR)/fetch_plugins.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@doxygen/examples/$(DEPDIR)/flags.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@doxygen/examples/$(DEPDIR)/legacy_callback_client_transmit.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@doxygen/examples/$(DEPDIR)/legacy_receiver.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@doxygen/examples/$(DEPDIR)/legacy_streaming_client.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@doxygen/examples/$(DEPDIR)/receiver.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@doxygen/examples/$(DEPDIR)/stdin_handler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@doxygen/examples/$(DEPDIR)/streaming_client.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@doxygen/examples/$(DEPDIR)/streaming_client_plugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@doxygen/examples/$(DEPDIR)/udp_server.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@examples/$(DEPDIR)/ShowLoader.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@examples/$(DEPDIR)/ShowPlayer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@examples/$(DEPDIR)/ShowRecorder.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@examples/$(DEPDIR)/ShowSaver.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@examples/$(DEPDIR)/examples_libolaconfig_la-OlaConfigurator.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@examples/$(DEPDIR)/examples_ola_artnet-ola-artnet.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@examples/$(DEPDIR)/examples_ola_e131-ola-e131.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@examples/$(DEPDIR)/examples_ola_usbpro-ola-usbpro.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@examples/$(DEPDIR)/ola-client.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@examples/$(DEPDIR)/ola-dmxconsole.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@examples/$(DEPDIR)/ola-dmxmonitor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@examples/$(DEPDIR)/ola-latency.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@examples/$(DEPDIR)/ola-rdm-discover.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@examples/$(DEPDIR)/ola-rdm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@examples/$(DEPDIR)/ola-recorder.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@examples/$(DEPDIR)/ola-streaming-client.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@examples/$(DEPDIR)/ola-throughput.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@examples/$(DEPDIR)/ola-timecode.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@examples/$(DEPDIR)/ola-uni-stats.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/E131TestFramework.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/e131_loadtest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/e131_transmit_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_E131Tester-BaseInflatorTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_E131Tester-CIDTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_E131Tester-DMPAddressTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_E131Tester-DMPInflatorTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_E131Tester-DMPPDUTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_E131Tester-E131InflatorTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_E131Tester-E131PDUTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_E131Tester-HeaderSetTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_E131Tester-PDUTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_E131Tester-RootInflatorTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_E131Tester-RootPDUTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_E131Tester-RootSenderTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_E133Tester-E133InflatorTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_E133Tester-E133PDUTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_E133Tester-RDMPDUTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_TransportTester-TCPTransportTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_TransportTester-UDPTransportTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_libolaacn_la-CID.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_libolaacn_la-CIDImpl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-BaseInflator.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-DMPAddress.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-DMPE131Inflator.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-DMPInflator.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-DMPPDU.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E131DiscoveryInflator.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E131Inflator.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E131Node.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E131PDU.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E131Sender.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E133Inflator.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E133PDU.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E133StatusInflator.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E133StatusPDU.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-PDU.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-PreamblePacker.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-RDMInflator.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-RDMPDU.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-RootInflator.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-RootPDU.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-RootSender.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-TCPTransport.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-UDPTransport.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/usb/$(DEPDIR)/libs_usb_LibUsbThreadTester-LibUsbThreadTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/usb/$(DEPDIR)/libs_usb_libolausb_la-HotplugAgent.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/usb/$(DEPDIR)/libs_usb_libolausb_la-JaRuleConstants.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/usb/$(DEPDIR)/libs_usb_libolausb_la-JaRulePortHandle.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/usb/$(DEPDIR)/libs_usb_libolausb_la-JaRulePortHandleImpl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/usb/$(DEPDIR)/libs_usb_libolausb_la-JaRuleWidget.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/usb/$(DEPDIR)/libs_usb_libolausb_la-JaRuleWidgetPort.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/usb/$(DEPDIR)/libs_usb_libolausb_la-LibUsbAdaptor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/usb/$(DEPDIR)/libs_usb_libolausb_la-LibUsbThread.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libs/usb/$(DEPDIR)/libs_usb_libolausb_la-Types.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ola/$(DEPDIR)/ola_OlaClientTester-OlaClientWrapperTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ola/$(DEPDIR)/ola_OlaClientTester-StreamingClientTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ola/$(DEPDIR)/ola_libola_la-AutoStart.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ola/$(DEPDIR)/ola_libola_la-ClientRDMAPIShim.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ola/$(DEPDIR)/ola_libola_la-ClientTypesFactory.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ola/$(DEPDIR)/ola_libola_la-Module.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ola/$(DEPDIR)/ola_libola_la-OlaCallbackClient.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ola/$(DEPDIR)/ola_libola_la-OlaClient.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ola/$(DEPDIR)/ola_libola_la-OlaClientCore.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ola/$(DEPDIR)/ola_libola_la-OlaClientWrapper.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ola/$(DEPDIR)/ola_libola_la-StreamingClient.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/$(DEPDIR)/Olad.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/$(DEPDIR)/olad_OlaTester-OlaServerServiceImplTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/$(DEPDIR)/olad_OlaTester-PluginManagerTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/$(DEPDIR)/olad_libolaserver_la-AvahiDiscoveryAgent.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/$(DEPDIR)/olad_libolaserver_la-BonjourDiscoveryAgent.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/$(DEPDIR)/olad_libolaserver_la-ClientBroker.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/$(DEPDIR)/olad_libolaserver_la-DiscoveryAgent.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/$(DEPDIR)/olad_libolaserver_la-DynamicPluginLoader.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/$(DEPDIR)/olad_libolaserver_la-HttpServerActions.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/$(DEPDIR)/olad_libolaserver_la-OlaDaemon.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/$(DEPDIR)/olad_libolaserver_la-OlaServer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/$(DEPDIR)/olad_libolaserver_la-OlaServerServiceImpl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/$(DEPDIR)/olad_libolaserver_la-OladHTTPServer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/$(DEPDIR)/olad_libolaserver_la-PluginManager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/$(DEPDIR)/olad_libolaserver_la-RDMHTTPModule.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/plugin_api/$(DEPDIR)/olad_plugin_api_ClientTester-ClientTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/plugin_api/$(DEPDIR)/olad_plugin_api_DeviceTester-DeviceManagerTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/plugin_api/$(DEPDIR)/olad_plugin_api_DeviceTester-DeviceTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/plugin_api/$(DEPDIR)/olad_plugin_api_DmxSourceTester-DmxSourceTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/plugin_api/$(DEPDIR)/olad_plugin_api_PortTester-PortManagerTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/plugin_api/$(DEPDIR)/olad_plugin_api_PortTester-PortTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/plugin_api/$(DEPDIR)/olad_plugin_api_PreferencesTester-PreferencesTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/plugin_api/$(DEPDIR)/olad_plugin_api_UniverseTester-UniverseTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-Client.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-Device.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-DeviceManager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-DmxSource.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-Plugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-PluginAdaptor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-Port.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-PortBroker.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-PortManager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-Preferences.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-Universe.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-UniverseStore.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/artnet/$(DEPDIR)/ArtNetNode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/artnet/$(DEPDIR)/artnet_loadtest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/artnet/$(DEPDIR)/plugins_artnet_ArtNetTester-ArtNetNodeTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/artnet/$(DEPDIR)/plugins_artnet_libolaartnet_la-ArtNetDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/artnet/$(DEPDIR)/plugins_artnet_libolaartnet_la-ArtNetPlugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/artnet/$(DEPDIR)/plugins_artnet_libolaartnet_la-ArtNetPort.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/artnet/messages/$(DEPDIR)/plugins_artnet_messages_libolaartnetconf_la-ArtNetConfigMessages.pb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/dmx4linux/$(DEPDIR)/Dmx4LinuxDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/dmx4linux/$(DEPDIR)/Dmx4LinuxPlugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/dmx4linux/$(DEPDIR)/Dmx4LinuxPort.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/dummy/$(DEPDIR)/DummyDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/dummy/$(DEPDIR)/DummyPlugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/dummy/$(DEPDIR)/DummyPort.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/dummy/$(DEPDIR)/plugins_dummy_DummyPluginTester-DummyPortTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/e131/$(DEPDIR)/plugins_e131_libolae131_la-E131Device.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/e131/$(DEPDIR)/plugins_e131_libolae131_la-E131Plugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/e131/$(DEPDIR)/plugins_e131_libolae131_la-E131Port.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/e131/messages/$(DEPDIR)/plugins_e131_messages_libolae131conf_la-E131ConfigMessages.pb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/espnet/$(DEPDIR)/EspNetDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/espnet/$(DEPDIR)/EspNetNode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/espnet/$(DEPDIR)/EspNetPlugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/espnet/$(DEPDIR)/EspNetPort.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/espnet/$(DEPDIR)/RunLengthDecoder.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/espnet/$(DEPDIR)/plugins_espnet_EspNetTester-RunLengthDecoder.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/espnet/$(DEPDIR)/plugins_espnet_EspNetTester-RunLengthDecoderTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/ftdidmx/$(DEPDIR)/FtdiDmxDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/ftdidmx/$(DEPDIR)/FtdiDmxPlugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/ftdidmx/$(DEPDIR)/FtdiDmxThread.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/ftdidmx/$(DEPDIR)/FtdiWidget.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/gpio/$(DEPDIR)/GPIODevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/gpio/$(DEPDIR)/GPIODriver.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/gpio/$(DEPDIR)/GPIOPlugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/gpio/$(DEPDIR)/GPIOPort.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/karate/$(DEPDIR)/KarateDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/karate/$(DEPDIR)/KarateLight.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/karate/$(DEPDIR)/KaratePlugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/karate/$(DEPDIR)/KarateThread.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/kinet/$(DEPDIR)/KiNetDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/kinet/$(DEPDIR)/KiNetNode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/kinet/$(DEPDIR)/KiNetPlugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/kinet/$(DEPDIR)/plugins_kinet_KiNetTester-KiNetNodeTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/milinst/$(DEPDIR)/MilInstDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/milinst/$(DEPDIR)/MilInstPlugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/milinst/$(DEPDIR)/MilInstPort.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/milinst/$(DEPDIR)/MilInstWidget.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/milinst/$(DEPDIR)/MilInstWidget1463.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/milinst/$(DEPDIR)/MilInstWidget1553.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/opendmx/$(DEPDIR)/OpenDmxDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/opendmx/$(DEPDIR)/OpenDmxPlugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/opendmx/$(DEPDIR)/OpenDmxThread.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/openpixelcontrol/$(DEPDIR)/OPCClient.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/openpixelcontrol/$(DEPDIR)/OPCDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/openpixelcontrol/$(DEPDIR)/OPCPlugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/openpixelcontrol/$(DEPDIR)/OPCPort.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/openpixelcontrol/$(DEPDIR)/OPCServer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/openpixelcontrol/$(DEPDIR)/plugins_openpixelcontrol_OPCClientTester-OPCClientTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/openpixelcontrol/$(DEPDIR)/plugins_openpixelcontrol_OPCServerTester-OPCServerTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/osc/$(DEPDIR)/plugins_osc_OSCTester-OSCAddressTemplateTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/osc/$(DEPDIR)/plugins_osc_OSCTester-OSCNodeTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/osc/$(DEPDIR)/plugins_osc_libolaosc_la-OSCDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/osc/$(DEPDIR)/plugins_osc_libolaosc_la-OSCPlugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/osc/$(DEPDIR)/plugins_osc_libolaosc_la-OSCPort.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/osc/$(DEPDIR)/plugins_osc_libolaoscnode_la-OSCAddressTemplate.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/osc/$(DEPDIR)/plugins_osc_libolaoscnode_la-OSCNode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/pathport/$(DEPDIR)/PathportDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/pathport/$(DEPDIR)/PathportNode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/pathport/$(DEPDIR)/PathportPlugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/pathport/$(DEPDIR)/PathportPort.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/renard/$(DEPDIR)/RenardDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/renard/$(DEPDIR)/RenardPlugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/renard/$(DEPDIR)/RenardPort.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/renard/$(DEPDIR)/RenardWidget.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/sandnet/$(DEPDIR)/SandNetDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/sandnet/$(DEPDIR)/SandNetNode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/sandnet/$(DEPDIR)/SandNetPlugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/sandnet/$(DEPDIR)/SandNetPort.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/shownet/$(DEPDIR)/ShowNetDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/shownet/$(DEPDIR)/ShowNetNode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/shownet/$(DEPDIR)/ShowNetPlugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/shownet/$(DEPDIR)/ShowNetPort.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/shownet/$(DEPDIR)/plugins_shownet_ShowNetTester-ShowNetNode.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/shownet/$(DEPDIR)/plugins_shownet_ShowNetTester-ShowNetNodeTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/spi/$(DEPDIR)/SPIBackend.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/spi/$(DEPDIR)/SPIDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/spi/$(DEPDIR)/SPIOutput.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/spi/$(DEPDIR)/SPIPlugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/spi/$(DEPDIR)/SPIPort.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/spi/$(DEPDIR)/SPIWriter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/spi/$(DEPDIR)/plugins_spi_SPITester-FakeSPIWriter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/spi/$(DEPDIR)/plugins_spi_SPITester-SPIBackendTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/spi/$(DEPDIR)/plugins_spi_SPITester-SPIOutputTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/stageprofi/$(DEPDIR)/StageProfiDetector.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/stageprofi/$(DEPDIR)/StageProfiDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/stageprofi/$(DEPDIR)/StageProfiPlugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/stageprofi/$(DEPDIR)/StageProfiPort.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/stageprofi/$(DEPDIR)/StageProfiWidget.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/uartdmx/$(DEPDIR)/UartDmxDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/uartdmx/$(DEPDIR)/UartDmxPlugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/uartdmx/$(DEPDIR)/UartDmxThread.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/uartdmx/$(DEPDIR)/UartWidget.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-AsyncPluginImpl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-DMXCProjectsNodleU1Device.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-DMXCProjectsNodleU1Port.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-GenericDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-GenericOutputPort.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-JaRuleDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-JaRuleOutputPort.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-SyncPluginImpl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-UsbDmxPlugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-AnymauDMX.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-AnymauDMXFactory.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbReceiver.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbSender.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbTransceiverBase.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-DMXCProjectsNodleU1.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-DMXCProjectsNodleU1Factory.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-EurolitePro.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-EuroliteProFactory.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-Flags.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-JaRuleFactory.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-ScanlimeFadecandy.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-ScanlimeFadecandyFactory.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-Sunlite.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-SunliteFactory.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-SunliteFirmwareLoader.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-SyncronizedWidgetObserver.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-ThreadedUsbReceiver.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-ThreadedUsbSender.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-VellemanK8062.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-VellemanK8062Factory.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/ArduinoWidget.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/BaseRobeWidget.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/BaseUsbProWidget.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/DmxTriWidget.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/DmxterWidget.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/EnttecUsbProWidget.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/GenericUsbProWidget.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/RobeWidget.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/RobeWidgetDetector.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/UltraDMXProWidget.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/UsbProWidgetDetector.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/WidgetDetectorThread.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_ArduinoWidgetTester-ArduinoWidgetTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_ArduinoWidgetTester-CommonWidgetTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_ArduinoWidgetTester-MockEndpoint.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseRobeWidgetTester-BaseRobeWidgetTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseRobeWidgetTester-CommonWidgetTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseRobeWidgetTester-MockEndpoint.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseUsbProWidgetTester-BaseUsbProWidgetTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseUsbProWidgetTester-CommonWidgetTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseUsbProWidgetTester-MockEndpoint.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxTriWidgetTester-CommonWidgetTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxTriWidgetTester-DmxTriWidgetTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxTriWidgetTester-MockEndpoint.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxterWidgetTester-CommonWidgetTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxterWidgetTester-DmxterWidgetTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxterWidgetTester-MockEndpoint.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_EnttecUsbProWidgetTester-CommonWidgetTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_EnttecUsbProWidgetTester-EnttecUsbProWidgetTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_EnttecUsbProWidgetTester-MockEndpoint.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetDetectorTester-CommonWidgetTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetDetectorTester-MockEndpoint.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetDetectorTester-RobeWidgetDetectorTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetTester-CommonWidgetTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetTester-MockEndpoint.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetTester-RobeWidgetTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_UltraDMXProWidgetTester-CommonWidgetTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_UltraDMXProWidgetTester-MockEndpoint.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_UltraDMXProWidgetTester-UltraDMXProWidgetTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_UsbProWidgetDetectorTester-CommonWidgetTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_UsbProWidgetDetectorTester-MockEndpoint.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_UsbProWidgetDetectorTester-UsbProWidgetDetectorTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_WidgetDetectorThreadTester-CommonWidgetTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_WidgetDetectorThreadTester-MockEndpoint.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_WidgetDetectorThreadTester-WidgetDetectorThreadTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_libolausbpro_la-ArduinoRGBDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_libolausbpro_la-DmxTriDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_libolausbpro_la-DmxterDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_libolausbpro_la-RobeDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_libolausbpro_la-UltraDMXProDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_libolausbpro_la-UsbProDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/$(DEPDIR)/plugins_usbpro_libolausbpro_la-UsbSerialPlugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@plugins/usbpro/messages/$(DEPDIR)/plugins_usbpro_messages_libolausbproconf_la-UsbProConfigMessages.pb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@protoc/$(DEPDIR)/protoc_ola_protoc_plugin-CppFileGenerator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@protoc/$(DEPDIR)/protoc_ola_protoc_plugin-CppGenerator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@protoc/$(DEPDIR)/protoc_ola_protoc_plugin-GeneratorHelpers.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@protoc/$(DEPDIR)/protoc_ola_protoc_plugin-ServiceGenerator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@protoc/$(DEPDIR)/protoc_ola_protoc_plugin-StrUtil.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@protoc/$(DEPDIR)/protoc_ola_protoc_plugin-ola-protoc-generator-plugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/e133/$(DEPDIR)/DesignatedControllerConnection.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/e133/$(DEPDIR)/DeviceManager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/e133/$(DEPDIR)/DeviceManagerImpl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/e133/$(DEPDIR)/E133Device.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/e133/$(DEPDIR)/E133Endpoint.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/e133/$(DEPDIR)/E133HealthCheckedConnection.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/e133/$(DEPDIR)/E133Receiver.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/e133/$(DEPDIR)/E133StatusHelper.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/e133/$(DEPDIR)/EndpointManager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/e133/$(DEPDIR)/ManagementEndpoint.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/e133/$(DEPDIR)/MessageBuilder.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/e133/$(DEPDIR)/SimpleE133Node.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/e133/$(DEPDIR)/basic-controller.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/e133/$(DEPDIR)/basic-device.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/e133/$(DEPDIR)/e133-controller.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/e133/$(DEPDIR)/e133-monitor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/e133/$(DEPDIR)/e133-receiver.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/ja-rule/$(DEPDIR)/tools_ja_rule_ja_rule-USBDeviceManager.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/ja-rule/$(DEPDIR)/tools_ja_rule_ja_rule-ja-rule.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/ja-rule/$(DEPDIR)/tools_ja_rule_ja_rule_controller-USBDeviceManager.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/ja-rule/$(DEPDIR)/tools_ja_rule_ja_rule_controller-ja-rule-controller.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/logic/$(DEPDIR)/DMXSignalProcessor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/logic/$(DEPDIR)/logic-rdm-sniffer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/ola_trigger/$(DEPDIR)/Action.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/ola_trigger/$(DEPDIR)/Context.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/ola_trigger/$(DEPDIR)/DMXTrigger.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/ola_trigger/$(DEPDIR)/VariableInterpolator.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-ActionTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-ContextTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-DMXTriggerTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-IntervalTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-SlotTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-VariableInterpolatorTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ola_trigger-ParserActions.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ola_trigger-config.tab.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ola_trigger-lex.yy.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ola_trigger-ola-trigger.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/rdmpro/$(DEPDIR)/rdm-sniffer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/usbpro/$(DEPDIR)/usbpro-firmware.Po@am__quote@ .cc.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cc.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cc.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< common/base/common_libolacommon_la-Credentials.lo: common/base/Credentials.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/base/common_libolacommon_la-Credentials.lo -MD -MP -MF common/base/$(DEPDIR)/common_libolacommon_la-Credentials.Tpo -c -o common/base/common_libolacommon_la-Credentials.lo `test -f 'common/base/Credentials.cpp' || echo '$(srcdir)/'`common/base/Credentials.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/base/$(DEPDIR)/common_libolacommon_la-Credentials.Tpo common/base/$(DEPDIR)/common_libolacommon_la-Credentials.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/base/Credentials.cpp' object='common/base/common_libolacommon_la-Credentials.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/base/common_libolacommon_la-Credentials.lo `test -f 'common/base/Credentials.cpp' || echo '$(srcdir)/'`common/base/Credentials.cpp common/base/common_libolacommon_la-Env.lo: common/base/Env.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/base/common_libolacommon_la-Env.lo -MD -MP -MF common/base/$(DEPDIR)/common_libolacommon_la-Env.Tpo -c -o common/base/common_libolacommon_la-Env.lo `test -f 'common/base/Env.cpp' || echo '$(srcdir)/'`common/base/Env.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/base/$(DEPDIR)/common_libolacommon_la-Env.Tpo common/base/$(DEPDIR)/common_libolacommon_la-Env.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/base/Env.cpp' object='common/base/common_libolacommon_la-Env.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/base/common_libolacommon_la-Env.lo `test -f 'common/base/Env.cpp' || echo '$(srcdir)/'`common/base/Env.cpp common/base/common_libolacommon_la-Flags.lo: common/base/Flags.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/base/common_libolacommon_la-Flags.lo -MD -MP -MF common/base/$(DEPDIR)/common_libolacommon_la-Flags.Tpo -c -o common/base/common_libolacommon_la-Flags.lo `test -f 'common/base/Flags.cpp' || echo '$(srcdir)/'`common/base/Flags.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/base/$(DEPDIR)/common_libolacommon_la-Flags.Tpo common/base/$(DEPDIR)/common_libolacommon_la-Flags.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/base/Flags.cpp' object='common/base/common_libolacommon_la-Flags.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/base/common_libolacommon_la-Flags.lo `test -f 'common/base/Flags.cpp' || echo '$(srcdir)/'`common/base/Flags.cpp common/base/common_libolacommon_la-Init.lo: common/base/Init.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/base/common_libolacommon_la-Init.lo -MD -MP -MF common/base/$(DEPDIR)/common_libolacommon_la-Init.Tpo -c -o common/base/common_libolacommon_la-Init.lo `test -f 'common/base/Init.cpp' || echo '$(srcdir)/'`common/base/Init.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/base/$(DEPDIR)/common_libolacommon_la-Init.Tpo common/base/$(DEPDIR)/common_libolacommon_la-Init.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/base/Init.cpp' object='common/base/common_libolacommon_la-Init.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/base/common_libolacommon_la-Init.lo `test -f 'common/base/Init.cpp' || echo '$(srcdir)/'`common/base/Init.cpp common/base/common_libolacommon_la-Logging.lo: common/base/Logging.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/base/common_libolacommon_la-Logging.lo -MD -MP -MF common/base/$(DEPDIR)/common_libolacommon_la-Logging.Tpo -c -o common/base/common_libolacommon_la-Logging.lo `test -f 'common/base/Logging.cpp' || echo '$(srcdir)/'`common/base/Logging.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/base/$(DEPDIR)/common_libolacommon_la-Logging.Tpo common/base/$(DEPDIR)/common_libolacommon_la-Logging.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/base/Logging.cpp' object='common/base/common_libolacommon_la-Logging.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/base/common_libolacommon_la-Logging.lo `test -f 'common/base/Logging.cpp' || echo '$(srcdir)/'`common/base/Logging.cpp common/base/common_libolacommon_la-SysExits.lo: common/base/SysExits.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/base/common_libolacommon_la-SysExits.lo -MD -MP -MF common/base/$(DEPDIR)/common_libolacommon_la-SysExits.Tpo -c -o common/base/common_libolacommon_la-SysExits.lo `test -f 'common/base/SysExits.cpp' || echo '$(srcdir)/'`common/base/SysExits.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/base/$(DEPDIR)/common_libolacommon_la-SysExits.Tpo common/base/$(DEPDIR)/common_libolacommon_la-SysExits.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/base/SysExits.cpp' object='common/base/common_libolacommon_la-SysExits.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/base/common_libolacommon_la-SysExits.lo `test -f 'common/base/SysExits.cpp' || echo '$(srcdir)/'`common/base/SysExits.cpp common/base/common_libolacommon_la-Version.lo: common/base/Version.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/base/common_libolacommon_la-Version.lo -MD -MP -MF common/base/$(DEPDIR)/common_libolacommon_la-Version.Tpo -c -o common/base/common_libolacommon_la-Version.lo `test -f 'common/base/Version.cpp' || echo '$(srcdir)/'`common/base/Version.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/base/$(DEPDIR)/common_libolacommon_la-Version.Tpo common/base/$(DEPDIR)/common_libolacommon_la-Version.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/base/Version.cpp' object='common/base/common_libolacommon_la-Version.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/base/common_libolacommon_la-Version.lo `test -f 'common/base/Version.cpp' || echo '$(srcdir)/'`common/base/Version.cpp common/dmx/common_libolacommon_la-RunLengthEncoder.lo: common/dmx/RunLengthEncoder.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/dmx/common_libolacommon_la-RunLengthEncoder.lo -MD -MP -MF common/dmx/$(DEPDIR)/common_libolacommon_la-RunLengthEncoder.Tpo -c -o common/dmx/common_libolacommon_la-RunLengthEncoder.lo `test -f 'common/dmx/RunLengthEncoder.cpp' || echo '$(srcdir)/'`common/dmx/RunLengthEncoder.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/dmx/$(DEPDIR)/common_libolacommon_la-RunLengthEncoder.Tpo common/dmx/$(DEPDIR)/common_libolacommon_la-RunLengthEncoder.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/dmx/RunLengthEncoder.cpp' object='common/dmx/common_libolacommon_la-RunLengthEncoder.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/dmx/common_libolacommon_la-RunLengthEncoder.lo `test -f 'common/dmx/RunLengthEncoder.cpp' || echo '$(srcdir)/'`common/dmx/RunLengthEncoder.cpp common/export_map/common_libolacommon_la-ExportMap.lo: common/export_map/ExportMap.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/export_map/common_libolacommon_la-ExportMap.lo -MD -MP -MF common/export_map/$(DEPDIR)/common_libolacommon_la-ExportMap.Tpo -c -o common/export_map/common_libolacommon_la-ExportMap.lo `test -f 'common/export_map/ExportMap.cpp' || echo '$(srcdir)/'`common/export_map/ExportMap.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/export_map/$(DEPDIR)/common_libolacommon_la-ExportMap.Tpo common/export_map/$(DEPDIR)/common_libolacommon_la-ExportMap.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/export_map/ExportMap.cpp' object='common/export_map/common_libolacommon_la-ExportMap.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/export_map/common_libolacommon_la-ExportMap.lo `test -f 'common/export_map/ExportMap.cpp' || echo '$(srcdir)/'`common/export_map/ExportMap.cpp common/file/common_libolacommon_la-Util.lo: common/file/Util.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/file/common_libolacommon_la-Util.lo -MD -MP -MF common/file/$(DEPDIR)/common_libolacommon_la-Util.Tpo -c -o common/file/common_libolacommon_la-Util.lo `test -f 'common/file/Util.cpp' || echo '$(srcdir)/'`common/file/Util.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/file/$(DEPDIR)/common_libolacommon_la-Util.Tpo common/file/$(DEPDIR)/common_libolacommon_la-Util.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/file/Util.cpp' object='common/file/common_libolacommon_la-Util.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/file/common_libolacommon_la-Util.lo `test -f 'common/file/Util.cpp' || echo '$(srcdir)/'`common/file/Util.cpp common/io/common_libolacommon_la-Descriptor.lo: common/io/Descriptor.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_libolacommon_la-Descriptor.lo -MD -MP -MF common/io/$(DEPDIR)/common_libolacommon_la-Descriptor.Tpo -c -o common/io/common_libolacommon_la-Descriptor.lo `test -f 'common/io/Descriptor.cpp' || echo '$(srcdir)/'`common/io/Descriptor.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_libolacommon_la-Descriptor.Tpo common/io/$(DEPDIR)/common_libolacommon_la-Descriptor.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/Descriptor.cpp' object='common/io/common_libolacommon_la-Descriptor.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_libolacommon_la-Descriptor.lo `test -f 'common/io/Descriptor.cpp' || echo '$(srcdir)/'`common/io/Descriptor.cpp common/io/common_libolacommon_la-ExtendedSerial.lo: common/io/ExtendedSerial.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_libolacommon_la-ExtendedSerial.lo -MD -MP -MF common/io/$(DEPDIR)/common_libolacommon_la-ExtendedSerial.Tpo -c -o common/io/common_libolacommon_la-ExtendedSerial.lo `test -f 'common/io/ExtendedSerial.cpp' || echo '$(srcdir)/'`common/io/ExtendedSerial.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_libolacommon_la-ExtendedSerial.Tpo common/io/$(DEPDIR)/common_libolacommon_la-ExtendedSerial.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/ExtendedSerial.cpp' object='common/io/common_libolacommon_la-ExtendedSerial.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_libolacommon_la-ExtendedSerial.lo `test -f 'common/io/ExtendedSerial.cpp' || echo '$(srcdir)/'`common/io/ExtendedSerial.cpp common/io/common_libolacommon_la-IOQueue.lo: common/io/IOQueue.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_libolacommon_la-IOQueue.lo -MD -MP -MF common/io/$(DEPDIR)/common_libolacommon_la-IOQueue.Tpo -c -o common/io/common_libolacommon_la-IOQueue.lo `test -f 'common/io/IOQueue.cpp' || echo '$(srcdir)/'`common/io/IOQueue.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_libolacommon_la-IOQueue.Tpo common/io/$(DEPDIR)/common_libolacommon_la-IOQueue.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/IOQueue.cpp' object='common/io/common_libolacommon_la-IOQueue.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_libolacommon_la-IOQueue.lo `test -f 'common/io/IOQueue.cpp' || echo '$(srcdir)/'`common/io/IOQueue.cpp common/io/common_libolacommon_la-IOStack.lo: common/io/IOStack.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_libolacommon_la-IOStack.lo -MD -MP -MF common/io/$(DEPDIR)/common_libolacommon_la-IOStack.Tpo -c -o common/io/common_libolacommon_la-IOStack.lo `test -f 'common/io/IOStack.cpp' || echo '$(srcdir)/'`common/io/IOStack.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_libolacommon_la-IOStack.Tpo common/io/$(DEPDIR)/common_libolacommon_la-IOStack.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/IOStack.cpp' object='common/io/common_libolacommon_la-IOStack.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_libolacommon_la-IOStack.lo `test -f 'common/io/IOStack.cpp' || echo '$(srcdir)/'`common/io/IOStack.cpp common/io/common_libolacommon_la-IOUtils.lo: common/io/IOUtils.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_libolacommon_la-IOUtils.lo -MD -MP -MF common/io/$(DEPDIR)/common_libolacommon_la-IOUtils.Tpo -c -o common/io/common_libolacommon_la-IOUtils.lo `test -f 'common/io/IOUtils.cpp' || echo '$(srcdir)/'`common/io/IOUtils.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_libolacommon_la-IOUtils.Tpo common/io/$(DEPDIR)/common_libolacommon_la-IOUtils.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/IOUtils.cpp' object='common/io/common_libolacommon_la-IOUtils.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_libolacommon_la-IOUtils.lo `test -f 'common/io/IOUtils.cpp' || echo '$(srcdir)/'`common/io/IOUtils.cpp common/io/common_libolacommon_la-NonBlockingSender.lo: common/io/NonBlockingSender.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_libolacommon_la-NonBlockingSender.lo -MD -MP -MF common/io/$(DEPDIR)/common_libolacommon_la-NonBlockingSender.Tpo -c -o common/io/common_libolacommon_la-NonBlockingSender.lo `test -f 'common/io/NonBlockingSender.cpp' || echo '$(srcdir)/'`common/io/NonBlockingSender.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_libolacommon_la-NonBlockingSender.Tpo common/io/$(DEPDIR)/common_libolacommon_la-NonBlockingSender.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/NonBlockingSender.cpp' object='common/io/common_libolacommon_la-NonBlockingSender.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_libolacommon_la-NonBlockingSender.lo `test -f 'common/io/NonBlockingSender.cpp' || echo '$(srcdir)/'`common/io/NonBlockingSender.cpp common/io/common_libolacommon_la-PollerInterface.lo: common/io/PollerInterface.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_libolacommon_la-PollerInterface.lo -MD -MP -MF common/io/$(DEPDIR)/common_libolacommon_la-PollerInterface.Tpo -c -o common/io/common_libolacommon_la-PollerInterface.lo `test -f 'common/io/PollerInterface.cpp' || echo '$(srcdir)/'`common/io/PollerInterface.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_libolacommon_la-PollerInterface.Tpo common/io/$(DEPDIR)/common_libolacommon_la-PollerInterface.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/PollerInterface.cpp' object='common/io/common_libolacommon_la-PollerInterface.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_libolacommon_la-PollerInterface.lo `test -f 'common/io/PollerInterface.cpp' || echo '$(srcdir)/'`common/io/PollerInterface.cpp common/io/common_libolacommon_la-SelectServer.lo: common/io/SelectServer.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_libolacommon_la-SelectServer.lo -MD -MP -MF common/io/$(DEPDIR)/common_libolacommon_la-SelectServer.Tpo -c -o common/io/common_libolacommon_la-SelectServer.lo `test -f 'common/io/SelectServer.cpp' || echo '$(srcdir)/'`common/io/SelectServer.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_libolacommon_la-SelectServer.Tpo common/io/$(DEPDIR)/common_libolacommon_la-SelectServer.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/SelectServer.cpp' object='common/io/common_libolacommon_la-SelectServer.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_libolacommon_la-SelectServer.lo `test -f 'common/io/SelectServer.cpp' || echo '$(srcdir)/'`common/io/SelectServer.cpp common/io/common_libolacommon_la-Serial.lo: common/io/Serial.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_libolacommon_la-Serial.lo -MD -MP -MF common/io/$(DEPDIR)/common_libolacommon_la-Serial.Tpo -c -o common/io/common_libolacommon_la-Serial.lo `test -f 'common/io/Serial.cpp' || echo '$(srcdir)/'`common/io/Serial.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_libolacommon_la-Serial.Tpo common/io/$(DEPDIR)/common_libolacommon_la-Serial.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/Serial.cpp' object='common/io/common_libolacommon_la-Serial.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_libolacommon_la-Serial.lo `test -f 'common/io/Serial.cpp' || echo '$(srcdir)/'`common/io/Serial.cpp common/io/common_libolacommon_la-StdinHandler.lo: common/io/StdinHandler.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_libolacommon_la-StdinHandler.lo -MD -MP -MF common/io/$(DEPDIR)/common_libolacommon_la-StdinHandler.Tpo -c -o common/io/common_libolacommon_la-StdinHandler.lo `test -f 'common/io/StdinHandler.cpp' || echo '$(srcdir)/'`common/io/StdinHandler.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_libolacommon_la-StdinHandler.Tpo common/io/$(DEPDIR)/common_libolacommon_la-StdinHandler.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/StdinHandler.cpp' object='common/io/common_libolacommon_la-StdinHandler.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_libolacommon_la-StdinHandler.lo `test -f 'common/io/StdinHandler.cpp' || echo '$(srcdir)/'`common/io/StdinHandler.cpp common/io/common_libolacommon_la-TimeoutManager.lo: common/io/TimeoutManager.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_libolacommon_la-TimeoutManager.lo -MD -MP -MF common/io/$(DEPDIR)/common_libolacommon_la-TimeoutManager.Tpo -c -o common/io/common_libolacommon_la-TimeoutManager.lo `test -f 'common/io/TimeoutManager.cpp' || echo '$(srcdir)/'`common/io/TimeoutManager.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_libolacommon_la-TimeoutManager.Tpo common/io/$(DEPDIR)/common_libolacommon_la-TimeoutManager.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/TimeoutManager.cpp' object='common/io/common_libolacommon_la-TimeoutManager.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_libolacommon_la-TimeoutManager.lo `test -f 'common/io/TimeoutManager.cpp' || echo '$(srcdir)/'`common/io/TimeoutManager.cpp common/io/common_libolacommon_la-WindowsPoller.lo: common/io/WindowsPoller.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_libolacommon_la-WindowsPoller.lo -MD -MP -MF common/io/$(DEPDIR)/common_libolacommon_la-WindowsPoller.Tpo -c -o common/io/common_libolacommon_la-WindowsPoller.lo `test -f 'common/io/WindowsPoller.cpp' || echo '$(srcdir)/'`common/io/WindowsPoller.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_libolacommon_la-WindowsPoller.Tpo common/io/$(DEPDIR)/common_libolacommon_la-WindowsPoller.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/WindowsPoller.cpp' object='common/io/common_libolacommon_la-WindowsPoller.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_libolacommon_la-WindowsPoller.lo `test -f 'common/io/WindowsPoller.cpp' || echo '$(srcdir)/'`common/io/WindowsPoller.cpp common/io/common_libolacommon_la-SelectPoller.lo: common/io/SelectPoller.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_libolacommon_la-SelectPoller.lo -MD -MP -MF common/io/$(DEPDIR)/common_libolacommon_la-SelectPoller.Tpo -c -o common/io/common_libolacommon_la-SelectPoller.lo `test -f 'common/io/SelectPoller.cpp' || echo '$(srcdir)/'`common/io/SelectPoller.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_libolacommon_la-SelectPoller.Tpo common/io/$(DEPDIR)/common_libolacommon_la-SelectPoller.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/SelectPoller.cpp' object='common/io/common_libolacommon_la-SelectPoller.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_libolacommon_la-SelectPoller.lo `test -f 'common/io/SelectPoller.cpp' || echo '$(srcdir)/'`common/io/SelectPoller.cpp common/io/common_libolacommon_la-EPoller.lo: common/io/EPoller.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_libolacommon_la-EPoller.lo -MD -MP -MF common/io/$(DEPDIR)/common_libolacommon_la-EPoller.Tpo -c -o common/io/common_libolacommon_la-EPoller.lo `test -f 'common/io/EPoller.cpp' || echo '$(srcdir)/'`common/io/EPoller.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_libolacommon_la-EPoller.Tpo common/io/$(DEPDIR)/common_libolacommon_la-EPoller.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/EPoller.cpp' object='common/io/common_libolacommon_la-EPoller.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_libolacommon_la-EPoller.lo `test -f 'common/io/EPoller.cpp' || echo '$(srcdir)/'`common/io/EPoller.cpp common/io/common_libolacommon_la-KQueuePoller.lo: common/io/KQueuePoller.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_libolacommon_la-KQueuePoller.lo -MD -MP -MF common/io/$(DEPDIR)/common_libolacommon_la-KQueuePoller.Tpo -c -o common/io/common_libolacommon_la-KQueuePoller.lo `test -f 'common/io/KQueuePoller.cpp' || echo '$(srcdir)/'`common/io/KQueuePoller.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_libolacommon_la-KQueuePoller.Tpo common/io/$(DEPDIR)/common_libolacommon_la-KQueuePoller.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/KQueuePoller.cpp' object='common/io/common_libolacommon_la-KQueuePoller.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_libolacommon_la-KQueuePoller.lo `test -f 'common/io/KQueuePoller.cpp' || echo '$(srcdir)/'`common/io/KQueuePoller.cpp common/math/common_libolacommon_la-Random.lo: common/math/Random.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/math/common_libolacommon_la-Random.lo -MD -MP -MF common/math/$(DEPDIR)/common_libolacommon_la-Random.Tpo -c -o common/math/common_libolacommon_la-Random.lo `test -f 'common/math/Random.cpp' || echo '$(srcdir)/'`common/math/Random.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/math/$(DEPDIR)/common_libolacommon_la-Random.Tpo common/math/$(DEPDIR)/common_libolacommon_la-Random.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/math/Random.cpp' object='common/math/common_libolacommon_la-Random.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/math/common_libolacommon_la-Random.lo `test -f 'common/math/Random.cpp' || echo '$(srcdir)/'`common/math/Random.cpp common/messaging/common_libolacommon_la-Descriptor.lo: common/messaging/Descriptor.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/messaging/common_libolacommon_la-Descriptor.lo -MD -MP -MF common/messaging/$(DEPDIR)/common_libolacommon_la-Descriptor.Tpo -c -o common/messaging/common_libolacommon_la-Descriptor.lo `test -f 'common/messaging/Descriptor.cpp' || echo '$(srcdir)/'`common/messaging/Descriptor.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/messaging/$(DEPDIR)/common_libolacommon_la-Descriptor.Tpo common/messaging/$(DEPDIR)/common_libolacommon_la-Descriptor.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/messaging/Descriptor.cpp' object='common/messaging/common_libolacommon_la-Descriptor.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/messaging/common_libolacommon_la-Descriptor.lo `test -f 'common/messaging/Descriptor.cpp' || echo '$(srcdir)/'`common/messaging/Descriptor.cpp common/messaging/common_libolacommon_la-Message.lo: common/messaging/Message.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/messaging/common_libolacommon_la-Message.lo -MD -MP -MF common/messaging/$(DEPDIR)/common_libolacommon_la-Message.Tpo -c -o common/messaging/common_libolacommon_la-Message.lo `test -f 'common/messaging/Message.cpp' || echo '$(srcdir)/'`common/messaging/Message.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/messaging/$(DEPDIR)/common_libolacommon_la-Message.Tpo common/messaging/$(DEPDIR)/common_libolacommon_la-Message.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/messaging/Message.cpp' object='common/messaging/common_libolacommon_la-Message.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/messaging/common_libolacommon_la-Message.lo `test -f 'common/messaging/Message.cpp' || echo '$(srcdir)/'`common/messaging/Message.cpp common/messaging/common_libolacommon_la-MessagePrinter.lo: common/messaging/MessagePrinter.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/messaging/common_libolacommon_la-MessagePrinter.lo -MD -MP -MF common/messaging/$(DEPDIR)/common_libolacommon_la-MessagePrinter.Tpo -c -o common/messaging/common_libolacommon_la-MessagePrinter.lo `test -f 'common/messaging/MessagePrinter.cpp' || echo '$(srcdir)/'`common/messaging/MessagePrinter.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/messaging/$(DEPDIR)/common_libolacommon_la-MessagePrinter.Tpo common/messaging/$(DEPDIR)/common_libolacommon_la-MessagePrinter.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/messaging/MessagePrinter.cpp' object='common/messaging/common_libolacommon_la-MessagePrinter.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/messaging/common_libolacommon_la-MessagePrinter.lo `test -f 'common/messaging/MessagePrinter.cpp' || echo '$(srcdir)/'`common/messaging/MessagePrinter.cpp common/messaging/common_libolacommon_la-SchemaPrinter.lo: common/messaging/SchemaPrinter.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/messaging/common_libolacommon_la-SchemaPrinter.lo -MD -MP -MF common/messaging/$(DEPDIR)/common_libolacommon_la-SchemaPrinter.Tpo -c -o common/messaging/common_libolacommon_la-SchemaPrinter.lo `test -f 'common/messaging/SchemaPrinter.cpp' || echo '$(srcdir)/'`common/messaging/SchemaPrinter.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/messaging/$(DEPDIR)/common_libolacommon_la-SchemaPrinter.Tpo common/messaging/$(DEPDIR)/common_libolacommon_la-SchemaPrinter.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/messaging/SchemaPrinter.cpp' object='common/messaging/common_libolacommon_la-SchemaPrinter.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/messaging/common_libolacommon_la-SchemaPrinter.lo `test -f 'common/messaging/SchemaPrinter.cpp' || echo '$(srcdir)/'`common/messaging/SchemaPrinter.cpp common/network/common_libolacommon_la-AdvancedTCPConnector.lo: common/network/AdvancedTCPConnector.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_libolacommon_la-AdvancedTCPConnector.lo -MD -MP -MF common/network/$(DEPDIR)/common_libolacommon_la-AdvancedTCPConnector.Tpo -c -o common/network/common_libolacommon_la-AdvancedTCPConnector.lo `test -f 'common/network/AdvancedTCPConnector.cpp' || echo '$(srcdir)/'`common/network/AdvancedTCPConnector.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_libolacommon_la-AdvancedTCPConnector.Tpo common/network/$(DEPDIR)/common_libolacommon_la-AdvancedTCPConnector.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/AdvancedTCPConnector.cpp' object='common/network/common_libolacommon_la-AdvancedTCPConnector.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_libolacommon_la-AdvancedTCPConnector.lo `test -f 'common/network/AdvancedTCPConnector.cpp' || echo '$(srcdir)/'`common/network/AdvancedTCPConnector.cpp common/network/common_libolacommon_la-HealthCheckedConnection.lo: common/network/HealthCheckedConnection.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_libolacommon_la-HealthCheckedConnection.lo -MD -MP -MF common/network/$(DEPDIR)/common_libolacommon_la-HealthCheckedConnection.Tpo -c -o common/network/common_libolacommon_la-HealthCheckedConnection.lo `test -f 'common/network/HealthCheckedConnection.cpp' || echo '$(srcdir)/'`common/network/HealthCheckedConnection.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_libolacommon_la-HealthCheckedConnection.Tpo common/network/$(DEPDIR)/common_libolacommon_la-HealthCheckedConnection.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/HealthCheckedConnection.cpp' object='common/network/common_libolacommon_la-HealthCheckedConnection.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_libolacommon_la-HealthCheckedConnection.lo `test -f 'common/network/HealthCheckedConnection.cpp' || echo '$(srcdir)/'`common/network/HealthCheckedConnection.cpp common/network/common_libolacommon_la-IPV4Address.lo: common/network/IPV4Address.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_libolacommon_la-IPV4Address.lo -MD -MP -MF common/network/$(DEPDIR)/common_libolacommon_la-IPV4Address.Tpo -c -o common/network/common_libolacommon_la-IPV4Address.lo `test -f 'common/network/IPV4Address.cpp' || echo '$(srcdir)/'`common/network/IPV4Address.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_libolacommon_la-IPV4Address.Tpo common/network/$(DEPDIR)/common_libolacommon_la-IPV4Address.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/IPV4Address.cpp' object='common/network/common_libolacommon_la-IPV4Address.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_libolacommon_la-IPV4Address.lo `test -f 'common/network/IPV4Address.cpp' || echo '$(srcdir)/'`common/network/IPV4Address.cpp common/network/common_libolacommon_la-Interface.lo: common/network/Interface.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_libolacommon_la-Interface.lo -MD -MP -MF common/network/$(DEPDIR)/common_libolacommon_la-Interface.Tpo -c -o common/network/common_libolacommon_la-Interface.lo `test -f 'common/network/Interface.cpp' || echo '$(srcdir)/'`common/network/Interface.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_libolacommon_la-Interface.Tpo common/network/$(DEPDIR)/common_libolacommon_la-Interface.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/Interface.cpp' object='common/network/common_libolacommon_la-Interface.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_libolacommon_la-Interface.lo `test -f 'common/network/Interface.cpp' || echo '$(srcdir)/'`common/network/Interface.cpp common/network/common_libolacommon_la-InterfacePicker.lo: common/network/InterfacePicker.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_libolacommon_la-InterfacePicker.lo -MD -MP -MF common/network/$(DEPDIR)/common_libolacommon_la-InterfacePicker.Tpo -c -o common/network/common_libolacommon_la-InterfacePicker.lo `test -f 'common/network/InterfacePicker.cpp' || echo '$(srcdir)/'`common/network/InterfacePicker.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_libolacommon_la-InterfacePicker.Tpo common/network/$(DEPDIR)/common_libolacommon_la-InterfacePicker.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/InterfacePicker.cpp' object='common/network/common_libolacommon_la-InterfacePicker.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_libolacommon_la-InterfacePicker.lo `test -f 'common/network/InterfacePicker.cpp' || echo '$(srcdir)/'`common/network/InterfacePicker.cpp common/network/common_libolacommon_la-MACAddress.lo: common/network/MACAddress.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_libolacommon_la-MACAddress.lo -MD -MP -MF common/network/$(DEPDIR)/common_libolacommon_la-MACAddress.Tpo -c -o common/network/common_libolacommon_la-MACAddress.lo `test -f 'common/network/MACAddress.cpp' || echo '$(srcdir)/'`common/network/MACAddress.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_libolacommon_la-MACAddress.Tpo common/network/$(DEPDIR)/common_libolacommon_la-MACAddress.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/MACAddress.cpp' object='common/network/common_libolacommon_la-MACAddress.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_libolacommon_la-MACAddress.lo `test -f 'common/network/MACAddress.cpp' || echo '$(srcdir)/'`common/network/MACAddress.cpp common/network/common_libolacommon_la-NetworkUtils.lo: common/network/NetworkUtils.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_libolacommon_la-NetworkUtils.lo -MD -MP -MF common/network/$(DEPDIR)/common_libolacommon_la-NetworkUtils.Tpo -c -o common/network/common_libolacommon_la-NetworkUtils.lo `test -f 'common/network/NetworkUtils.cpp' || echo '$(srcdir)/'`common/network/NetworkUtils.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_libolacommon_la-NetworkUtils.Tpo common/network/$(DEPDIR)/common_libolacommon_la-NetworkUtils.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/NetworkUtils.cpp' object='common/network/common_libolacommon_la-NetworkUtils.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_libolacommon_la-NetworkUtils.lo `test -f 'common/network/NetworkUtils.cpp' || echo '$(srcdir)/'`common/network/NetworkUtils.cpp common/network/common_libolacommon_la-Socket.lo: common/network/Socket.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_libolacommon_la-Socket.lo -MD -MP -MF common/network/$(DEPDIR)/common_libolacommon_la-Socket.Tpo -c -o common/network/common_libolacommon_la-Socket.lo `test -f 'common/network/Socket.cpp' || echo '$(srcdir)/'`common/network/Socket.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_libolacommon_la-Socket.Tpo common/network/$(DEPDIR)/common_libolacommon_la-Socket.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/Socket.cpp' object='common/network/common_libolacommon_la-Socket.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_libolacommon_la-Socket.lo `test -f 'common/network/Socket.cpp' || echo '$(srcdir)/'`common/network/Socket.cpp common/network/common_libolacommon_la-SocketAddress.lo: common/network/SocketAddress.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_libolacommon_la-SocketAddress.lo -MD -MP -MF common/network/$(DEPDIR)/common_libolacommon_la-SocketAddress.Tpo -c -o common/network/common_libolacommon_la-SocketAddress.lo `test -f 'common/network/SocketAddress.cpp' || echo '$(srcdir)/'`common/network/SocketAddress.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_libolacommon_la-SocketAddress.Tpo common/network/$(DEPDIR)/common_libolacommon_la-SocketAddress.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/SocketAddress.cpp' object='common/network/common_libolacommon_la-SocketAddress.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_libolacommon_la-SocketAddress.lo `test -f 'common/network/SocketAddress.cpp' || echo '$(srcdir)/'`common/network/SocketAddress.cpp common/network/common_libolacommon_la-SocketCloser.lo: common/network/SocketCloser.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_libolacommon_la-SocketCloser.lo -MD -MP -MF common/network/$(DEPDIR)/common_libolacommon_la-SocketCloser.Tpo -c -o common/network/common_libolacommon_la-SocketCloser.lo `test -f 'common/network/SocketCloser.cpp' || echo '$(srcdir)/'`common/network/SocketCloser.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_libolacommon_la-SocketCloser.Tpo common/network/$(DEPDIR)/common_libolacommon_la-SocketCloser.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/SocketCloser.cpp' object='common/network/common_libolacommon_la-SocketCloser.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_libolacommon_la-SocketCloser.lo `test -f 'common/network/SocketCloser.cpp' || echo '$(srcdir)/'`common/network/SocketCloser.cpp common/network/common_libolacommon_la-SocketHelper.lo: common/network/SocketHelper.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_libolacommon_la-SocketHelper.lo -MD -MP -MF common/network/$(DEPDIR)/common_libolacommon_la-SocketHelper.Tpo -c -o common/network/common_libolacommon_la-SocketHelper.lo `test -f 'common/network/SocketHelper.cpp' || echo '$(srcdir)/'`common/network/SocketHelper.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_libolacommon_la-SocketHelper.Tpo common/network/$(DEPDIR)/common_libolacommon_la-SocketHelper.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/SocketHelper.cpp' object='common/network/common_libolacommon_la-SocketHelper.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_libolacommon_la-SocketHelper.lo `test -f 'common/network/SocketHelper.cpp' || echo '$(srcdir)/'`common/network/SocketHelper.cpp common/network/common_libolacommon_la-TCPConnector.lo: common/network/TCPConnector.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_libolacommon_la-TCPConnector.lo -MD -MP -MF common/network/$(DEPDIR)/common_libolacommon_la-TCPConnector.Tpo -c -o common/network/common_libolacommon_la-TCPConnector.lo `test -f 'common/network/TCPConnector.cpp' || echo '$(srcdir)/'`common/network/TCPConnector.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_libolacommon_la-TCPConnector.Tpo common/network/$(DEPDIR)/common_libolacommon_la-TCPConnector.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/TCPConnector.cpp' object='common/network/common_libolacommon_la-TCPConnector.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_libolacommon_la-TCPConnector.lo `test -f 'common/network/TCPConnector.cpp' || echo '$(srcdir)/'`common/network/TCPConnector.cpp common/network/common_libolacommon_la-TCPSocket.lo: common/network/TCPSocket.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_libolacommon_la-TCPSocket.lo -MD -MP -MF common/network/$(DEPDIR)/common_libolacommon_la-TCPSocket.Tpo -c -o common/network/common_libolacommon_la-TCPSocket.lo `test -f 'common/network/TCPSocket.cpp' || echo '$(srcdir)/'`common/network/TCPSocket.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_libolacommon_la-TCPSocket.Tpo common/network/$(DEPDIR)/common_libolacommon_la-TCPSocket.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/TCPSocket.cpp' object='common/network/common_libolacommon_la-TCPSocket.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_libolacommon_la-TCPSocket.lo `test -f 'common/network/TCPSocket.cpp' || echo '$(srcdir)/'`common/network/TCPSocket.cpp common/network/common_libolacommon_la-WindowsInterfacePicker.lo: common/network/WindowsInterfacePicker.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_libolacommon_la-WindowsInterfacePicker.lo -MD -MP -MF common/network/$(DEPDIR)/common_libolacommon_la-WindowsInterfacePicker.Tpo -c -o common/network/common_libolacommon_la-WindowsInterfacePicker.lo `test -f 'common/network/WindowsInterfacePicker.cpp' || echo '$(srcdir)/'`common/network/WindowsInterfacePicker.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_libolacommon_la-WindowsInterfacePicker.Tpo common/network/$(DEPDIR)/common_libolacommon_la-WindowsInterfacePicker.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/WindowsInterfacePicker.cpp' object='common/network/common_libolacommon_la-WindowsInterfacePicker.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_libolacommon_la-WindowsInterfacePicker.lo `test -f 'common/network/WindowsInterfacePicker.cpp' || echo '$(srcdir)/'`common/network/WindowsInterfacePicker.cpp common/network/common_libolacommon_la-PosixInterfacePicker.lo: common/network/PosixInterfacePicker.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_libolacommon_la-PosixInterfacePicker.lo -MD -MP -MF common/network/$(DEPDIR)/common_libolacommon_la-PosixInterfacePicker.Tpo -c -o common/network/common_libolacommon_la-PosixInterfacePicker.lo `test -f 'common/network/PosixInterfacePicker.cpp' || echo '$(srcdir)/'`common/network/PosixInterfacePicker.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_libolacommon_la-PosixInterfacePicker.Tpo common/network/$(DEPDIR)/common_libolacommon_la-PosixInterfacePicker.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/PosixInterfacePicker.cpp' object='common/network/common_libolacommon_la-PosixInterfacePicker.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_libolacommon_la-PosixInterfacePicker.lo `test -f 'common/network/PosixInterfacePicker.cpp' || echo '$(srcdir)/'`common/network/PosixInterfacePicker.cpp common/rdm/common_libolacommon_la-AckTimerResponder.lo: common/rdm/AckTimerResponder.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-AckTimerResponder.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-AckTimerResponder.Tpo -c -o common/rdm/common_libolacommon_la-AckTimerResponder.lo `test -f 'common/rdm/AckTimerResponder.cpp' || echo '$(srcdir)/'`common/rdm/AckTimerResponder.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-AckTimerResponder.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-AckTimerResponder.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/AckTimerResponder.cpp' object='common/rdm/common_libolacommon_la-AckTimerResponder.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-AckTimerResponder.lo `test -f 'common/rdm/AckTimerResponder.cpp' || echo '$(srcdir)/'`common/rdm/AckTimerResponder.cpp common/rdm/common_libolacommon_la-AdvancedDimmerResponder.lo: common/rdm/AdvancedDimmerResponder.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-AdvancedDimmerResponder.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-AdvancedDimmerResponder.Tpo -c -o common/rdm/common_libolacommon_la-AdvancedDimmerResponder.lo `test -f 'common/rdm/AdvancedDimmerResponder.cpp' || echo '$(srcdir)/'`common/rdm/AdvancedDimmerResponder.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-AdvancedDimmerResponder.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-AdvancedDimmerResponder.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/AdvancedDimmerResponder.cpp' object='common/rdm/common_libolacommon_la-AdvancedDimmerResponder.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-AdvancedDimmerResponder.lo `test -f 'common/rdm/AdvancedDimmerResponder.cpp' || echo '$(srcdir)/'`common/rdm/AdvancedDimmerResponder.cpp common/rdm/common_libolacommon_la-CommandPrinter.lo: common/rdm/CommandPrinter.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-CommandPrinter.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-CommandPrinter.Tpo -c -o common/rdm/common_libolacommon_la-CommandPrinter.lo `test -f 'common/rdm/CommandPrinter.cpp' || echo '$(srcdir)/'`common/rdm/CommandPrinter.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-CommandPrinter.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-CommandPrinter.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/CommandPrinter.cpp' object='common/rdm/common_libolacommon_la-CommandPrinter.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-CommandPrinter.lo `test -f 'common/rdm/CommandPrinter.cpp' || echo '$(srcdir)/'`common/rdm/CommandPrinter.cpp common/rdm/common_libolacommon_la-DescriptorConsistencyChecker.lo: common/rdm/DescriptorConsistencyChecker.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-DescriptorConsistencyChecker.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-DescriptorConsistencyChecker.Tpo -c -o common/rdm/common_libolacommon_la-DescriptorConsistencyChecker.lo `test -f 'common/rdm/DescriptorConsistencyChecker.cpp' || echo '$(srcdir)/'`common/rdm/DescriptorConsistencyChecker.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-DescriptorConsistencyChecker.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-DescriptorConsistencyChecker.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/DescriptorConsistencyChecker.cpp' object='common/rdm/common_libolacommon_la-DescriptorConsistencyChecker.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-DescriptorConsistencyChecker.lo `test -f 'common/rdm/DescriptorConsistencyChecker.cpp' || echo '$(srcdir)/'`common/rdm/DescriptorConsistencyChecker.cpp common/rdm/common_libolacommon_la-DimmerResponder.lo: common/rdm/DimmerResponder.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-DimmerResponder.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-DimmerResponder.Tpo -c -o common/rdm/common_libolacommon_la-DimmerResponder.lo `test -f 'common/rdm/DimmerResponder.cpp' || echo '$(srcdir)/'`common/rdm/DimmerResponder.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-DimmerResponder.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-DimmerResponder.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/DimmerResponder.cpp' object='common/rdm/common_libolacommon_la-DimmerResponder.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-DimmerResponder.lo `test -f 'common/rdm/DimmerResponder.cpp' || echo '$(srcdir)/'`common/rdm/DimmerResponder.cpp common/rdm/common_libolacommon_la-DimmerRootDevice.lo: common/rdm/DimmerRootDevice.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-DimmerRootDevice.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-DimmerRootDevice.Tpo -c -o common/rdm/common_libolacommon_la-DimmerRootDevice.lo `test -f 'common/rdm/DimmerRootDevice.cpp' || echo '$(srcdir)/'`common/rdm/DimmerRootDevice.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-DimmerRootDevice.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-DimmerRootDevice.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/DimmerRootDevice.cpp' object='common/rdm/common_libolacommon_la-DimmerRootDevice.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-DimmerRootDevice.lo `test -f 'common/rdm/DimmerRootDevice.cpp' || echo '$(srcdir)/'`common/rdm/DimmerRootDevice.cpp common/rdm/common_libolacommon_la-DimmerSubDevice.lo: common/rdm/DimmerSubDevice.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-DimmerSubDevice.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-DimmerSubDevice.Tpo -c -o common/rdm/common_libolacommon_la-DimmerSubDevice.lo `test -f 'common/rdm/DimmerSubDevice.cpp' || echo '$(srcdir)/'`common/rdm/DimmerSubDevice.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-DimmerSubDevice.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-DimmerSubDevice.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/DimmerSubDevice.cpp' object='common/rdm/common_libolacommon_la-DimmerSubDevice.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-DimmerSubDevice.lo `test -f 'common/rdm/DimmerSubDevice.cpp' || echo '$(srcdir)/'`common/rdm/DimmerSubDevice.cpp common/rdm/common_libolacommon_la-DiscoveryAgent.lo: common/rdm/DiscoveryAgent.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-DiscoveryAgent.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-DiscoveryAgent.Tpo -c -o common/rdm/common_libolacommon_la-DiscoveryAgent.lo `test -f 'common/rdm/DiscoveryAgent.cpp' || echo '$(srcdir)/'`common/rdm/DiscoveryAgent.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-DiscoveryAgent.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-DiscoveryAgent.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/DiscoveryAgent.cpp' object='common/rdm/common_libolacommon_la-DiscoveryAgent.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-DiscoveryAgent.lo `test -f 'common/rdm/DiscoveryAgent.cpp' || echo '$(srcdir)/'`common/rdm/DiscoveryAgent.cpp common/rdm/common_libolacommon_la-DummyResponder.lo: common/rdm/DummyResponder.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-DummyResponder.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-DummyResponder.Tpo -c -o common/rdm/common_libolacommon_la-DummyResponder.lo `test -f 'common/rdm/DummyResponder.cpp' || echo '$(srcdir)/'`common/rdm/DummyResponder.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-DummyResponder.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-DummyResponder.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/DummyResponder.cpp' object='common/rdm/common_libolacommon_la-DummyResponder.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-DummyResponder.lo `test -f 'common/rdm/DummyResponder.cpp' || echo '$(srcdir)/'`common/rdm/DummyResponder.cpp common/rdm/common_libolacommon_la-FakeNetworkManager.lo: common/rdm/FakeNetworkManager.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-FakeNetworkManager.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-FakeNetworkManager.Tpo -c -o common/rdm/common_libolacommon_la-FakeNetworkManager.lo `test -f 'common/rdm/FakeNetworkManager.cpp' || echo '$(srcdir)/'`common/rdm/FakeNetworkManager.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-FakeNetworkManager.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-FakeNetworkManager.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/FakeNetworkManager.cpp' object='common/rdm/common_libolacommon_la-FakeNetworkManager.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-FakeNetworkManager.lo `test -f 'common/rdm/FakeNetworkManager.cpp' || echo '$(srcdir)/'`common/rdm/FakeNetworkManager.cpp common/rdm/common_libolacommon_la-GroupSizeCalculator.lo: common/rdm/GroupSizeCalculator.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-GroupSizeCalculator.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-GroupSizeCalculator.Tpo -c -o common/rdm/common_libolacommon_la-GroupSizeCalculator.lo `test -f 'common/rdm/GroupSizeCalculator.cpp' || echo '$(srcdir)/'`common/rdm/GroupSizeCalculator.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-GroupSizeCalculator.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-GroupSizeCalculator.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/GroupSizeCalculator.cpp' object='common/rdm/common_libolacommon_la-GroupSizeCalculator.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-GroupSizeCalculator.lo `test -f 'common/rdm/GroupSizeCalculator.cpp' || echo '$(srcdir)/'`common/rdm/GroupSizeCalculator.cpp common/rdm/common_libolacommon_la-MessageDeserializer.lo: common/rdm/MessageDeserializer.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-MessageDeserializer.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-MessageDeserializer.Tpo -c -o common/rdm/common_libolacommon_la-MessageDeserializer.lo `test -f 'common/rdm/MessageDeserializer.cpp' || echo '$(srcdir)/'`common/rdm/MessageDeserializer.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-MessageDeserializer.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-MessageDeserializer.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/MessageDeserializer.cpp' object='common/rdm/common_libolacommon_la-MessageDeserializer.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-MessageDeserializer.lo `test -f 'common/rdm/MessageDeserializer.cpp' || echo '$(srcdir)/'`common/rdm/MessageDeserializer.cpp common/rdm/common_libolacommon_la-MessageSerializer.lo: common/rdm/MessageSerializer.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-MessageSerializer.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-MessageSerializer.Tpo -c -o common/rdm/common_libolacommon_la-MessageSerializer.lo `test -f 'common/rdm/MessageSerializer.cpp' || echo '$(srcdir)/'`common/rdm/MessageSerializer.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-MessageSerializer.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-MessageSerializer.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/MessageSerializer.cpp' object='common/rdm/common_libolacommon_la-MessageSerializer.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-MessageSerializer.lo `test -f 'common/rdm/MessageSerializer.cpp' || echo '$(srcdir)/'`common/rdm/MessageSerializer.cpp common/rdm/common_libolacommon_la-MovingLightResponder.lo: common/rdm/MovingLightResponder.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-MovingLightResponder.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-MovingLightResponder.Tpo -c -o common/rdm/common_libolacommon_la-MovingLightResponder.lo `test -f 'common/rdm/MovingLightResponder.cpp' || echo '$(srcdir)/'`common/rdm/MovingLightResponder.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-MovingLightResponder.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-MovingLightResponder.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/MovingLightResponder.cpp' object='common/rdm/common_libolacommon_la-MovingLightResponder.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-MovingLightResponder.lo `test -f 'common/rdm/MovingLightResponder.cpp' || echo '$(srcdir)/'`common/rdm/MovingLightResponder.cpp common/rdm/common_libolacommon_la-NetworkManager.lo: common/rdm/NetworkManager.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-NetworkManager.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-NetworkManager.Tpo -c -o common/rdm/common_libolacommon_la-NetworkManager.lo `test -f 'common/rdm/NetworkManager.cpp' || echo '$(srcdir)/'`common/rdm/NetworkManager.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-NetworkManager.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-NetworkManager.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/NetworkManager.cpp' object='common/rdm/common_libolacommon_la-NetworkManager.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-NetworkManager.lo `test -f 'common/rdm/NetworkManager.cpp' || echo '$(srcdir)/'`common/rdm/NetworkManager.cpp common/rdm/common_libolacommon_la-NetworkResponder.lo: common/rdm/NetworkResponder.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-NetworkResponder.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-NetworkResponder.Tpo -c -o common/rdm/common_libolacommon_la-NetworkResponder.lo `test -f 'common/rdm/NetworkResponder.cpp' || echo '$(srcdir)/'`common/rdm/NetworkResponder.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-NetworkResponder.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-NetworkResponder.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/NetworkResponder.cpp' object='common/rdm/common_libolacommon_la-NetworkResponder.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-NetworkResponder.lo `test -f 'common/rdm/NetworkResponder.cpp' || echo '$(srcdir)/'`common/rdm/NetworkResponder.cpp common/rdm/common_libolacommon_la-OpenLightingEnums.lo: common/rdm/OpenLightingEnums.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-OpenLightingEnums.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-OpenLightingEnums.Tpo -c -o common/rdm/common_libolacommon_la-OpenLightingEnums.lo `test -f 'common/rdm/OpenLightingEnums.cpp' || echo '$(srcdir)/'`common/rdm/OpenLightingEnums.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-OpenLightingEnums.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-OpenLightingEnums.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/OpenLightingEnums.cpp' object='common/rdm/common_libolacommon_la-OpenLightingEnums.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-OpenLightingEnums.lo `test -f 'common/rdm/OpenLightingEnums.cpp' || echo '$(srcdir)/'`common/rdm/OpenLightingEnums.cpp common/rdm/common_libolacommon_la-PidStore.lo: common/rdm/PidStore.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-PidStore.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-PidStore.Tpo -c -o common/rdm/common_libolacommon_la-PidStore.lo `test -f 'common/rdm/PidStore.cpp' || echo '$(srcdir)/'`common/rdm/PidStore.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-PidStore.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-PidStore.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/PidStore.cpp' object='common/rdm/common_libolacommon_la-PidStore.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-PidStore.lo `test -f 'common/rdm/PidStore.cpp' || echo '$(srcdir)/'`common/rdm/PidStore.cpp common/rdm/common_libolacommon_la-PidStoreHelper.lo: common/rdm/PidStoreHelper.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-PidStoreHelper.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-PidStoreHelper.Tpo -c -o common/rdm/common_libolacommon_la-PidStoreHelper.lo `test -f 'common/rdm/PidStoreHelper.cpp' || echo '$(srcdir)/'`common/rdm/PidStoreHelper.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-PidStoreHelper.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-PidStoreHelper.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/PidStoreHelper.cpp' object='common/rdm/common_libolacommon_la-PidStoreHelper.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-PidStoreHelper.lo `test -f 'common/rdm/PidStoreHelper.cpp' || echo '$(srcdir)/'`common/rdm/PidStoreHelper.cpp common/rdm/common_libolacommon_la-PidStoreLoader.lo: common/rdm/PidStoreLoader.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-PidStoreLoader.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-PidStoreLoader.Tpo -c -o common/rdm/common_libolacommon_la-PidStoreLoader.lo `test -f 'common/rdm/PidStoreLoader.cpp' || echo '$(srcdir)/'`common/rdm/PidStoreLoader.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-PidStoreLoader.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-PidStoreLoader.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/PidStoreLoader.cpp' object='common/rdm/common_libolacommon_la-PidStoreLoader.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-PidStoreLoader.lo `test -f 'common/rdm/PidStoreLoader.cpp' || echo '$(srcdir)/'`common/rdm/PidStoreLoader.cpp common/rdm/common_libolacommon_la-QueueingRDMController.lo: common/rdm/QueueingRDMController.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-QueueingRDMController.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-QueueingRDMController.Tpo -c -o common/rdm/common_libolacommon_la-QueueingRDMController.lo `test -f 'common/rdm/QueueingRDMController.cpp' || echo '$(srcdir)/'`common/rdm/QueueingRDMController.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-QueueingRDMController.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-QueueingRDMController.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/QueueingRDMController.cpp' object='common/rdm/common_libolacommon_la-QueueingRDMController.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-QueueingRDMController.lo `test -f 'common/rdm/QueueingRDMController.cpp' || echo '$(srcdir)/'`common/rdm/QueueingRDMController.cpp common/rdm/common_libolacommon_la-RDMAPI.lo: common/rdm/RDMAPI.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-RDMAPI.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-RDMAPI.Tpo -c -o common/rdm/common_libolacommon_la-RDMAPI.lo `test -f 'common/rdm/RDMAPI.cpp' || echo '$(srcdir)/'`common/rdm/RDMAPI.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-RDMAPI.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-RDMAPI.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/RDMAPI.cpp' object='common/rdm/common_libolacommon_la-RDMAPI.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-RDMAPI.lo `test -f 'common/rdm/RDMAPI.cpp' || echo '$(srcdir)/'`common/rdm/RDMAPI.cpp common/rdm/common_libolacommon_la-RDMCommand.lo: common/rdm/RDMCommand.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-RDMCommand.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-RDMCommand.Tpo -c -o common/rdm/common_libolacommon_la-RDMCommand.lo `test -f 'common/rdm/RDMCommand.cpp' || echo '$(srcdir)/'`common/rdm/RDMCommand.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-RDMCommand.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-RDMCommand.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/RDMCommand.cpp' object='common/rdm/common_libolacommon_la-RDMCommand.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-RDMCommand.lo `test -f 'common/rdm/RDMCommand.cpp' || echo '$(srcdir)/'`common/rdm/RDMCommand.cpp common/rdm/common_libolacommon_la-RDMCommandSerializer.lo: common/rdm/RDMCommandSerializer.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-RDMCommandSerializer.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-RDMCommandSerializer.Tpo -c -o common/rdm/common_libolacommon_la-RDMCommandSerializer.lo `test -f 'common/rdm/RDMCommandSerializer.cpp' || echo '$(srcdir)/'`common/rdm/RDMCommandSerializer.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-RDMCommandSerializer.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-RDMCommandSerializer.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/RDMCommandSerializer.cpp' object='common/rdm/common_libolacommon_la-RDMCommandSerializer.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-RDMCommandSerializer.lo `test -f 'common/rdm/RDMCommandSerializer.cpp' || echo '$(srcdir)/'`common/rdm/RDMCommandSerializer.cpp common/rdm/common_libolacommon_la-RDMFrame.lo: common/rdm/RDMFrame.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-RDMFrame.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-RDMFrame.Tpo -c -o common/rdm/common_libolacommon_la-RDMFrame.lo `test -f 'common/rdm/RDMFrame.cpp' || echo '$(srcdir)/'`common/rdm/RDMFrame.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-RDMFrame.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-RDMFrame.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/RDMFrame.cpp' object='common/rdm/common_libolacommon_la-RDMFrame.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-RDMFrame.lo `test -f 'common/rdm/RDMFrame.cpp' || echo '$(srcdir)/'`common/rdm/RDMFrame.cpp common/rdm/common_libolacommon_la-RDMHelper.lo: common/rdm/RDMHelper.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-RDMHelper.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-RDMHelper.Tpo -c -o common/rdm/common_libolacommon_la-RDMHelper.lo `test -f 'common/rdm/RDMHelper.cpp' || echo '$(srcdir)/'`common/rdm/RDMHelper.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-RDMHelper.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-RDMHelper.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/RDMHelper.cpp' object='common/rdm/common_libolacommon_la-RDMHelper.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-RDMHelper.lo `test -f 'common/rdm/RDMHelper.cpp' || echo '$(srcdir)/'`common/rdm/RDMHelper.cpp common/rdm/common_libolacommon_la-RDMReply.lo: common/rdm/RDMReply.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-RDMReply.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-RDMReply.Tpo -c -o common/rdm/common_libolacommon_la-RDMReply.lo `test -f 'common/rdm/RDMReply.cpp' || echo '$(srcdir)/'`common/rdm/RDMReply.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-RDMReply.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-RDMReply.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/RDMReply.cpp' object='common/rdm/common_libolacommon_la-RDMReply.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-RDMReply.lo `test -f 'common/rdm/RDMReply.cpp' || echo '$(srcdir)/'`common/rdm/RDMReply.cpp common/rdm/common_libolacommon_la-ResponderHelper.lo: common/rdm/ResponderHelper.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-ResponderHelper.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-ResponderHelper.Tpo -c -o common/rdm/common_libolacommon_la-ResponderHelper.lo `test -f 'common/rdm/ResponderHelper.cpp' || echo '$(srcdir)/'`common/rdm/ResponderHelper.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-ResponderHelper.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-ResponderHelper.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/ResponderHelper.cpp' object='common/rdm/common_libolacommon_la-ResponderHelper.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-ResponderHelper.lo `test -f 'common/rdm/ResponderHelper.cpp' || echo '$(srcdir)/'`common/rdm/ResponderHelper.cpp common/rdm/common_libolacommon_la-ResponderLoadSensor.lo: common/rdm/ResponderLoadSensor.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-ResponderLoadSensor.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-ResponderLoadSensor.Tpo -c -o common/rdm/common_libolacommon_la-ResponderLoadSensor.lo `test -f 'common/rdm/ResponderLoadSensor.cpp' || echo '$(srcdir)/'`common/rdm/ResponderLoadSensor.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-ResponderLoadSensor.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-ResponderLoadSensor.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/ResponderLoadSensor.cpp' object='common/rdm/common_libolacommon_la-ResponderLoadSensor.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-ResponderLoadSensor.lo `test -f 'common/rdm/ResponderLoadSensor.cpp' || echo '$(srcdir)/'`common/rdm/ResponderLoadSensor.cpp common/rdm/common_libolacommon_la-ResponderPersonality.lo: common/rdm/ResponderPersonality.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-ResponderPersonality.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-ResponderPersonality.Tpo -c -o common/rdm/common_libolacommon_la-ResponderPersonality.lo `test -f 'common/rdm/ResponderPersonality.cpp' || echo '$(srcdir)/'`common/rdm/ResponderPersonality.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-ResponderPersonality.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-ResponderPersonality.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/ResponderPersonality.cpp' object='common/rdm/common_libolacommon_la-ResponderPersonality.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-ResponderPersonality.lo `test -f 'common/rdm/ResponderPersonality.cpp' || echo '$(srcdir)/'`common/rdm/ResponderPersonality.cpp common/rdm/common_libolacommon_la-ResponderSettings.lo: common/rdm/ResponderSettings.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-ResponderSettings.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-ResponderSettings.Tpo -c -o common/rdm/common_libolacommon_la-ResponderSettings.lo `test -f 'common/rdm/ResponderSettings.cpp' || echo '$(srcdir)/'`common/rdm/ResponderSettings.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-ResponderSettings.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-ResponderSettings.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/ResponderSettings.cpp' object='common/rdm/common_libolacommon_la-ResponderSettings.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-ResponderSettings.lo `test -f 'common/rdm/ResponderSettings.cpp' || echo '$(srcdir)/'`common/rdm/ResponderSettings.cpp common/rdm/common_libolacommon_la-ResponderSlotData.lo: common/rdm/ResponderSlotData.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-ResponderSlotData.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-ResponderSlotData.Tpo -c -o common/rdm/common_libolacommon_la-ResponderSlotData.lo `test -f 'common/rdm/ResponderSlotData.cpp' || echo '$(srcdir)/'`common/rdm/ResponderSlotData.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-ResponderSlotData.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-ResponderSlotData.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/ResponderSlotData.cpp' object='common/rdm/common_libolacommon_la-ResponderSlotData.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-ResponderSlotData.lo `test -f 'common/rdm/ResponderSlotData.cpp' || echo '$(srcdir)/'`common/rdm/ResponderSlotData.cpp common/rdm/common_libolacommon_la-SensorResponder.lo: common/rdm/SensorResponder.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-SensorResponder.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-SensorResponder.Tpo -c -o common/rdm/common_libolacommon_la-SensorResponder.lo `test -f 'common/rdm/SensorResponder.cpp' || echo '$(srcdir)/'`common/rdm/SensorResponder.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-SensorResponder.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-SensorResponder.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/SensorResponder.cpp' object='common/rdm/common_libolacommon_la-SensorResponder.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-SensorResponder.lo `test -f 'common/rdm/SensorResponder.cpp' || echo '$(srcdir)/'`common/rdm/SensorResponder.cpp common/rdm/common_libolacommon_la-StringMessageBuilder.lo: common/rdm/StringMessageBuilder.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-StringMessageBuilder.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-StringMessageBuilder.Tpo -c -o common/rdm/common_libolacommon_la-StringMessageBuilder.lo `test -f 'common/rdm/StringMessageBuilder.cpp' || echo '$(srcdir)/'`common/rdm/StringMessageBuilder.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-StringMessageBuilder.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-StringMessageBuilder.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/StringMessageBuilder.cpp' object='common/rdm/common_libolacommon_la-StringMessageBuilder.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-StringMessageBuilder.lo `test -f 'common/rdm/StringMessageBuilder.cpp' || echo '$(srcdir)/'`common/rdm/StringMessageBuilder.cpp common/rdm/common_libolacommon_la-SubDeviceDispatcher.lo: common/rdm/SubDeviceDispatcher.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-SubDeviceDispatcher.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-SubDeviceDispatcher.Tpo -c -o common/rdm/common_libolacommon_la-SubDeviceDispatcher.lo `test -f 'common/rdm/SubDeviceDispatcher.cpp' || echo '$(srcdir)/'`common/rdm/SubDeviceDispatcher.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-SubDeviceDispatcher.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-SubDeviceDispatcher.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/SubDeviceDispatcher.cpp' object='common/rdm/common_libolacommon_la-SubDeviceDispatcher.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-SubDeviceDispatcher.lo `test -f 'common/rdm/SubDeviceDispatcher.cpp' || echo '$(srcdir)/'`common/rdm/SubDeviceDispatcher.cpp common/rdm/common_libolacommon_la-UID.lo: common/rdm/UID.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-UID.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-UID.Tpo -c -o common/rdm/common_libolacommon_la-UID.lo `test -f 'common/rdm/UID.cpp' || echo '$(srcdir)/'`common/rdm/UID.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-UID.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-UID.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/UID.cpp' object='common/rdm/common_libolacommon_la-UID.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-UID.lo `test -f 'common/rdm/UID.cpp' || echo '$(srcdir)/'`common/rdm/UID.cpp common/rdm/common_libolacommon_la-VariableFieldSizeCalculator.lo: common/rdm/VariableFieldSizeCalculator.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-VariableFieldSizeCalculator.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-VariableFieldSizeCalculator.Tpo -c -o common/rdm/common_libolacommon_la-VariableFieldSizeCalculator.lo `test -f 'common/rdm/VariableFieldSizeCalculator.cpp' || echo '$(srcdir)/'`common/rdm/VariableFieldSizeCalculator.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-VariableFieldSizeCalculator.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-VariableFieldSizeCalculator.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/VariableFieldSizeCalculator.cpp' object='common/rdm/common_libolacommon_la-VariableFieldSizeCalculator.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-VariableFieldSizeCalculator.lo `test -f 'common/rdm/VariableFieldSizeCalculator.cpp' || echo '$(srcdir)/'`common/rdm/VariableFieldSizeCalculator.cpp common/rpc/common_libolacommon_la-RpcChannel.lo: common/rpc/RpcChannel.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rpc/common_libolacommon_la-RpcChannel.lo -MD -MP -MF common/rpc/$(DEPDIR)/common_libolacommon_la-RpcChannel.Tpo -c -o common/rpc/common_libolacommon_la-RpcChannel.lo `test -f 'common/rpc/RpcChannel.cpp' || echo '$(srcdir)/'`common/rpc/RpcChannel.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rpc/$(DEPDIR)/common_libolacommon_la-RpcChannel.Tpo common/rpc/$(DEPDIR)/common_libolacommon_la-RpcChannel.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rpc/RpcChannel.cpp' object='common/rpc/common_libolacommon_la-RpcChannel.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rpc/common_libolacommon_la-RpcChannel.lo `test -f 'common/rpc/RpcChannel.cpp' || echo '$(srcdir)/'`common/rpc/RpcChannel.cpp common/rpc/common_libolacommon_la-RpcController.lo: common/rpc/RpcController.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rpc/common_libolacommon_la-RpcController.lo -MD -MP -MF common/rpc/$(DEPDIR)/common_libolacommon_la-RpcController.Tpo -c -o common/rpc/common_libolacommon_la-RpcController.lo `test -f 'common/rpc/RpcController.cpp' || echo '$(srcdir)/'`common/rpc/RpcController.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rpc/$(DEPDIR)/common_libolacommon_la-RpcController.Tpo common/rpc/$(DEPDIR)/common_libolacommon_la-RpcController.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rpc/RpcController.cpp' object='common/rpc/common_libolacommon_la-RpcController.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rpc/common_libolacommon_la-RpcController.lo `test -f 'common/rpc/RpcController.cpp' || echo '$(srcdir)/'`common/rpc/RpcController.cpp common/rpc/common_libolacommon_la-RpcServer.lo: common/rpc/RpcServer.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rpc/common_libolacommon_la-RpcServer.lo -MD -MP -MF common/rpc/$(DEPDIR)/common_libolacommon_la-RpcServer.Tpo -c -o common/rpc/common_libolacommon_la-RpcServer.lo `test -f 'common/rpc/RpcServer.cpp' || echo '$(srcdir)/'`common/rpc/RpcServer.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rpc/$(DEPDIR)/common_libolacommon_la-RpcServer.Tpo common/rpc/$(DEPDIR)/common_libolacommon_la-RpcServer.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rpc/RpcServer.cpp' object='common/rpc/common_libolacommon_la-RpcServer.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rpc/common_libolacommon_la-RpcServer.lo `test -f 'common/rpc/RpcServer.cpp' || echo '$(srcdir)/'`common/rpc/RpcServer.cpp common/strings/common_libolacommon_la-Format.lo: common/strings/Format.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/strings/common_libolacommon_la-Format.lo -MD -MP -MF common/strings/$(DEPDIR)/common_libolacommon_la-Format.Tpo -c -o common/strings/common_libolacommon_la-Format.lo `test -f 'common/strings/Format.cpp' || echo '$(srcdir)/'`common/strings/Format.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/strings/$(DEPDIR)/common_libolacommon_la-Format.Tpo common/strings/$(DEPDIR)/common_libolacommon_la-Format.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/strings/Format.cpp' object='common/strings/common_libolacommon_la-Format.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/strings/common_libolacommon_la-Format.lo `test -f 'common/strings/Format.cpp' || echo '$(srcdir)/'`common/strings/Format.cpp common/strings/common_libolacommon_la-Utils.lo: common/strings/Utils.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/strings/common_libolacommon_la-Utils.lo -MD -MP -MF common/strings/$(DEPDIR)/common_libolacommon_la-Utils.Tpo -c -o common/strings/common_libolacommon_la-Utils.lo `test -f 'common/strings/Utils.cpp' || echo '$(srcdir)/'`common/strings/Utils.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/strings/$(DEPDIR)/common_libolacommon_la-Utils.Tpo common/strings/$(DEPDIR)/common_libolacommon_la-Utils.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/strings/Utils.cpp' object='common/strings/common_libolacommon_la-Utils.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/strings/common_libolacommon_la-Utils.lo `test -f 'common/strings/Utils.cpp' || echo '$(srcdir)/'`common/strings/Utils.cpp common/system/common_libolacommon_la-Limits.lo: common/system/Limits.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/system/common_libolacommon_la-Limits.lo -MD -MP -MF common/system/$(DEPDIR)/common_libolacommon_la-Limits.Tpo -c -o common/system/common_libolacommon_la-Limits.lo `test -f 'common/system/Limits.cpp' || echo '$(srcdir)/'`common/system/Limits.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/system/$(DEPDIR)/common_libolacommon_la-Limits.Tpo common/system/$(DEPDIR)/common_libolacommon_la-Limits.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/system/Limits.cpp' object='common/system/common_libolacommon_la-Limits.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/system/common_libolacommon_la-Limits.lo `test -f 'common/system/Limits.cpp' || echo '$(srcdir)/'`common/system/Limits.cpp common/system/common_libolacommon_la-SystemUtils.lo: common/system/SystemUtils.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/system/common_libolacommon_la-SystemUtils.lo -MD -MP -MF common/system/$(DEPDIR)/common_libolacommon_la-SystemUtils.Tpo -c -o common/system/common_libolacommon_la-SystemUtils.lo `test -f 'common/system/SystemUtils.cpp' || echo '$(srcdir)/'`common/system/SystemUtils.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/system/$(DEPDIR)/common_libolacommon_la-SystemUtils.Tpo common/system/$(DEPDIR)/common_libolacommon_la-SystemUtils.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/system/SystemUtils.cpp' object='common/system/common_libolacommon_la-SystemUtils.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/system/common_libolacommon_la-SystemUtils.lo `test -f 'common/system/SystemUtils.cpp' || echo '$(srcdir)/'`common/system/SystemUtils.cpp common/thread/common_libolacommon_la-ConsumerThread.lo: common/thread/ConsumerThread.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/thread/common_libolacommon_la-ConsumerThread.lo -MD -MP -MF common/thread/$(DEPDIR)/common_libolacommon_la-ConsumerThread.Tpo -c -o common/thread/common_libolacommon_la-ConsumerThread.lo `test -f 'common/thread/ConsumerThread.cpp' || echo '$(srcdir)/'`common/thread/ConsumerThread.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/thread/$(DEPDIR)/common_libolacommon_la-ConsumerThread.Tpo common/thread/$(DEPDIR)/common_libolacommon_la-ConsumerThread.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/thread/ConsumerThread.cpp' object='common/thread/common_libolacommon_la-ConsumerThread.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/thread/common_libolacommon_la-ConsumerThread.lo `test -f 'common/thread/ConsumerThread.cpp' || echo '$(srcdir)/'`common/thread/ConsumerThread.cpp common/thread/common_libolacommon_la-ExecutorThread.lo: common/thread/ExecutorThread.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/thread/common_libolacommon_la-ExecutorThread.lo -MD -MP -MF common/thread/$(DEPDIR)/common_libolacommon_la-ExecutorThread.Tpo -c -o common/thread/common_libolacommon_la-ExecutorThread.lo `test -f 'common/thread/ExecutorThread.cpp' || echo '$(srcdir)/'`common/thread/ExecutorThread.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/thread/$(DEPDIR)/common_libolacommon_la-ExecutorThread.Tpo common/thread/$(DEPDIR)/common_libolacommon_la-ExecutorThread.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/thread/ExecutorThread.cpp' object='common/thread/common_libolacommon_la-ExecutorThread.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/thread/common_libolacommon_la-ExecutorThread.lo `test -f 'common/thread/ExecutorThread.cpp' || echo '$(srcdir)/'`common/thread/ExecutorThread.cpp common/thread/common_libolacommon_la-Mutex.lo: common/thread/Mutex.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/thread/common_libolacommon_la-Mutex.lo -MD -MP -MF common/thread/$(DEPDIR)/common_libolacommon_la-Mutex.Tpo -c -o common/thread/common_libolacommon_la-Mutex.lo `test -f 'common/thread/Mutex.cpp' || echo '$(srcdir)/'`common/thread/Mutex.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/thread/$(DEPDIR)/common_libolacommon_la-Mutex.Tpo common/thread/$(DEPDIR)/common_libolacommon_la-Mutex.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/thread/Mutex.cpp' object='common/thread/common_libolacommon_la-Mutex.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/thread/common_libolacommon_la-Mutex.lo `test -f 'common/thread/Mutex.cpp' || echo '$(srcdir)/'`common/thread/Mutex.cpp common/thread/common_libolacommon_la-PeriodicThread.lo: common/thread/PeriodicThread.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/thread/common_libolacommon_la-PeriodicThread.lo -MD -MP -MF common/thread/$(DEPDIR)/common_libolacommon_la-PeriodicThread.Tpo -c -o common/thread/common_libolacommon_la-PeriodicThread.lo `test -f 'common/thread/PeriodicThread.cpp' || echo '$(srcdir)/'`common/thread/PeriodicThread.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/thread/$(DEPDIR)/common_libolacommon_la-PeriodicThread.Tpo common/thread/$(DEPDIR)/common_libolacommon_la-PeriodicThread.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/thread/PeriodicThread.cpp' object='common/thread/common_libolacommon_la-PeriodicThread.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/thread/common_libolacommon_la-PeriodicThread.lo `test -f 'common/thread/PeriodicThread.cpp' || echo '$(srcdir)/'`common/thread/PeriodicThread.cpp common/thread/common_libolacommon_la-SignalThread.lo: common/thread/SignalThread.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/thread/common_libolacommon_la-SignalThread.lo -MD -MP -MF common/thread/$(DEPDIR)/common_libolacommon_la-SignalThread.Tpo -c -o common/thread/common_libolacommon_la-SignalThread.lo `test -f 'common/thread/SignalThread.cpp' || echo '$(srcdir)/'`common/thread/SignalThread.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/thread/$(DEPDIR)/common_libolacommon_la-SignalThread.Tpo common/thread/$(DEPDIR)/common_libolacommon_la-SignalThread.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/thread/SignalThread.cpp' object='common/thread/common_libolacommon_la-SignalThread.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/thread/common_libolacommon_la-SignalThread.lo `test -f 'common/thread/SignalThread.cpp' || echo '$(srcdir)/'`common/thread/SignalThread.cpp common/thread/common_libolacommon_la-Thread.lo: common/thread/Thread.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/thread/common_libolacommon_la-Thread.lo -MD -MP -MF common/thread/$(DEPDIR)/common_libolacommon_la-Thread.Tpo -c -o common/thread/common_libolacommon_la-Thread.lo `test -f 'common/thread/Thread.cpp' || echo '$(srcdir)/'`common/thread/Thread.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/thread/$(DEPDIR)/common_libolacommon_la-Thread.Tpo common/thread/$(DEPDIR)/common_libolacommon_la-Thread.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/thread/Thread.cpp' object='common/thread/common_libolacommon_la-Thread.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/thread/common_libolacommon_la-Thread.lo `test -f 'common/thread/Thread.cpp' || echo '$(srcdir)/'`common/thread/Thread.cpp common/thread/common_libolacommon_la-ThreadPool.lo: common/thread/ThreadPool.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/thread/common_libolacommon_la-ThreadPool.lo -MD -MP -MF common/thread/$(DEPDIR)/common_libolacommon_la-ThreadPool.Tpo -c -o common/thread/common_libolacommon_la-ThreadPool.lo `test -f 'common/thread/ThreadPool.cpp' || echo '$(srcdir)/'`common/thread/ThreadPool.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/thread/$(DEPDIR)/common_libolacommon_la-ThreadPool.Tpo common/thread/$(DEPDIR)/common_libolacommon_la-ThreadPool.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/thread/ThreadPool.cpp' object='common/thread/common_libolacommon_la-ThreadPool.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/thread/common_libolacommon_la-ThreadPool.lo `test -f 'common/thread/ThreadPool.cpp' || echo '$(srcdir)/'`common/thread/ThreadPool.cpp common/thread/common_libolacommon_la-Utils.lo: common/thread/Utils.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/thread/common_libolacommon_la-Utils.lo -MD -MP -MF common/thread/$(DEPDIR)/common_libolacommon_la-Utils.Tpo -c -o common/thread/common_libolacommon_la-Utils.lo `test -f 'common/thread/Utils.cpp' || echo '$(srcdir)/'`common/thread/Utils.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/thread/$(DEPDIR)/common_libolacommon_la-Utils.Tpo common/thread/$(DEPDIR)/common_libolacommon_la-Utils.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/thread/Utils.cpp' object='common/thread/common_libolacommon_la-Utils.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/thread/common_libolacommon_la-Utils.lo `test -f 'common/thread/Utils.cpp' || echo '$(srcdir)/'`common/thread/Utils.cpp common/timecode/common_libolacommon_la-TimeCode.lo: common/timecode/TimeCode.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/timecode/common_libolacommon_la-TimeCode.lo -MD -MP -MF common/timecode/$(DEPDIR)/common_libolacommon_la-TimeCode.Tpo -c -o common/timecode/common_libolacommon_la-TimeCode.lo `test -f 'common/timecode/TimeCode.cpp' || echo '$(srcdir)/'`common/timecode/TimeCode.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/timecode/$(DEPDIR)/common_libolacommon_la-TimeCode.Tpo common/timecode/$(DEPDIR)/common_libolacommon_la-TimeCode.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/timecode/TimeCode.cpp' object='common/timecode/common_libolacommon_la-TimeCode.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/timecode/common_libolacommon_la-TimeCode.lo `test -f 'common/timecode/TimeCode.cpp' || echo '$(srcdir)/'`common/timecode/TimeCode.cpp common/utils/common_libolacommon_la-ActionQueue.lo: common/utils/ActionQueue.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/utils/common_libolacommon_la-ActionQueue.lo -MD -MP -MF common/utils/$(DEPDIR)/common_libolacommon_la-ActionQueue.Tpo -c -o common/utils/common_libolacommon_la-ActionQueue.lo `test -f 'common/utils/ActionQueue.cpp' || echo '$(srcdir)/'`common/utils/ActionQueue.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/utils/$(DEPDIR)/common_libolacommon_la-ActionQueue.Tpo common/utils/$(DEPDIR)/common_libolacommon_la-ActionQueue.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/utils/ActionQueue.cpp' object='common/utils/common_libolacommon_la-ActionQueue.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/utils/common_libolacommon_la-ActionQueue.lo `test -f 'common/utils/ActionQueue.cpp' || echo '$(srcdir)/'`common/utils/ActionQueue.cpp common/utils/common_libolacommon_la-Clock.lo: common/utils/Clock.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/utils/common_libolacommon_la-Clock.lo -MD -MP -MF common/utils/$(DEPDIR)/common_libolacommon_la-Clock.Tpo -c -o common/utils/common_libolacommon_la-Clock.lo `test -f 'common/utils/Clock.cpp' || echo '$(srcdir)/'`common/utils/Clock.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/utils/$(DEPDIR)/common_libolacommon_la-Clock.Tpo common/utils/$(DEPDIR)/common_libolacommon_la-Clock.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/utils/Clock.cpp' object='common/utils/common_libolacommon_la-Clock.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/utils/common_libolacommon_la-Clock.lo `test -f 'common/utils/Clock.cpp' || echo '$(srcdir)/'`common/utils/Clock.cpp common/utils/common_libolacommon_la-DmxBuffer.lo: common/utils/DmxBuffer.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/utils/common_libolacommon_la-DmxBuffer.lo -MD -MP -MF common/utils/$(DEPDIR)/common_libolacommon_la-DmxBuffer.Tpo -c -o common/utils/common_libolacommon_la-DmxBuffer.lo `test -f 'common/utils/DmxBuffer.cpp' || echo '$(srcdir)/'`common/utils/DmxBuffer.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/utils/$(DEPDIR)/common_libolacommon_la-DmxBuffer.Tpo common/utils/$(DEPDIR)/common_libolacommon_la-DmxBuffer.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/utils/DmxBuffer.cpp' object='common/utils/common_libolacommon_la-DmxBuffer.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/utils/common_libolacommon_la-DmxBuffer.lo `test -f 'common/utils/DmxBuffer.cpp' || echo '$(srcdir)/'`common/utils/DmxBuffer.cpp common/utils/common_libolacommon_la-StringUtils.lo: common/utils/StringUtils.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/utils/common_libolacommon_la-StringUtils.lo -MD -MP -MF common/utils/$(DEPDIR)/common_libolacommon_la-StringUtils.Tpo -c -o common/utils/common_libolacommon_la-StringUtils.lo `test -f 'common/utils/StringUtils.cpp' || echo '$(srcdir)/'`common/utils/StringUtils.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/utils/$(DEPDIR)/common_libolacommon_la-StringUtils.Tpo common/utils/$(DEPDIR)/common_libolacommon_la-StringUtils.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/utils/StringUtils.cpp' object='common/utils/common_libolacommon_la-StringUtils.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/utils/common_libolacommon_la-StringUtils.lo `test -f 'common/utils/StringUtils.cpp' || echo '$(srcdir)/'`common/utils/StringUtils.cpp common/utils/common_libolacommon_la-TokenBucket.lo: common/utils/TokenBucket.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/utils/common_libolacommon_la-TokenBucket.lo -MD -MP -MF common/utils/$(DEPDIR)/common_libolacommon_la-TokenBucket.Tpo -c -o common/utils/common_libolacommon_la-TokenBucket.lo `test -f 'common/utils/TokenBucket.cpp' || echo '$(srcdir)/'`common/utils/TokenBucket.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/utils/$(DEPDIR)/common_libolacommon_la-TokenBucket.Tpo common/utils/$(DEPDIR)/common_libolacommon_la-TokenBucket.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/utils/TokenBucket.cpp' object='common/utils/common_libolacommon_la-TokenBucket.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/utils/common_libolacommon_la-TokenBucket.lo `test -f 'common/utils/TokenBucket.cpp' || echo '$(srcdir)/'`common/utils/TokenBucket.cpp common/utils/common_libolacommon_la-Watchdog.lo: common/utils/Watchdog.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/utils/common_libolacommon_la-Watchdog.lo -MD -MP -MF common/utils/$(DEPDIR)/common_libolacommon_la-Watchdog.Tpo -c -o common/utils/common_libolacommon_la-Watchdog.lo `test -f 'common/utils/Watchdog.cpp' || echo '$(srcdir)/'`common/utils/Watchdog.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/utils/$(DEPDIR)/common_libolacommon_la-Watchdog.Tpo common/utils/$(DEPDIR)/common_libolacommon_la-Watchdog.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/utils/Watchdog.cpp' object='common/utils/common_libolacommon_la-Watchdog.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/utils/common_libolacommon_la-Watchdog.lo `test -f 'common/utils/Watchdog.cpp' || echo '$(srcdir)/'`common/utils/Watchdog.cpp common/rdm/common_libolacommon_la-Pids.pb.lo: common/rdm/Pids.pb.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_libolacommon_la-Pids.pb.lo -MD -MP -MF common/rdm/$(DEPDIR)/common_libolacommon_la-Pids.pb.Tpo -c -o common/rdm/common_libolacommon_la-Pids.pb.lo `test -f 'common/rdm/Pids.pb.cc' || echo '$(srcdir)/'`common/rdm/Pids.pb.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_libolacommon_la-Pids.pb.Tpo common/rdm/$(DEPDIR)/common_libolacommon_la-Pids.pb.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/Pids.pb.cc' object='common/rdm/common_libolacommon_la-Pids.pb.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_libolacommon_la-Pids.pb.lo `test -f 'common/rdm/Pids.pb.cc' || echo '$(srcdir)/'`common/rdm/Pids.pb.cc common/rpc/common_libolacommon_la-Rpc.pb.lo: common/rpc/Rpc.pb.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -MT common/rpc/common_libolacommon_la-Rpc.pb.lo -MD -MP -MF common/rpc/$(DEPDIR)/common_libolacommon_la-Rpc.pb.Tpo -c -o common/rpc/common_libolacommon_la-Rpc.pb.lo `test -f 'common/rpc/Rpc.pb.cc' || echo '$(srcdir)/'`common/rpc/Rpc.pb.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rpc/$(DEPDIR)/common_libolacommon_la-Rpc.pb.Tpo common/rpc/$(DEPDIR)/common_libolacommon_la-Rpc.pb.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rpc/Rpc.pb.cc' object='common/rpc/common_libolacommon_la-Rpc.pb.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_libolacommon_la_CXXFLAGS) $(CXXFLAGS) -c -o common/rpc/common_libolacommon_la-Rpc.pb.lo `test -f 'common/rpc/Rpc.pb.cc' || echo '$(srcdir)/'`common/rpc/Rpc.pb.cc common/protocol/common_protocol_libolaproto_la-Ola.pb.lo: common/protocol/Ola.pb.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_protocol_libolaproto_la_CXXFLAGS) $(CXXFLAGS) -MT common/protocol/common_protocol_libolaproto_la-Ola.pb.lo -MD -MP -MF common/protocol/$(DEPDIR)/common_protocol_libolaproto_la-Ola.pb.Tpo -c -o common/protocol/common_protocol_libolaproto_la-Ola.pb.lo `test -f 'common/protocol/Ola.pb.cc' || echo '$(srcdir)/'`common/protocol/Ola.pb.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/protocol/$(DEPDIR)/common_protocol_libolaproto_la-Ola.pb.Tpo common/protocol/$(DEPDIR)/common_protocol_libolaproto_la-Ola.pb.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/protocol/Ola.pb.cc' object='common/protocol/common_protocol_libolaproto_la-Ola.pb.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_protocol_libolaproto_la_CXXFLAGS) $(CXXFLAGS) -c -o common/protocol/common_protocol_libolaproto_la-Ola.pb.lo `test -f 'common/protocol/Ola.pb.cc' || echo '$(srcdir)/'`common/protocol/Ola.pb.cc common/protocol/common_protocol_libolaproto_la-OlaService.pb.lo: common/protocol/OlaService.pb.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_protocol_libolaproto_la_CXXFLAGS) $(CXXFLAGS) -MT common/protocol/common_protocol_libolaproto_la-OlaService.pb.lo -MD -MP -MF common/protocol/$(DEPDIR)/common_protocol_libolaproto_la-OlaService.pb.Tpo -c -o common/protocol/common_protocol_libolaproto_la-OlaService.pb.lo `test -f 'common/protocol/OlaService.pb.cpp' || echo '$(srcdir)/'`common/protocol/OlaService.pb.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/protocol/$(DEPDIR)/common_protocol_libolaproto_la-OlaService.pb.Tpo common/protocol/$(DEPDIR)/common_protocol_libolaproto_la-OlaService.pb.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/protocol/OlaService.pb.cpp' object='common/protocol/common_protocol_libolaproto_la-OlaService.pb.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_protocol_libolaproto_la_CXXFLAGS) $(CXXFLAGS) -c -o common/protocol/common_protocol_libolaproto_la-OlaService.pb.lo `test -f 'common/protocol/OlaService.pb.cpp' || echo '$(srcdir)/'`common/protocol/OlaService.pb.cpp examples/examples_libolaconfig_la-OlaConfigurator.lo: examples/OlaConfigurator.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(examples_libolaconfig_la_CXXFLAGS) $(CXXFLAGS) -MT examples/examples_libolaconfig_la-OlaConfigurator.lo -MD -MP -MF examples/$(DEPDIR)/examples_libolaconfig_la-OlaConfigurator.Tpo -c -o examples/examples_libolaconfig_la-OlaConfigurator.lo `test -f 'examples/OlaConfigurator.cpp' || echo '$(srcdir)/'`examples/OlaConfigurator.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) examples/$(DEPDIR)/examples_libolaconfig_la-OlaConfigurator.Tpo examples/$(DEPDIR)/examples_libolaconfig_la-OlaConfigurator.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='examples/OlaConfigurator.cpp' object='examples/examples_libolaconfig_la-OlaConfigurator.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(examples_libolaconfig_la_CXXFLAGS) $(CXXFLAGS) -c -o examples/examples_libolaconfig_la-OlaConfigurator.lo `test -f 'examples/OlaConfigurator.cpp' || echo '$(srcdir)/'`examples/OlaConfigurator.cpp libs/acn/libs_acn_libolaacn_la-CID.lo: libs/acn/CID.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolaacn_la_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_libolaacn_la-CID.lo -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_libolaacn_la-CID.Tpo -c -o libs/acn/libs_acn_libolaacn_la-CID.lo `test -f 'libs/acn/CID.cpp' || echo '$(srcdir)/'`libs/acn/CID.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_libolaacn_la-CID.Tpo libs/acn/$(DEPDIR)/libs_acn_libolaacn_la-CID.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/CID.cpp' object='libs/acn/libs_acn_libolaacn_la-CID.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolaacn_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_libolaacn_la-CID.lo `test -f 'libs/acn/CID.cpp' || echo '$(srcdir)/'`libs/acn/CID.cpp libs/acn/libs_acn_libolaacn_la-CIDImpl.lo: libs/acn/CIDImpl.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolaacn_la_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_libolaacn_la-CIDImpl.lo -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_libolaacn_la-CIDImpl.Tpo -c -o libs/acn/libs_acn_libolaacn_la-CIDImpl.lo `test -f 'libs/acn/CIDImpl.cpp' || echo '$(srcdir)/'`libs/acn/CIDImpl.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_libolaacn_la-CIDImpl.Tpo libs/acn/$(DEPDIR)/libs_acn_libolaacn_la-CIDImpl.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/CIDImpl.cpp' object='libs/acn/libs_acn_libolaacn_la-CIDImpl.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolaacn_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_libolaacn_la-CIDImpl.lo `test -f 'libs/acn/CIDImpl.cpp' || echo '$(srcdir)/'`libs/acn/CIDImpl.cpp libs/acn/libs_acn_libolae131core_la-BaseInflator.lo: libs/acn/BaseInflator.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_libolae131core_la-BaseInflator.lo -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-BaseInflator.Tpo -c -o libs/acn/libs_acn_libolae131core_la-BaseInflator.lo `test -f 'libs/acn/BaseInflator.cpp' || echo '$(srcdir)/'`libs/acn/BaseInflator.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-BaseInflator.Tpo libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-BaseInflator.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/BaseInflator.cpp' object='libs/acn/libs_acn_libolae131core_la-BaseInflator.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_libolae131core_la-BaseInflator.lo `test -f 'libs/acn/BaseInflator.cpp' || echo '$(srcdir)/'`libs/acn/BaseInflator.cpp libs/acn/libs_acn_libolae131core_la-DMPAddress.lo: libs/acn/DMPAddress.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_libolae131core_la-DMPAddress.lo -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-DMPAddress.Tpo -c -o libs/acn/libs_acn_libolae131core_la-DMPAddress.lo `test -f 'libs/acn/DMPAddress.cpp' || echo '$(srcdir)/'`libs/acn/DMPAddress.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-DMPAddress.Tpo libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-DMPAddress.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/DMPAddress.cpp' object='libs/acn/libs_acn_libolae131core_la-DMPAddress.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_libolae131core_la-DMPAddress.lo `test -f 'libs/acn/DMPAddress.cpp' || echo '$(srcdir)/'`libs/acn/DMPAddress.cpp libs/acn/libs_acn_libolae131core_la-DMPE131Inflator.lo: libs/acn/DMPE131Inflator.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_libolae131core_la-DMPE131Inflator.lo -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-DMPE131Inflator.Tpo -c -o libs/acn/libs_acn_libolae131core_la-DMPE131Inflator.lo `test -f 'libs/acn/DMPE131Inflator.cpp' || echo '$(srcdir)/'`libs/acn/DMPE131Inflator.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-DMPE131Inflator.Tpo libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-DMPE131Inflator.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/DMPE131Inflator.cpp' object='libs/acn/libs_acn_libolae131core_la-DMPE131Inflator.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_libolae131core_la-DMPE131Inflator.lo `test -f 'libs/acn/DMPE131Inflator.cpp' || echo '$(srcdir)/'`libs/acn/DMPE131Inflator.cpp libs/acn/libs_acn_libolae131core_la-DMPInflator.lo: libs/acn/DMPInflator.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_libolae131core_la-DMPInflator.lo -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-DMPInflator.Tpo -c -o libs/acn/libs_acn_libolae131core_la-DMPInflator.lo `test -f 'libs/acn/DMPInflator.cpp' || echo '$(srcdir)/'`libs/acn/DMPInflator.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-DMPInflator.Tpo libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-DMPInflator.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/DMPInflator.cpp' object='libs/acn/libs_acn_libolae131core_la-DMPInflator.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_libolae131core_la-DMPInflator.lo `test -f 'libs/acn/DMPInflator.cpp' || echo '$(srcdir)/'`libs/acn/DMPInflator.cpp libs/acn/libs_acn_libolae131core_la-DMPPDU.lo: libs/acn/DMPPDU.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_libolae131core_la-DMPPDU.lo -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-DMPPDU.Tpo -c -o libs/acn/libs_acn_libolae131core_la-DMPPDU.lo `test -f 'libs/acn/DMPPDU.cpp' || echo '$(srcdir)/'`libs/acn/DMPPDU.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-DMPPDU.Tpo libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-DMPPDU.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/DMPPDU.cpp' object='libs/acn/libs_acn_libolae131core_la-DMPPDU.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_libolae131core_la-DMPPDU.lo `test -f 'libs/acn/DMPPDU.cpp' || echo '$(srcdir)/'`libs/acn/DMPPDU.cpp libs/acn/libs_acn_libolae131core_la-E131DiscoveryInflator.lo: libs/acn/E131DiscoveryInflator.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_libolae131core_la-E131DiscoveryInflator.lo -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E131DiscoveryInflator.Tpo -c -o libs/acn/libs_acn_libolae131core_la-E131DiscoveryInflator.lo `test -f 'libs/acn/E131DiscoveryInflator.cpp' || echo '$(srcdir)/'`libs/acn/E131DiscoveryInflator.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E131DiscoveryInflator.Tpo libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E131DiscoveryInflator.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/E131DiscoveryInflator.cpp' object='libs/acn/libs_acn_libolae131core_la-E131DiscoveryInflator.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_libolae131core_la-E131DiscoveryInflator.lo `test -f 'libs/acn/E131DiscoveryInflator.cpp' || echo '$(srcdir)/'`libs/acn/E131DiscoveryInflator.cpp libs/acn/libs_acn_libolae131core_la-E131Inflator.lo: libs/acn/E131Inflator.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_libolae131core_la-E131Inflator.lo -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E131Inflator.Tpo -c -o libs/acn/libs_acn_libolae131core_la-E131Inflator.lo `test -f 'libs/acn/E131Inflator.cpp' || echo '$(srcdir)/'`libs/acn/E131Inflator.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E131Inflator.Tpo libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E131Inflator.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/E131Inflator.cpp' object='libs/acn/libs_acn_libolae131core_la-E131Inflator.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_libolae131core_la-E131Inflator.lo `test -f 'libs/acn/E131Inflator.cpp' || echo '$(srcdir)/'`libs/acn/E131Inflator.cpp libs/acn/libs_acn_libolae131core_la-E131Node.lo: libs/acn/E131Node.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_libolae131core_la-E131Node.lo -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E131Node.Tpo -c -o libs/acn/libs_acn_libolae131core_la-E131Node.lo `test -f 'libs/acn/E131Node.cpp' || echo '$(srcdir)/'`libs/acn/E131Node.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E131Node.Tpo libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E131Node.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/E131Node.cpp' object='libs/acn/libs_acn_libolae131core_la-E131Node.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_libolae131core_la-E131Node.lo `test -f 'libs/acn/E131Node.cpp' || echo '$(srcdir)/'`libs/acn/E131Node.cpp libs/acn/libs_acn_libolae131core_la-E131PDU.lo: libs/acn/E131PDU.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_libolae131core_la-E131PDU.lo -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E131PDU.Tpo -c -o libs/acn/libs_acn_libolae131core_la-E131PDU.lo `test -f 'libs/acn/E131PDU.cpp' || echo '$(srcdir)/'`libs/acn/E131PDU.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E131PDU.Tpo libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E131PDU.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/E131PDU.cpp' object='libs/acn/libs_acn_libolae131core_la-E131PDU.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_libolae131core_la-E131PDU.lo `test -f 'libs/acn/E131PDU.cpp' || echo '$(srcdir)/'`libs/acn/E131PDU.cpp libs/acn/libs_acn_libolae131core_la-E131Sender.lo: libs/acn/E131Sender.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_libolae131core_la-E131Sender.lo -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E131Sender.Tpo -c -o libs/acn/libs_acn_libolae131core_la-E131Sender.lo `test -f 'libs/acn/E131Sender.cpp' || echo '$(srcdir)/'`libs/acn/E131Sender.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E131Sender.Tpo libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E131Sender.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/E131Sender.cpp' object='libs/acn/libs_acn_libolae131core_la-E131Sender.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_libolae131core_la-E131Sender.lo `test -f 'libs/acn/E131Sender.cpp' || echo '$(srcdir)/'`libs/acn/E131Sender.cpp libs/acn/libs_acn_libolae131core_la-E133Inflator.lo: libs/acn/E133Inflator.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_libolae131core_la-E133Inflator.lo -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E133Inflator.Tpo -c -o libs/acn/libs_acn_libolae131core_la-E133Inflator.lo `test -f 'libs/acn/E133Inflator.cpp' || echo '$(srcdir)/'`libs/acn/E133Inflator.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E133Inflator.Tpo libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E133Inflator.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/E133Inflator.cpp' object='libs/acn/libs_acn_libolae131core_la-E133Inflator.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_libolae131core_la-E133Inflator.lo `test -f 'libs/acn/E133Inflator.cpp' || echo '$(srcdir)/'`libs/acn/E133Inflator.cpp libs/acn/libs_acn_libolae131core_la-E133PDU.lo: libs/acn/E133PDU.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_libolae131core_la-E133PDU.lo -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E133PDU.Tpo -c -o libs/acn/libs_acn_libolae131core_la-E133PDU.lo `test -f 'libs/acn/E133PDU.cpp' || echo '$(srcdir)/'`libs/acn/E133PDU.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E133PDU.Tpo libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E133PDU.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/E133PDU.cpp' object='libs/acn/libs_acn_libolae131core_la-E133PDU.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_libolae131core_la-E133PDU.lo `test -f 'libs/acn/E133PDU.cpp' || echo '$(srcdir)/'`libs/acn/E133PDU.cpp libs/acn/libs_acn_libolae131core_la-E133StatusInflator.lo: libs/acn/E133StatusInflator.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_libolae131core_la-E133StatusInflator.lo -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E133StatusInflator.Tpo -c -o libs/acn/libs_acn_libolae131core_la-E133StatusInflator.lo `test -f 'libs/acn/E133StatusInflator.cpp' || echo '$(srcdir)/'`libs/acn/E133StatusInflator.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E133StatusInflator.Tpo libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E133StatusInflator.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/E133StatusInflator.cpp' object='libs/acn/libs_acn_libolae131core_la-E133StatusInflator.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_libolae131core_la-E133StatusInflator.lo `test -f 'libs/acn/E133StatusInflator.cpp' || echo '$(srcdir)/'`libs/acn/E133StatusInflator.cpp libs/acn/libs_acn_libolae131core_la-E133StatusPDU.lo: libs/acn/E133StatusPDU.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_libolae131core_la-E133StatusPDU.lo -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E133StatusPDU.Tpo -c -o libs/acn/libs_acn_libolae131core_la-E133StatusPDU.lo `test -f 'libs/acn/E133StatusPDU.cpp' || echo '$(srcdir)/'`libs/acn/E133StatusPDU.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E133StatusPDU.Tpo libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-E133StatusPDU.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/E133StatusPDU.cpp' object='libs/acn/libs_acn_libolae131core_la-E133StatusPDU.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_libolae131core_la-E133StatusPDU.lo `test -f 'libs/acn/E133StatusPDU.cpp' || echo '$(srcdir)/'`libs/acn/E133StatusPDU.cpp libs/acn/libs_acn_libolae131core_la-PDU.lo: libs/acn/PDU.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_libolae131core_la-PDU.lo -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-PDU.Tpo -c -o libs/acn/libs_acn_libolae131core_la-PDU.lo `test -f 'libs/acn/PDU.cpp' || echo '$(srcdir)/'`libs/acn/PDU.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-PDU.Tpo libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-PDU.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/PDU.cpp' object='libs/acn/libs_acn_libolae131core_la-PDU.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_libolae131core_la-PDU.lo `test -f 'libs/acn/PDU.cpp' || echo '$(srcdir)/'`libs/acn/PDU.cpp libs/acn/libs_acn_libolae131core_la-PreamblePacker.lo: libs/acn/PreamblePacker.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_libolae131core_la-PreamblePacker.lo -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-PreamblePacker.Tpo -c -o libs/acn/libs_acn_libolae131core_la-PreamblePacker.lo `test -f 'libs/acn/PreamblePacker.cpp' || echo '$(srcdir)/'`libs/acn/PreamblePacker.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-PreamblePacker.Tpo libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-PreamblePacker.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/PreamblePacker.cpp' object='libs/acn/libs_acn_libolae131core_la-PreamblePacker.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_libolae131core_la-PreamblePacker.lo `test -f 'libs/acn/PreamblePacker.cpp' || echo '$(srcdir)/'`libs/acn/PreamblePacker.cpp libs/acn/libs_acn_libolae131core_la-RDMInflator.lo: libs/acn/RDMInflator.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_libolae131core_la-RDMInflator.lo -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-RDMInflator.Tpo -c -o libs/acn/libs_acn_libolae131core_la-RDMInflator.lo `test -f 'libs/acn/RDMInflator.cpp' || echo '$(srcdir)/'`libs/acn/RDMInflator.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-RDMInflator.Tpo libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-RDMInflator.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/RDMInflator.cpp' object='libs/acn/libs_acn_libolae131core_la-RDMInflator.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_libolae131core_la-RDMInflator.lo `test -f 'libs/acn/RDMInflator.cpp' || echo '$(srcdir)/'`libs/acn/RDMInflator.cpp libs/acn/libs_acn_libolae131core_la-RDMPDU.lo: libs/acn/RDMPDU.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_libolae131core_la-RDMPDU.lo -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-RDMPDU.Tpo -c -o libs/acn/libs_acn_libolae131core_la-RDMPDU.lo `test -f 'libs/acn/RDMPDU.cpp' || echo '$(srcdir)/'`libs/acn/RDMPDU.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-RDMPDU.Tpo libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-RDMPDU.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/RDMPDU.cpp' object='libs/acn/libs_acn_libolae131core_la-RDMPDU.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_libolae131core_la-RDMPDU.lo `test -f 'libs/acn/RDMPDU.cpp' || echo '$(srcdir)/'`libs/acn/RDMPDU.cpp libs/acn/libs_acn_libolae131core_la-RootInflator.lo: libs/acn/RootInflator.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_libolae131core_la-RootInflator.lo -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-RootInflator.Tpo -c -o libs/acn/libs_acn_libolae131core_la-RootInflator.lo `test -f 'libs/acn/RootInflator.cpp' || echo '$(srcdir)/'`libs/acn/RootInflator.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-RootInflator.Tpo libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-RootInflator.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/RootInflator.cpp' object='libs/acn/libs_acn_libolae131core_la-RootInflator.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_libolae131core_la-RootInflator.lo `test -f 'libs/acn/RootInflator.cpp' || echo '$(srcdir)/'`libs/acn/RootInflator.cpp libs/acn/libs_acn_libolae131core_la-RootPDU.lo: libs/acn/RootPDU.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_libolae131core_la-RootPDU.lo -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-RootPDU.Tpo -c -o libs/acn/libs_acn_libolae131core_la-RootPDU.lo `test -f 'libs/acn/RootPDU.cpp' || echo '$(srcdir)/'`libs/acn/RootPDU.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-RootPDU.Tpo libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-RootPDU.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/RootPDU.cpp' object='libs/acn/libs_acn_libolae131core_la-RootPDU.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_libolae131core_la-RootPDU.lo `test -f 'libs/acn/RootPDU.cpp' || echo '$(srcdir)/'`libs/acn/RootPDU.cpp libs/acn/libs_acn_libolae131core_la-RootSender.lo: libs/acn/RootSender.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_libolae131core_la-RootSender.lo -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-RootSender.Tpo -c -o libs/acn/libs_acn_libolae131core_la-RootSender.lo `test -f 'libs/acn/RootSender.cpp' || echo '$(srcdir)/'`libs/acn/RootSender.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-RootSender.Tpo libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-RootSender.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/RootSender.cpp' object='libs/acn/libs_acn_libolae131core_la-RootSender.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_libolae131core_la-RootSender.lo `test -f 'libs/acn/RootSender.cpp' || echo '$(srcdir)/'`libs/acn/RootSender.cpp libs/acn/libs_acn_libolae131core_la-TCPTransport.lo: libs/acn/TCPTransport.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_libolae131core_la-TCPTransport.lo -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-TCPTransport.Tpo -c -o libs/acn/libs_acn_libolae131core_la-TCPTransport.lo `test -f 'libs/acn/TCPTransport.cpp' || echo '$(srcdir)/'`libs/acn/TCPTransport.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-TCPTransport.Tpo libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-TCPTransport.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/TCPTransport.cpp' object='libs/acn/libs_acn_libolae131core_la-TCPTransport.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_libolae131core_la-TCPTransport.lo `test -f 'libs/acn/TCPTransport.cpp' || echo '$(srcdir)/'`libs/acn/TCPTransport.cpp libs/acn/libs_acn_libolae131core_la-UDPTransport.lo: libs/acn/UDPTransport.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_libolae131core_la-UDPTransport.lo -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-UDPTransport.Tpo -c -o libs/acn/libs_acn_libolae131core_la-UDPTransport.lo `test -f 'libs/acn/UDPTransport.cpp' || echo '$(srcdir)/'`libs/acn/UDPTransport.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-UDPTransport.Tpo libs/acn/$(DEPDIR)/libs_acn_libolae131core_la-UDPTransport.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/UDPTransport.cpp' object='libs/acn/libs_acn_libolae131core_la-UDPTransport.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_acn_libolae131core_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_libolae131core_la-UDPTransport.lo `test -f 'libs/acn/UDPTransport.cpp' || echo '$(srcdir)/'`libs/acn/UDPTransport.cpp libs/usb/libs_usb_libolausb_la-HotplugAgent.lo: libs/usb/HotplugAgent.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_usb_libolausb_la_CXXFLAGS) $(CXXFLAGS) -MT libs/usb/libs_usb_libolausb_la-HotplugAgent.lo -MD -MP -MF libs/usb/$(DEPDIR)/libs_usb_libolausb_la-HotplugAgent.Tpo -c -o libs/usb/libs_usb_libolausb_la-HotplugAgent.lo `test -f 'libs/usb/HotplugAgent.cpp' || echo '$(srcdir)/'`libs/usb/HotplugAgent.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/usb/$(DEPDIR)/libs_usb_libolausb_la-HotplugAgent.Tpo libs/usb/$(DEPDIR)/libs_usb_libolausb_la-HotplugAgent.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/usb/HotplugAgent.cpp' object='libs/usb/libs_usb_libolausb_la-HotplugAgent.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_usb_libolausb_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/usb/libs_usb_libolausb_la-HotplugAgent.lo `test -f 'libs/usb/HotplugAgent.cpp' || echo '$(srcdir)/'`libs/usb/HotplugAgent.cpp libs/usb/libs_usb_libolausb_la-JaRuleConstants.lo: libs/usb/JaRuleConstants.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_usb_libolausb_la_CXXFLAGS) $(CXXFLAGS) -MT libs/usb/libs_usb_libolausb_la-JaRuleConstants.lo -MD -MP -MF libs/usb/$(DEPDIR)/libs_usb_libolausb_la-JaRuleConstants.Tpo -c -o libs/usb/libs_usb_libolausb_la-JaRuleConstants.lo `test -f 'libs/usb/JaRuleConstants.cpp' || echo '$(srcdir)/'`libs/usb/JaRuleConstants.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/usb/$(DEPDIR)/libs_usb_libolausb_la-JaRuleConstants.Tpo libs/usb/$(DEPDIR)/libs_usb_libolausb_la-JaRuleConstants.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/usb/JaRuleConstants.cpp' object='libs/usb/libs_usb_libolausb_la-JaRuleConstants.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_usb_libolausb_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/usb/libs_usb_libolausb_la-JaRuleConstants.lo `test -f 'libs/usb/JaRuleConstants.cpp' || echo '$(srcdir)/'`libs/usb/JaRuleConstants.cpp libs/usb/libs_usb_libolausb_la-JaRulePortHandle.lo: libs/usb/JaRulePortHandle.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_usb_libolausb_la_CXXFLAGS) $(CXXFLAGS) -MT libs/usb/libs_usb_libolausb_la-JaRulePortHandle.lo -MD -MP -MF libs/usb/$(DEPDIR)/libs_usb_libolausb_la-JaRulePortHandle.Tpo -c -o libs/usb/libs_usb_libolausb_la-JaRulePortHandle.lo `test -f 'libs/usb/JaRulePortHandle.cpp' || echo '$(srcdir)/'`libs/usb/JaRulePortHandle.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/usb/$(DEPDIR)/libs_usb_libolausb_la-JaRulePortHandle.Tpo libs/usb/$(DEPDIR)/libs_usb_libolausb_la-JaRulePortHandle.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/usb/JaRulePortHandle.cpp' object='libs/usb/libs_usb_libolausb_la-JaRulePortHandle.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_usb_libolausb_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/usb/libs_usb_libolausb_la-JaRulePortHandle.lo `test -f 'libs/usb/JaRulePortHandle.cpp' || echo '$(srcdir)/'`libs/usb/JaRulePortHandle.cpp libs/usb/libs_usb_libolausb_la-JaRulePortHandleImpl.lo: libs/usb/JaRulePortHandleImpl.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_usb_libolausb_la_CXXFLAGS) $(CXXFLAGS) -MT libs/usb/libs_usb_libolausb_la-JaRulePortHandleImpl.lo -MD -MP -MF libs/usb/$(DEPDIR)/libs_usb_libolausb_la-JaRulePortHandleImpl.Tpo -c -o libs/usb/libs_usb_libolausb_la-JaRulePortHandleImpl.lo `test -f 'libs/usb/JaRulePortHandleImpl.cpp' || echo '$(srcdir)/'`libs/usb/JaRulePortHandleImpl.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/usb/$(DEPDIR)/libs_usb_libolausb_la-JaRulePortHandleImpl.Tpo libs/usb/$(DEPDIR)/libs_usb_libolausb_la-JaRulePortHandleImpl.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/usb/JaRulePortHandleImpl.cpp' object='libs/usb/libs_usb_libolausb_la-JaRulePortHandleImpl.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_usb_libolausb_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/usb/libs_usb_libolausb_la-JaRulePortHandleImpl.lo `test -f 'libs/usb/JaRulePortHandleImpl.cpp' || echo '$(srcdir)/'`libs/usb/JaRulePortHandleImpl.cpp libs/usb/libs_usb_libolausb_la-JaRuleWidget.lo: libs/usb/JaRuleWidget.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_usb_libolausb_la_CXXFLAGS) $(CXXFLAGS) -MT libs/usb/libs_usb_libolausb_la-JaRuleWidget.lo -MD -MP -MF libs/usb/$(DEPDIR)/libs_usb_libolausb_la-JaRuleWidget.Tpo -c -o libs/usb/libs_usb_libolausb_la-JaRuleWidget.lo `test -f 'libs/usb/JaRuleWidget.cpp' || echo '$(srcdir)/'`libs/usb/JaRuleWidget.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/usb/$(DEPDIR)/libs_usb_libolausb_la-JaRuleWidget.Tpo libs/usb/$(DEPDIR)/libs_usb_libolausb_la-JaRuleWidget.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/usb/JaRuleWidget.cpp' object='libs/usb/libs_usb_libolausb_la-JaRuleWidget.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_usb_libolausb_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/usb/libs_usb_libolausb_la-JaRuleWidget.lo `test -f 'libs/usb/JaRuleWidget.cpp' || echo '$(srcdir)/'`libs/usb/JaRuleWidget.cpp libs/usb/libs_usb_libolausb_la-JaRuleWidgetPort.lo: libs/usb/JaRuleWidgetPort.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_usb_libolausb_la_CXXFLAGS) $(CXXFLAGS) -MT libs/usb/libs_usb_libolausb_la-JaRuleWidgetPort.lo -MD -MP -MF libs/usb/$(DEPDIR)/libs_usb_libolausb_la-JaRuleWidgetPort.Tpo -c -o libs/usb/libs_usb_libolausb_la-JaRuleWidgetPort.lo `test -f 'libs/usb/JaRuleWidgetPort.cpp' || echo '$(srcdir)/'`libs/usb/JaRuleWidgetPort.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/usb/$(DEPDIR)/libs_usb_libolausb_la-JaRuleWidgetPort.Tpo libs/usb/$(DEPDIR)/libs_usb_libolausb_la-JaRuleWidgetPort.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/usb/JaRuleWidgetPort.cpp' object='libs/usb/libs_usb_libolausb_la-JaRuleWidgetPort.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_usb_libolausb_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/usb/libs_usb_libolausb_la-JaRuleWidgetPort.lo `test -f 'libs/usb/JaRuleWidgetPort.cpp' || echo '$(srcdir)/'`libs/usb/JaRuleWidgetPort.cpp libs/usb/libs_usb_libolausb_la-LibUsbAdaptor.lo: libs/usb/LibUsbAdaptor.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_usb_libolausb_la_CXXFLAGS) $(CXXFLAGS) -MT libs/usb/libs_usb_libolausb_la-LibUsbAdaptor.lo -MD -MP -MF libs/usb/$(DEPDIR)/libs_usb_libolausb_la-LibUsbAdaptor.Tpo -c -o libs/usb/libs_usb_libolausb_la-LibUsbAdaptor.lo `test -f 'libs/usb/LibUsbAdaptor.cpp' || echo '$(srcdir)/'`libs/usb/LibUsbAdaptor.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/usb/$(DEPDIR)/libs_usb_libolausb_la-LibUsbAdaptor.Tpo libs/usb/$(DEPDIR)/libs_usb_libolausb_la-LibUsbAdaptor.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/usb/LibUsbAdaptor.cpp' object='libs/usb/libs_usb_libolausb_la-LibUsbAdaptor.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_usb_libolausb_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/usb/libs_usb_libolausb_la-LibUsbAdaptor.lo `test -f 'libs/usb/LibUsbAdaptor.cpp' || echo '$(srcdir)/'`libs/usb/LibUsbAdaptor.cpp libs/usb/libs_usb_libolausb_la-LibUsbThread.lo: libs/usb/LibUsbThread.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_usb_libolausb_la_CXXFLAGS) $(CXXFLAGS) -MT libs/usb/libs_usb_libolausb_la-LibUsbThread.lo -MD -MP -MF libs/usb/$(DEPDIR)/libs_usb_libolausb_la-LibUsbThread.Tpo -c -o libs/usb/libs_usb_libolausb_la-LibUsbThread.lo `test -f 'libs/usb/LibUsbThread.cpp' || echo '$(srcdir)/'`libs/usb/LibUsbThread.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/usb/$(DEPDIR)/libs_usb_libolausb_la-LibUsbThread.Tpo libs/usb/$(DEPDIR)/libs_usb_libolausb_la-LibUsbThread.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/usb/LibUsbThread.cpp' object='libs/usb/libs_usb_libolausb_la-LibUsbThread.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_usb_libolausb_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/usb/libs_usb_libolausb_la-LibUsbThread.lo `test -f 'libs/usb/LibUsbThread.cpp' || echo '$(srcdir)/'`libs/usb/LibUsbThread.cpp libs/usb/libs_usb_libolausb_la-Types.lo: libs/usb/Types.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_usb_libolausb_la_CXXFLAGS) $(CXXFLAGS) -MT libs/usb/libs_usb_libolausb_la-Types.lo -MD -MP -MF libs/usb/$(DEPDIR)/libs_usb_libolausb_la-Types.Tpo -c -o libs/usb/libs_usb_libolausb_la-Types.lo `test -f 'libs/usb/Types.cpp' || echo '$(srcdir)/'`libs/usb/Types.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/usb/$(DEPDIR)/libs_usb_libolausb_la-Types.Tpo libs/usb/$(DEPDIR)/libs_usb_libolausb_la-Types.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/usb/Types.cpp' object='libs/usb/libs_usb_libolausb_la-Types.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_usb_libolausb_la_CXXFLAGS) $(CXXFLAGS) -c -o libs/usb/libs_usb_libolausb_la-Types.lo `test -f 'libs/usb/Types.cpp' || echo '$(srcdir)/'`libs/usb/Types.cpp ola/ola_libola_la-AutoStart.lo: ola/AutoStart.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ola_libola_la_CXXFLAGS) $(CXXFLAGS) -MT ola/ola_libola_la-AutoStart.lo -MD -MP -MF ola/$(DEPDIR)/ola_libola_la-AutoStart.Tpo -c -o ola/ola_libola_la-AutoStart.lo `test -f 'ola/AutoStart.cpp' || echo '$(srcdir)/'`ola/AutoStart.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ola/$(DEPDIR)/ola_libola_la-AutoStart.Tpo ola/$(DEPDIR)/ola_libola_la-AutoStart.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ola/AutoStart.cpp' object='ola/ola_libola_la-AutoStart.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ola_libola_la_CXXFLAGS) $(CXXFLAGS) -c -o ola/ola_libola_la-AutoStart.lo `test -f 'ola/AutoStart.cpp' || echo '$(srcdir)/'`ola/AutoStart.cpp ola/ola_libola_la-ClientRDMAPIShim.lo: ola/ClientRDMAPIShim.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ola_libola_la_CXXFLAGS) $(CXXFLAGS) -MT ola/ola_libola_la-ClientRDMAPIShim.lo -MD -MP -MF ola/$(DEPDIR)/ola_libola_la-ClientRDMAPIShim.Tpo -c -o ola/ola_libola_la-ClientRDMAPIShim.lo `test -f 'ola/ClientRDMAPIShim.cpp' || echo '$(srcdir)/'`ola/ClientRDMAPIShim.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ola/$(DEPDIR)/ola_libola_la-ClientRDMAPIShim.Tpo ola/$(DEPDIR)/ola_libola_la-ClientRDMAPIShim.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ola/ClientRDMAPIShim.cpp' object='ola/ola_libola_la-ClientRDMAPIShim.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ola_libola_la_CXXFLAGS) $(CXXFLAGS) -c -o ola/ola_libola_la-ClientRDMAPIShim.lo `test -f 'ola/ClientRDMAPIShim.cpp' || echo '$(srcdir)/'`ola/ClientRDMAPIShim.cpp ola/ola_libola_la-ClientTypesFactory.lo: ola/ClientTypesFactory.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ola_libola_la_CXXFLAGS) $(CXXFLAGS) -MT ola/ola_libola_la-ClientTypesFactory.lo -MD -MP -MF ola/$(DEPDIR)/ola_libola_la-ClientTypesFactory.Tpo -c -o ola/ola_libola_la-ClientTypesFactory.lo `test -f 'ola/ClientTypesFactory.cpp' || echo '$(srcdir)/'`ola/ClientTypesFactory.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ola/$(DEPDIR)/ola_libola_la-ClientTypesFactory.Tpo ola/$(DEPDIR)/ola_libola_la-ClientTypesFactory.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ola/ClientTypesFactory.cpp' object='ola/ola_libola_la-ClientTypesFactory.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ola_libola_la_CXXFLAGS) $(CXXFLAGS) -c -o ola/ola_libola_la-ClientTypesFactory.lo `test -f 'ola/ClientTypesFactory.cpp' || echo '$(srcdir)/'`ola/ClientTypesFactory.cpp ola/ola_libola_la-Module.lo: ola/Module.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ola_libola_la_CXXFLAGS) $(CXXFLAGS) -MT ola/ola_libola_la-Module.lo -MD -MP -MF ola/$(DEPDIR)/ola_libola_la-Module.Tpo -c -o ola/ola_libola_la-Module.lo `test -f 'ola/Module.cpp' || echo '$(srcdir)/'`ola/Module.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ola/$(DEPDIR)/ola_libola_la-Module.Tpo ola/$(DEPDIR)/ola_libola_la-Module.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ola/Module.cpp' object='ola/ola_libola_la-Module.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ola_libola_la_CXXFLAGS) $(CXXFLAGS) -c -o ola/ola_libola_la-Module.lo `test -f 'ola/Module.cpp' || echo '$(srcdir)/'`ola/Module.cpp ola/ola_libola_la-OlaCallbackClient.lo: ola/OlaCallbackClient.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ola_libola_la_CXXFLAGS) $(CXXFLAGS) -MT ola/ola_libola_la-OlaCallbackClient.lo -MD -MP -MF ola/$(DEPDIR)/ola_libola_la-OlaCallbackClient.Tpo -c -o ola/ola_libola_la-OlaCallbackClient.lo `test -f 'ola/OlaCallbackClient.cpp' || echo '$(srcdir)/'`ola/OlaCallbackClient.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ola/$(DEPDIR)/ola_libola_la-OlaCallbackClient.Tpo ola/$(DEPDIR)/ola_libola_la-OlaCallbackClient.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ola/OlaCallbackClient.cpp' object='ola/ola_libola_la-OlaCallbackClient.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ola_libola_la_CXXFLAGS) $(CXXFLAGS) -c -o ola/ola_libola_la-OlaCallbackClient.lo `test -f 'ola/OlaCallbackClient.cpp' || echo '$(srcdir)/'`ola/OlaCallbackClient.cpp ola/ola_libola_la-OlaClient.lo: ola/OlaClient.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ola_libola_la_CXXFLAGS) $(CXXFLAGS) -MT ola/ola_libola_la-OlaClient.lo -MD -MP -MF ola/$(DEPDIR)/ola_libola_la-OlaClient.Tpo -c -o ola/ola_libola_la-OlaClient.lo `test -f 'ola/OlaClient.cpp' || echo '$(srcdir)/'`ola/OlaClient.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ola/$(DEPDIR)/ola_libola_la-OlaClient.Tpo ola/$(DEPDIR)/ola_libola_la-OlaClient.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ola/OlaClient.cpp' object='ola/ola_libola_la-OlaClient.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ola_libola_la_CXXFLAGS) $(CXXFLAGS) -c -o ola/ola_libola_la-OlaClient.lo `test -f 'ola/OlaClient.cpp' || echo '$(srcdir)/'`ola/OlaClient.cpp ola/ola_libola_la-OlaClientCore.lo: ola/OlaClientCore.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ola_libola_la_CXXFLAGS) $(CXXFLAGS) -MT ola/ola_libola_la-OlaClientCore.lo -MD -MP -MF ola/$(DEPDIR)/ola_libola_la-OlaClientCore.Tpo -c -o ola/ola_libola_la-OlaClientCore.lo `test -f 'ola/OlaClientCore.cpp' || echo '$(srcdir)/'`ola/OlaClientCore.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ola/$(DEPDIR)/ola_libola_la-OlaClientCore.Tpo ola/$(DEPDIR)/ola_libola_la-OlaClientCore.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ola/OlaClientCore.cpp' object='ola/ola_libola_la-OlaClientCore.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ola_libola_la_CXXFLAGS) $(CXXFLAGS) -c -o ola/ola_libola_la-OlaClientCore.lo `test -f 'ola/OlaClientCore.cpp' || echo '$(srcdir)/'`ola/OlaClientCore.cpp ola/ola_libola_la-OlaClientWrapper.lo: ola/OlaClientWrapper.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ola_libola_la_CXXFLAGS) $(CXXFLAGS) -MT ola/ola_libola_la-OlaClientWrapper.lo -MD -MP -MF ola/$(DEPDIR)/ola_libola_la-OlaClientWrapper.Tpo -c -o ola/ola_libola_la-OlaClientWrapper.lo `test -f 'ola/OlaClientWrapper.cpp' || echo '$(srcdir)/'`ola/OlaClientWrapper.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ola/$(DEPDIR)/ola_libola_la-OlaClientWrapper.Tpo ola/$(DEPDIR)/ola_libola_la-OlaClientWrapper.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ola/OlaClientWrapper.cpp' object='ola/ola_libola_la-OlaClientWrapper.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ola_libola_la_CXXFLAGS) $(CXXFLAGS) -c -o ola/ola_libola_la-OlaClientWrapper.lo `test -f 'ola/OlaClientWrapper.cpp' || echo '$(srcdir)/'`ola/OlaClientWrapper.cpp ola/ola_libola_la-StreamingClient.lo: ola/StreamingClient.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ola_libola_la_CXXFLAGS) $(CXXFLAGS) -MT ola/ola_libola_la-StreamingClient.lo -MD -MP -MF ola/$(DEPDIR)/ola_libola_la-StreamingClient.Tpo -c -o ola/ola_libola_la-StreamingClient.lo `test -f 'ola/StreamingClient.cpp' || echo '$(srcdir)/'`ola/StreamingClient.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ola/$(DEPDIR)/ola_libola_la-StreamingClient.Tpo ola/$(DEPDIR)/ola_libola_la-StreamingClient.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ola/StreamingClient.cpp' object='ola/ola_libola_la-StreamingClient.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ola_libola_la_CXXFLAGS) $(CXXFLAGS) -c -o ola/ola_libola_la-StreamingClient.lo `test -f 'ola/StreamingClient.cpp' || echo '$(srcdir)/'`ola/StreamingClient.cpp olad/olad_libolaserver_la-ClientBroker.lo: olad/ClientBroker.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_libolaserver_la_CXXFLAGS) $(CXXFLAGS) -MT olad/olad_libolaserver_la-ClientBroker.lo -MD -MP -MF olad/$(DEPDIR)/olad_libolaserver_la-ClientBroker.Tpo -c -o olad/olad_libolaserver_la-ClientBroker.lo `test -f 'olad/ClientBroker.cpp' || echo '$(srcdir)/'`olad/ClientBroker.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/$(DEPDIR)/olad_libolaserver_la-ClientBroker.Tpo olad/$(DEPDIR)/olad_libolaserver_la-ClientBroker.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/ClientBroker.cpp' object='olad/olad_libolaserver_la-ClientBroker.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_libolaserver_la_CXXFLAGS) $(CXXFLAGS) -c -o olad/olad_libolaserver_la-ClientBroker.lo `test -f 'olad/ClientBroker.cpp' || echo '$(srcdir)/'`olad/ClientBroker.cpp olad/olad_libolaserver_la-DiscoveryAgent.lo: olad/DiscoveryAgent.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_libolaserver_la_CXXFLAGS) $(CXXFLAGS) -MT olad/olad_libolaserver_la-DiscoveryAgent.lo -MD -MP -MF olad/$(DEPDIR)/olad_libolaserver_la-DiscoveryAgent.Tpo -c -o olad/olad_libolaserver_la-DiscoveryAgent.lo `test -f 'olad/DiscoveryAgent.cpp' || echo '$(srcdir)/'`olad/DiscoveryAgent.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/$(DEPDIR)/olad_libolaserver_la-DiscoveryAgent.Tpo olad/$(DEPDIR)/olad_libolaserver_la-DiscoveryAgent.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/DiscoveryAgent.cpp' object='olad/olad_libolaserver_la-DiscoveryAgent.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_libolaserver_la_CXXFLAGS) $(CXXFLAGS) -c -o olad/olad_libolaserver_la-DiscoveryAgent.lo `test -f 'olad/DiscoveryAgent.cpp' || echo '$(srcdir)/'`olad/DiscoveryAgent.cpp olad/olad_libolaserver_la-DynamicPluginLoader.lo: olad/DynamicPluginLoader.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_libolaserver_la_CXXFLAGS) $(CXXFLAGS) -MT olad/olad_libolaserver_la-DynamicPluginLoader.lo -MD -MP -MF olad/$(DEPDIR)/olad_libolaserver_la-DynamicPluginLoader.Tpo -c -o olad/olad_libolaserver_la-DynamicPluginLoader.lo `test -f 'olad/DynamicPluginLoader.cpp' || echo '$(srcdir)/'`olad/DynamicPluginLoader.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/$(DEPDIR)/olad_libolaserver_la-DynamicPluginLoader.Tpo olad/$(DEPDIR)/olad_libolaserver_la-DynamicPluginLoader.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/DynamicPluginLoader.cpp' object='olad/olad_libolaserver_la-DynamicPluginLoader.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_libolaserver_la_CXXFLAGS) $(CXXFLAGS) -c -o olad/olad_libolaserver_la-DynamicPluginLoader.lo `test -f 'olad/DynamicPluginLoader.cpp' || echo '$(srcdir)/'`olad/DynamicPluginLoader.cpp olad/olad_libolaserver_la-OlaServerServiceImpl.lo: olad/OlaServerServiceImpl.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_libolaserver_la_CXXFLAGS) $(CXXFLAGS) -MT olad/olad_libolaserver_la-OlaServerServiceImpl.lo -MD -MP -MF olad/$(DEPDIR)/olad_libolaserver_la-OlaServerServiceImpl.Tpo -c -o olad/olad_libolaserver_la-OlaServerServiceImpl.lo `test -f 'olad/OlaServerServiceImpl.cpp' || echo '$(srcdir)/'`olad/OlaServerServiceImpl.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/$(DEPDIR)/olad_libolaserver_la-OlaServerServiceImpl.Tpo olad/$(DEPDIR)/olad_libolaserver_la-OlaServerServiceImpl.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/OlaServerServiceImpl.cpp' object='olad/olad_libolaserver_la-OlaServerServiceImpl.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_libolaserver_la_CXXFLAGS) $(CXXFLAGS) -c -o olad/olad_libolaserver_la-OlaServerServiceImpl.lo `test -f 'olad/OlaServerServiceImpl.cpp' || echo '$(srcdir)/'`olad/OlaServerServiceImpl.cpp olad/olad_libolaserver_la-PluginManager.lo: olad/PluginManager.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_libolaserver_la_CXXFLAGS) $(CXXFLAGS) -MT olad/olad_libolaserver_la-PluginManager.lo -MD -MP -MF olad/$(DEPDIR)/olad_libolaserver_la-PluginManager.Tpo -c -o olad/olad_libolaserver_la-PluginManager.lo `test -f 'olad/PluginManager.cpp' || echo '$(srcdir)/'`olad/PluginManager.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/$(DEPDIR)/olad_libolaserver_la-PluginManager.Tpo olad/$(DEPDIR)/olad_libolaserver_la-PluginManager.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/PluginManager.cpp' object='olad/olad_libolaserver_la-PluginManager.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_libolaserver_la_CXXFLAGS) $(CXXFLAGS) -c -o olad/olad_libolaserver_la-PluginManager.lo `test -f 'olad/PluginManager.cpp' || echo '$(srcdir)/'`olad/PluginManager.cpp olad/olad_libolaserver_la-BonjourDiscoveryAgent.lo: olad/BonjourDiscoveryAgent.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_libolaserver_la_CXXFLAGS) $(CXXFLAGS) -MT olad/olad_libolaserver_la-BonjourDiscoveryAgent.lo -MD -MP -MF olad/$(DEPDIR)/olad_libolaserver_la-BonjourDiscoveryAgent.Tpo -c -o olad/olad_libolaserver_la-BonjourDiscoveryAgent.lo `test -f 'olad/BonjourDiscoveryAgent.cpp' || echo '$(srcdir)/'`olad/BonjourDiscoveryAgent.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/$(DEPDIR)/olad_libolaserver_la-BonjourDiscoveryAgent.Tpo olad/$(DEPDIR)/olad_libolaserver_la-BonjourDiscoveryAgent.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/BonjourDiscoveryAgent.cpp' object='olad/olad_libolaserver_la-BonjourDiscoveryAgent.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_libolaserver_la_CXXFLAGS) $(CXXFLAGS) -c -o olad/olad_libolaserver_la-BonjourDiscoveryAgent.lo `test -f 'olad/BonjourDiscoveryAgent.cpp' || echo '$(srcdir)/'`olad/BonjourDiscoveryAgent.cpp olad/olad_libolaserver_la-AvahiDiscoveryAgent.lo: olad/AvahiDiscoveryAgent.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_libolaserver_la_CXXFLAGS) $(CXXFLAGS) -MT olad/olad_libolaserver_la-AvahiDiscoveryAgent.lo -MD -MP -MF olad/$(DEPDIR)/olad_libolaserver_la-AvahiDiscoveryAgent.Tpo -c -o olad/olad_libolaserver_la-AvahiDiscoveryAgent.lo `test -f 'olad/AvahiDiscoveryAgent.cpp' || echo '$(srcdir)/'`olad/AvahiDiscoveryAgent.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/$(DEPDIR)/olad_libolaserver_la-AvahiDiscoveryAgent.Tpo olad/$(DEPDIR)/olad_libolaserver_la-AvahiDiscoveryAgent.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/AvahiDiscoveryAgent.cpp' object='olad/olad_libolaserver_la-AvahiDiscoveryAgent.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_libolaserver_la_CXXFLAGS) $(CXXFLAGS) -c -o olad/olad_libolaserver_la-AvahiDiscoveryAgent.lo `test -f 'olad/AvahiDiscoveryAgent.cpp' || echo '$(srcdir)/'`olad/AvahiDiscoveryAgent.cpp olad/olad_libolaserver_la-HttpServerActions.lo: olad/HttpServerActions.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_libolaserver_la_CXXFLAGS) $(CXXFLAGS) -MT olad/olad_libolaserver_la-HttpServerActions.lo -MD -MP -MF olad/$(DEPDIR)/olad_libolaserver_la-HttpServerActions.Tpo -c -o olad/olad_libolaserver_la-HttpServerActions.lo `test -f 'olad/HttpServerActions.cpp' || echo '$(srcdir)/'`olad/HttpServerActions.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/$(DEPDIR)/olad_libolaserver_la-HttpServerActions.Tpo olad/$(DEPDIR)/olad_libolaserver_la-HttpServerActions.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/HttpServerActions.cpp' object='olad/olad_libolaserver_la-HttpServerActions.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_libolaserver_la_CXXFLAGS) $(CXXFLAGS) -c -o olad/olad_libolaserver_la-HttpServerActions.lo `test -f 'olad/HttpServerActions.cpp' || echo '$(srcdir)/'`olad/HttpServerActions.cpp olad/olad_libolaserver_la-OladHTTPServer.lo: olad/OladHTTPServer.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_libolaserver_la_CXXFLAGS) $(CXXFLAGS) -MT olad/olad_libolaserver_la-OladHTTPServer.lo -MD -MP -MF olad/$(DEPDIR)/olad_libolaserver_la-OladHTTPServer.Tpo -c -o olad/olad_libolaserver_la-OladHTTPServer.lo `test -f 'olad/OladHTTPServer.cpp' || echo '$(srcdir)/'`olad/OladHTTPServer.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/$(DEPDIR)/olad_libolaserver_la-OladHTTPServer.Tpo olad/$(DEPDIR)/olad_libolaserver_la-OladHTTPServer.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/OladHTTPServer.cpp' object='olad/olad_libolaserver_la-OladHTTPServer.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_libolaserver_la_CXXFLAGS) $(CXXFLAGS) -c -o olad/olad_libolaserver_la-OladHTTPServer.lo `test -f 'olad/OladHTTPServer.cpp' || echo '$(srcdir)/'`olad/OladHTTPServer.cpp olad/olad_libolaserver_la-RDMHTTPModule.lo: olad/RDMHTTPModule.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_libolaserver_la_CXXFLAGS) $(CXXFLAGS) -MT olad/olad_libolaserver_la-RDMHTTPModule.lo -MD -MP -MF olad/$(DEPDIR)/olad_libolaserver_la-RDMHTTPModule.Tpo -c -o olad/olad_libolaserver_la-RDMHTTPModule.lo `test -f 'olad/RDMHTTPModule.cpp' || echo '$(srcdir)/'`olad/RDMHTTPModule.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/$(DEPDIR)/olad_libolaserver_la-RDMHTTPModule.Tpo olad/$(DEPDIR)/olad_libolaserver_la-RDMHTTPModule.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/RDMHTTPModule.cpp' object='olad/olad_libolaserver_la-RDMHTTPModule.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_libolaserver_la_CXXFLAGS) $(CXXFLAGS) -c -o olad/olad_libolaserver_la-RDMHTTPModule.lo `test -f 'olad/RDMHTTPModule.cpp' || echo '$(srcdir)/'`olad/RDMHTTPModule.cpp olad/olad_libolaserver_la-OlaServer.lo: olad/OlaServer.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_libolaserver_la_CXXFLAGS) $(CXXFLAGS) -MT olad/olad_libolaserver_la-OlaServer.lo -MD -MP -MF olad/$(DEPDIR)/olad_libolaserver_la-OlaServer.Tpo -c -o olad/olad_libolaserver_la-OlaServer.lo `test -f 'olad/OlaServer.cpp' || echo '$(srcdir)/'`olad/OlaServer.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/$(DEPDIR)/olad_libolaserver_la-OlaServer.Tpo olad/$(DEPDIR)/olad_libolaserver_la-OlaServer.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/OlaServer.cpp' object='olad/olad_libolaserver_la-OlaServer.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_libolaserver_la_CXXFLAGS) $(CXXFLAGS) -c -o olad/olad_libolaserver_la-OlaServer.lo `test -f 'olad/OlaServer.cpp' || echo '$(srcdir)/'`olad/OlaServer.cpp olad/olad_libolaserver_la-OlaDaemon.lo: olad/OlaDaemon.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_libolaserver_la_CXXFLAGS) $(CXXFLAGS) -MT olad/olad_libolaserver_la-OlaDaemon.lo -MD -MP -MF olad/$(DEPDIR)/olad_libolaserver_la-OlaDaemon.Tpo -c -o olad/olad_libolaserver_la-OlaDaemon.lo `test -f 'olad/OlaDaemon.cpp' || echo '$(srcdir)/'`olad/OlaDaemon.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/$(DEPDIR)/olad_libolaserver_la-OlaDaemon.Tpo olad/$(DEPDIR)/olad_libolaserver_la-OlaDaemon.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/OlaDaemon.cpp' object='olad/olad_libolaserver_la-OlaDaemon.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_libolaserver_la_CXXFLAGS) $(CXXFLAGS) -c -o olad/olad_libolaserver_la-OlaDaemon.lo `test -f 'olad/OlaDaemon.cpp' || echo '$(srcdir)/'`olad/OlaDaemon.cpp olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Client.lo: olad/plugin_api/Client.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_libolaserverplugininterface_la_CXXFLAGS) $(CXXFLAGS) -MT olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Client.lo -MD -MP -MF olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-Client.Tpo -c -o olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Client.lo `test -f 'olad/plugin_api/Client.cpp' || echo '$(srcdir)/'`olad/plugin_api/Client.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-Client.Tpo olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-Client.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/plugin_api/Client.cpp' object='olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Client.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_libolaserverplugininterface_la_CXXFLAGS) $(CXXFLAGS) -c -o olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Client.lo `test -f 'olad/plugin_api/Client.cpp' || echo '$(srcdir)/'`olad/plugin_api/Client.cpp olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Device.lo: olad/plugin_api/Device.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_libolaserverplugininterface_la_CXXFLAGS) $(CXXFLAGS) -MT olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Device.lo -MD -MP -MF olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-Device.Tpo -c -o olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Device.lo `test -f 'olad/plugin_api/Device.cpp' || echo '$(srcdir)/'`olad/plugin_api/Device.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-Device.Tpo olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-Device.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/plugin_api/Device.cpp' object='olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Device.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_libolaserverplugininterface_la_CXXFLAGS) $(CXXFLAGS) -c -o olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Device.lo `test -f 'olad/plugin_api/Device.cpp' || echo '$(srcdir)/'`olad/plugin_api/Device.cpp olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-DeviceManager.lo: olad/plugin_api/DeviceManager.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_libolaserverplugininterface_la_CXXFLAGS) $(CXXFLAGS) -MT olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-DeviceManager.lo -MD -MP -MF olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-DeviceManager.Tpo -c -o olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-DeviceManager.lo `test -f 'olad/plugin_api/DeviceManager.cpp' || echo '$(srcdir)/'`olad/plugin_api/DeviceManager.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-DeviceManager.Tpo olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-DeviceManager.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/plugin_api/DeviceManager.cpp' object='olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-DeviceManager.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_libolaserverplugininterface_la_CXXFLAGS) $(CXXFLAGS) -c -o olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-DeviceManager.lo `test -f 'olad/plugin_api/DeviceManager.cpp' || echo '$(srcdir)/'`olad/plugin_api/DeviceManager.cpp olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-DmxSource.lo: olad/plugin_api/DmxSource.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_libolaserverplugininterface_la_CXXFLAGS) $(CXXFLAGS) -MT olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-DmxSource.lo -MD -MP -MF olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-DmxSource.Tpo -c -o olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-DmxSource.lo `test -f 'olad/plugin_api/DmxSource.cpp' || echo '$(srcdir)/'`olad/plugin_api/DmxSource.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-DmxSource.Tpo olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-DmxSource.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/plugin_api/DmxSource.cpp' object='olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-DmxSource.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_libolaserverplugininterface_la_CXXFLAGS) $(CXXFLAGS) -c -o olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-DmxSource.lo `test -f 'olad/plugin_api/DmxSource.cpp' || echo '$(srcdir)/'`olad/plugin_api/DmxSource.cpp olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Plugin.lo: olad/plugin_api/Plugin.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_libolaserverplugininterface_la_CXXFLAGS) $(CXXFLAGS) -MT olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Plugin.lo -MD -MP -MF olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-Plugin.Tpo -c -o olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Plugin.lo `test -f 'olad/plugin_api/Plugin.cpp' || echo '$(srcdir)/'`olad/plugin_api/Plugin.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-Plugin.Tpo olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-Plugin.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/plugin_api/Plugin.cpp' object='olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Plugin.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_libolaserverplugininterface_la_CXXFLAGS) $(CXXFLAGS) -c -o olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Plugin.lo `test -f 'olad/plugin_api/Plugin.cpp' || echo '$(srcdir)/'`olad/plugin_api/Plugin.cpp olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-PluginAdaptor.lo: olad/plugin_api/PluginAdaptor.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_libolaserverplugininterface_la_CXXFLAGS) $(CXXFLAGS) -MT olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-PluginAdaptor.lo -MD -MP -MF olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-PluginAdaptor.Tpo -c -o olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-PluginAdaptor.lo `test -f 'olad/plugin_api/PluginAdaptor.cpp' || echo '$(srcdir)/'`olad/plugin_api/PluginAdaptor.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-PluginAdaptor.Tpo olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-PluginAdaptor.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/plugin_api/PluginAdaptor.cpp' object='olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-PluginAdaptor.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_libolaserverplugininterface_la_CXXFLAGS) $(CXXFLAGS) -c -o olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-PluginAdaptor.lo `test -f 'olad/plugin_api/PluginAdaptor.cpp' || echo '$(srcdir)/'`olad/plugin_api/PluginAdaptor.cpp olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Port.lo: olad/plugin_api/Port.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_libolaserverplugininterface_la_CXXFLAGS) $(CXXFLAGS) -MT olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Port.lo -MD -MP -MF olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-Port.Tpo -c -o olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Port.lo `test -f 'olad/plugin_api/Port.cpp' || echo '$(srcdir)/'`olad/plugin_api/Port.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-Port.Tpo olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-Port.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/plugin_api/Port.cpp' object='olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Port.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_libolaserverplugininterface_la_CXXFLAGS) $(CXXFLAGS) -c -o olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Port.lo `test -f 'olad/plugin_api/Port.cpp' || echo '$(srcdir)/'`olad/plugin_api/Port.cpp olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-PortBroker.lo: olad/plugin_api/PortBroker.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_libolaserverplugininterface_la_CXXFLAGS) $(CXXFLAGS) -MT olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-PortBroker.lo -MD -MP -MF olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-PortBroker.Tpo -c -o olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-PortBroker.lo `test -f 'olad/plugin_api/PortBroker.cpp' || echo '$(srcdir)/'`olad/plugin_api/PortBroker.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-PortBroker.Tpo olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-PortBroker.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/plugin_api/PortBroker.cpp' object='olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-PortBroker.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_libolaserverplugininterface_la_CXXFLAGS) $(CXXFLAGS) -c -o olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-PortBroker.lo `test -f 'olad/plugin_api/PortBroker.cpp' || echo '$(srcdir)/'`olad/plugin_api/PortBroker.cpp olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-PortManager.lo: olad/plugin_api/PortManager.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_libolaserverplugininterface_la_CXXFLAGS) $(CXXFLAGS) -MT olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-PortManager.lo -MD -MP -MF olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-PortManager.Tpo -c -o olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-PortManager.lo `test -f 'olad/plugin_api/PortManager.cpp' || echo '$(srcdir)/'`olad/plugin_api/PortManager.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-PortManager.Tpo olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-PortManager.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/plugin_api/PortManager.cpp' object='olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-PortManager.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_libolaserverplugininterface_la_CXXFLAGS) $(CXXFLAGS) -c -o olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-PortManager.lo `test -f 'olad/plugin_api/PortManager.cpp' || echo '$(srcdir)/'`olad/plugin_api/PortManager.cpp olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Preferences.lo: olad/plugin_api/Preferences.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_libolaserverplugininterface_la_CXXFLAGS) $(CXXFLAGS) -MT olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Preferences.lo -MD -MP -MF olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-Preferences.Tpo -c -o olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Preferences.lo `test -f 'olad/plugin_api/Preferences.cpp' || echo '$(srcdir)/'`olad/plugin_api/Preferences.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-Preferences.Tpo olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-Preferences.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/plugin_api/Preferences.cpp' object='olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Preferences.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_libolaserverplugininterface_la_CXXFLAGS) $(CXXFLAGS) -c -o olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Preferences.lo `test -f 'olad/plugin_api/Preferences.cpp' || echo '$(srcdir)/'`olad/plugin_api/Preferences.cpp olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Universe.lo: olad/plugin_api/Universe.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_libolaserverplugininterface_la_CXXFLAGS) $(CXXFLAGS) -MT olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Universe.lo -MD -MP -MF olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-Universe.Tpo -c -o olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Universe.lo `test -f 'olad/plugin_api/Universe.cpp' || echo '$(srcdir)/'`olad/plugin_api/Universe.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-Universe.Tpo olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-Universe.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/plugin_api/Universe.cpp' object='olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Universe.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_libolaserverplugininterface_la_CXXFLAGS) $(CXXFLAGS) -c -o olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-Universe.lo `test -f 'olad/plugin_api/Universe.cpp' || echo '$(srcdir)/'`olad/plugin_api/Universe.cpp olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-UniverseStore.lo: olad/plugin_api/UniverseStore.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_libolaserverplugininterface_la_CXXFLAGS) $(CXXFLAGS) -MT olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-UniverseStore.lo -MD -MP -MF olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-UniverseStore.Tpo -c -o olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-UniverseStore.lo `test -f 'olad/plugin_api/UniverseStore.cpp' || echo '$(srcdir)/'`olad/plugin_api/UniverseStore.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-UniverseStore.Tpo olad/plugin_api/$(DEPDIR)/olad_plugin_api_libolaserverplugininterface_la-UniverseStore.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/plugin_api/UniverseStore.cpp' object='olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-UniverseStore.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_libolaserverplugininterface_la_CXXFLAGS) $(CXXFLAGS) -c -o olad/plugin_api/olad_plugin_api_libolaserverplugininterface_la-UniverseStore.lo `test -f 'olad/plugin_api/UniverseStore.cpp' || echo '$(srcdir)/'`olad/plugin_api/UniverseStore.cpp plugins/artnet/plugins_artnet_libolaartnet_la-ArtNetPlugin.lo: plugins/artnet/ArtNetPlugin.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_artnet_libolaartnet_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/artnet/plugins_artnet_libolaartnet_la-ArtNetPlugin.lo -MD -MP -MF plugins/artnet/$(DEPDIR)/plugins_artnet_libolaartnet_la-ArtNetPlugin.Tpo -c -o plugins/artnet/plugins_artnet_libolaartnet_la-ArtNetPlugin.lo `test -f 'plugins/artnet/ArtNetPlugin.cpp' || echo '$(srcdir)/'`plugins/artnet/ArtNetPlugin.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/artnet/$(DEPDIR)/plugins_artnet_libolaartnet_la-ArtNetPlugin.Tpo plugins/artnet/$(DEPDIR)/plugins_artnet_libolaartnet_la-ArtNetPlugin.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/artnet/ArtNetPlugin.cpp' object='plugins/artnet/plugins_artnet_libolaartnet_la-ArtNetPlugin.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_artnet_libolaartnet_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/artnet/plugins_artnet_libolaartnet_la-ArtNetPlugin.lo `test -f 'plugins/artnet/ArtNetPlugin.cpp' || echo '$(srcdir)/'`plugins/artnet/ArtNetPlugin.cpp plugins/artnet/plugins_artnet_libolaartnet_la-ArtNetDevice.lo: plugins/artnet/ArtNetDevice.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_artnet_libolaartnet_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/artnet/plugins_artnet_libolaartnet_la-ArtNetDevice.lo -MD -MP -MF plugins/artnet/$(DEPDIR)/plugins_artnet_libolaartnet_la-ArtNetDevice.Tpo -c -o plugins/artnet/plugins_artnet_libolaartnet_la-ArtNetDevice.lo `test -f 'plugins/artnet/ArtNetDevice.cpp' || echo '$(srcdir)/'`plugins/artnet/ArtNetDevice.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/artnet/$(DEPDIR)/plugins_artnet_libolaartnet_la-ArtNetDevice.Tpo plugins/artnet/$(DEPDIR)/plugins_artnet_libolaartnet_la-ArtNetDevice.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/artnet/ArtNetDevice.cpp' object='plugins/artnet/plugins_artnet_libolaartnet_la-ArtNetDevice.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_artnet_libolaartnet_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/artnet/plugins_artnet_libolaartnet_la-ArtNetDevice.lo `test -f 'plugins/artnet/ArtNetDevice.cpp' || echo '$(srcdir)/'`plugins/artnet/ArtNetDevice.cpp plugins/artnet/plugins_artnet_libolaartnet_la-ArtNetPort.lo: plugins/artnet/ArtNetPort.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_artnet_libolaartnet_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/artnet/plugins_artnet_libolaartnet_la-ArtNetPort.lo -MD -MP -MF plugins/artnet/$(DEPDIR)/plugins_artnet_libolaartnet_la-ArtNetPort.Tpo -c -o plugins/artnet/plugins_artnet_libolaartnet_la-ArtNetPort.lo `test -f 'plugins/artnet/ArtNetPort.cpp' || echo '$(srcdir)/'`plugins/artnet/ArtNetPort.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/artnet/$(DEPDIR)/plugins_artnet_libolaartnet_la-ArtNetPort.Tpo plugins/artnet/$(DEPDIR)/plugins_artnet_libolaartnet_la-ArtNetPort.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/artnet/ArtNetPort.cpp' object='plugins/artnet/plugins_artnet_libolaartnet_la-ArtNetPort.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_artnet_libolaartnet_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/artnet/plugins_artnet_libolaartnet_la-ArtNetPort.lo `test -f 'plugins/artnet/ArtNetPort.cpp' || echo '$(srcdir)/'`plugins/artnet/ArtNetPort.cpp plugins/artnet/messages/plugins_artnet_messages_libolaartnetconf_la-ArtNetConfigMessages.pb.lo: plugins/artnet/messages/ArtNetConfigMessages.pb.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_artnet_messages_libolaartnetconf_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/artnet/messages/plugins_artnet_messages_libolaartnetconf_la-ArtNetConfigMessages.pb.lo -MD -MP -MF plugins/artnet/messages/$(DEPDIR)/plugins_artnet_messages_libolaartnetconf_la-ArtNetConfigMessages.pb.Tpo -c -o plugins/artnet/messages/plugins_artnet_messages_libolaartnetconf_la-ArtNetConfigMessages.pb.lo `test -f 'plugins/artnet/messages/ArtNetConfigMessages.pb.cc' || echo '$(srcdir)/'`plugins/artnet/messages/ArtNetConfigMessages.pb.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/artnet/messages/$(DEPDIR)/plugins_artnet_messages_libolaartnetconf_la-ArtNetConfigMessages.pb.Tpo plugins/artnet/messages/$(DEPDIR)/plugins_artnet_messages_libolaartnetconf_la-ArtNetConfigMessages.pb.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/artnet/messages/ArtNetConfigMessages.pb.cc' object='plugins/artnet/messages/plugins_artnet_messages_libolaartnetconf_la-ArtNetConfigMessages.pb.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_artnet_messages_libolaartnetconf_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/artnet/messages/plugins_artnet_messages_libolaartnetconf_la-ArtNetConfigMessages.pb.lo `test -f 'plugins/artnet/messages/ArtNetConfigMessages.pb.cc' || echo '$(srcdir)/'`plugins/artnet/messages/ArtNetConfigMessages.pb.cc plugins/e131/plugins_e131_libolae131_la-E131Device.lo: plugins/e131/E131Device.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_e131_libolae131_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/e131/plugins_e131_libolae131_la-E131Device.lo -MD -MP -MF plugins/e131/$(DEPDIR)/plugins_e131_libolae131_la-E131Device.Tpo -c -o plugins/e131/plugins_e131_libolae131_la-E131Device.lo `test -f 'plugins/e131/E131Device.cpp' || echo '$(srcdir)/'`plugins/e131/E131Device.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/e131/$(DEPDIR)/plugins_e131_libolae131_la-E131Device.Tpo plugins/e131/$(DEPDIR)/plugins_e131_libolae131_la-E131Device.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/e131/E131Device.cpp' object='plugins/e131/plugins_e131_libolae131_la-E131Device.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_e131_libolae131_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/e131/plugins_e131_libolae131_la-E131Device.lo `test -f 'plugins/e131/E131Device.cpp' || echo '$(srcdir)/'`plugins/e131/E131Device.cpp plugins/e131/plugins_e131_libolae131_la-E131Plugin.lo: plugins/e131/E131Plugin.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_e131_libolae131_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/e131/plugins_e131_libolae131_la-E131Plugin.lo -MD -MP -MF plugins/e131/$(DEPDIR)/plugins_e131_libolae131_la-E131Plugin.Tpo -c -o plugins/e131/plugins_e131_libolae131_la-E131Plugin.lo `test -f 'plugins/e131/E131Plugin.cpp' || echo '$(srcdir)/'`plugins/e131/E131Plugin.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/e131/$(DEPDIR)/plugins_e131_libolae131_la-E131Plugin.Tpo plugins/e131/$(DEPDIR)/plugins_e131_libolae131_la-E131Plugin.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/e131/E131Plugin.cpp' object='plugins/e131/plugins_e131_libolae131_la-E131Plugin.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_e131_libolae131_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/e131/plugins_e131_libolae131_la-E131Plugin.lo `test -f 'plugins/e131/E131Plugin.cpp' || echo '$(srcdir)/'`plugins/e131/E131Plugin.cpp plugins/e131/plugins_e131_libolae131_la-E131Port.lo: plugins/e131/E131Port.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_e131_libolae131_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/e131/plugins_e131_libolae131_la-E131Port.lo -MD -MP -MF plugins/e131/$(DEPDIR)/plugins_e131_libolae131_la-E131Port.Tpo -c -o plugins/e131/plugins_e131_libolae131_la-E131Port.lo `test -f 'plugins/e131/E131Port.cpp' || echo '$(srcdir)/'`plugins/e131/E131Port.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/e131/$(DEPDIR)/plugins_e131_libolae131_la-E131Port.Tpo plugins/e131/$(DEPDIR)/plugins_e131_libolae131_la-E131Port.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/e131/E131Port.cpp' object='plugins/e131/plugins_e131_libolae131_la-E131Port.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_e131_libolae131_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/e131/plugins_e131_libolae131_la-E131Port.lo `test -f 'plugins/e131/E131Port.cpp' || echo '$(srcdir)/'`plugins/e131/E131Port.cpp plugins/e131/messages/plugins_e131_messages_libolae131conf_la-E131ConfigMessages.pb.lo: plugins/e131/messages/E131ConfigMessages.pb.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_e131_messages_libolae131conf_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/e131/messages/plugins_e131_messages_libolae131conf_la-E131ConfigMessages.pb.lo -MD -MP -MF plugins/e131/messages/$(DEPDIR)/plugins_e131_messages_libolae131conf_la-E131ConfigMessages.pb.Tpo -c -o plugins/e131/messages/plugins_e131_messages_libolae131conf_la-E131ConfigMessages.pb.lo `test -f 'plugins/e131/messages/E131ConfigMessages.pb.cc' || echo '$(srcdir)/'`plugins/e131/messages/E131ConfigMessages.pb.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/e131/messages/$(DEPDIR)/plugins_e131_messages_libolae131conf_la-E131ConfigMessages.pb.Tpo plugins/e131/messages/$(DEPDIR)/plugins_e131_messages_libolae131conf_la-E131ConfigMessages.pb.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/e131/messages/E131ConfigMessages.pb.cc' object='plugins/e131/messages/plugins_e131_messages_libolae131conf_la-E131ConfigMessages.pb.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_e131_messages_libolae131conf_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/e131/messages/plugins_e131_messages_libolae131conf_la-E131ConfigMessages.pb.lo `test -f 'plugins/e131/messages/E131ConfigMessages.pb.cc' || echo '$(srcdir)/'`plugins/e131/messages/E131ConfigMessages.pb.cc plugins/osc/plugins_osc_libolaosc_la-OSCDevice.lo: plugins/osc/OSCDevice.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_osc_libolaosc_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/osc/plugins_osc_libolaosc_la-OSCDevice.lo -MD -MP -MF plugins/osc/$(DEPDIR)/plugins_osc_libolaosc_la-OSCDevice.Tpo -c -o plugins/osc/plugins_osc_libolaosc_la-OSCDevice.lo `test -f 'plugins/osc/OSCDevice.cpp' || echo '$(srcdir)/'`plugins/osc/OSCDevice.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/osc/$(DEPDIR)/plugins_osc_libolaosc_la-OSCDevice.Tpo plugins/osc/$(DEPDIR)/plugins_osc_libolaosc_la-OSCDevice.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/osc/OSCDevice.cpp' object='plugins/osc/plugins_osc_libolaosc_la-OSCDevice.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_osc_libolaosc_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/osc/plugins_osc_libolaosc_la-OSCDevice.lo `test -f 'plugins/osc/OSCDevice.cpp' || echo '$(srcdir)/'`plugins/osc/OSCDevice.cpp plugins/osc/plugins_osc_libolaosc_la-OSCPlugin.lo: plugins/osc/OSCPlugin.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_osc_libolaosc_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/osc/plugins_osc_libolaosc_la-OSCPlugin.lo -MD -MP -MF plugins/osc/$(DEPDIR)/plugins_osc_libolaosc_la-OSCPlugin.Tpo -c -o plugins/osc/plugins_osc_libolaosc_la-OSCPlugin.lo `test -f 'plugins/osc/OSCPlugin.cpp' || echo '$(srcdir)/'`plugins/osc/OSCPlugin.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/osc/$(DEPDIR)/plugins_osc_libolaosc_la-OSCPlugin.Tpo plugins/osc/$(DEPDIR)/plugins_osc_libolaosc_la-OSCPlugin.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/osc/OSCPlugin.cpp' object='plugins/osc/plugins_osc_libolaosc_la-OSCPlugin.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_osc_libolaosc_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/osc/plugins_osc_libolaosc_la-OSCPlugin.lo `test -f 'plugins/osc/OSCPlugin.cpp' || echo '$(srcdir)/'`plugins/osc/OSCPlugin.cpp plugins/osc/plugins_osc_libolaosc_la-OSCPort.lo: plugins/osc/OSCPort.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_osc_libolaosc_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/osc/plugins_osc_libolaosc_la-OSCPort.lo -MD -MP -MF plugins/osc/$(DEPDIR)/plugins_osc_libolaosc_la-OSCPort.Tpo -c -o plugins/osc/plugins_osc_libolaosc_la-OSCPort.lo `test -f 'plugins/osc/OSCPort.cpp' || echo '$(srcdir)/'`plugins/osc/OSCPort.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/osc/$(DEPDIR)/plugins_osc_libolaosc_la-OSCPort.Tpo plugins/osc/$(DEPDIR)/plugins_osc_libolaosc_la-OSCPort.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/osc/OSCPort.cpp' object='plugins/osc/plugins_osc_libolaosc_la-OSCPort.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_osc_libolaosc_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/osc/plugins_osc_libolaosc_la-OSCPort.lo `test -f 'plugins/osc/OSCPort.cpp' || echo '$(srcdir)/'`plugins/osc/OSCPort.cpp plugins/osc/plugins_osc_libolaoscnode_la-OSCAddressTemplate.lo: plugins/osc/OSCAddressTemplate.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_osc_libolaoscnode_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/osc/plugins_osc_libolaoscnode_la-OSCAddressTemplate.lo -MD -MP -MF plugins/osc/$(DEPDIR)/plugins_osc_libolaoscnode_la-OSCAddressTemplate.Tpo -c -o plugins/osc/plugins_osc_libolaoscnode_la-OSCAddressTemplate.lo `test -f 'plugins/osc/OSCAddressTemplate.cpp' || echo '$(srcdir)/'`plugins/osc/OSCAddressTemplate.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/osc/$(DEPDIR)/plugins_osc_libolaoscnode_la-OSCAddressTemplate.Tpo plugins/osc/$(DEPDIR)/plugins_osc_libolaoscnode_la-OSCAddressTemplate.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/osc/OSCAddressTemplate.cpp' object='plugins/osc/plugins_osc_libolaoscnode_la-OSCAddressTemplate.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_osc_libolaoscnode_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/osc/plugins_osc_libolaoscnode_la-OSCAddressTemplate.lo `test -f 'plugins/osc/OSCAddressTemplate.cpp' || echo '$(srcdir)/'`plugins/osc/OSCAddressTemplate.cpp plugins/osc/plugins_osc_libolaoscnode_la-OSCNode.lo: plugins/osc/OSCNode.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_osc_libolaoscnode_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/osc/plugins_osc_libolaoscnode_la-OSCNode.lo -MD -MP -MF plugins/osc/$(DEPDIR)/plugins_osc_libolaoscnode_la-OSCNode.Tpo -c -o plugins/osc/plugins_osc_libolaoscnode_la-OSCNode.lo `test -f 'plugins/osc/OSCNode.cpp' || echo '$(srcdir)/'`plugins/osc/OSCNode.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/osc/$(DEPDIR)/plugins_osc_libolaoscnode_la-OSCNode.Tpo plugins/osc/$(DEPDIR)/plugins_osc_libolaoscnode_la-OSCNode.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/osc/OSCNode.cpp' object='plugins/osc/plugins_osc_libolaoscnode_la-OSCNode.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_osc_libolaoscnode_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/osc/plugins_osc_libolaoscnode_la-OSCNode.lo `test -f 'plugins/osc/OSCNode.cpp' || echo '$(srcdir)/'`plugins/osc/OSCNode.cpp plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-AsyncPluginImpl.lo: plugins/usbdmx/AsyncPluginImpl.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmx_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-AsyncPluginImpl.lo -MD -MP -MF plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-AsyncPluginImpl.Tpo -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-AsyncPluginImpl.lo `test -f 'plugins/usbdmx/AsyncPluginImpl.cpp' || echo '$(srcdir)/'`plugins/usbdmx/AsyncPluginImpl.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-AsyncPluginImpl.Tpo plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-AsyncPluginImpl.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbdmx/AsyncPluginImpl.cpp' object='plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-AsyncPluginImpl.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmx_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-AsyncPluginImpl.lo `test -f 'plugins/usbdmx/AsyncPluginImpl.cpp' || echo '$(srcdir)/'`plugins/usbdmx/AsyncPluginImpl.cpp plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-DMXCProjectsNodleU1Device.lo: plugins/usbdmx/DMXCProjectsNodleU1Device.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmx_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-DMXCProjectsNodleU1Device.lo -MD -MP -MF plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-DMXCProjectsNodleU1Device.Tpo -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-DMXCProjectsNodleU1Device.lo `test -f 'plugins/usbdmx/DMXCProjectsNodleU1Device.cpp' || echo '$(srcdir)/'`plugins/usbdmx/DMXCProjectsNodleU1Device.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-DMXCProjectsNodleU1Device.Tpo plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-DMXCProjectsNodleU1Device.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbdmx/DMXCProjectsNodleU1Device.cpp' object='plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-DMXCProjectsNodleU1Device.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmx_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-DMXCProjectsNodleU1Device.lo `test -f 'plugins/usbdmx/DMXCProjectsNodleU1Device.cpp' || echo '$(srcdir)/'`plugins/usbdmx/DMXCProjectsNodleU1Device.cpp plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-DMXCProjectsNodleU1Port.lo: plugins/usbdmx/DMXCProjectsNodleU1Port.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmx_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-DMXCProjectsNodleU1Port.lo -MD -MP -MF plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-DMXCProjectsNodleU1Port.Tpo -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-DMXCProjectsNodleU1Port.lo `test -f 'plugins/usbdmx/DMXCProjectsNodleU1Port.cpp' || echo '$(srcdir)/'`plugins/usbdmx/DMXCProjectsNodleU1Port.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-DMXCProjectsNodleU1Port.Tpo plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-DMXCProjectsNodleU1Port.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbdmx/DMXCProjectsNodleU1Port.cpp' object='plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-DMXCProjectsNodleU1Port.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmx_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-DMXCProjectsNodleU1Port.lo `test -f 'plugins/usbdmx/DMXCProjectsNodleU1Port.cpp' || echo '$(srcdir)/'`plugins/usbdmx/DMXCProjectsNodleU1Port.cpp plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-GenericDevice.lo: plugins/usbdmx/GenericDevice.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmx_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-GenericDevice.lo -MD -MP -MF plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-GenericDevice.Tpo -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-GenericDevice.lo `test -f 'plugins/usbdmx/GenericDevice.cpp' || echo '$(srcdir)/'`plugins/usbdmx/GenericDevice.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-GenericDevice.Tpo plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-GenericDevice.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbdmx/GenericDevice.cpp' object='plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-GenericDevice.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmx_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-GenericDevice.lo `test -f 'plugins/usbdmx/GenericDevice.cpp' || echo '$(srcdir)/'`plugins/usbdmx/GenericDevice.cpp plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-GenericOutputPort.lo: plugins/usbdmx/GenericOutputPort.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmx_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-GenericOutputPort.lo -MD -MP -MF plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-GenericOutputPort.Tpo -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-GenericOutputPort.lo `test -f 'plugins/usbdmx/GenericOutputPort.cpp' || echo '$(srcdir)/'`plugins/usbdmx/GenericOutputPort.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-GenericOutputPort.Tpo plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-GenericOutputPort.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbdmx/GenericOutputPort.cpp' object='plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-GenericOutputPort.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmx_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-GenericOutputPort.lo `test -f 'plugins/usbdmx/GenericOutputPort.cpp' || echo '$(srcdir)/'`plugins/usbdmx/GenericOutputPort.cpp plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-JaRuleDevice.lo: plugins/usbdmx/JaRuleDevice.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmx_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-JaRuleDevice.lo -MD -MP -MF plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-JaRuleDevice.Tpo -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-JaRuleDevice.lo `test -f 'plugins/usbdmx/JaRuleDevice.cpp' || echo '$(srcdir)/'`plugins/usbdmx/JaRuleDevice.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-JaRuleDevice.Tpo plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-JaRuleDevice.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbdmx/JaRuleDevice.cpp' object='plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-JaRuleDevice.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmx_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-JaRuleDevice.lo `test -f 'plugins/usbdmx/JaRuleDevice.cpp' || echo '$(srcdir)/'`plugins/usbdmx/JaRuleDevice.cpp plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-JaRuleOutputPort.lo: plugins/usbdmx/JaRuleOutputPort.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmx_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-JaRuleOutputPort.lo -MD -MP -MF plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-JaRuleOutputPort.Tpo -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-JaRuleOutputPort.lo `test -f 'plugins/usbdmx/JaRuleOutputPort.cpp' || echo '$(srcdir)/'`plugins/usbdmx/JaRuleOutputPort.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-JaRuleOutputPort.Tpo plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-JaRuleOutputPort.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbdmx/JaRuleOutputPort.cpp' object='plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-JaRuleOutputPort.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmx_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-JaRuleOutputPort.lo `test -f 'plugins/usbdmx/JaRuleOutputPort.cpp' || echo '$(srcdir)/'`plugins/usbdmx/JaRuleOutputPort.cpp plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-SyncPluginImpl.lo: plugins/usbdmx/SyncPluginImpl.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmx_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-SyncPluginImpl.lo -MD -MP -MF plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-SyncPluginImpl.Tpo -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-SyncPluginImpl.lo `test -f 'plugins/usbdmx/SyncPluginImpl.cpp' || echo '$(srcdir)/'`plugins/usbdmx/SyncPluginImpl.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-SyncPluginImpl.Tpo plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-SyncPluginImpl.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbdmx/SyncPluginImpl.cpp' object='plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-SyncPluginImpl.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmx_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-SyncPluginImpl.lo `test -f 'plugins/usbdmx/SyncPluginImpl.cpp' || echo '$(srcdir)/'`plugins/usbdmx/SyncPluginImpl.cpp plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-UsbDmxPlugin.lo: plugins/usbdmx/UsbDmxPlugin.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmx_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-UsbDmxPlugin.lo -MD -MP -MF plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-UsbDmxPlugin.Tpo -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-UsbDmxPlugin.lo `test -f 'plugins/usbdmx/UsbDmxPlugin.cpp' || echo '$(srcdir)/'`plugins/usbdmx/UsbDmxPlugin.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-UsbDmxPlugin.Tpo plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmx_la-UsbDmxPlugin.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbdmx/UsbDmxPlugin.cpp' object='plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-UsbDmxPlugin.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmx_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmx_la-UsbDmxPlugin.lo `test -f 'plugins/usbdmx/UsbDmxPlugin.cpp' || echo '$(srcdir)/'`plugins/usbdmx/UsbDmxPlugin.cpp plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AnymauDMX.lo: plugins/usbdmx/AnymauDMX.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AnymauDMX.lo -MD -MP -MF plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-AnymauDMX.Tpo -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AnymauDMX.lo `test -f 'plugins/usbdmx/AnymauDMX.cpp' || echo '$(srcdir)/'`plugins/usbdmx/AnymauDMX.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-AnymauDMX.Tpo plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-AnymauDMX.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbdmx/AnymauDMX.cpp' object='plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AnymauDMX.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AnymauDMX.lo `test -f 'plugins/usbdmx/AnymauDMX.cpp' || echo '$(srcdir)/'`plugins/usbdmx/AnymauDMX.cpp plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AnymauDMXFactory.lo: plugins/usbdmx/AnymauDMXFactory.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AnymauDMXFactory.lo -MD -MP -MF plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-AnymauDMXFactory.Tpo -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AnymauDMXFactory.lo `test -f 'plugins/usbdmx/AnymauDMXFactory.cpp' || echo '$(srcdir)/'`plugins/usbdmx/AnymauDMXFactory.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-AnymauDMXFactory.Tpo plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-AnymauDMXFactory.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbdmx/AnymauDMXFactory.cpp' object='plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AnymauDMXFactory.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AnymauDMXFactory.lo `test -f 'plugins/usbdmx/AnymauDMXFactory.cpp' || echo '$(srcdir)/'`plugins/usbdmx/AnymauDMXFactory.cpp plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbReceiver.lo: plugins/usbdmx/AsyncUsbReceiver.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbReceiver.lo -MD -MP -MF plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbReceiver.Tpo -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbReceiver.lo `test -f 'plugins/usbdmx/AsyncUsbReceiver.cpp' || echo '$(srcdir)/'`plugins/usbdmx/AsyncUsbReceiver.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbReceiver.Tpo plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbReceiver.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbdmx/AsyncUsbReceiver.cpp' object='plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbReceiver.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbReceiver.lo `test -f 'plugins/usbdmx/AsyncUsbReceiver.cpp' || echo '$(srcdir)/'`plugins/usbdmx/AsyncUsbReceiver.cpp plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbSender.lo: plugins/usbdmx/AsyncUsbSender.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbSender.lo -MD -MP -MF plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbSender.Tpo -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbSender.lo `test -f 'plugins/usbdmx/AsyncUsbSender.cpp' || echo '$(srcdir)/'`plugins/usbdmx/AsyncUsbSender.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbSender.Tpo plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbSender.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbdmx/AsyncUsbSender.cpp' object='plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbSender.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbSender.lo `test -f 'plugins/usbdmx/AsyncUsbSender.cpp' || echo '$(srcdir)/'`plugins/usbdmx/AsyncUsbSender.cpp plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbTransceiverBase.lo: plugins/usbdmx/AsyncUsbTransceiverBase.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbTransceiverBase.lo -MD -MP -MF plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbTransceiverBase.Tpo -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbTransceiverBase.lo `test -f 'plugins/usbdmx/AsyncUsbTransceiverBase.cpp' || echo '$(srcdir)/'`plugins/usbdmx/AsyncUsbTransceiverBase.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbTransceiverBase.Tpo plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbTransceiverBase.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbdmx/AsyncUsbTransceiverBase.cpp' object='plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbTransceiverBase.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-AsyncUsbTransceiverBase.lo `test -f 'plugins/usbdmx/AsyncUsbTransceiverBase.cpp' || echo '$(srcdir)/'`plugins/usbdmx/AsyncUsbTransceiverBase.cpp plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-DMXCProjectsNodleU1.lo: plugins/usbdmx/DMXCProjectsNodleU1.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-DMXCProjectsNodleU1.lo -MD -MP -MF plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-DMXCProjectsNodleU1.Tpo -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-DMXCProjectsNodleU1.lo `test -f 'plugins/usbdmx/DMXCProjectsNodleU1.cpp' || echo '$(srcdir)/'`plugins/usbdmx/DMXCProjectsNodleU1.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-DMXCProjectsNodleU1.Tpo plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-DMXCProjectsNodleU1.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbdmx/DMXCProjectsNodleU1.cpp' object='plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-DMXCProjectsNodleU1.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-DMXCProjectsNodleU1.lo `test -f 'plugins/usbdmx/DMXCProjectsNodleU1.cpp' || echo '$(srcdir)/'`plugins/usbdmx/DMXCProjectsNodleU1.cpp plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-DMXCProjectsNodleU1Factory.lo: plugins/usbdmx/DMXCProjectsNodleU1Factory.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-DMXCProjectsNodleU1Factory.lo -MD -MP -MF plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-DMXCProjectsNodleU1Factory.Tpo -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-DMXCProjectsNodleU1Factory.lo `test -f 'plugins/usbdmx/DMXCProjectsNodleU1Factory.cpp' || echo '$(srcdir)/'`plugins/usbdmx/DMXCProjectsNodleU1Factory.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-DMXCProjectsNodleU1Factory.Tpo plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-DMXCProjectsNodleU1Factory.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbdmx/DMXCProjectsNodleU1Factory.cpp' object='plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-DMXCProjectsNodleU1Factory.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-DMXCProjectsNodleU1Factory.lo `test -f 'plugins/usbdmx/DMXCProjectsNodleU1Factory.cpp' || echo '$(srcdir)/'`plugins/usbdmx/DMXCProjectsNodleU1Factory.cpp plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-EurolitePro.lo: plugins/usbdmx/EurolitePro.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-EurolitePro.lo -MD -MP -MF plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-EurolitePro.Tpo -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-EurolitePro.lo `test -f 'plugins/usbdmx/EurolitePro.cpp' || echo '$(srcdir)/'`plugins/usbdmx/EurolitePro.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-EurolitePro.Tpo plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-EurolitePro.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbdmx/EurolitePro.cpp' object='plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-EurolitePro.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-EurolitePro.lo `test -f 'plugins/usbdmx/EurolitePro.cpp' || echo '$(srcdir)/'`plugins/usbdmx/EurolitePro.cpp plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-EuroliteProFactory.lo: plugins/usbdmx/EuroliteProFactory.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-EuroliteProFactory.lo -MD -MP -MF plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-EuroliteProFactory.Tpo -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-EuroliteProFactory.lo `test -f 'plugins/usbdmx/EuroliteProFactory.cpp' || echo '$(srcdir)/'`plugins/usbdmx/EuroliteProFactory.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-EuroliteProFactory.Tpo plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-EuroliteProFactory.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbdmx/EuroliteProFactory.cpp' object='plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-EuroliteProFactory.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-EuroliteProFactory.lo `test -f 'plugins/usbdmx/EuroliteProFactory.cpp' || echo '$(srcdir)/'`plugins/usbdmx/EuroliteProFactory.cpp plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-Flags.lo: plugins/usbdmx/Flags.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-Flags.lo -MD -MP -MF plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-Flags.Tpo -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-Flags.lo `test -f 'plugins/usbdmx/Flags.cpp' || echo '$(srcdir)/'`plugins/usbdmx/Flags.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-Flags.Tpo plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-Flags.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbdmx/Flags.cpp' object='plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-Flags.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-Flags.lo `test -f 'plugins/usbdmx/Flags.cpp' || echo '$(srcdir)/'`plugins/usbdmx/Flags.cpp plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-JaRuleFactory.lo: plugins/usbdmx/JaRuleFactory.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-JaRuleFactory.lo -MD -MP -MF plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-JaRuleFactory.Tpo -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-JaRuleFactory.lo `test -f 'plugins/usbdmx/JaRuleFactory.cpp' || echo '$(srcdir)/'`plugins/usbdmx/JaRuleFactory.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-JaRuleFactory.Tpo plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-JaRuleFactory.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbdmx/JaRuleFactory.cpp' object='plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-JaRuleFactory.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-JaRuleFactory.lo `test -f 'plugins/usbdmx/JaRuleFactory.cpp' || echo '$(srcdir)/'`plugins/usbdmx/JaRuleFactory.cpp plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-ScanlimeFadecandy.lo: plugins/usbdmx/ScanlimeFadecandy.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-ScanlimeFadecandy.lo -MD -MP -MF plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-ScanlimeFadecandy.Tpo -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-ScanlimeFadecandy.lo `test -f 'plugins/usbdmx/ScanlimeFadecandy.cpp' || echo '$(srcdir)/'`plugins/usbdmx/ScanlimeFadecandy.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-ScanlimeFadecandy.Tpo plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-ScanlimeFadecandy.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbdmx/ScanlimeFadecandy.cpp' object='plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-ScanlimeFadecandy.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-ScanlimeFadecandy.lo `test -f 'plugins/usbdmx/ScanlimeFadecandy.cpp' || echo '$(srcdir)/'`plugins/usbdmx/ScanlimeFadecandy.cpp plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-ScanlimeFadecandyFactory.lo: plugins/usbdmx/ScanlimeFadecandyFactory.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-ScanlimeFadecandyFactory.lo -MD -MP -MF plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-ScanlimeFadecandyFactory.Tpo -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-ScanlimeFadecandyFactory.lo `test -f 'plugins/usbdmx/ScanlimeFadecandyFactory.cpp' || echo '$(srcdir)/'`plugins/usbdmx/ScanlimeFadecandyFactory.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-ScanlimeFadecandyFactory.Tpo plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-ScanlimeFadecandyFactory.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbdmx/ScanlimeFadecandyFactory.cpp' object='plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-ScanlimeFadecandyFactory.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-ScanlimeFadecandyFactory.lo `test -f 'plugins/usbdmx/ScanlimeFadecandyFactory.cpp' || echo '$(srcdir)/'`plugins/usbdmx/ScanlimeFadecandyFactory.cpp plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-Sunlite.lo: plugins/usbdmx/Sunlite.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-Sunlite.lo -MD -MP -MF plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-Sunlite.Tpo -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-Sunlite.lo `test -f 'plugins/usbdmx/Sunlite.cpp' || echo '$(srcdir)/'`plugins/usbdmx/Sunlite.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-Sunlite.Tpo plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-Sunlite.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbdmx/Sunlite.cpp' object='plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-Sunlite.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-Sunlite.lo `test -f 'plugins/usbdmx/Sunlite.cpp' || echo '$(srcdir)/'`plugins/usbdmx/Sunlite.cpp plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-SunliteFactory.lo: plugins/usbdmx/SunliteFactory.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-SunliteFactory.lo -MD -MP -MF plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-SunliteFactory.Tpo -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-SunliteFactory.lo `test -f 'plugins/usbdmx/SunliteFactory.cpp' || echo '$(srcdir)/'`plugins/usbdmx/SunliteFactory.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-SunliteFactory.Tpo plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-SunliteFactory.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbdmx/SunliteFactory.cpp' object='plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-SunliteFactory.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-SunliteFactory.lo `test -f 'plugins/usbdmx/SunliteFactory.cpp' || echo '$(srcdir)/'`plugins/usbdmx/SunliteFactory.cpp plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-SunliteFirmwareLoader.lo: plugins/usbdmx/SunliteFirmwareLoader.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-SunliteFirmwareLoader.lo -MD -MP -MF plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-SunliteFirmwareLoader.Tpo -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-SunliteFirmwareLoader.lo `test -f 'plugins/usbdmx/SunliteFirmwareLoader.cpp' || echo '$(srcdir)/'`plugins/usbdmx/SunliteFirmwareLoader.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-SunliteFirmwareLoader.Tpo plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-SunliteFirmwareLoader.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbdmx/SunliteFirmwareLoader.cpp' object='plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-SunliteFirmwareLoader.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-SunliteFirmwareLoader.lo `test -f 'plugins/usbdmx/SunliteFirmwareLoader.cpp' || echo '$(srcdir)/'`plugins/usbdmx/SunliteFirmwareLoader.cpp plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-SyncronizedWidgetObserver.lo: plugins/usbdmx/SyncronizedWidgetObserver.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-SyncronizedWidgetObserver.lo -MD -MP -MF plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-SyncronizedWidgetObserver.Tpo -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-SyncronizedWidgetObserver.lo `test -f 'plugins/usbdmx/SyncronizedWidgetObserver.cpp' || echo '$(srcdir)/'`plugins/usbdmx/SyncronizedWidgetObserver.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-SyncronizedWidgetObserver.Tpo plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-SyncronizedWidgetObserver.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbdmx/SyncronizedWidgetObserver.cpp' object='plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-SyncronizedWidgetObserver.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-SyncronizedWidgetObserver.lo `test -f 'plugins/usbdmx/SyncronizedWidgetObserver.cpp' || echo '$(srcdir)/'`plugins/usbdmx/SyncronizedWidgetObserver.cpp plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-ThreadedUsbReceiver.lo: plugins/usbdmx/ThreadedUsbReceiver.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-ThreadedUsbReceiver.lo -MD -MP -MF plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-ThreadedUsbReceiver.Tpo -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-ThreadedUsbReceiver.lo `test -f 'plugins/usbdmx/ThreadedUsbReceiver.cpp' || echo '$(srcdir)/'`plugins/usbdmx/ThreadedUsbReceiver.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-ThreadedUsbReceiver.Tpo plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-ThreadedUsbReceiver.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbdmx/ThreadedUsbReceiver.cpp' object='plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-ThreadedUsbReceiver.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-ThreadedUsbReceiver.lo `test -f 'plugins/usbdmx/ThreadedUsbReceiver.cpp' || echo '$(srcdir)/'`plugins/usbdmx/ThreadedUsbReceiver.cpp plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-ThreadedUsbSender.lo: plugins/usbdmx/ThreadedUsbSender.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-ThreadedUsbSender.lo -MD -MP -MF plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-ThreadedUsbSender.Tpo -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-ThreadedUsbSender.lo `test -f 'plugins/usbdmx/ThreadedUsbSender.cpp' || echo '$(srcdir)/'`plugins/usbdmx/ThreadedUsbSender.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-ThreadedUsbSender.Tpo plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-ThreadedUsbSender.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbdmx/ThreadedUsbSender.cpp' object='plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-ThreadedUsbSender.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-ThreadedUsbSender.lo `test -f 'plugins/usbdmx/ThreadedUsbSender.cpp' || echo '$(srcdir)/'`plugins/usbdmx/ThreadedUsbSender.cpp plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-VellemanK8062.lo: plugins/usbdmx/VellemanK8062.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-VellemanK8062.lo -MD -MP -MF plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-VellemanK8062.Tpo -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-VellemanK8062.lo `test -f 'plugins/usbdmx/VellemanK8062.cpp' || echo '$(srcdir)/'`plugins/usbdmx/VellemanK8062.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-VellemanK8062.Tpo plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-VellemanK8062.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbdmx/VellemanK8062.cpp' object='plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-VellemanK8062.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-VellemanK8062.lo `test -f 'plugins/usbdmx/VellemanK8062.cpp' || echo '$(srcdir)/'`plugins/usbdmx/VellemanK8062.cpp plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-VellemanK8062Factory.lo: plugins/usbdmx/VellemanK8062Factory.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-VellemanK8062Factory.lo -MD -MP -MF plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-VellemanK8062Factory.Tpo -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-VellemanK8062Factory.lo `test -f 'plugins/usbdmx/VellemanK8062Factory.cpp' || echo '$(srcdir)/'`plugins/usbdmx/VellemanK8062Factory.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-VellemanK8062Factory.Tpo plugins/usbdmx/$(DEPDIR)/plugins_usbdmx_libolausbdmxwidget_la-VellemanK8062Factory.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbdmx/VellemanK8062Factory.cpp' object='plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-VellemanK8062Factory.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbdmx/plugins_usbdmx_libolausbdmxwidget_la-VellemanK8062Factory.lo `test -f 'plugins/usbdmx/VellemanK8062Factory.cpp' || echo '$(srcdir)/'`plugins/usbdmx/VellemanK8062Factory.cpp plugins/usbpro/plugins_usbpro_libolausbpro_la-ArduinoRGBDevice.lo: plugins/usbpro/ArduinoRGBDevice.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_libolausbpro_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_libolausbpro_la-ArduinoRGBDevice.lo -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_libolausbpro_la-ArduinoRGBDevice.Tpo -c -o plugins/usbpro/plugins_usbpro_libolausbpro_la-ArduinoRGBDevice.lo `test -f 'plugins/usbpro/ArduinoRGBDevice.cpp' || echo '$(srcdir)/'`plugins/usbpro/ArduinoRGBDevice.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_libolausbpro_la-ArduinoRGBDevice.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_libolausbpro_la-ArduinoRGBDevice.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/ArduinoRGBDevice.cpp' object='plugins/usbpro/plugins_usbpro_libolausbpro_la-ArduinoRGBDevice.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_libolausbpro_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_libolausbpro_la-ArduinoRGBDevice.lo `test -f 'plugins/usbpro/ArduinoRGBDevice.cpp' || echo '$(srcdir)/'`plugins/usbpro/ArduinoRGBDevice.cpp plugins/usbpro/plugins_usbpro_libolausbpro_la-DmxTriDevice.lo: plugins/usbpro/DmxTriDevice.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_libolausbpro_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_libolausbpro_la-DmxTriDevice.lo -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_libolausbpro_la-DmxTriDevice.Tpo -c -o plugins/usbpro/plugins_usbpro_libolausbpro_la-DmxTriDevice.lo `test -f 'plugins/usbpro/DmxTriDevice.cpp' || echo '$(srcdir)/'`plugins/usbpro/DmxTriDevice.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_libolausbpro_la-DmxTriDevice.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_libolausbpro_la-DmxTriDevice.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/DmxTriDevice.cpp' object='plugins/usbpro/plugins_usbpro_libolausbpro_la-DmxTriDevice.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_libolausbpro_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_libolausbpro_la-DmxTriDevice.lo `test -f 'plugins/usbpro/DmxTriDevice.cpp' || echo '$(srcdir)/'`plugins/usbpro/DmxTriDevice.cpp plugins/usbpro/plugins_usbpro_libolausbpro_la-DmxterDevice.lo: plugins/usbpro/DmxterDevice.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_libolausbpro_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_libolausbpro_la-DmxterDevice.lo -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_libolausbpro_la-DmxterDevice.Tpo -c -o plugins/usbpro/plugins_usbpro_libolausbpro_la-DmxterDevice.lo `test -f 'plugins/usbpro/DmxterDevice.cpp' || echo '$(srcdir)/'`plugins/usbpro/DmxterDevice.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_libolausbpro_la-DmxterDevice.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_libolausbpro_la-DmxterDevice.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/DmxterDevice.cpp' object='plugins/usbpro/plugins_usbpro_libolausbpro_la-DmxterDevice.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_libolausbpro_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_libolausbpro_la-DmxterDevice.lo `test -f 'plugins/usbpro/DmxterDevice.cpp' || echo '$(srcdir)/'`plugins/usbpro/DmxterDevice.cpp plugins/usbpro/plugins_usbpro_libolausbpro_la-RobeDevice.lo: plugins/usbpro/RobeDevice.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_libolausbpro_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_libolausbpro_la-RobeDevice.lo -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_libolausbpro_la-RobeDevice.Tpo -c -o plugins/usbpro/plugins_usbpro_libolausbpro_la-RobeDevice.lo `test -f 'plugins/usbpro/RobeDevice.cpp' || echo '$(srcdir)/'`plugins/usbpro/RobeDevice.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_libolausbpro_la-RobeDevice.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_libolausbpro_la-RobeDevice.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/RobeDevice.cpp' object='plugins/usbpro/plugins_usbpro_libolausbpro_la-RobeDevice.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_libolausbpro_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_libolausbpro_la-RobeDevice.lo `test -f 'plugins/usbpro/RobeDevice.cpp' || echo '$(srcdir)/'`plugins/usbpro/RobeDevice.cpp plugins/usbpro/plugins_usbpro_libolausbpro_la-UltraDMXProDevice.lo: plugins/usbpro/UltraDMXProDevice.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_libolausbpro_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_libolausbpro_la-UltraDMXProDevice.lo -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_libolausbpro_la-UltraDMXProDevice.Tpo -c -o plugins/usbpro/plugins_usbpro_libolausbpro_la-UltraDMXProDevice.lo `test -f 'plugins/usbpro/UltraDMXProDevice.cpp' || echo '$(srcdir)/'`plugins/usbpro/UltraDMXProDevice.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_libolausbpro_la-UltraDMXProDevice.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_libolausbpro_la-UltraDMXProDevice.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/UltraDMXProDevice.cpp' object='plugins/usbpro/plugins_usbpro_libolausbpro_la-UltraDMXProDevice.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_libolausbpro_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_libolausbpro_la-UltraDMXProDevice.lo `test -f 'plugins/usbpro/UltraDMXProDevice.cpp' || echo '$(srcdir)/'`plugins/usbpro/UltraDMXProDevice.cpp plugins/usbpro/plugins_usbpro_libolausbpro_la-UsbProDevice.lo: plugins/usbpro/UsbProDevice.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_libolausbpro_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_libolausbpro_la-UsbProDevice.lo -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_libolausbpro_la-UsbProDevice.Tpo -c -o plugins/usbpro/plugins_usbpro_libolausbpro_la-UsbProDevice.lo `test -f 'plugins/usbpro/UsbProDevice.cpp' || echo '$(srcdir)/'`plugins/usbpro/UsbProDevice.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_libolausbpro_la-UsbProDevice.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_libolausbpro_la-UsbProDevice.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/UsbProDevice.cpp' object='plugins/usbpro/plugins_usbpro_libolausbpro_la-UsbProDevice.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_libolausbpro_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_libolausbpro_la-UsbProDevice.lo `test -f 'plugins/usbpro/UsbProDevice.cpp' || echo '$(srcdir)/'`plugins/usbpro/UsbProDevice.cpp plugins/usbpro/plugins_usbpro_libolausbpro_la-UsbSerialPlugin.lo: plugins/usbpro/UsbSerialPlugin.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_libolausbpro_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_libolausbpro_la-UsbSerialPlugin.lo -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_libolausbpro_la-UsbSerialPlugin.Tpo -c -o plugins/usbpro/plugins_usbpro_libolausbpro_la-UsbSerialPlugin.lo `test -f 'plugins/usbpro/UsbSerialPlugin.cpp' || echo '$(srcdir)/'`plugins/usbpro/UsbSerialPlugin.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_libolausbpro_la-UsbSerialPlugin.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_libolausbpro_la-UsbSerialPlugin.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/UsbSerialPlugin.cpp' object='plugins/usbpro/plugins_usbpro_libolausbpro_la-UsbSerialPlugin.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_libolausbpro_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_libolausbpro_la-UsbSerialPlugin.lo `test -f 'plugins/usbpro/UsbSerialPlugin.cpp' || echo '$(srcdir)/'`plugins/usbpro/UsbSerialPlugin.cpp plugins/usbpro/messages/plugins_usbpro_messages_libolausbproconf_la-UsbProConfigMessages.pb.lo: plugins/usbpro/messages/UsbProConfigMessages.pb.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_messages_libolausbproconf_la_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/messages/plugins_usbpro_messages_libolausbproconf_la-UsbProConfigMessages.pb.lo -MD -MP -MF plugins/usbpro/messages/$(DEPDIR)/plugins_usbpro_messages_libolausbproconf_la-UsbProConfigMessages.pb.Tpo -c -o plugins/usbpro/messages/plugins_usbpro_messages_libolausbproconf_la-UsbProConfigMessages.pb.lo `test -f 'plugins/usbpro/messages/UsbProConfigMessages.pb.cc' || echo '$(srcdir)/'`plugins/usbpro/messages/UsbProConfigMessages.pb.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/messages/$(DEPDIR)/plugins_usbpro_messages_libolausbproconf_la-UsbProConfigMessages.pb.Tpo plugins/usbpro/messages/$(DEPDIR)/plugins_usbpro_messages_libolausbproconf_la-UsbProConfigMessages.pb.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/messages/UsbProConfigMessages.pb.cc' object='plugins/usbpro/messages/plugins_usbpro_messages_libolausbproconf_la-UsbProConfigMessages.pb.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_messages_libolausbproconf_la_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/messages/plugins_usbpro_messages_libolausbproconf_la-UsbProConfigMessages.pb.lo `test -f 'plugins/usbpro/messages/UsbProConfigMessages.pb.cc' || echo '$(srcdir)/'`plugins/usbpro/messages/UsbProConfigMessages.pb.cc common/base/common_base_CredentialsTester-CredentialsTest.o: common/base/CredentialsTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_base_CredentialsTester_CXXFLAGS) $(CXXFLAGS) -MT common/base/common_base_CredentialsTester-CredentialsTest.o -MD -MP -MF common/base/$(DEPDIR)/common_base_CredentialsTester-CredentialsTest.Tpo -c -o common/base/common_base_CredentialsTester-CredentialsTest.o `test -f 'common/base/CredentialsTest.cpp' || echo '$(srcdir)/'`common/base/CredentialsTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/base/$(DEPDIR)/common_base_CredentialsTester-CredentialsTest.Tpo common/base/$(DEPDIR)/common_base_CredentialsTester-CredentialsTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/base/CredentialsTest.cpp' object='common/base/common_base_CredentialsTester-CredentialsTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_base_CredentialsTester_CXXFLAGS) $(CXXFLAGS) -c -o common/base/common_base_CredentialsTester-CredentialsTest.o `test -f 'common/base/CredentialsTest.cpp' || echo '$(srcdir)/'`common/base/CredentialsTest.cpp common/base/common_base_CredentialsTester-CredentialsTest.obj: common/base/CredentialsTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_base_CredentialsTester_CXXFLAGS) $(CXXFLAGS) -MT common/base/common_base_CredentialsTester-CredentialsTest.obj -MD -MP -MF common/base/$(DEPDIR)/common_base_CredentialsTester-CredentialsTest.Tpo -c -o common/base/common_base_CredentialsTester-CredentialsTest.obj `if test -f 'common/base/CredentialsTest.cpp'; then $(CYGPATH_W) 'common/base/CredentialsTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/base/CredentialsTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/base/$(DEPDIR)/common_base_CredentialsTester-CredentialsTest.Tpo common/base/$(DEPDIR)/common_base_CredentialsTester-CredentialsTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/base/CredentialsTest.cpp' object='common/base/common_base_CredentialsTester-CredentialsTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_base_CredentialsTester_CXXFLAGS) $(CXXFLAGS) -c -o common/base/common_base_CredentialsTester-CredentialsTest.obj `if test -f 'common/base/CredentialsTest.cpp'; then $(CYGPATH_W) 'common/base/CredentialsTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/base/CredentialsTest.cpp'; fi` common/base/common_base_FlagsTester-FlagsTest.o: common/base/FlagsTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_base_FlagsTester_CXXFLAGS) $(CXXFLAGS) -MT common/base/common_base_FlagsTester-FlagsTest.o -MD -MP -MF common/base/$(DEPDIR)/common_base_FlagsTester-FlagsTest.Tpo -c -o common/base/common_base_FlagsTester-FlagsTest.o `test -f 'common/base/FlagsTest.cpp' || echo '$(srcdir)/'`common/base/FlagsTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/base/$(DEPDIR)/common_base_FlagsTester-FlagsTest.Tpo common/base/$(DEPDIR)/common_base_FlagsTester-FlagsTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/base/FlagsTest.cpp' object='common/base/common_base_FlagsTester-FlagsTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_base_FlagsTester_CXXFLAGS) $(CXXFLAGS) -c -o common/base/common_base_FlagsTester-FlagsTest.o `test -f 'common/base/FlagsTest.cpp' || echo '$(srcdir)/'`common/base/FlagsTest.cpp common/base/common_base_FlagsTester-FlagsTest.obj: common/base/FlagsTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_base_FlagsTester_CXXFLAGS) $(CXXFLAGS) -MT common/base/common_base_FlagsTester-FlagsTest.obj -MD -MP -MF common/base/$(DEPDIR)/common_base_FlagsTester-FlagsTest.Tpo -c -o common/base/common_base_FlagsTester-FlagsTest.obj `if test -f 'common/base/FlagsTest.cpp'; then $(CYGPATH_W) 'common/base/FlagsTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/base/FlagsTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/base/$(DEPDIR)/common_base_FlagsTester-FlagsTest.Tpo common/base/$(DEPDIR)/common_base_FlagsTester-FlagsTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/base/FlagsTest.cpp' object='common/base/common_base_FlagsTester-FlagsTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_base_FlagsTester_CXXFLAGS) $(CXXFLAGS) -c -o common/base/common_base_FlagsTester-FlagsTest.obj `if test -f 'common/base/FlagsTest.cpp'; then $(CYGPATH_W) 'common/base/FlagsTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/base/FlagsTest.cpp'; fi` common/base/common_base_LoggingTester-LoggingTest.o: common/base/LoggingTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_base_LoggingTester_CXXFLAGS) $(CXXFLAGS) -MT common/base/common_base_LoggingTester-LoggingTest.o -MD -MP -MF common/base/$(DEPDIR)/common_base_LoggingTester-LoggingTest.Tpo -c -o common/base/common_base_LoggingTester-LoggingTest.o `test -f 'common/base/LoggingTest.cpp' || echo '$(srcdir)/'`common/base/LoggingTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/base/$(DEPDIR)/common_base_LoggingTester-LoggingTest.Tpo common/base/$(DEPDIR)/common_base_LoggingTester-LoggingTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/base/LoggingTest.cpp' object='common/base/common_base_LoggingTester-LoggingTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_base_LoggingTester_CXXFLAGS) $(CXXFLAGS) -c -o common/base/common_base_LoggingTester-LoggingTest.o `test -f 'common/base/LoggingTest.cpp' || echo '$(srcdir)/'`common/base/LoggingTest.cpp common/base/common_base_LoggingTester-LoggingTest.obj: common/base/LoggingTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_base_LoggingTester_CXXFLAGS) $(CXXFLAGS) -MT common/base/common_base_LoggingTester-LoggingTest.obj -MD -MP -MF common/base/$(DEPDIR)/common_base_LoggingTester-LoggingTest.Tpo -c -o common/base/common_base_LoggingTester-LoggingTest.obj `if test -f 'common/base/LoggingTest.cpp'; then $(CYGPATH_W) 'common/base/LoggingTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/base/LoggingTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/base/$(DEPDIR)/common_base_LoggingTester-LoggingTest.Tpo common/base/$(DEPDIR)/common_base_LoggingTester-LoggingTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/base/LoggingTest.cpp' object='common/base/common_base_LoggingTester-LoggingTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_base_LoggingTester_CXXFLAGS) $(CXXFLAGS) -c -o common/base/common_base_LoggingTester-LoggingTest.obj `if test -f 'common/base/LoggingTest.cpp'; then $(CYGPATH_W) 'common/base/LoggingTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/base/LoggingTest.cpp'; fi` common/dmx/common_dmx_RunLengthEncoderTester-RunLengthEncoderTest.o: common/dmx/RunLengthEncoderTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_dmx_RunLengthEncoderTester_CXXFLAGS) $(CXXFLAGS) -MT common/dmx/common_dmx_RunLengthEncoderTester-RunLengthEncoderTest.o -MD -MP -MF common/dmx/$(DEPDIR)/common_dmx_RunLengthEncoderTester-RunLengthEncoderTest.Tpo -c -o common/dmx/common_dmx_RunLengthEncoderTester-RunLengthEncoderTest.o `test -f 'common/dmx/RunLengthEncoderTest.cpp' || echo '$(srcdir)/'`common/dmx/RunLengthEncoderTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/dmx/$(DEPDIR)/common_dmx_RunLengthEncoderTester-RunLengthEncoderTest.Tpo common/dmx/$(DEPDIR)/common_dmx_RunLengthEncoderTester-RunLengthEncoderTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/dmx/RunLengthEncoderTest.cpp' object='common/dmx/common_dmx_RunLengthEncoderTester-RunLengthEncoderTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_dmx_RunLengthEncoderTester_CXXFLAGS) $(CXXFLAGS) -c -o common/dmx/common_dmx_RunLengthEncoderTester-RunLengthEncoderTest.o `test -f 'common/dmx/RunLengthEncoderTest.cpp' || echo '$(srcdir)/'`common/dmx/RunLengthEncoderTest.cpp common/dmx/common_dmx_RunLengthEncoderTester-RunLengthEncoderTest.obj: common/dmx/RunLengthEncoderTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_dmx_RunLengthEncoderTester_CXXFLAGS) $(CXXFLAGS) -MT common/dmx/common_dmx_RunLengthEncoderTester-RunLengthEncoderTest.obj -MD -MP -MF common/dmx/$(DEPDIR)/common_dmx_RunLengthEncoderTester-RunLengthEncoderTest.Tpo -c -o common/dmx/common_dmx_RunLengthEncoderTester-RunLengthEncoderTest.obj `if test -f 'common/dmx/RunLengthEncoderTest.cpp'; then $(CYGPATH_W) 'common/dmx/RunLengthEncoderTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/dmx/RunLengthEncoderTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/dmx/$(DEPDIR)/common_dmx_RunLengthEncoderTester-RunLengthEncoderTest.Tpo common/dmx/$(DEPDIR)/common_dmx_RunLengthEncoderTester-RunLengthEncoderTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/dmx/RunLengthEncoderTest.cpp' object='common/dmx/common_dmx_RunLengthEncoderTester-RunLengthEncoderTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_dmx_RunLengthEncoderTester_CXXFLAGS) $(CXXFLAGS) -c -o common/dmx/common_dmx_RunLengthEncoderTester-RunLengthEncoderTest.obj `if test -f 'common/dmx/RunLengthEncoderTest.cpp'; then $(CYGPATH_W) 'common/dmx/RunLengthEncoderTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/dmx/RunLengthEncoderTest.cpp'; fi` common/export_map/common_export_map_ExportMapTester-ExportMapTest.o: common/export_map/ExportMapTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_export_map_ExportMapTester_CXXFLAGS) $(CXXFLAGS) -MT common/export_map/common_export_map_ExportMapTester-ExportMapTest.o -MD -MP -MF common/export_map/$(DEPDIR)/common_export_map_ExportMapTester-ExportMapTest.Tpo -c -o common/export_map/common_export_map_ExportMapTester-ExportMapTest.o `test -f 'common/export_map/ExportMapTest.cpp' || echo '$(srcdir)/'`common/export_map/ExportMapTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/export_map/$(DEPDIR)/common_export_map_ExportMapTester-ExportMapTest.Tpo common/export_map/$(DEPDIR)/common_export_map_ExportMapTester-ExportMapTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/export_map/ExportMapTest.cpp' object='common/export_map/common_export_map_ExportMapTester-ExportMapTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_export_map_ExportMapTester_CXXFLAGS) $(CXXFLAGS) -c -o common/export_map/common_export_map_ExportMapTester-ExportMapTest.o `test -f 'common/export_map/ExportMapTest.cpp' || echo '$(srcdir)/'`common/export_map/ExportMapTest.cpp common/export_map/common_export_map_ExportMapTester-ExportMapTest.obj: common/export_map/ExportMapTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_export_map_ExportMapTester_CXXFLAGS) $(CXXFLAGS) -MT common/export_map/common_export_map_ExportMapTester-ExportMapTest.obj -MD -MP -MF common/export_map/$(DEPDIR)/common_export_map_ExportMapTester-ExportMapTest.Tpo -c -o common/export_map/common_export_map_ExportMapTester-ExportMapTest.obj `if test -f 'common/export_map/ExportMapTest.cpp'; then $(CYGPATH_W) 'common/export_map/ExportMapTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/export_map/ExportMapTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/export_map/$(DEPDIR)/common_export_map_ExportMapTester-ExportMapTest.Tpo common/export_map/$(DEPDIR)/common_export_map_ExportMapTester-ExportMapTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/export_map/ExportMapTest.cpp' object='common/export_map/common_export_map_ExportMapTester-ExportMapTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_export_map_ExportMapTester_CXXFLAGS) $(CXXFLAGS) -c -o common/export_map/common_export_map_ExportMapTester-ExportMapTest.obj `if test -f 'common/export_map/ExportMapTest.cpp'; then $(CYGPATH_W) 'common/export_map/ExportMapTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/export_map/ExportMapTest.cpp'; fi` common/file/common_file_UtilTester-UtilTest.o: common/file/UtilTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_file_UtilTester_CXXFLAGS) $(CXXFLAGS) -MT common/file/common_file_UtilTester-UtilTest.o -MD -MP -MF common/file/$(DEPDIR)/common_file_UtilTester-UtilTest.Tpo -c -o common/file/common_file_UtilTester-UtilTest.o `test -f 'common/file/UtilTest.cpp' || echo '$(srcdir)/'`common/file/UtilTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/file/$(DEPDIR)/common_file_UtilTester-UtilTest.Tpo common/file/$(DEPDIR)/common_file_UtilTester-UtilTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/file/UtilTest.cpp' object='common/file/common_file_UtilTester-UtilTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_file_UtilTester_CXXFLAGS) $(CXXFLAGS) -c -o common/file/common_file_UtilTester-UtilTest.o `test -f 'common/file/UtilTest.cpp' || echo '$(srcdir)/'`common/file/UtilTest.cpp common/file/common_file_UtilTester-UtilTest.obj: common/file/UtilTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_file_UtilTester_CXXFLAGS) $(CXXFLAGS) -MT common/file/common_file_UtilTester-UtilTest.obj -MD -MP -MF common/file/$(DEPDIR)/common_file_UtilTester-UtilTest.Tpo -c -o common/file/common_file_UtilTester-UtilTest.obj `if test -f 'common/file/UtilTest.cpp'; then $(CYGPATH_W) 'common/file/UtilTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/file/UtilTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/file/$(DEPDIR)/common_file_UtilTester-UtilTest.Tpo common/file/$(DEPDIR)/common_file_UtilTester-UtilTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/file/UtilTest.cpp' object='common/file/common_file_UtilTester-UtilTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_file_UtilTester_CXXFLAGS) $(CXXFLAGS) -c -o common/file/common_file_UtilTester-UtilTest.obj `if test -f 'common/file/UtilTest.cpp'; then $(CYGPATH_W) 'common/file/UtilTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/file/UtilTest.cpp'; fi` common/io/common_io_DescriptorTester-DescriptorTest.o: common/io/DescriptorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_DescriptorTester_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_io_DescriptorTester-DescriptorTest.o -MD -MP -MF common/io/$(DEPDIR)/common_io_DescriptorTester-DescriptorTest.Tpo -c -o common/io/common_io_DescriptorTester-DescriptorTest.o `test -f 'common/io/DescriptorTest.cpp' || echo '$(srcdir)/'`common/io/DescriptorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_io_DescriptorTester-DescriptorTest.Tpo common/io/$(DEPDIR)/common_io_DescriptorTester-DescriptorTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/DescriptorTest.cpp' object='common/io/common_io_DescriptorTester-DescriptorTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_DescriptorTester_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_io_DescriptorTester-DescriptorTest.o `test -f 'common/io/DescriptorTest.cpp' || echo '$(srcdir)/'`common/io/DescriptorTest.cpp common/io/common_io_DescriptorTester-DescriptorTest.obj: common/io/DescriptorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_DescriptorTester_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_io_DescriptorTester-DescriptorTest.obj -MD -MP -MF common/io/$(DEPDIR)/common_io_DescriptorTester-DescriptorTest.Tpo -c -o common/io/common_io_DescriptorTester-DescriptorTest.obj `if test -f 'common/io/DescriptorTest.cpp'; then $(CYGPATH_W) 'common/io/DescriptorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/io/DescriptorTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_io_DescriptorTester-DescriptorTest.Tpo common/io/$(DEPDIR)/common_io_DescriptorTester-DescriptorTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/DescriptorTest.cpp' object='common/io/common_io_DescriptorTester-DescriptorTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_DescriptorTester_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_io_DescriptorTester-DescriptorTest.obj `if test -f 'common/io/DescriptorTest.cpp'; then $(CYGPATH_W) 'common/io/DescriptorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/io/DescriptorTest.cpp'; fi` common/io/common_io_IOQueueTester-IOQueueTest.o: common/io/IOQueueTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_IOQueueTester_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_io_IOQueueTester-IOQueueTest.o -MD -MP -MF common/io/$(DEPDIR)/common_io_IOQueueTester-IOQueueTest.Tpo -c -o common/io/common_io_IOQueueTester-IOQueueTest.o `test -f 'common/io/IOQueueTest.cpp' || echo '$(srcdir)/'`common/io/IOQueueTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_io_IOQueueTester-IOQueueTest.Tpo common/io/$(DEPDIR)/common_io_IOQueueTester-IOQueueTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/IOQueueTest.cpp' object='common/io/common_io_IOQueueTester-IOQueueTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_IOQueueTester_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_io_IOQueueTester-IOQueueTest.o `test -f 'common/io/IOQueueTest.cpp' || echo '$(srcdir)/'`common/io/IOQueueTest.cpp common/io/common_io_IOQueueTester-IOQueueTest.obj: common/io/IOQueueTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_IOQueueTester_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_io_IOQueueTester-IOQueueTest.obj -MD -MP -MF common/io/$(DEPDIR)/common_io_IOQueueTester-IOQueueTest.Tpo -c -o common/io/common_io_IOQueueTester-IOQueueTest.obj `if test -f 'common/io/IOQueueTest.cpp'; then $(CYGPATH_W) 'common/io/IOQueueTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/io/IOQueueTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_io_IOQueueTester-IOQueueTest.Tpo common/io/$(DEPDIR)/common_io_IOQueueTester-IOQueueTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/IOQueueTest.cpp' object='common/io/common_io_IOQueueTester-IOQueueTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_IOQueueTester_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_io_IOQueueTester-IOQueueTest.obj `if test -f 'common/io/IOQueueTest.cpp'; then $(CYGPATH_W) 'common/io/IOQueueTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/io/IOQueueTest.cpp'; fi` common/io/common_io_IOStackTester-IOStackTest.o: common/io/IOStackTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_IOStackTester_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_io_IOStackTester-IOStackTest.o -MD -MP -MF common/io/$(DEPDIR)/common_io_IOStackTester-IOStackTest.Tpo -c -o common/io/common_io_IOStackTester-IOStackTest.o `test -f 'common/io/IOStackTest.cpp' || echo '$(srcdir)/'`common/io/IOStackTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_io_IOStackTester-IOStackTest.Tpo common/io/$(DEPDIR)/common_io_IOStackTester-IOStackTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/IOStackTest.cpp' object='common/io/common_io_IOStackTester-IOStackTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_IOStackTester_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_io_IOStackTester-IOStackTest.o `test -f 'common/io/IOStackTest.cpp' || echo '$(srcdir)/'`common/io/IOStackTest.cpp common/io/common_io_IOStackTester-IOStackTest.obj: common/io/IOStackTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_IOStackTester_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_io_IOStackTester-IOStackTest.obj -MD -MP -MF common/io/$(DEPDIR)/common_io_IOStackTester-IOStackTest.Tpo -c -o common/io/common_io_IOStackTester-IOStackTest.obj `if test -f 'common/io/IOStackTest.cpp'; then $(CYGPATH_W) 'common/io/IOStackTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/io/IOStackTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_io_IOStackTester-IOStackTest.Tpo common/io/$(DEPDIR)/common_io_IOStackTester-IOStackTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/IOStackTest.cpp' object='common/io/common_io_IOStackTester-IOStackTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_IOStackTester_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_io_IOStackTester-IOStackTest.obj `if test -f 'common/io/IOStackTest.cpp'; then $(CYGPATH_W) 'common/io/IOStackTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/io/IOStackTest.cpp'; fi` common/io/common_io_MemoryBlockTester-MemoryBlockTest.o: common/io/MemoryBlockTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_MemoryBlockTester_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_io_MemoryBlockTester-MemoryBlockTest.o -MD -MP -MF common/io/$(DEPDIR)/common_io_MemoryBlockTester-MemoryBlockTest.Tpo -c -o common/io/common_io_MemoryBlockTester-MemoryBlockTest.o `test -f 'common/io/MemoryBlockTest.cpp' || echo '$(srcdir)/'`common/io/MemoryBlockTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_io_MemoryBlockTester-MemoryBlockTest.Tpo common/io/$(DEPDIR)/common_io_MemoryBlockTester-MemoryBlockTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/MemoryBlockTest.cpp' object='common/io/common_io_MemoryBlockTester-MemoryBlockTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_MemoryBlockTester_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_io_MemoryBlockTester-MemoryBlockTest.o `test -f 'common/io/MemoryBlockTest.cpp' || echo '$(srcdir)/'`common/io/MemoryBlockTest.cpp common/io/common_io_MemoryBlockTester-MemoryBlockTest.obj: common/io/MemoryBlockTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_MemoryBlockTester_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_io_MemoryBlockTester-MemoryBlockTest.obj -MD -MP -MF common/io/$(DEPDIR)/common_io_MemoryBlockTester-MemoryBlockTest.Tpo -c -o common/io/common_io_MemoryBlockTester-MemoryBlockTest.obj `if test -f 'common/io/MemoryBlockTest.cpp'; then $(CYGPATH_W) 'common/io/MemoryBlockTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/io/MemoryBlockTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_io_MemoryBlockTester-MemoryBlockTest.Tpo common/io/$(DEPDIR)/common_io_MemoryBlockTester-MemoryBlockTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/MemoryBlockTest.cpp' object='common/io/common_io_MemoryBlockTester-MemoryBlockTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_MemoryBlockTester_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_io_MemoryBlockTester-MemoryBlockTest.obj `if test -f 'common/io/MemoryBlockTest.cpp'; then $(CYGPATH_W) 'common/io/MemoryBlockTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/io/MemoryBlockTest.cpp'; fi` common/io/common_io_SelectServerTester-SelectServerTest.o: common/io/SelectServerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_SelectServerTester_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_io_SelectServerTester-SelectServerTest.o -MD -MP -MF common/io/$(DEPDIR)/common_io_SelectServerTester-SelectServerTest.Tpo -c -o common/io/common_io_SelectServerTester-SelectServerTest.o `test -f 'common/io/SelectServerTest.cpp' || echo '$(srcdir)/'`common/io/SelectServerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_io_SelectServerTester-SelectServerTest.Tpo common/io/$(DEPDIR)/common_io_SelectServerTester-SelectServerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/SelectServerTest.cpp' object='common/io/common_io_SelectServerTester-SelectServerTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_SelectServerTester_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_io_SelectServerTester-SelectServerTest.o `test -f 'common/io/SelectServerTest.cpp' || echo '$(srcdir)/'`common/io/SelectServerTest.cpp common/io/common_io_SelectServerTester-SelectServerTest.obj: common/io/SelectServerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_SelectServerTester_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_io_SelectServerTester-SelectServerTest.obj -MD -MP -MF common/io/$(DEPDIR)/common_io_SelectServerTester-SelectServerTest.Tpo -c -o common/io/common_io_SelectServerTester-SelectServerTest.obj `if test -f 'common/io/SelectServerTest.cpp'; then $(CYGPATH_W) 'common/io/SelectServerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/io/SelectServerTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_io_SelectServerTester-SelectServerTest.Tpo common/io/$(DEPDIR)/common_io_SelectServerTester-SelectServerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/SelectServerTest.cpp' object='common/io/common_io_SelectServerTester-SelectServerTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_SelectServerTester_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_io_SelectServerTester-SelectServerTest.obj `if test -f 'common/io/SelectServerTest.cpp'; then $(CYGPATH_W) 'common/io/SelectServerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/io/SelectServerTest.cpp'; fi` common/io/common_io_SelectServerTester-SelectServerThreadTest.o: common/io/SelectServerThreadTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_SelectServerTester_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_io_SelectServerTester-SelectServerThreadTest.o -MD -MP -MF common/io/$(DEPDIR)/common_io_SelectServerTester-SelectServerThreadTest.Tpo -c -o common/io/common_io_SelectServerTester-SelectServerThreadTest.o `test -f 'common/io/SelectServerThreadTest.cpp' || echo '$(srcdir)/'`common/io/SelectServerThreadTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_io_SelectServerTester-SelectServerThreadTest.Tpo common/io/$(DEPDIR)/common_io_SelectServerTester-SelectServerThreadTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/SelectServerThreadTest.cpp' object='common/io/common_io_SelectServerTester-SelectServerThreadTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_SelectServerTester_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_io_SelectServerTester-SelectServerThreadTest.o `test -f 'common/io/SelectServerThreadTest.cpp' || echo '$(srcdir)/'`common/io/SelectServerThreadTest.cpp common/io/common_io_SelectServerTester-SelectServerThreadTest.obj: common/io/SelectServerThreadTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_SelectServerTester_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_io_SelectServerTester-SelectServerThreadTest.obj -MD -MP -MF common/io/$(DEPDIR)/common_io_SelectServerTester-SelectServerThreadTest.Tpo -c -o common/io/common_io_SelectServerTester-SelectServerThreadTest.obj `if test -f 'common/io/SelectServerThreadTest.cpp'; then $(CYGPATH_W) 'common/io/SelectServerThreadTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/io/SelectServerThreadTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_io_SelectServerTester-SelectServerThreadTest.Tpo common/io/$(DEPDIR)/common_io_SelectServerTester-SelectServerThreadTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/SelectServerThreadTest.cpp' object='common/io/common_io_SelectServerTester-SelectServerThreadTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_SelectServerTester_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_io_SelectServerTester-SelectServerThreadTest.obj `if test -f 'common/io/SelectServerThreadTest.cpp'; then $(CYGPATH_W) 'common/io/SelectServerThreadTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/io/SelectServerThreadTest.cpp'; fi` common/io/common_io_StreamTester-InputStreamTest.o: common/io/InputStreamTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_StreamTester_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_io_StreamTester-InputStreamTest.o -MD -MP -MF common/io/$(DEPDIR)/common_io_StreamTester-InputStreamTest.Tpo -c -o common/io/common_io_StreamTester-InputStreamTest.o `test -f 'common/io/InputStreamTest.cpp' || echo '$(srcdir)/'`common/io/InputStreamTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_io_StreamTester-InputStreamTest.Tpo common/io/$(DEPDIR)/common_io_StreamTester-InputStreamTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/InputStreamTest.cpp' object='common/io/common_io_StreamTester-InputStreamTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_StreamTester_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_io_StreamTester-InputStreamTest.o `test -f 'common/io/InputStreamTest.cpp' || echo '$(srcdir)/'`common/io/InputStreamTest.cpp common/io/common_io_StreamTester-InputStreamTest.obj: common/io/InputStreamTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_StreamTester_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_io_StreamTester-InputStreamTest.obj -MD -MP -MF common/io/$(DEPDIR)/common_io_StreamTester-InputStreamTest.Tpo -c -o common/io/common_io_StreamTester-InputStreamTest.obj `if test -f 'common/io/InputStreamTest.cpp'; then $(CYGPATH_W) 'common/io/InputStreamTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/io/InputStreamTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_io_StreamTester-InputStreamTest.Tpo common/io/$(DEPDIR)/common_io_StreamTester-InputStreamTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/InputStreamTest.cpp' object='common/io/common_io_StreamTester-InputStreamTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_StreamTester_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_io_StreamTester-InputStreamTest.obj `if test -f 'common/io/InputStreamTest.cpp'; then $(CYGPATH_W) 'common/io/InputStreamTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/io/InputStreamTest.cpp'; fi` common/io/common_io_StreamTester-OutputStreamTest.o: common/io/OutputStreamTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_StreamTester_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_io_StreamTester-OutputStreamTest.o -MD -MP -MF common/io/$(DEPDIR)/common_io_StreamTester-OutputStreamTest.Tpo -c -o common/io/common_io_StreamTester-OutputStreamTest.o `test -f 'common/io/OutputStreamTest.cpp' || echo '$(srcdir)/'`common/io/OutputStreamTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_io_StreamTester-OutputStreamTest.Tpo common/io/$(DEPDIR)/common_io_StreamTester-OutputStreamTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/OutputStreamTest.cpp' object='common/io/common_io_StreamTester-OutputStreamTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_StreamTester_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_io_StreamTester-OutputStreamTest.o `test -f 'common/io/OutputStreamTest.cpp' || echo '$(srcdir)/'`common/io/OutputStreamTest.cpp common/io/common_io_StreamTester-OutputStreamTest.obj: common/io/OutputStreamTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_StreamTester_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_io_StreamTester-OutputStreamTest.obj -MD -MP -MF common/io/$(DEPDIR)/common_io_StreamTester-OutputStreamTest.Tpo -c -o common/io/common_io_StreamTester-OutputStreamTest.obj `if test -f 'common/io/OutputStreamTest.cpp'; then $(CYGPATH_W) 'common/io/OutputStreamTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/io/OutputStreamTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_io_StreamTester-OutputStreamTest.Tpo common/io/$(DEPDIR)/common_io_StreamTester-OutputStreamTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/OutputStreamTest.cpp' object='common/io/common_io_StreamTester-OutputStreamTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_StreamTester_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_io_StreamTester-OutputStreamTest.obj `if test -f 'common/io/OutputStreamTest.cpp'; then $(CYGPATH_W) 'common/io/OutputStreamTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/io/OutputStreamTest.cpp'; fi` common/io/common_io_TimeoutManagerTester-TimeoutManagerTest.o: common/io/TimeoutManagerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_TimeoutManagerTester_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_io_TimeoutManagerTester-TimeoutManagerTest.o -MD -MP -MF common/io/$(DEPDIR)/common_io_TimeoutManagerTester-TimeoutManagerTest.Tpo -c -o common/io/common_io_TimeoutManagerTester-TimeoutManagerTest.o `test -f 'common/io/TimeoutManagerTest.cpp' || echo '$(srcdir)/'`common/io/TimeoutManagerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_io_TimeoutManagerTester-TimeoutManagerTest.Tpo common/io/$(DEPDIR)/common_io_TimeoutManagerTester-TimeoutManagerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/TimeoutManagerTest.cpp' object='common/io/common_io_TimeoutManagerTester-TimeoutManagerTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_TimeoutManagerTester_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_io_TimeoutManagerTester-TimeoutManagerTest.o `test -f 'common/io/TimeoutManagerTest.cpp' || echo '$(srcdir)/'`common/io/TimeoutManagerTest.cpp common/io/common_io_TimeoutManagerTester-TimeoutManagerTest.obj: common/io/TimeoutManagerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_TimeoutManagerTester_CXXFLAGS) $(CXXFLAGS) -MT common/io/common_io_TimeoutManagerTester-TimeoutManagerTest.obj -MD -MP -MF common/io/$(DEPDIR)/common_io_TimeoutManagerTester-TimeoutManagerTest.Tpo -c -o common/io/common_io_TimeoutManagerTester-TimeoutManagerTest.obj `if test -f 'common/io/TimeoutManagerTest.cpp'; then $(CYGPATH_W) 'common/io/TimeoutManagerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/io/TimeoutManagerTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/io/$(DEPDIR)/common_io_TimeoutManagerTester-TimeoutManagerTest.Tpo common/io/$(DEPDIR)/common_io_TimeoutManagerTester-TimeoutManagerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/io/TimeoutManagerTest.cpp' object='common/io/common_io_TimeoutManagerTester-TimeoutManagerTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_io_TimeoutManagerTester_CXXFLAGS) $(CXXFLAGS) -c -o common/io/common_io_TimeoutManagerTester-TimeoutManagerTest.obj `if test -f 'common/io/TimeoutManagerTest.cpp'; then $(CYGPATH_W) 'common/io/TimeoutManagerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/io/TimeoutManagerTest.cpp'; fi` common/messaging/common_messaging_DescriptorTester-DescriptorTest.o: common/messaging/DescriptorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_messaging_DescriptorTester_CXXFLAGS) $(CXXFLAGS) -MT common/messaging/common_messaging_DescriptorTester-DescriptorTest.o -MD -MP -MF common/messaging/$(DEPDIR)/common_messaging_DescriptorTester-DescriptorTest.Tpo -c -o common/messaging/common_messaging_DescriptorTester-DescriptorTest.o `test -f 'common/messaging/DescriptorTest.cpp' || echo '$(srcdir)/'`common/messaging/DescriptorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/messaging/$(DEPDIR)/common_messaging_DescriptorTester-DescriptorTest.Tpo common/messaging/$(DEPDIR)/common_messaging_DescriptorTester-DescriptorTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/messaging/DescriptorTest.cpp' object='common/messaging/common_messaging_DescriptorTester-DescriptorTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_messaging_DescriptorTester_CXXFLAGS) $(CXXFLAGS) -c -o common/messaging/common_messaging_DescriptorTester-DescriptorTest.o `test -f 'common/messaging/DescriptorTest.cpp' || echo '$(srcdir)/'`common/messaging/DescriptorTest.cpp common/messaging/common_messaging_DescriptorTester-DescriptorTest.obj: common/messaging/DescriptorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_messaging_DescriptorTester_CXXFLAGS) $(CXXFLAGS) -MT common/messaging/common_messaging_DescriptorTester-DescriptorTest.obj -MD -MP -MF common/messaging/$(DEPDIR)/common_messaging_DescriptorTester-DescriptorTest.Tpo -c -o common/messaging/common_messaging_DescriptorTester-DescriptorTest.obj `if test -f 'common/messaging/DescriptorTest.cpp'; then $(CYGPATH_W) 'common/messaging/DescriptorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/messaging/DescriptorTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/messaging/$(DEPDIR)/common_messaging_DescriptorTester-DescriptorTest.Tpo common/messaging/$(DEPDIR)/common_messaging_DescriptorTester-DescriptorTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/messaging/DescriptorTest.cpp' object='common/messaging/common_messaging_DescriptorTester-DescriptorTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_messaging_DescriptorTester_CXXFLAGS) $(CXXFLAGS) -c -o common/messaging/common_messaging_DescriptorTester-DescriptorTest.obj `if test -f 'common/messaging/DescriptorTest.cpp'; then $(CYGPATH_W) 'common/messaging/DescriptorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/messaging/DescriptorTest.cpp'; fi` common/messaging/common_messaging_DescriptorTester-SchemaPrinterTest.o: common/messaging/SchemaPrinterTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_messaging_DescriptorTester_CXXFLAGS) $(CXXFLAGS) -MT common/messaging/common_messaging_DescriptorTester-SchemaPrinterTest.o -MD -MP -MF common/messaging/$(DEPDIR)/common_messaging_DescriptorTester-SchemaPrinterTest.Tpo -c -o common/messaging/common_messaging_DescriptorTester-SchemaPrinterTest.o `test -f 'common/messaging/SchemaPrinterTest.cpp' || echo '$(srcdir)/'`common/messaging/SchemaPrinterTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/messaging/$(DEPDIR)/common_messaging_DescriptorTester-SchemaPrinterTest.Tpo common/messaging/$(DEPDIR)/common_messaging_DescriptorTester-SchemaPrinterTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/messaging/SchemaPrinterTest.cpp' object='common/messaging/common_messaging_DescriptorTester-SchemaPrinterTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_messaging_DescriptorTester_CXXFLAGS) $(CXXFLAGS) -c -o common/messaging/common_messaging_DescriptorTester-SchemaPrinterTest.o `test -f 'common/messaging/SchemaPrinterTest.cpp' || echo '$(srcdir)/'`common/messaging/SchemaPrinterTest.cpp common/messaging/common_messaging_DescriptorTester-SchemaPrinterTest.obj: common/messaging/SchemaPrinterTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_messaging_DescriptorTester_CXXFLAGS) $(CXXFLAGS) -MT common/messaging/common_messaging_DescriptorTester-SchemaPrinterTest.obj -MD -MP -MF common/messaging/$(DEPDIR)/common_messaging_DescriptorTester-SchemaPrinterTest.Tpo -c -o common/messaging/common_messaging_DescriptorTester-SchemaPrinterTest.obj `if test -f 'common/messaging/SchemaPrinterTest.cpp'; then $(CYGPATH_W) 'common/messaging/SchemaPrinterTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/messaging/SchemaPrinterTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/messaging/$(DEPDIR)/common_messaging_DescriptorTester-SchemaPrinterTest.Tpo common/messaging/$(DEPDIR)/common_messaging_DescriptorTester-SchemaPrinterTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/messaging/SchemaPrinterTest.cpp' object='common/messaging/common_messaging_DescriptorTester-SchemaPrinterTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_messaging_DescriptorTester_CXXFLAGS) $(CXXFLAGS) -c -o common/messaging/common_messaging_DescriptorTester-SchemaPrinterTest.obj `if test -f 'common/messaging/SchemaPrinterTest.cpp'; then $(CYGPATH_W) 'common/messaging/SchemaPrinterTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/messaging/SchemaPrinterTest.cpp'; fi` common/messaging/common_messaging_DescriptorTester-MessagePrinterTest.o: common/messaging/MessagePrinterTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_messaging_DescriptorTester_CXXFLAGS) $(CXXFLAGS) -MT common/messaging/common_messaging_DescriptorTester-MessagePrinterTest.o -MD -MP -MF common/messaging/$(DEPDIR)/common_messaging_DescriptorTester-MessagePrinterTest.Tpo -c -o common/messaging/common_messaging_DescriptorTester-MessagePrinterTest.o `test -f 'common/messaging/MessagePrinterTest.cpp' || echo '$(srcdir)/'`common/messaging/MessagePrinterTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/messaging/$(DEPDIR)/common_messaging_DescriptorTester-MessagePrinterTest.Tpo common/messaging/$(DEPDIR)/common_messaging_DescriptorTester-MessagePrinterTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/messaging/MessagePrinterTest.cpp' object='common/messaging/common_messaging_DescriptorTester-MessagePrinterTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_messaging_DescriptorTester_CXXFLAGS) $(CXXFLAGS) -c -o common/messaging/common_messaging_DescriptorTester-MessagePrinterTest.o `test -f 'common/messaging/MessagePrinterTest.cpp' || echo '$(srcdir)/'`common/messaging/MessagePrinterTest.cpp common/messaging/common_messaging_DescriptorTester-MessagePrinterTest.obj: common/messaging/MessagePrinterTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_messaging_DescriptorTester_CXXFLAGS) $(CXXFLAGS) -MT common/messaging/common_messaging_DescriptorTester-MessagePrinterTest.obj -MD -MP -MF common/messaging/$(DEPDIR)/common_messaging_DescriptorTester-MessagePrinterTest.Tpo -c -o common/messaging/common_messaging_DescriptorTester-MessagePrinterTest.obj `if test -f 'common/messaging/MessagePrinterTest.cpp'; then $(CYGPATH_W) 'common/messaging/MessagePrinterTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/messaging/MessagePrinterTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/messaging/$(DEPDIR)/common_messaging_DescriptorTester-MessagePrinterTest.Tpo common/messaging/$(DEPDIR)/common_messaging_DescriptorTester-MessagePrinterTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/messaging/MessagePrinterTest.cpp' object='common/messaging/common_messaging_DescriptorTester-MessagePrinterTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_messaging_DescriptorTester_CXXFLAGS) $(CXXFLAGS) -c -o common/messaging/common_messaging_DescriptorTester-MessagePrinterTest.obj `if test -f 'common/messaging/MessagePrinterTest.cpp'; then $(CYGPATH_W) 'common/messaging/MessagePrinterTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/messaging/MessagePrinterTest.cpp'; fi` common/network/common_network_HealthCheckedConnectionTester-HealthCheckedConnectionTest.o: common/network/HealthCheckedConnectionTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_HealthCheckedConnectionTester_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_network_HealthCheckedConnectionTester-HealthCheckedConnectionTest.o -MD -MP -MF common/network/$(DEPDIR)/common_network_HealthCheckedConnectionTester-HealthCheckedConnectionTest.Tpo -c -o common/network/common_network_HealthCheckedConnectionTester-HealthCheckedConnectionTest.o `test -f 'common/network/HealthCheckedConnectionTest.cpp' || echo '$(srcdir)/'`common/network/HealthCheckedConnectionTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_network_HealthCheckedConnectionTester-HealthCheckedConnectionTest.Tpo common/network/$(DEPDIR)/common_network_HealthCheckedConnectionTester-HealthCheckedConnectionTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/HealthCheckedConnectionTest.cpp' object='common/network/common_network_HealthCheckedConnectionTester-HealthCheckedConnectionTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_HealthCheckedConnectionTester_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_network_HealthCheckedConnectionTester-HealthCheckedConnectionTest.o `test -f 'common/network/HealthCheckedConnectionTest.cpp' || echo '$(srcdir)/'`common/network/HealthCheckedConnectionTest.cpp common/network/common_network_HealthCheckedConnectionTester-HealthCheckedConnectionTest.obj: common/network/HealthCheckedConnectionTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_HealthCheckedConnectionTester_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_network_HealthCheckedConnectionTester-HealthCheckedConnectionTest.obj -MD -MP -MF common/network/$(DEPDIR)/common_network_HealthCheckedConnectionTester-HealthCheckedConnectionTest.Tpo -c -o common/network/common_network_HealthCheckedConnectionTester-HealthCheckedConnectionTest.obj `if test -f 'common/network/HealthCheckedConnectionTest.cpp'; then $(CYGPATH_W) 'common/network/HealthCheckedConnectionTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/network/HealthCheckedConnectionTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_network_HealthCheckedConnectionTester-HealthCheckedConnectionTest.Tpo common/network/$(DEPDIR)/common_network_HealthCheckedConnectionTester-HealthCheckedConnectionTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/HealthCheckedConnectionTest.cpp' object='common/network/common_network_HealthCheckedConnectionTester-HealthCheckedConnectionTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_HealthCheckedConnectionTester_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_network_HealthCheckedConnectionTester-HealthCheckedConnectionTest.obj `if test -f 'common/network/HealthCheckedConnectionTest.cpp'; then $(CYGPATH_W) 'common/network/HealthCheckedConnectionTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/network/HealthCheckedConnectionTest.cpp'; fi` common/network/common_network_NetworkTester-IPV4AddressTest.o: common/network/IPV4AddressTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_NetworkTester_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_network_NetworkTester-IPV4AddressTest.o -MD -MP -MF common/network/$(DEPDIR)/common_network_NetworkTester-IPV4AddressTest.Tpo -c -o common/network/common_network_NetworkTester-IPV4AddressTest.o `test -f 'common/network/IPV4AddressTest.cpp' || echo '$(srcdir)/'`common/network/IPV4AddressTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_network_NetworkTester-IPV4AddressTest.Tpo common/network/$(DEPDIR)/common_network_NetworkTester-IPV4AddressTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/IPV4AddressTest.cpp' object='common/network/common_network_NetworkTester-IPV4AddressTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_NetworkTester_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_network_NetworkTester-IPV4AddressTest.o `test -f 'common/network/IPV4AddressTest.cpp' || echo '$(srcdir)/'`common/network/IPV4AddressTest.cpp common/network/common_network_NetworkTester-IPV4AddressTest.obj: common/network/IPV4AddressTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_NetworkTester_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_network_NetworkTester-IPV4AddressTest.obj -MD -MP -MF common/network/$(DEPDIR)/common_network_NetworkTester-IPV4AddressTest.Tpo -c -o common/network/common_network_NetworkTester-IPV4AddressTest.obj `if test -f 'common/network/IPV4AddressTest.cpp'; then $(CYGPATH_W) 'common/network/IPV4AddressTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/network/IPV4AddressTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_network_NetworkTester-IPV4AddressTest.Tpo common/network/$(DEPDIR)/common_network_NetworkTester-IPV4AddressTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/IPV4AddressTest.cpp' object='common/network/common_network_NetworkTester-IPV4AddressTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_NetworkTester_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_network_NetworkTester-IPV4AddressTest.obj `if test -f 'common/network/IPV4AddressTest.cpp'; then $(CYGPATH_W) 'common/network/IPV4AddressTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/network/IPV4AddressTest.cpp'; fi` common/network/common_network_NetworkTester-InterfacePickerTest.o: common/network/InterfacePickerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_NetworkTester_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_network_NetworkTester-InterfacePickerTest.o -MD -MP -MF common/network/$(DEPDIR)/common_network_NetworkTester-InterfacePickerTest.Tpo -c -o common/network/common_network_NetworkTester-InterfacePickerTest.o `test -f 'common/network/InterfacePickerTest.cpp' || echo '$(srcdir)/'`common/network/InterfacePickerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_network_NetworkTester-InterfacePickerTest.Tpo common/network/$(DEPDIR)/common_network_NetworkTester-InterfacePickerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/InterfacePickerTest.cpp' object='common/network/common_network_NetworkTester-InterfacePickerTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_NetworkTester_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_network_NetworkTester-InterfacePickerTest.o `test -f 'common/network/InterfacePickerTest.cpp' || echo '$(srcdir)/'`common/network/InterfacePickerTest.cpp common/network/common_network_NetworkTester-InterfacePickerTest.obj: common/network/InterfacePickerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_NetworkTester_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_network_NetworkTester-InterfacePickerTest.obj -MD -MP -MF common/network/$(DEPDIR)/common_network_NetworkTester-InterfacePickerTest.Tpo -c -o common/network/common_network_NetworkTester-InterfacePickerTest.obj `if test -f 'common/network/InterfacePickerTest.cpp'; then $(CYGPATH_W) 'common/network/InterfacePickerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/network/InterfacePickerTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_network_NetworkTester-InterfacePickerTest.Tpo common/network/$(DEPDIR)/common_network_NetworkTester-InterfacePickerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/InterfacePickerTest.cpp' object='common/network/common_network_NetworkTester-InterfacePickerTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_NetworkTester_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_network_NetworkTester-InterfacePickerTest.obj `if test -f 'common/network/InterfacePickerTest.cpp'; then $(CYGPATH_W) 'common/network/InterfacePickerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/network/InterfacePickerTest.cpp'; fi` common/network/common_network_NetworkTester-InterfaceTest.o: common/network/InterfaceTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_NetworkTester_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_network_NetworkTester-InterfaceTest.o -MD -MP -MF common/network/$(DEPDIR)/common_network_NetworkTester-InterfaceTest.Tpo -c -o common/network/common_network_NetworkTester-InterfaceTest.o `test -f 'common/network/InterfaceTest.cpp' || echo '$(srcdir)/'`common/network/InterfaceTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_network_NetworkTester-InterfaceTest.Tpo common/network/$(DEPDIR)/common_network_NetworkTester-InterfaceTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/InterfaceTest.cpp' object='common/network/common_network_NetworkTester-InterfaceTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_NetworkTester_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_network_NetworkTester-InterfaceTest.o `test -f 'common/network/InterfaceTest.cpp' || echo '$(srcdir)/'`common/network/InterfaceTest.cpp common/network/common_network_NetworkTester-InterfaceTest.obj: common/network/InterfaceTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_NetworkTester_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_network_NetworkTester-InterfaceTest.obj -MD -MP -MF common/network/$(DEPDIR)/common_network_NetworkTester-InterfaceTest.Tpo -c -o common/network/common_network_NetworkTester-InterfaceTest.obj `if test -f 'common/network/InterfaceTest.cpp'; then $(CYGPATH_W) 'common/network/InterfaceTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/network/InterfaceTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_network_NetworkTester-InterfaceTest.Tpo common/network/$(DEPDIR)/common_network_NetworkTester-InterfaceTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/InterfaceTest.cpp' object='common/network/common_network_NetworkTester-InterfaceTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_NetworkTester_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_network_NetworkTester-InterfaceTest.obj `if test -f 'common/network/InterfaceTest.cpp'; then $(CYGPATH_W) 'common/network/InterfaceTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/network/InterfaceTest.cpp'; fi` common/network/common_network_NetworkTester-MACAddressTest.o: common/network/MACAddressTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_NetworkTester_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_network_NetworkTester-MACAddressTest.o -MD -MP -MF common/network/$(DEPDIR)/common_network_NetworkTester-MACAddressTest.Tpo -c -o common/network/common_network_NetworkTester-MACAddressTest.o `test -f 'common/network/MACAddressTest.cpp' || echo '$(srcdir)/'`common/network/MACAddressTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_network_NetworkTester-MACAddressTest.Tpo common/network/$(DEPDIR)/common_network_NetworkTester-MACAddressTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/MACAddressTest.cpp' object='common/network/common_network_NetworkTester-MACAddressTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_NetworkTester_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_network_NetworkTester-MACAddressTest.o `test -f 'common/network/MACAddressTest.cpp' || echo '$(srcdir)/'`common/network/MACAddressTest.cpp common/network/common_network_NetworkTester-MACAddressTest.obj: common/network/MACAddressTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_NetworkTester_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_network_NetworkTester-MACAddressTest.obj -MD -MP -MF common/network/$(DEPDIR)/common_network_NetworkTester-MACAddressTest.Tpo -c -o common/network/common_network_NetworkTester-MACAddressTest.obj `if test -f 'common/network/MACAddressTest.cpp'; then $(CYGPATH_W) 'common/network/MACAddressTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/network/MACAddressTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_network_NetworkTester-MACAddressTest.Tpo common/network/$(DEPDIR)/common_network_NetworkTester-MACAddressTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/MACAddressTest.cpp' object='common/network/common_network_NetworkTester-MACAddressTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_NetworkTester_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_network_NetworkTester-MACAddressTest.obj `if test -f 'common/network/MACAddressTest.cpp'; then $(CYGPATH_W) 'common/network/MACAddressTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/network/MACAddressTest.cpp'; fi` common/network/common_network_NetworkTester-NetworkUtilsTest.o: common/network/NetworkUtilsTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_NetworkTester_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_network_NetworkTester-NetworkUtilsTest.o -MD -MP -MF common/network/$(DEPDIR)/common_network_NetworkTester-NetworkUtilsTest.Tpo -c -o common/network/common_network_NetworkTester-NetworkUtilsTest.o `test -f 'common/network/NetworkUtilsTest.cpp' || echo '$(srcdir)/'`common/network/NetworkUtilsTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_network_NetworkTester-NetworkUtilsTest.Tpo common/network/$(DEPDIR)/common_network_NetworkTester-NetworkUtilsTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/NetworkUtilsTest.cpp' object='common/network/common_network_NetworkTester-NetworkUtilsTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_NetworkTester_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_network_NetworkTester-NetworkUtilsTest.o `test -f 'common/network/NetworkUtilsTest.cpp' || echo '$(srcdir)/'`common/network/NetworkUtilsTest.cpp common/network/common_network_NetworkTester-NetworkUtilsTest.obj: common/network/NetworkUtilsTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_NetworkTester_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_network_NetworkTester-NetworkUtilsTest.obj -MD -MP -MF common/network/$(DEPDIR)/common_network_NetworkTester-NetworkUtilsTest.Tpo -c -o common/network/common_network_NetworkTester-NetworkUtilsTest.obj `if test -f 'common/network/NetworkUtilsTest.cpp'; then $(CYGPATH_W) 'common/network/NetworkUtilsTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/network/NetworkUtilsTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_network_NetworkTester-NetworkUtilsTest.Tpo common/network/$(DEPDIR)/common_network_NetworkTester-NetworkUtilsTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/NetworkUtilsTest.cpp' object='common/network/common_network_NetworkTester-NetworkUtilsTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_NetworkTester_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_network_NetworkTester-NetworkUtilsTest.obj `if test -f 'common/network/NetworkUtilsTest.cpp'; then $(CYGPATH_W) 'common/network/NetworkUtilsTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/network/NetworkUtilsTest.cpp'; fi` common/network/common_network_NetworkTester-SocketAddressTest.o: common/network/SocketAddressTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_NetworkTester_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_network_NetworkTester-SocketAddressTest.o -MD -MP -MF common/network/$(DEPDIR)/common_network_NetworkTester-SocketAddressTest.Tpo -c -o common/network/common_network_NetworkTester-SocketAddressTest.o `test -f 'common/network/SocketAddressTest.cpp' || echo '$(srcdir)/'`common/network/SocketAddressTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_network_NetworkTester-SocketAddressTest.Tpo common/network/$(DEPDIR)/common_network_NetworkTester-SocketAddressTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/SocketAddressTest.cpp' object='common/network/common_network_NetworkTester-SocketAddressTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_NetworkTester_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_network_NetworkTester-SocketAddressTest.o `test -f 'common/network/SocketAddressTest.cpp' || echo '$(srcdir)/'`common/network/SocketAddressTest.cpp common/network/common_network_NetworkTester-SocketAddressTest.obj: common/network/SocketAddressTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_NetworkTester_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_network_NetworkTester-SocketAddressTest.obj -MD -MP -MF common/network/$(DEPDIR)/common_network_NetworkTester-SocketAddressTest.Tpo -c -o common/network/common_network_NetworkTester-SocketAddressTest.obj `if test -f 'common/network/SocketAddressTest.cpp'; then $(CYGPATH_W) 'common/network/SocketAddressTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/network/SocketAddressTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_network_NetworkTester-SocketAddressTest.Tpo common/network/$(DEPDIR)/common_network_NetworkTester-SocketAddressTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/SocketAddressTest.cpp' object='common/network/common_network_NetworkTester-SocketAddressTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_NetworkTester_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_network_NetworkTester-SocketAddressTest.obj `if test -f 'common/network/SocketAddressTest.cpp'; then $(CYGPATH_W) 'common/network/SocketAddressTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/network/SocketAddressTest.cpp'; fi` common/network/common_network_NetworkTester-SocketTest.o: common/network/SocketTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_NetworkTester_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_network_NetworkTester-SocketTest.o -MD -MP -MF common/network/$(DEPDIR)/common_network_NetworkTester-SocketTest.Tpo -c -o common/network/common_network_NetworkTester-SocketTest.o `test -f 'common/network/SocketTest.cpp' || echo '$(srcdir)/'`common/network/SocketTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_network_NetworkTester-SocketTest.Tpo common/network/$(DEPDIR)/common_network_NetworkTester-SocketTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/SocketTest.cpp' object='common/network/common_network_NetworkTester-SocketTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_NetworkTester_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_network_NetworkTester-SocketTest.o `test -f 'common/network/SocketTest.cpp' || echo '$(srcdir)/'`common/network/SocketTest.cpp common/network/common_network_NetworkTester-SocketTest.obj: common/network/SocketTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_NetworkTester_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_network_NetworkTester-SocketTest.obj -MD -MP -MF common/network/$(DEPDIR)/common_network_NetworkTester-SocketTest.Tpo -c -o common/network/common_network_NetworkTester-SocketTest.obj `if test -f 'common/network/SocketTest.cpp'; then $(CYGPATH_W) 'common/network/SocketTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/network/SocketTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_network_NetworkTester-SocketTest.Tpo common/network/$(DEPDIR)/common_network_NetworkTester-SocketTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/SocketTest.cpp' object='common/network/common_network_NetworkTester-SocketTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_NetworkTester_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_network_NetworkTester-SocketTest.obj `if test -f 'common/network/SocketTest.cpp'; then $(CYGPATH_W) 'common/network/SocketTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/network/SocketTest.cpp'; fi` common/network/common_network_TCPConnectorTester-AdvancedTCPConnectorTest.o: common/network/AdvancedTCPConnectorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_TCPConnectorTester_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_network_TCPConnectorTester-AdvancedTCPConnectorTest.o -MD -MP -MF common/network/$(DEPDIR)/common_network_TCPConnectorTester-AdvancedTCPConnectorTest.Tpo -c -o common/network/common_network_TCPConnectorTester-AdvancedTCPConnectorTest.o `test -f 'common/network/AdvancedTCPConnectorTest.cpp' || echo '$(srcdir)/'`common/network/AdvancedTCPConnectorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_network_TCPConnectorTester-AdvancedTCPConnectorTest.Tpo common/network/$(DEPDIR)/common_network_TCPConnectorTester-AdvancedTCPConnectorTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/AdvancedTCPConnectorTest.cpp' object='common/network/common_network_TCPConnectorTester-AdvancedTCPConnectorTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_TCPConnectorTester_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_network_TCPConnectorTester-AdvancedTCPConnectorTest.o `test -f 'common/network/AdvancedTCPConnectorTest.cpp' || echo '$(srcdir)/'`common/network/AdvancedTCPConnectorTest.cpp common/network/common_network_TCPConnectorTester-AdvancedTCPConnectorTest.obj: common/network/AdvancedTCPConnectorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_TCPConnectorTester_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_network_TCPConnectorTester-AdvancedTCPConnectorTest.obj -MD -MP -MF common/network/$(DEPDIR)/common_network_TCPConnectorTester-AdvancedTCPConnectorTest.Tpo -c -o common/network/common_network_TCPConnectorTester-AdvancedTCPConnectorTest.obj `if test -f 'common/network/AdvancedTCPConnectorTest.cpp'; then $(CYGPATH_W) 'common/network/AdvancedTCPConnectorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/network/AdvancedTCPConnectorTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_network_TCPConnectorTester-AdvancedTCPConnectorTest.Tpo common/network/$(DEPDIR)/common_network_TCPConnectorTester-AdvancedTCPConnectorTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/AdvancedTCPConnectorTest.cpp' object='common/network/common_network_TCPConnectorTester-AdvancedTCPConnectorTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_TCPConnectorTester_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_network_TCPConnectorTester-AdvancedTCPConnectorTest.obj `if test -f 'common/network/AdvancedTCPConnectorTest.cpp'; then $(CYGPATH_W) 'common/network/AdvancedTCPConnectorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/network/AdvancedTCPConnectorTest.cpp'; fi` common/network/common_network_TCPConnectorTester-TCPConnectorTest.o: common/network/TCPConnectorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_TCPConnectorTester_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_network_TCPConnectorTester-TCPConnectorTest.o -MD -MP -MF common/network/$(DEPDIR)/common_network_TCPConnectorTester-TCPConnectorTest.Tpo -c -o common/network/common_network_TCPConnectorTester-TCPConnectorTest.o `test -f 'common/network/TCPConnectorTest.cpp' || echo '$(srcdir)/'`common/network/TCPConnectorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_network_TCPConnectorTester-TCPConnectorTest.Tpo common/network/$(DEPDIR)/common_network_TCPConnectorTester-TCPConnectorTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/TCPConnectorTest.cpp' object='common/network/common_network_TCPConnectorTester-TCPConnectorTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_TCPConnectorTester_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_network_TCPConnectorTester-TCPConnectorTest.o `test -f 'common/network/TCPConnectorTest.cpp' || echo '$(srcdir)/'`common/network/TCPConnectorTest.cpp common/network/common_network_TCPConnectorTester-TCPConnectorTest.obj: common/network/TCPConnectorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_TCPConnectorTester_CXXFLAGS) $(CXXFLAGS) -MT common/network/common_network_TCPConnectorTester-TCPConnectorTest.obj -MD -MP -MF common/network/$(DEPDIR)/common_network_TCPConnectorTester-TCPConnectorTest.Tpo -c -o common/network/common_network_TCPConnectorTester-TCPConnectorTest.obj `if test -f 'common/network/TCPConnectorTest.cpp'; then $(CYGPATH_W) 'common/network/TCPConnectorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/network/TCPConnectorTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/network/$(DEPDIR)/common_network_TCPConnectorTester-TCPConnectorTest.Tpo common/network/$(DEPDIR)/common_network_TCPConnectorTester-TCPConnectorTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/network/TCPConnectorTest.cpp' object='common/network/common_network_TCPConnectorTester-TCPConnectorTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_network_TCPConnectorTester_CXXFLAGS) $(CXXFLAGS) -c -o common/network/common_network_TCPConnectorTester-TCPConnectorTest.obj `if test -f 'common/network/TCPConnectorTest.cpp'; then $(CYGPATH_W) 'common/network/TCPConnectorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/network/TCPConnectorTest.cpp'; fi` common/rdm/common_rdm_DiscoveryAgentTester-DiscoveryAgentTest.o: common/rdm/DiscoveryAgentTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_DiscoveryAgentTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_DiscoveryAgentTester-DiscoveryAgentTest.o -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_DiscoveryAgentTester-DiscoveryAgentTest.Tpo -c -o common/rdm/common_rdm_DiscoveryAgentTester-DiscoveryAgentTest.o `test -f 'common/rdm/DiscoveryAgentTest.cpp' || echo '$(srcdir)/'`common/rdm/DiscoveryAgentTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_DiscoveryAgentTester-DiscoveryAgentTest.Tpo common/rdm/$(DEPDIR)/common_rdm_DiscoveryAgentTester-DiscoveryAgentTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/DiscoveryAgentTest.cpp' object='common/rdm/common_rdm_DiscoveryAgentTester-DiscoveryAgentTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_DiscoveryAgentTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_DiscoveryAgentTester-DiscoveryAgentTest.o `test -f 'common/rdm/DiscoveryAgentTest.cpp' || echo '$(srcdir)/'`common/rdm/DiscoveryAgentTest.cpp common/rdm/common_rdm_DiscoveryAgentTester-DiscoveryAgentTest.obj: common/rdm/DiscoveryAgentTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_DiscoveryAgentTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_DiscoveryAgentTester-DiscoveryAgentTest.obj -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_DiscoveryAgentTester-DiscoveryAgentTest.Tpo -c -o common/rdm/common_rdm_DiscoveryAgentTester-DiscoveryAgentTest.obj `if test -f 'common/rdm/DiscoveryAgentTest.cpp'; then $(CYGPATH_W) 'common/rdm/DiscoveryAgentTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/DiscoveryAgentTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_DiscoveryAgentTester-DiscoveryAgentTest.Tpo common/rdm/$(DEPDIR)/common_rdm_DiscoveryAgentTester-DiscoveryAgentTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/DiscoveryAgentTest.cpp' object='common/rdm/common_rdm_DiscoveryAgentTester-DiscoveryAgentTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_DiscoveryAgentTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_DiscoveryAgentTester-DiscoveryAgentTest.obj `if test -f 'common/rdm/DiscoveryAgentTest.cpp'; then $(CYGPATH_W) 'common/rdm/DiscoveryAgentTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/DiscoveryAgentTest.cpp'; fi` common/rdm/common_rdm_PidStoreTester-DescriptorConsistencyCheckerTest.o: common/rdm/DescriptorConsistencyCheckerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_PidStoreTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_PidStoreTester-DescriptorConsistencyCheckerTest.o -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_PidStoreTester-DescriptorConsistencyCheckerTest.Tpo -c -o common/rdm/common_rdm_PidStoreTester-DescriptorConsistencyCheckerTest.o `test -f 'common/rdm/DescriptorConsistencyCheckerTest.cpp' || echo '$(srcdir)/'`common/rdm/DescriptorConsistencyCheckerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_PidStoreTester-DescriptorConsistencyCheckerTest.Tpo common/rdm/$(DEPDIR)/common_rdm_PidStoreTester-DescriptorConsistencyCheckerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/DescriptorConsistencyCheckerTest.cpp' object='common/rdm/common_rdm_PidStoreTester-DescriptorConsistencyCheckerTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_PidStoreTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_PidStoreTester-DescriptorConsistencyCheckerTest.o `test -f 'common/rdm/DescriptorConsistencyCheckerTest.cpp' || echo '$(srcdir)/'`common/rdm/DescriptorConsistencyCheckerTest.cpp common/rdm/common_rdm_PidStoreTester-DescriptorConsistencyCheckerTest.obj: common/rdm/DescriptorConsistencyCheckerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_PidStoreTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_PidStoreTester-DescriptorConsistencyCheckerTest.obj -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_PidStoreTester-DescriptorConsistencyCheckerTest.Tpo -c -o common/rdm/common_rdm_PidStoreTester-DescriptorConsistencyCheckerTest.obj `if test -f 'common/rdm/DescriptorConsistencyCheckerTest.cpp'; then $(CYGPATH_W) 'common/rdm/DescriptorConsistencyCheckerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/DescriptorConsistencyCheckerTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_PidStoreTester-DescriptorConsistencyCheckerTest.Tpo common/rdm/$(DEPDIR)/common_rdm_PidStoreTester-DescriptorConsistencyCheckerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/DescriptorConsistencyCheckerTest.cpp' object='common/rdm/common_rdm_PidStoreTester-DescriptorConsistencyCheckerTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_PidStoreTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_PidStoreTester-DescriptorConsistencyCheckerTest.obj `if test -f 'common/rdm/DescriptorConsistencyCheckerTest.cpp'; then $(CYGPATH_W) 'common/rdm/DescriptorConsistencyCheckerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/DescriptorConsistencyCheckerTest.cpp'; fi` common/rdm/common_rdm_PidStoreTester-PidStoreTest.o: common/rdm/PidStoreTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_PidStoreTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_PidStoreTester-PidStoreTest.o -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_PidStoreTester-PidStoreTest.Tpo -c -o common/rdm/common_rdm_PidStoreTester-PidStoreTest.o `test -f 'common/rdm/PidStoreTest.cpp' || echo '$(srcdir)/'`common/rdm/PidStoreTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_PidStoreTester-PidStoreTest.Tpo common/rdm/$(DEPDIR)/common_rdm_PidStoreTester-PidStoreTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/PidStoreTest.cpp' object='common/rdm/common_rdm_PidStoreTester-PidStoreTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_PidStoreTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_PidStoreTester-PidStoreTest.o `test -f 'common/rdm/PidStoreTest.cpp' || echo '$(srcdir)/'`common/rdm/PidStoreTest.cpp common/rdm/common_rdm_PidStoreTester-PidStoreTest.obj: common/rdm/PidStoreTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_PidStoreTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_PidStoreTester-PidStoreTest.obj -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_PidStoreTester-PidStoreTest.Tpo -c -o common/rdm/common_rdm_PidStoreTester-PidStoreTest.obj `if test -f 'common/rdm/PidStoreTest.cpp'; then $(CYGPATH_W) 'common/rdm/PidStoreTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/PidStoreTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_PidStoreTester-PidStoreTest.Tpo common/rdm/$(DEPDIR)/common_rdm_PidStoreTester-PidStoreTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/PidStoreTest.cpp' object='common/rdm/common_rdm_PidStoreTester-PidStoreTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_PidStoreTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_PidStoreTester-PidStoreTest.obj `if test -f 'common/rdm/PidStoreTest.cpp'; then $(CYGPATH_W) 'common/rdm/PidStoreTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/PidStoreTest.cpp'; fi` common/rdm/common_rdm_QueueingRDMControllerTester-QueueingRDMControllerTest.o: common/rdm/QueueingRDMControllerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_QueueingRDMControllerTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_QueueingRDMControllerTester-QueueingRDMControllerTest.o -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_QueueingRDMControllerTester-QueueingRDMControllerTest.Tpo -c -o common/rdm/common_rdm_QueueingRDMControllerTester-QueueingRDMControllerTest.o `test -f 'common/rdm/QueueingRDMControllerTest.cpp' || echo '$(srcdir)/'`common/rdm/QueueingRDMControllerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_QueueingRDMControllerTester-QueueingRDMControllerTest.Tpo common/rdm/$(DEPDIR)/common_rdm_QueueingRDMControllerTester-QueueingRDMControllerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/QueueingRDMControllerTest.cpp' object='common/rdm/common_rdm_QueueingRDMControllerTester-QueueingRDMControllerTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_QueueingRDMControllerTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_QueueingRDMControllerTester-QueueingRDMControllerTest.o `test -f 'common/rdm/QueueingRDMControllerTest.cpp' || echo '$(srcdir)/'`common/rdm/QueueingRDMControllerTest.cpp common/rdm/common_rdm_QueueingRDMControllerTester-QueueingRDMControllerTest.obj: common/rdm/QueueingRDMControllerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_QueueingRDMControllerTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_QueueingRDMControllerTester-QueueingRDMControllerTest.obj -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_QueueingRDMControllerTester-QueueingRDMControllerTest.Tpo -c -o common/rdm/common_rdm_QueueingRDMControllerTester-QueueingRDMControllerTest.obj `if test -f 'common/rdm/QueueingRDMControllerTest.cpp'; then $(CYGPATH_W) 'common/rdm/QueueingRDMControllerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/QueueingRDMControllerTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_QueueingRDMControllerTester-QueueingRDMControllerTest.Tpo common/rdm/$(DEPDIR)/common_rdm_QueueingRDMControllerTester-QueueingRDMControllerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/QueueingRDMControllerTest.cpp' object='common/rdm/common_rdm_QueueingRDMControllerTester-QueueingRDMControllerTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_QueueingRDMControllerTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_QueueingRDMControllerTester-QueueingRDMControllerTest.obj `if test -f 'common/rdm/QueueingRDMControllerTest.cpp'; then $(CYGPATH_W) 'common/rdm/QueueingRDMControllerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/QueueingRDMControllerTest.cpp'; fi` common/rdm/common_rdm_RDMAPITester-RDMAPITest.o: common/rdm/RDMAPITest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMAPITester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_RDMAPITester-RDMAPITest.o -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_RDMAPITester-RDMAPITest.Tpo -c -o common/rdm/common_rdm_RDMAPITester-RDMAPITest.o `test -f 'common/rdm/RDMAPITest.cpp' || echo '$(srcdir)/'`common/rdm/RDMAPITest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_RDMAPITester-RDMAPITest.Tpo common/rdm/$(DEPDIR)/common_rdm_RDMAPITester-RDMAPITest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/RDMAPITest.cpp' object='common/rdm/common_rdm_RDMAPITester-RDMAPITest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMAPITester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_RDMAPITester-RDMAPITest.o `test -f 'common/rdm/RDMAPITest.cpp' || echo '$(srcdir)/'`common/rdm/RDMAPITest.cpp common/rdm/common_rdm_RDMAPITester-RDMAPITest.obj: common/rdm/RDMAPITest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMAPITester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_RDMAPITester-RDMAPITest.obj -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_RDMAPITester-RDMAPITest.Tpo -c -o common/rdm/common_rdm_RDMAPITester-RDMAPITest.obj `if test -f 'common/rdm/RDMAPITest.cpp'; then $(CYGPATH_W) 'common/rdm/RDMAPITest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/RDMAPITest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_RDMAPITester-RDMAPITest.Tpo common/rdm/$(DEPDIR)/common_rdm_RDMAPITester-RDMAPITest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/RDMAPITest.cpp' object='common/rdm/common_rdm_RDMAPITester-RDMAPITest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMAPITester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_RDMAPITester-RDMAPITest.obj `if test -f 'common/rdm/RDMAPITest.cpp'; then $(CYGPATH_W) 'common/rdm/RDMAPITest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/RDMAPITest.cpp'; fi` common/rdm/common_rdm_RDMCommandSerializerTester-RDMCommandSerializerTest.o: common/rdm/RDMCommandSerializerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMCommandSerializerTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_RDMCommandSerializerTester-RDMCommandSerializerTest.o -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_RDMCommandSerializerTester-RDMCommandSerializerTest.Tpo -c -o common/rdm/common_rdm_RDMCommandSerializerTester-RDMCommandSerializerTest.o `test -f 'common/rdm/RDMCommandSerializerTest.cpp' || echo '$(srcdir)/'`common/rdm/RDMCommandSerializerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_RDMCommandSerializerTester-RDMCommandSerializerTest.Tpo common/rdm/$(DEPDIR)/common_rdm_RDMCommandSerializerTester-RDMCommandSerializerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/RDMCommandSerializerTest.cpp' object='common/rdm/common_rdm_RDMCommandSerializerTester-RDMCommandSerializerTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMCommandSerializerTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_RDMCommandSerializerTester-RDMCommandSerializerTest.o `test -f 'common/rdm/RDMCommandSerializerTest.cpp' || echo '$(srcdir)/'`common/rdm/RDMCommandSerializerTest.cpp common/rdm/common_rdm_RDMCommandSerializerTester-RDMCommandSerializerTest.obj: common/rdm/RDMCommandSerializerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMCommandSerializerTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_RDMCommandSerializerTester-RDMCommandSerializerTest.obj -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_RDMCommandSerializerTester-RDMCommandSerializerTest.Tpo -c -o common/rdm/common_rdm_RDMCommandSerializerTester-RDMCommandSerializerTest.obj `if test -f 'common/rdm/RDMCommandSerializerTest.cpp'; then $(CYGPATH_W) 'common/rdm/RDMCommandSerializerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/RDMCommandSerializerTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_RDMCommandSerializerTester-RDMCommandSerializerTest.Tpo common/rdm/$(DEPDIR)/common_rdm_RDMCommandSerializerTester-RDMCommandSerializerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/RDMCommandSerializerTest.cpp' object='common/rdm/common_rdm_RDMCommandSerializerTester-RDMCommandSerializerTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMCommandSerializerTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_RDMCommandSerializerTester-RDMCommandSerializerTest.obj `if test -f 'common/rdm/RDMCommandSerializerTest.cpp'; then $(CYGPATH_W) 'common/rdm/RDMCommandSerializerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/RDMCommandSerializerTest.cpp'; fi` common/rdm/common_rdm_RDMCommandTester-RDMCommandTest.o: common/rdm/RDMCommandTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMCommandTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_RDMCommandTester-RDMCommandTest.o -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_RDMCommandTester-RDMCommandTest.Tpo -c -o common/rdm/common_rdm_RDMCommandTester-RDMCommandTest.o `test -f 'common/rdm/RDMCommandTest.cpp' || echo '$(srcdir)/'`common/rdm/RDMCommandTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_RDMCommandTester-RDMCommandTest.Tpo common/rdm/$(DEPDIR)/common_rdm_RDMCommandTester-RDMCommandTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/RDMCommandTest.cpp' object='common/rdm/common_rdm_RDMCommandTester-RDMCommandTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMCommandTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_RDMCommandTester-RDMCommandTest.o `test -f 'common/rdm/RDMCommandTest.cpp' || echo '$(srcdir)/'`common/rdm/RDMCommandTest.cpp common/rdm/common_rdm_RDMCommandTester-RDMCommandTest.obj: common/rdm/RDMCommandTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMCommandTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_RDMCommandTester-RDMCommandTest.obj -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_RDMCommandTester-RDMCommandTest.Tpo -c -o common/rdm/common_rdm_RDMCommandTester-RDMCommandTest.obj `if test -f 'common/rdm/RDMCommandTest.cpp'; then $(CYGPATH_W) 'common/rdm/RDMCommandTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/RDMCommandTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_RDMCommandTester-RDMCommandTest.Tpo common/rdm/$(DEPDIR)/common_rdm_RDMCommandTester-RDMCommandTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/RDMCommandTest.cpp' object='common/rdm/common_rdm_RDMCommandTester-RDMCommandTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMCommandTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_RDMCommandTester-RDMCommandTest.obj `if test -f 'common/rdm/RDMCommandTest.cpp'; then $(CYGPATH_W) 'common/rdm/RDMCommandTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/RDMCommandTest.cpp'; fi` common/rdm/common_rdm_RDMFrameTester-RDMFrameTest.o: common/rdm/RDMFrameTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMFrameTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_RDMFrameTester-RDMFrameTest.o -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_RDMFrameTester-RDMFrameTest.Tpo -c -o common/rdm/common_rdm_RDMFrameTester-RDMFrameTest.o `test -f 'common/rdm/RDMFrameTest.cpp' || echo '$(srcdir)/'`common/rdm/RDMFrameTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_RDMFrameTester-RDMFrameTest.Tpo common/rdm/$(DEPDIR)/common_rdm_RDMFrameTester-RDMFrameTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/RDMFrameTest.cpp' object='common/rdm/common_rdm_RDMFrameTester-RDMFrameTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMFrameTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_RDMFrameTester-RDMFrameTest.o `test -f 'common/rdm/RDMFrameTest.cpp' || echo '$(srcdir)/'`common/rdm/RDMFrameTest.cpp common/rdm/common_rdm_RDMFrameTester-RDMFrameTest.obj: common/rdm/RDMFrameTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMFrameTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_RDMFrameTester-RDMFrameTest.obj -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_RDMFrameTester-RDMFrameTest.Tpo -c -o common/rdm/common_rdm_RDMFrameTester-RDMFrameTest.obj `if test -f 'common/rdm/RDMFrameTest.cpp'; then $(CYGPATH_W) 'common/rdm/RDMFrameTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/RDMFrameTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_RDMFrameTester-RDMFrameTest.Tpo common/rdm/$(DEPDIR)/common_rdm_RDMFrameTester-RDMFrameTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/RDMFrameTest.cpp' object='common/rdm/common_rdm_RDMFrameTester-RDMFrameTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMFrameTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_RDMFrameTester-RDMFrameTest.obj `if test -f 'common/rdm/RDMFrameTest.cpp'; then $(CYGPATH_W) 'common/rdm/RDMFrameTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/RDMFrameTest.cpp'; fi` common/rdm/common_rdm_RDMHelperTester-RDMHelperTest.o: common/rdm/RDMHelperTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMHelperTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_RDMHelperTester-RDMHelperTest.o -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_RDMHelperTester-RDMHelperTest.Tpo -c -o common/rdm/common_rdm_RDMHelperTester-RDMHelperTest.o `test -f 'common/rdm/RDMHelperTest.cpp' || echo '$(srcdir)/'`common/rdm/RDMHelperTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_RDMHelperTester-RDMHelperTest.Tpo common/rdm/$(DEPDIR)/common_rdm_RDMHelperTester-RDMHelperTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/RDMHelperTest.cpp' object='common/rdm/common_rdm_RDMHelperTester-RDMHelperTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMHelperTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_RDMHelperTester-RDMHelperTest.o `test -f 'common/rdm/RDMHelperTest.cpp' || echo '$(srcdir)/'`common/rdm/RDMHelperTest.cpp common/rdm/common_rdm_RDMHelperTester-RDMHelperTest.obj: common/rdm/RDMHelperTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMHelperTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_RDMHelperTester-RDMHelperTest.obj -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_RDMHelperTester-RDMHelperTest.Tpo -c -o common/rdm/common_rdm_RDMHelperTester-RDMHelperTest.obj `if test -f 'common/rdm/RDMHelperTest.cpp'; then $(CYGPATH_W) 'common/rdm/RDMHelperTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/RDMHelperTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_RDMHelperTester-RDMHelperTest.Tpo common/rdm/$(DEPDIR)/common_rdm_RDMHelperTester-RDMHelperTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/RDMHelperTest.cpp' object='common/rdm/common_rdm_RDMHelperTester-RDMHelperTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMHelperTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_RDMHelperTester-RDMHelperTest.obj `if test -f 'common/rdm/RDMHelperTest.cpp'; then $(CYGPATH_W) 'common/rdm/RDMHelperTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/RDMHelperTest.cpp'; fi` common/rdm/common_rdm_RDMMessageTester-GroupSizeCalculatorTest.o: common/rdm/GroupSizeCalculatorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMMessageTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_RDMMessageTester-GroupSizeCalculatorTest.o -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-GroupSizeCalculatorTest.Tpo -c -o common/rdm/common_rdm_RDMMessageTester-GroupSizeCalculatorTest.o `test -f 'common/rdm/GroupSizeCalculatorTest.cpp' || echo '$(srcdir)/'`common/rdm/GroupSizeCalculatorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-GroupSizeCalculatorTest.Tpo common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-GroupSizeCalculatorTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/GroupSizeCalculatorTest.cpp' object='common/rdm/common_rdm_RDMMessageTester-GroupSizeCalculatorTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMMessageTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_RDMMessageTester-GroupSizeCalculatorTest.o `test -f 'common/rdm/GroupSizeCalculatorTest.cpp' || echo '$(srcdir)/'`common/rdm/GroupSizeCalculatorTest.cpp common/rdm/common_rdm_RDMMessageTester-GroupSizeCalculatorTest.obj: common/rdm/GroupSizeCalculatorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMMessageTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_RDMMessageTester-GroupSizeCalculatorTest.obj -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-GroupSizeCalculatorTest.Tpo -c -o common/rdm/common_rdm_RDMMessageTester-GroupSizeCalculatorTest.obj `if test -f 'common/rdm/GroupSizeCalculatorTest.cpp'; then $(CYGPATH_W) 'common/rdm/GroupSizeCalculatorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/GroupSizeCalculatorTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-GroupSizeCalculatorTest.Tpo common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-GroupSizeCalculatorTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/GroupSizeCalculatorTest.cpp' object='common/rdm/common_rdm_RDMMessageTester-GroupSizeCalculatorTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMMessageTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_RDMMessageTester-GroupSizeCalculatorTest.obj `if test -f 'common/rdm/GroupSizeCalculatorTest.cpp'; then $(CYGPATH_W) 'common/rdm/GroupSizeCalculatorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/GroupSizeCalculatorTest.cpp'; fi` common/rdm/common_rdm_RDMMessageTester-MessageSerializerTest.o: common/rdm/MessageSerializerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMMessageTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_RDMMessageTester-MessageSerializerTest.o -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-MessageSerializerTest.Tpo -c -o common/rdm/common_rdm_RDMMessageTester-MessageSerializerTest.o `test -f 'common/rdm/MessageSerializerTest.cpp' || echo '$(srcdir)/'`common/rdm/MessageSerializerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-MessageSerializerTest.Tpo common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-MessageSerializerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/MessageSerializerTest.cpp' object='common/rdm/common_rdm_RDMMessageTester-MessageSerializerTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMMessageTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_RDMMessageTester-MessageSerializerTest.o `test -f 'common/rdm/MessageSerializerTest.cpp' || echo '$(srcdir)/'`common/rdm/MessageSerializerTest.cpp common/rdm/common_rdm_RDMMessageTester-MessageSerializerTest.obj: common/rdm/MessageSerializerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMMessageTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_RDMMessageTester-MessageSerializerTest.obj -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-MessageSerializerTest.Tpo -c -o common/rdm/common_rdm_RDMMessageTester-MessageSerializerTest.obj `if test -f 'common/rdm/MessageSerializerTest.cpp'; then $(CYGPATH_W) 'common/rdm/MessageSerializerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/MessageSerializerTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-MessageSerializerTest.Tpo common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-MessageSerializerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/MessageSerializerTest.cpp' object='common/rdm/common_rdm_RDMMessageTester-MessageSerializerTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMMessageTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_RDMMessageTester-MessageSerializerTest.obj `if test -f 'common/rdm/MessageSerializerTest.cpp'; then $(CYGPATH_W) 'common/rdm/MessageSerializerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/MessageSerializerTest.cpp'; fi` common/rdm/common_rdm_RDMMessageTester-MessageDeserializerTest.o: common/rdm/MessageDeserializerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMMessageTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_RDMMessageTester-MessageDeserializerTest.o -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-MessageDeserializerTest.Tpo -c -o common/rdm/common_rdm_RDMMessageTester-MessageDeserializerTest.o `test -f 'common/rdm/MessageDeserializerTest.cpp' || echo '$(srcdir)/'`common/rdm/MessageDeserializerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-MessageDeserializerTest.Tpo common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-MessageDeserializerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/MessageDeserializerTest.cpp' object='common/rdm/common_rdm_RDMMessageTester-MessageDeserializerTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMMessageTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_RDMMessageTester-MessageDeserializerTest.o `test -f 'common/rdm/MessageDeserializerTest.cpp' || echo '$(srcdir)/'`common/rdm/MessageDeserializerTest.cpp common/rdm/common_rdm_RDMMessageTester-MessageDeserializerTest.obj: common/rdm/MessageDeserializerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMMessageTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_RDMMessageTester-MessageDeserializerTest.obj -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-MessageDeserializerTest.Tpo -c -o common/rdm/common_rdm_RDMMessageTester-MessageDeserializerTest.obj `if test -f 'common/rdm/MessageDeserializerTest.cpp'; then $(CYGPATH_W) 'common/rdm/MessageDeserializerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/MessageDeserializerTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-MessageDeserializerTest.Tpo common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-MessageDeserializerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/MessageDeserializerTest.cpp' object='common/rdm/common_rdm_RDMMessageTester-MessageDeserializerTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMMessageTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_RDMMessageTester-MessageDeserializerTest.obj `if test -f 'common/rdm/MessageDeserializerTest.cpp'; then $(CYGPATH_W) 'common/rdm/MessageDeserializerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/MessageDeserializerTest.cpp'; fi` common/rdm/common_rdm_RDMMessageTester-RDMMessageInterationTest.o: common/rdm/RDMMessageInterationTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMMessageTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_RDMMessageTester-RDMMessageInterationTest.o -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-RDMMessageInterationTest.Tpo -c -o common/rdm/common_rdm_RDMMessageTester-RDMMessageInterationTest.o `test -f 'common/rdm/RDMMessageInterationTest.cpp' || echo '$(srcdir)/'`common/rdm/RDMMessageInterationTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-RDMMessageInterationTest.Tpo common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-RDMMessageInterationTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/RDMMessageInterationTest.cpp' object='common/rdm/common_rdm_RDMMessageTester-RDMMessageInterationTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMMessageTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_RDMMessageTester-RDMMessageInterationTest.o `test -f 'common/rdm/RDMMessageInterationTest.cpp' || echo '$(srcdir)/'`common/rdm/RDMMessageInterationTest.cpp common/rdm/common_rdm_RDMMessageTester-RDMMessageInterationTest.obj: common/rdm/RDMMessageInterationTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMMessageTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_RDMMessageTester-RDMMessageInterationTest.obj -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-RDMMessageInterationTest.Tpo -c -o common/rdm/common_rdm_RDMMessageTester-RDMMessageInterationTest.obj `if test -f 'common/rdm/RDMMessageInterationTest.cpp'; then $(CYGPATH_W) 'common/rdm/RDMMessageInterationTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/RDMMessageInterationTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-RDMMessageInterationTest.Tpo common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-RDMMessageInterationTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/RDMMessageInterationTest.cpp' object='common/rdm/common_rdm_RDMMessageTester-RDMMessageInterationTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMMessageTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_RDMMessageTester-RDMMessageInterationTest.obj `if test -f 'common/rdm/RDMMessageInterationTest.cpp'; then $(CYGPATH_W) 'common/rdm/RDMMessageInterationTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/RDMMessageInterationTest.cpp'; fi` common/rdm/common_rdm_RDMMessageTester-StringMessageBuilderTest.o: common/rdm/StringMessageBuilderTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMMessageTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_RDMMessageTester-StringMessageBuilderTest.o -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-StringMessageBuilderTest.Tpo -c -o common/rdm/common_rdm_RDMMessageTester-StringMessageBuilderTest.o `test -f 'common/rdm/StringMessageBuilderTest.cpp' || echo '$(srcdir)/'`common/rdm/StringMessageBuilderTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-StringMessageBuilderTest.Tpo common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-StringMessageBuilderTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/StringMessageBuilderTest.cpp' object='common/rdm/common_rdm_RDMMessageTester-StringMessageBuilderTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMMessageTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_RDMMessageTester-StringMessageBuilderTest.o `test -f 'common/rdm/StringMessageBuilderTest.cpp' || echo '$(srcdir)/'`common/rdm/StringMessageBuilderTest.cpp common/rdm/common_rdm_RDMMessageTester-StringMessageBuilderTest.obj: common/rdm/StringMessageBuilderTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMMessageTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_RDMMessageTester-StringMessageBuilderTest.obj -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-StringMessageBuilderTest.Tpo -c -o common/rdm/common_rdm_RDMMessageTester-StringMessageBuilderTest.obj `if test -f 'common/rdm/StringMessageBuilderTest.cpp'; then $(CYGPATH_W) 'common/rdm/StringMessageBuilderTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/StringMessageBuilderTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-StringMessageBuilderTest.Tpo common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-StringMessageBuilderTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/StringMessageBuilderTest.cpp' object='common/rdm/common_rdm_RDMMessageTester-StringMessageBuilderTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMMessageTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_RDMMessageTester-StringMessageBuilderTest.obj `if test -f 'common/rdm/StringMessageBuilderTest.cpp'; then $(CYGPATH_W) 'common/rdm/StringMessageBuilderTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/StringMessageBuilderTest.cpp'; fi` common/rdm/common_rdm_RDMMessageTester-VariableFieldSizeCalculatorTest.o: common/rdm/VariableFieldSizeCalculatorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMMessageTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_RDMMessageTester-VariableFieldSizeCalculatorTest.o -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-VariableFieldSizeCalculatorTest.Tpo -c -o common/rdm/common_rdm_RDMMessageTester-VariableFieldSizeCalculatorTest.o `test -f 'common/rdm/VariableFieldSizeCalculatorTest.cpp' || echo '$(srcdir)/'`common/rdm/VariableFieldSizeCalculatorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-VariableFieldSizeCalculatorTest.Tpo common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-VariableFieldSizeCalculatorTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/VariableFieldSizeCalculatorTest.cpp' object='common/rdm/common_rdm_RDMMessageTester-VariableFieldSizeCalculatorTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMMessageTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_RDMMessageTester-VariableFieldSizeCalculatorTest.o `test -f 'common/rdm/VariableFieldSizeCalculatorTest.cpp' || echo '$(srcdir)/'`common/rdm/VariableFieldSizeCalculatorTest.cpp common/rdm/common_rdm_RDMMessageTester-VariableFieldSizeCalculatorTest.obj: common/rdm/VariableFieldSizeCalculatorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMMessageTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_RDMMessageTester-VariableFieldSizeCalculatorTest.obj -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-VariableFieldSizeCalculatorTest.Tpo -c -o common/rdm/common_rdm_RDMMessageTester-VariableFieldSizeCalculatorTest.obj `if test -f 'common/rdm/VariableFieldSizeCalculatorTest.cpp'; then $(CYGPATH_W) 'common/rdm/VariableFieldSizeCalculatorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/VariableFieldSizeCalculatorTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-VariableFieldSizeCalculatorTest.Tpo common/rdm/$(DEPDIR)/common_rdm_RDMMessageTester-VariableFieldSizeCalculatorTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/VariableFieldSizeCalculatorTest.cpp' object='common/rdm/common_rdm_RDMMessageTester-VariableFieldSizeCalculatorTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMMessageTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_RDMMessageTester-VariableFieldSizeCalculatorTest.obj `if test -f 'common/rdm/VariableFieldSizeCalculatorTest.cpp'; then $(CYGPATH_W) 'common/rdm/VariableFieldSizeCalculatorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/VariableFieldSizeCalculatorTest.cpp'; fi` common/rdm/common_rdm_RDMReplyTester-RDMReplyTest.o: common/rdm/RDMReplyTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMReplyTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_RDMReplyTester-RDMReplyTest.o -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_RDMReplyTester-RDMReplyTest.Tpo -c -o common/rdm/common_rdm_RDMReplyTester-RDMReplyTest.o `test -f 'common/rdm/RDMReplyTest.cpp' || echo '$(srcdir)/'`common/rdm/RDMReplyTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_RDMReplyTester-RDMReplyTest.Tpo common/rdm/$(DEPDIR)/common_rdm_RDMReplyTester-RDMReplyTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/RDMReplyTest.cpp' object='common/rdm/common_rdm_RDMReplyTester-RDMReplyTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMReplyTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_RDMReplyTester-RDMReplyTest.o `test -f 'common/rdm/RDMReplyTest.cpp' || echo '$(srcdir)/'`common/rdm/RDMReplyTest.cpp common/rdm/common_rdm_RDMReplyTester-RDMReplyTest.obj: common/rdm/RDMReplyTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMReplyTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_RDMReplyTester-RDMReplyTest.obj -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_RDMReplyTester-RDMReplyTest.Tpo -c -o common/rdm/common_rdm_RDMReplyTester-RDMReplyTest.obj `if test -f 'common/rdm/RDMReplyTest.cpp'; then $(CYGPATH_W) 'common/rdm/RDMReplyTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/RDMReplyTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_RDMReplyTester-RDMReplyTest.Tpo common/rdm/$(DEPDIR)/common_rdm_RDMReplyTester-RDMReplyTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/RDMReplyTest.cpp' object='common/rdm/common_rdm_RDMReplyTester-RDMReplyTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_RDMReplyTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_RDMReplyTester-RDMReplyTest.obj `if test -f 'common/rdm/RDMReplyTest.cpp'; then $(CYGPATH_W) 'common/rdm/RDMReplyTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/RDMReplyTest.cpp'; fi` common/rdm/common_rdm_UIDAllocatorTester-UIDAllocatorTest.o: common/rdm/UIDAllocatorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_UIDAllocatorTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_UIDAllocatorTester-UIDAllocatorTest.o -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_UIDAllocatorTester-UIDAllocatorTest.Tpo -c -o common/rdm/common_rdm_UIDAllocatorTester-UIDAllocatorTest.o `test -f 'common/rdm/UIDAllocatorTest.cpp' || echo '$(srcdir)/'`common/rdm/UIDAllocatorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_UIDAllocatorTester-UIDAllocatorTest.Tpo common/rdm/$(DEPDIR)/common_rdm_UIDAllocatorTester-UIDAllocatorTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/UIDAllocatorTest.cpp' object='common/rdm/common_rdm_UIDAllocatorTester-UIDAllocatorTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_UIDAllocatorTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_UIDAllocatorTester-UIDAllocatorTest.o `test -f 'common/rdm/UIDAllocatorTest.cpp' || echo '$(srcdir)/'`common/rdm/UIDAllocatorTest.cpp common/rdm/common_rdm_UIDAllocatorTester-UIDAllocatorTest.obj: common/rdm/UIDAllocatorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_UIDAllocatorTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_UIDAllocatorTester-UIDAllocatorTest.obj -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_UIDAllocatorTester-UIDAllocatorTest.Tpo -c -o common/rdm/common_rdm_UIDAllocatorTester-UIDAllocatorTest.obj `if test -f 'common/rdm/UIDAllocatorTest.cpp'; then $(CYGPATH_W) 'common/rdm/UIDAllocatorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/UIDAllocatorTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_UIDAllocatorTester-UIDAllocatorTest.Tpo common/rdm/$(DEPDIR)/common_rdm_UIDAllocatorTester-UIDAllocatorTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/UIDAllocatorTest.cpp' object='common/rdm/common_rdm_UIDAllocatorTester-UIDAllocatorTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_UIDAllocatorTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_UIDAllocatorTester-UIDAllocatorTest.obj `if test -f 'common/rdm/UIDAllocatorTest.cpp'; then $(CYGPATH_W) 'common/rdm/UIDAllocatorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/UIDAllocatorTest.cpp'; fi` common/rdm/common_rdm_UIDTester-UIDTest.o: common/rdm/UIDTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_UIDTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_UIDTester-UIDTest.o -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_UIDTester-UIDTest.Tpo -c -o common/rdm/common_rdm_UIDTester-UIDTest.o `test -f 'common/rdm/UIDTest.cpp' || echo '$(srcdir)/'`common/rdm/UIDTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_UIDTester-UIDTest.Tpo common/rdm/$(DEPDIR)/common_rdm_UIDTester-UIDTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/UIDTest.cpp' object='common/rdm/common_rdm_UIDTester-UIDTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_UIDTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_UIDTester-UIDTest.o `test -f 'common/rdm/UIDTest.cpp' || echo '$(srcdir)/'`common/rdm/UIDTest.cpp common/rdm/common_rdm_UIDTester-UIDTest.obj: common/rdm/UIDTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_UIDTester_CXXFLAGS) $(CXXFLAGS) -MT common/rdm/common_rdm_UIDTester-UIDTest.obj -MD -MP -MF common/rdm/$(DEPDIR)/common_rdm_UIDTester-UIDTest.Tpo -c -o common/rdm/common_rdm_UIDTester-UIDTest.obj `if test -f 'common/rdm/UIDTest.cpp'; then $(CYGPATH_W) 'common/rdm/UIDTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/UIDTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rdm/$(DEPDIR)/common_rdm_UIDTester-UIDTest.Tpo common/rdm/$(DEPDIR)/common_rdm_UIDTester-UIDTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rdm/UIDTest.cpp' object='common/rdm/common_rdm_UIDTester-UIDTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rdm_UIDTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rdm/common_rdm_UIDTester-UIDTest.obj `if test -f 'common/rdm/UIDTest.cpp'; then $(CYGPATH_W) 'common/rdm/UIDTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rdm/UIDTest.cpp'; fi` common/rpc/common_rpc_RpcServerTester-RpcServerTest.o: common/rpc/RpcServerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcServerTester_CXXFLAGS) $(CXXFLAGS) -MT common/rpc/common_rpc_RpcServerTester-RpcServerTest.o -MD -MP -MF common/rpc/$(DEPDIR)/common_rpc_RpcServerTester-RpcServerTest.Tpo -c -o common/rpc/common_rpc_RpcServerTester-RpcServerTest.o `test -f 'common/rpc/RpcServerTest.cpp' || echo '$(srcdir)/'`common/rpc/RpcServerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rpc/$(DEPDIR)/common_rpc_RpcServerTester-RpcServerTest.Tpo common/rpc/$(DEPDIR)/common_rpc_RpcServerTester-RpcServerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rpc/RpcServerTest.cpp' object='common/rpc/common_rpc_RpcServerTester-RpcServerTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcServerTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rpc/common_rpc_RpcServerTester-RpcServerTest.o `test -f 'common/rpc/RpcServerTest.cpp' || echo '$(srcdir)/'`common/rpc/RpcServerTest.cpp common/rpc/common_rpc_RpcServerTester-RpcServerTest.obj: common/rpc/RpcServerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcServerTester_CXXFLAGS) $(CXXFLAGS) -MT common/rpc/common_rpc_RpcServerTester-RpcServerTest.obj -MD -MP -MF common/rpc/$(DEPDIR)/common_rpc_RpcServerTester-RpcServerTest.Tpo -c -o common/rpc/common_rpc_RpcServerTester-RpcServerTest.obj `if test -f 'common/rpc/RpcServerTest.cpp'; then $(CYGPATH_W) 'common/rpc/RpcServerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rpc/RpcServerTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rpc/$(DEPDIR)/common_rpc_RpcServerTester-RpcServerTest.Tpo common/rpc/$(DEPDIR)/common_rpc_RpcServerTester-RpcServerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rpc/RpcServerTest.cpp' object='common/rpc/common_rpc_RpcServerTester-RpcServerTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcServerTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rpc/common_rpc_RpcServerTester-RpcServerTest.obj `if test -f 'common/rpc/RpcServerTest.cpp'; then $(CYGPATH_W) 'common/rpc/RpcServerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rpc/RpcServerTest.cpp'; fi` common/rpc/common_rpc_RpcServerTester-TestService.o: common/rpc/TestService.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcServerTester_CXXFLAGS) $(CXXFLAGS) -MT common/rpc/common_rpc_RpcServerTester-TestService.o -MD -MP -MF common/rpc/$(DEPDIR)/common_rpc_RpcServerTester-TestService.Tpo -c -o common/rpc/common_rpc_RpcServerTester-TestService.o `test -f 'common/rpc/TestService.cpp' || echo '$(srcdir)/'`common/rpc/TestService.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rpc/$(DEPDIR)/common_rpc_RpcServerTester-TestService.Tpo common/rpc/$(DEPDIR)/common_rpc_RpcServerTester-TestService.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rpc/TestService.cpp' object='common/rpc/common_rpc_RpcServerTester-TestService.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcServerTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rpc/common_rpc_RpcServerTester-TestService.o `test -f 'common/rpc/TestService.cpp' || echo '$(srcdir)/'`common/rpc/TestService.cpp common/rpc/common_rpc_RpcServerTester-TestService.obj: common/rpc/TestService.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcServerTester_CXXFLAGS) $(CXXFLAGS) -MT common/rpc/common_rpc_RpcServerTester-TestService.obj -MD -MP -MF common/rpc/$(DEPDIR)/common_rpc_RpcServerTester-TestService.Tpo -c -o common/rpc/common_rpc_RpcServerTester-TestService.obj `if test -f 'common/rpc/TestService.cpp'; then $(CYGPATH_W) 'common/rpc/TestService.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rpc/TestService.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rpc/$(DEPDIR)/common_rpc_RpcServerTester-TestService.Tpo common/rpc/$(DEPDIR)/common_rpc_RpcServerTester-TestService.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rpc/TestService.cpp' object='common/rpc/common_rpc_RpcServerTester-TestService.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcServerTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rpc/common_rpc_RpcServerTester-TestService.obj `if test -f 'common/rpc/TestService.cpp'; then $(CYGPATH_W) 'common/rpc/TestService.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rpc/TestService.cpp'; fi` common/rpc/common_rpc_RpcServerTester-TestService.pb.o: common/rpc/TestService.pb.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcServerTester_CXXFLAGS) $(CXXFLAGS) -MT common/rpc/common_rpc_RpcServerTester-TestService.pb.o -MD -MP -MF common/rpc/$(DEPDIR)/common_rpc_RpcServerTester-TestService.pb.Tpo -c -o common/rpc/common_rpc_RpcServerTester-TestService.pb.o `test -f 'common/rpc/TestService.pb.cc' || echo '$(srcdir)/'`common/rpc/TestService.pb.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rpc/$(DEPDIR)/common_rpc_RpcServerTester-TestService.pb.Tpo common/rpc/$(DEPDIR)/common_rpc_RpcServerTester-TestService.pb.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rpc/TestService.pb.cc' object='common/rpc/common_rpc_RpcServerTester-TestService.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcServerTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rpc/common_rpc_RpcServerTester-TestService.pb.o `test -f 'common/rpc/TestService.pb.cc' || echo '$(srcdir)/'`common/rpc/TestService.pb.cc common/rpc/common_rpc_RpcServerTester-TestService.pb.obj: common/rpc/TestService.pb.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcServerTester_CXXFLAGS) $(CXXFLAGS) -MT common/rpc/common_rpc_RpcServerTester-TestService.pb.obj -MD -MP -MF common/rpc/$(DEPDIR)/common_rpc_RpcServerTester-TestService.pb.Tpo -c -o common/rpc/common_rpc_RpcServerTester-TestService.pb.obj `if test -f 'common/rpc/TestService.pb.cc'; then $(CYGPATH_W) 'common/rpc/TestService.pb.cc'; else $(CYGPATH_W) '$(srcdir)/common/rpc/TestService.pb.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rpc/$(DEPDIR)/common_rpc_RpcServerTester-TestService.pb.Tpo common/rpc/$(DEPDIR)/common_rpc_RpcServerTester-TestService.pb.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rpc/TestService.pb.cc' object='common/rpc/common_rpc_RpcServerTester-TestService.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcServerTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rpc/common_rpc_RpcServerTester-TestService.pb.obj `if test -f 'common/rpc/TestService.pb.cc'; then $(CYGPATH_W) 'common/rpc/TestService.pb.cc'; else $(CYGPATH_W) '$(srcdir)/common/rpc/TestService.pb.cc'; fi` common/rpc/common_rpc_RpcServerTester-TestServiceService.pb.o: common/rpc/TestServiceService.pb.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcServerTester_CXXFLAGS) $(CXXFLAGS) -MT common/rpc/common_rpc_RpcServerTester-TestServiceService.pb.o -MD -MP -MF common/rpc/$(DEPDIR)/common_rpc_RpcServerTester-TestServiceService.pb.Tpo -c -o common/rpc/common_rpc_RpcServerTester-TestServiceService.pb.o `test -f 'common/rpc/TestServiceService.pb.cpp' || echo '$(srcdir)/'`common/rpc/TestServiceService.pb.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rpc/$(DEPDIR)/common_rpc_RpcServerTester-TestServiceService.pb.Tpo common/rpc/$(DEPDIR)/common_rpc_RpcServerTester-TestServiceService.pb.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rpc/TestServiceService.pb.cpp' object='common/rpc/common_rpc_RpcServerTester-TestServiceService.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcServerTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rpc/common_rpc_RpcServerTester-TestServiceService.pb.o `test -f 'common/rpc/TestServiceService.pb.cpp' || echo '$(srcdir)/'`common/rpc/TestServiceService.pb.cpp common/rpc/common_rpc_RpcServerTester-TestServiceService.pb.obj: common/rpc/TestServiceService.pb.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcServerTester_CXXFLAGS) $(CXXFLAGS) -MT common/rpc/common_rpc_RpcServerTester-TestServiceService.pb.obj -MD -MP -MF common/rpc/$(DEPDIR)/common_rpc_RpcServerTester-TestServiceService.pb.Tpo -c -o common/rpc/common_rpc_RpcServerTester-TestServiceService.pb.obj `if test -f 'common/rpc/TestServiceService.pb.cpp'; then $(CYGPATH_W) 'common/rpc/TestServiceService.pb.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rpc/TestServiceService.pb.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rpc/$(DEPDIR)/common_rpc_RpcServerTester-TestServiceService.pb.Tpo common/rpc/$(DEPDIR)/common_rpc_RpcServerTester-TestServiceService.pb.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rpc/TestServiceService.pb.cpp' object='common/rpc/common_rpc_RpcServerTester-TestServiceService.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcServerTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rpc/common_rpc_RpcServerTester-TestServiceService.pb.obj `if test -f 'common/rpc/TestServiceService.pb.cpp'; then $(CYGPATH_W) 'common/rpc/TestServiceService.pb.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rpc/TestServiceService.pb.cpp'; fi` common/rpc/common_rpc_RpcTester-RpcControllerTest.o: common/rpc/RpcControllerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcTester_CXXFLAGS) $(CXXFLAGS) -MT common/rpc/common_rpc_RpcTester-RpcControllerTest.o -MD -MP -MF common/rpc/$(DEPDIR)/common_rpc_RpcTester-RpcControllerTest.Tpo -c -o common/rpc/common_rpc_RpcTester-RpcControllerTest.o `test -f 'common/rpc/RpcControllerTest.cpp' || echo '$(srcdir)/'`common/rpc/RpcControllerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rpc/$(DEPDIR)/common_rpc_RpcTester-RpcControllerTest.Tpo common/rpc/$(DEPDIR)/common_rpc_RpcTester-RpcControllerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rpc/RpcControllerTest.cpp' object='common/rpc/common_rpc_RpcTester-RpcControllerTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rpc/common_rpc_RpcTester-RpcControllerTest.o `test -f 'common/rpc/RpcControllerTest.cpp' || echo '$(srcdir)/'`common/rpc/RpcControllerTest.cpp common/rpc/common_rpc_RpcTester-RpcControllerTest.obj: common/rpc/RpcControllerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcTester_CXXFLAGS) $(CXXFLAGS) -MT common/rpc/common_rpc_RpcTester-RpcControllerTest.obj -MD -MP -MF common/rpc/$(DEPDIR)/common_rpc_RpcTester-RpcControllerTest.Tpo -c -o common/rpc/common_rpc_RpcTester-RpcControllerTest.obj `if test -f 'common/rpc/RpcControllerTest.cpp'; then $(CYGPATH_W) 'common/rpc/RpcControllerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rpc/RpcControllerTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rpc/$(DEPDIR)/common_rpc_RpcTester-RpcControllerTest.Tpo common/rpc/$(DEPDIR)/common_rpc_RpcTester-RpcControllerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rpc/RpcControllerTest.cpp' object='common/rpc/common_rpc_RpcTester-RpcControllerTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rpc/common_rpc_RpcTester-RpcControllerTest.obj `if test -f 'common/rpc/RpcControllerTest.cpp'; then $(CYGPATH_W) 'common/rpc/RpcControllerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rpc/RpcControllerTest.cpp'; fi` common/rpc/common_rpc_RpcTester-RpcChannelTest.o: common/rpc/RpcChannelTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcTester_CXXFLAGS) $(CXXFLAGS) -MT common/rpc/common_rpc_RpcTester-RpcChannelTest.o -MD -MP -MF common/rpc/$(DEPDIR)/common_rpc_RpcTester-RpcChannelTest.Tpo -c -o common/rpc/common_rpc_RpcTester-RpcChannelTest.o `test -f 'common/rpc/RpcChannelTest.cpp' || echo '$(srcdir)/'`common/rpc/RpcChannelTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rpc/$(DEPDIR)/common_rpc_RpcTester-RpcChannelTest.Tpo common/rpc/$(DEPDIR)/common_rpc_RpcTester-RpcChannelTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rpc/RpcChannelTest.cpp' object='common/rpc/common_rpc_RpcTester-RpcChannelTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rpc/common_rpc_RpcTester-RpcChannelTest.o `test -f 'common/rpc/RpcChannelTest.cpp' || echo '$(srcdir)/'`common/rpc/RpcChannelTest.cpp common/rpc/common_rpc_RpcTester-RpcChannelTest.obj: common/rpc/RpcChannelTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcTester_CXXFLAGS) $(CXXFLAGS) -MT common/rpc/common_rpc_RpcTester-RpcChannelTest.obj -MD -MP -MF common/rpc/$(DEPDIR)/common_rpc_RpcTester-RpcChannelTest.Tpo -c -o common/rpc/common_rpc_RpcTester-RpcChannelTest.obj `if test -f 'common/rpc/RpcChannelTest.cpp'; then $(CYGPATH_W) 'common/rpc/RpcChannelTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rpc/RpcChannelTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rpc/$(DEPDIR)/common_rpc_RpcTester-RpcChannelTest.Tpo common/rpc/$(DEPDIR)/common_rpc_RpcTester-RpcChannelTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rpc/RpcChannelTest.cpp' object='common/rpc/common_rpc_RpcTester-RpcChannelTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rpc/common_rpc_RpcTester-RpcChannelTest.obj `if test -f 'common/rpc/RpcChannelTest.cpp'; then $(CYGPATH_W) 'common/rpc/RpcChannelTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rpc/RpcChannelTest.cpp'; fi` common/rpc/common_rpc_RpcTester-RpcHeaderTest.o: common/rpc/RpcHeaderTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcTester_CXXFLAGS) $(CXXFLAGS) -MT common/rpc/common_rpc_RpcTester-RpcHeaderTest.o -MD -MP -MF common/rpc/$(DEPDIR)/common_rpc_RpcTester-RpcHeaderTest.Tpo -c -o common/rpc/common_rpc_RpcTester-RpcHeaderTest.o `test -f 'common/rpc/RpcHeaderTest.cpp' || echo '$(srcdir)/'`common/rpc/RpcHeaderTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rpc/$(DEPDIR)/common_rpc_RpcTester-RpcHeaderTest.Tpo common/rpc/$(DEPDIR)/common_rpc_RpcTester-RpcHeaderTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rpc/RpcHeaderTest.cpp' object='common/rpc/common_rpc_RpcTester-RpcHeaderTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rpc/common_rpc_RpcTester-RpcHeaderTest.o `test -f 'common/rpc/RpcHeaderTest.cpp' || echo '$(srcdir)/'`common/rpc/RpcHeaderTest.cpp common/rpc/common_rpc_RpcTester-RpcHeaderTest.obj: common/rpc/RpcHeaderTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcTester_CXXFLAGS) $(CXXFLAGS) -MT common/rpc/common_rpc_RpcTester-RpcHeaderTest.obj -MD -MP -MF common/rpc/$(DEPDIR)/common_rpc_RpcTester-RpcHeaderTest.Tpo -c -o common/rpc/common_rpc_RpcTester-RpcHeaderTest.obj `if test -f 'common/rpc/RpcHeaderTest.cpp'; then $(CYGPATH_W) 'common/rpc/RpcHeaderTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rpc/RpcHeaderTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rpc/$(DEPDIR)/common_rpc_RpcTester-RpcHeaderTest.Tpo common/rpc/$(DEPDIR)/common_rpc_RpcTester-RpcHeaderTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rpc/RpcHeaderTest.cpp' object='common/rpc/common_rpc_RpcTester-RpcHeaderTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rpc/common_rpc_RpcTester-RpcHeaderTest.obj `if test -f 'common/rpc/RpcHeaderTest.cpp'; then $(CYGPATH_W) 'common/rpc/RpcHeaderTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rpc/RpcHeaderTest.cpp'; fi` common/rpc/common_rpc_RpcTester-TestService.o: common/rpc/TestService.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcTester_CXXFLAGS) $(CXXFLAGS) -MT common/rpc/common_rpc_RpcTester-TestService.o -MD -MP -MF common/rpc/$(DEPDIR)/common_rpc_RpcTester-TestService.Tpo -c -o common/rpc/common_rpc_RpcTester-TestService.o `test -f 'common/rpc/TestService.cpp' || echo '$(srcdir)/'`common/rpc/TestService.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rpc/$(DEPDIR)/common_rpc_RpcTester-TestService.Tpo common/rpc/$(DEPDIR)/common_rpc_RpcTester-TestService.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rpc/TestService.cpp' object='common/rpc/common_rpc_RpcTester-TestService.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rpc/common_rpc_RpcTester-TestService.o `test -f 'common/rpc/TestService.cpp' || echo '$(srcdir)/'`common/rpc/TestService.cpp common/rpc/common_rpc_RpcTester-TestService.obj: common/rpc/TestService.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcTester_CXXFLAGS) $(CXXFLAGS) -MT common/rpc/common_rpc_RpcTester-TestService.obj -MD -MP -MF common/rpc/$(DEPDIR)/common_rpc_RpcTester-TestService.Tpo -c -o common/rpc/common_rpc_RpcTester-TestService.obj `if test -f 'common/rpc/TestService.cpp'; then $(CYGPATH_W) 'common/rpc/TestService.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rpc/TestService.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rpc/$(DEPDIR)/common_rpc_RpcTester-TestService.Tpo common/rpc/$(DEPDIR)/common_rpc_RpcTester-TestService.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rpc/TestService.cpp' object='common/rpc/common_rpc_RpcTester-TestService.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rpc/common_rpc_RpcTester-TestService.obj `if test -f 'common/rpc/TestService.cpp'; then $(CYGPATH_W) 'common/rpc/TestService.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rpc/TestService.cpp'; fi` common/rpc/common_rpc_RpcTester-TestService.pb.o: common/rpc/TestService.pb.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcTester_CXXFLAGS) $(CXXFLAGS) -MT common/rpc/common_rpc_RpcTester-TestService.pb.o -MD -MP -MF common/rpc/$(DEPDIR)/common_rpc_RpcTester-TestService.pb.Tpo -c -o common/rpc/common_rpc_RpcTester-TestService.pb.o `test -f 'common/rpc/TestService.pb.cc' || echo '$(srcdir)/'`common/rpc/TestService.pb.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rpc/$(DEPDIR)/common_rpc_RpcTester-TestService.pb.Tpo common/rpc/$(DEPDIR)/common_rpc_RpcTester-TestService.pb.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rpc/TestService.pb.cc' object='common/rpc/common_rpc_RpcTester-TestService.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rpc/common_rpc_RpcTester-TestService.pb.o `test -f 'common/rpc/TestService.pb.cc' || echo '$(srcdir)/'`common/rpc/TestService.pb.cc common/rpc/common_rpc_RpcTester-TestService.pb.obj: common/rpc/TestService.pb.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcTester_CXXFLAGS) $(CXXFLAGS) -MT common/rpc/common_rpc_RpcTester-TestService.pb.obj -MD -MP -MF common/rpc/$(DEPDIR)/common_rpc_RpcTester-TestService.pb.Tpo -c -o common/rpc/common_rpc_RpcTester-TestService.pb.obj `if test -f 'common/rpc/TestService.pb.cc'; then $(CYGPATH_W) 'common/rpc/TestService.pb.cc'; else $(CYGPATH_W) '$(srcdir)/common/rpc/TestService.pb.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rpc/$(DEPDIR)/common_rpc_RpcTester-TestService.pb.Tpo common/rpc/$(DEPDIR)/common_rpc_RpcTester-TestService.pb.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rpc/TestService.pb.cc' object='common/rpc/common_rpc_RpcTester-TestService.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rpc/common_rpc_RpcTester-TestService.pb.obj `if test -f 'common/rpc/TestService.pb.cc'; then $(CYGPATH_W) 'common/rpc/TestService.pb.cc'; else $(CYGPATH_W) '$(srcdir)/common/rpc/TestService.pb.cc'; fi` common/rpc/common_rpc_RpcTester-TestServiceService.pb.o: common/rpc/TestServiceService.pb.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcTester_CXXFLAGS) $(CXXFLAGS) -MT common/rpc/common_rpc_RpcTester-TestServiceService.pb.o -MD -MP -MF common/rpc/$(DEPDIR)/common_rpc_RpcTester-TestServiceService.pb.Tpo -c -o common/rpc/common_rpc_RpcTester-TestServiceService.pb.o `test -f 'common/rpc/TestServiceService.pb.cpp' || echo '$(srcdir)/'`common/rpc/TestServiceService.pb.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rpc/$(DEPDIR)/common_rpc_RpcTester-TestServiceService.pb.Tpo common/rpc/$(DEPDIR)/common_rpc_RpcTester-TestServiceService.pb.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rpc/TestServiceService.pb.cpp' object='common/rpc/common_rpc_RpcTester-TestServiceService.pb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rpc/common_rpc_RpcTester-TestServiceService.pb.o `test -f 'common/rpc/TestServiceService.pb.cpp' || echo '$(srcdir)/'`common/rpc/TestServiceService.pb.cpp common/rpc/common_rpc_RpcTester-TestServiceService.pb.obj: common/rpc/TestServiceService.pb.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcTester_CXXFLAGS) $(CXXFLAGS) -MT common/rpc/common_rpc_RpcTester-TestServiceService.pb.obj -MD -MP -MF common/rpc/$(DEPDIR)/common_rpc_RpcTester-TestServiceService.pb.Tpo -c -o common/rpc/common_rpc_RpcTester-TestServiceService.pb.obj `if test -f 'common/rpc/TestServiceService.pb.cpp'; then $(CYGPATH_W) 'common/rpc/TestServiceService.pb.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rpc/TestServiceService.pb.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/rpc/$(DEPDIR)/common_rpc_RpcTester-TestServiceService.pb.Tpo common/rpc/$(DEPDIR)/common_rpc_RpcTester-TestServiceService.pb.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/rpc/TestServiceService.pb.cpp' object='common/rpc/common_rpc_RpcTester-TestServiceService.pb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_rpc_RpcTester_CXXFLAGS) $(CXXFLAGS) -c -o common/rpc/common_rpc_RpcTester-TestServiceService.pb.obj `if test -f 'common/rpc/TestServiceService.pb.cpp'; then $(CYGPATH_W) 'common/rpc/TestServiceService.pb.cpp'; else $(CYGPATH_W) '$(srcdir)/common/rpc/TestServiceService.pb.cpp'; fi` common/strings/common_strings_UtilsTester-UtilsTest.o: common/strings/UtilsTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_strings_UtilsTester_CXXFLAGS) $(CXXFLAGS) -MT common/strings/common_strings_UtilsTester-UtilsTest.o -MD -MP -MF common/strings/$(DEPDIR)/common_strings_UtilsTester-UtilsTest.Tpo -c -o common/strings/common_strings_UtilsTester-UtilsTest.o `test -f 'common/strings/UtilsTest.cpp' || echo '$(srcdir)/'`common/strings/UtilsTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/strings/$(DEPDIR)/common_strings_UtilsTester-UtilsTest.Tpo common/strings/$(DEPDIR)/common_strings_UtilsTester-UtilsTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/strings/UtilsTest.cpp' object='common/strings/common_strings_UtilsTester-UtilsTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_strings_UtilsTester_CXXFLAGS) $(CXXFLAGS) -c -o common/strings/common_strings_UtilsTester-UtilsTest.o `test -f 'common/strings/UtilsTest.cpp' || echo '$(srcdir)/'`common/strings/UtilsTest.cpp common/strings/common_strings_UtilsTester-UtilsTest.obj: common/strings/UtilsTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_strings_UtilsTester_CXXFLAGS) $(CXXFLAGS) -MT common/strings/common_strings_UtilsTester-UtilsTest.obj -MD -MP -MF common/strings/$(DEPDIR)/common_strings_UtilsTester-UtilsTest.Tpo -c -o common/strings/common_strings_UtilsTester-UtilsTest.obj `if test -f 'common/strings/UtilsTest.cpp'; then $(CYGPATH_W) 'common/strings/UtilsTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/strings/UtilsTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/strings/$(DEPDIR)/common_strings_UtilsTester-UtilsTest.Tpo common/strings/$(DEPDIR)/common_strings_UtilsTester-UtilsTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/strings/UtilsTest.cpp' object='common/strings/common_strings_UtilsTester-UtilsTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_strings_UtilsTester_CXXFLAGS) $(CXXFLAGS) -c -o common/strings/common_strings_UtilsTester-UtilsTest.obj `if test -f 'common/strings/UtilsTest.cpp'; then $(CYGPATH_W) 'common/strings/UtilsTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/strings/UtilsTest.cpp'; fi` common/thread/common_thread_ExecutorThreadTester-ExecutorThreadTest.o: common/thread/ExecutorThreadTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_thread_ExecutorThreadTester_CXXFLAGS) $(CXXFLAGS) -MT common/thread/common_thread_ExecutorThreadTester-ExecutorThreadTest.o -MD -MP -MF common/thread/$(DEPDIR)/common_thread_ExecutorThreadTester-ExecutorThreadTest.Tpo -c -o common/thread/common_thread_ExecutorThreadTester-ExecutorThreadTest.o `test -f 'common/thread/ExecutorThreadTest.cpp' || echo '$(srcdir)/'`common/thread/ExecutorThreadTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/thread/$(DEPDIR)/common_thread_ExecutorThreadTester-ExecutorThreadTest.Tpo common/thread/$(DEPDIR)/common_thread_ExecutorThreadTester-ExecutorThreadTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/thread/ExecutorThreadTest.cpp' object='common/thread/common_thread_ExecutorThreadTester-ExecutorThreadTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_thread_ExecutorThreadTester_CXXFLAGS) $(CXXFLAGS) -c -o common/thread/common_thread_ExecutorThreadTester-ExecutorThreadTest.o `test -f 'common/thread/ExecutorThreadTest.cpp' || echo '$(srcdir)/'`common/thread/ExecutorThreadTest.cpp common/thread/common_thread_ExecutorThreadTester-ExecutorThreadTest.obj: common/thread/ExecutorThreadTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_thread_ExecutorThreadTester_CXXFLAGS) $(CXXFLAGS) -MT common/thread/common_thread_ExecutorThreadTester-ExecutorThreadTest.obj -MD -MP -MF common/thread/$(DEPDIR)/common_thread_ExecutorThreadTester-ExecutorThreadTest.Tpo -c -o common/thread/common_thread_ExecutorThreadTester-ExecutorThreadTest.obj `if test -f 'common/thread/ExecutorThreadTest.cpp'; then $(CYGPATH_W) 'common/thread/ExecutorThreadTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/thread/ExecutorThreadTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/thread/$(DEPDIR)/common_thread_ExecutorThreadTester-ExecutorThreadTest.Tpo common/thread/$(DEPDIR)/common_thread_ExecutorThreadTester-ExecutorThreadTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/thread/ExecutorThreadTest.cpp' object='common/thread/common_thread_ExecutorThreadTester-ExecutorThreadTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_thread_ExecutorThreadTester_CXXFLAGS) $(CXXFLAGS) -c -o common/thread/common_thread_ExecutorThreadTester-ExecutorThreadTest.obj `if test -f 'common/thread/ExecutorThreadTest.cpp'; then $(CYGPATH_W) 'common/thread/ExecutorThreadTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/thread/ExecutorThreadTest.cpp'; fi` common/thread/common_thread_FutureTester-FutureTest.o: common/thread/FutureTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_thread_FutureTester_CXXFLAGS) $(CXXFLAGS) -MT common/thread/common_thread_FutureTester-FutureTest.o -MD -MP -MF common/thread/$(DEPDIR)/common_thread_FutureTester-FutureTest.Tpo -c -o common/thread/common_thread_FutureTester-FutureTest.o `test -f 'common/thread/FutureTest.cpp' || echo '$(srcdir)/'`common/thread/FutureTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/thread/$(DEPDIR)/common_thread_FutureTester-FutureTest.Tpo common/thread/$(DEPDIR)/common_thread_FutureTester-FutureTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/thread/FutureTest.cpp' object='common/thread/common_thread_FutureTester-FutureTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_thread_FutureTester_CXXFLAGS) $(CXXFLAGS) -c -o common/thread/common_thread_FutureTester-FutureTest.o `test -f 'common/thread/FutureTest.cpp' || echo '$(srcdir)/'`common/thread/FutureTest.cpp common/thread/common_thread_FutureTester-FutureTest.obj: common/thread/FutureTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_thread_FutureTester_CXXFLAGS) $(CXXFLAGS) -MT common/thread/common_thread_FutureTester-FutureTest.obj -MD -MP -MF common/thread/$(DEPDIR)/common_thread_FutureTester-FutureTest.Tpo -c -o common/thread/common_thread_FutureTester-FutureTest.obj `if test -f 'common/thread/FutureTest.cpp'; then $(CYGPATH_W) 'common/thread/FutureTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/thread/FutureTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/thread/$(DEPDIR)/common_thread_FutureTester-FutureTest.Tpo common/thread/$(DEPDIR)/common_thread_FutureTester-FutureTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/thread/FutureTest.cpp' object='common/thread/common_thread_FutureTester-FutureTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_thread_FutureTester_CXXFLAGS) $(CXXFLAGS) -c -o common/thread/common_thread_FutureTester-FutureTest.obj `if test -f 'common/thread/FutureTest.cpp'; then $(CYGPATH_W) 'common/thread/FutureTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/thread/FutureTest.cpp'; fi` common/thread/common_thread_ThreadTester-ThreadPoolTest.o: common/thread/ThreadPoolTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_thread_ThreadTester_CXXFLAGS) $(CXXFLAGS) -MT common/thread/common_thread_ThreadTester-ThreadPoolTest.o -MD -MP -MF common/thread/$(DEPDIR)/common_thread_ThreadTester-ThreadPoolTest.Tpo -c -o common/thread/common_thread_ThreadTester-ThreadPoolTest.o `test -f 'common/thread/ThreadPoolTest.cpp' || echo '$(srcdir)/'`common/thread/ThreadPoolTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/thread/$(DEPDIR)/common_thread_ThreadTester-ThreadPoolTest.Tpo common/thread/$(DEPDIR)/common_thread_ThreadTester-ThreadPoolTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/thread/ThreadPoolTest.cpp' object='common/thread/common_thread_ThreadTester-ThreadPoolTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_thread_ThreadTester_CXXFLAGS) $(CXXFLAGS) -c -o common/thread/common_thread_ThreadTester-ThreadPoolTest.o `test -f 'common/thread/ThreadPoolTest.cpp' || echo '$(srcdir)/'`common/thread/ThreadPoolTest.cpp common/thread/common_thread_ThreadTester-ThreadPoolTest.obj: common/thread/ThreadPoolTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_thread_ThreadTester_CXXFLAGS) $(CXXFLAGS) -MT common/thread/common_thread_ThreadTester-ThreadPoolTest.obj -MD -MP -MF common/thread/$(DEPDIR)/common_thread_ThreadTester-ThreadPoolTest.Tpo -c -o common/thread/common_thread_ThreadTester-ThreadPoolTest.obj `if test -f 'common/thread/ThreadPoolTest.cpp'; then $(CYGPATH_W) 'common/thread/ThreadPoolTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/thread/ThreadPoolTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/thread/$(DEPDIR)/common_thread_ThreadTester-ThreadPoolTest.Tpo common/thread/$(DEPDIR)/common_thread_ThreadTester-ThreadPoolTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/thread/ThreadPoolTest.cpp' object='common/thread/common_thread_ThreadTester-ThreadPoolTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_thread_ThreadTester_CXXFLAGS) $(CXXFLAGS) -c -o common/thread/common_thread_ThreadTester-ThreadPoolTest.obj `if test -f 'common/thread/ThreadPoolTest.cpp'; then $(CYGPATH_W) 'common/thread/ThreadPoolTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/thread/ThreadPoolTest.cpp'; fi` common/thread/common_thread_ThreadTester-ThreadTest.o: common/thread/ThreadTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_thread_ThreadTester_CXXFLAGS) $(CXXFLAGS) -MT common/thread/common_thread_ThreadTester-ThreadTest.o -MD -MP -MF common/thread/$(DEPDIR)/common_thread_ThreadTester-ThreadTest.Tpo -c -o common/thread/common_thread_ThreadTester-ThreadTest.o `test -f 'common/thread/ThreadTest.cpp' || echo '$(srcdir)/'`common/thread/ThreadTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/thread/$(DEPDIR)/common_thread_ThreadTester-ThreadTest.Tpo common/thread/$(DEPDIR)/common_thread_ThreadTester-ThreadTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/thread/ThreadTest.cpp' object='common/thread/common_thread_ThreadTester-ThreadTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_thread_ThreadTester_CXXFLAGS) $(CXXFLAGS) -c -o common/thread/common_thread_ThreadTester-ThreadTest.o `test -f 'common/thread/ThreadTest.cpp' || echo '$(srcdir)/'`common/thread/ThreadTest.cpp common/thread/common_thread_ThreadTester-ThreadTest.obj: common/thread/ThreadTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_thread_ThreadTester_CXXFLAGS) $(CXXFLAGS) -MT common/thread/common_thread_ThreadTester-ThreadTest.obj -MD -MP -MF common/thread/$(DEPDIR)/common_thread_ThreadTester-ThreadTest.Tpo -c -o common/thread/common_thread_ThreadTester-ThreadTest.obj `if test -f 'common/thread/ThreadTest.cpp'; then $(CYGPATH_W) 'common/thread/ThreadTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/thread/ThreadTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/thread/$(DEPDIR)/common_thread_ThreadTester-ThreadTest.Tpo common/thread/$(DEPDIR)/common_thread_ThreadTester-ThreadTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/thread/ThreadTest.cpp' object='common/thread/common_thread_ThreadTester-ThreadTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_thread_ThreadTester_CXXFLAGS) $(CXXFLAGS) -c -o common/thread/common_thread_ThreadTester-ThreadTest.obj `if test -f 'common/thread/ThreadTest.cpp'; then $(CYGPATH_W) 'common/thread/ThreadTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/thread/ThreadTest.cpp'; fi` common/timecode/common_timecode_TimeCodeTester-TimeCodeTest.o: common/timecode/TimeCodeTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_timecode_TimeCodeTester_CXXFLAGS) $(CXXFLAGS) -MT common/timecode/common_timecode_TimeCodeTester-TimeCodeTest.o -MD -MP -MF common/timecode/$(DEPDIR)/common_timecode_TimeCodeTester-TimeCodeTest.Tpo -c -o common/timecode/common_timecode_TimeCodeTester-TimeCodeTest.o `test -f 'common/timecode/TimeCodeTest.cpp' || echo '$(srcdir)/'`common/timecode/TimeCodeTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/timecode/$(DEPDIR)/common_timecode_TimeCodeTester-TimeCodeTest.Tpo common/timecode/$(DEPDIR)/common_timecode_TimeCodeTester-TimeCodeTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/timecode/TimeCodeTest.cpp' object='common/timecode/common_timecode_TimeCodeTester-TimeCodeTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_timecode_TimeCodeTester_CXXFLAGS) $(CXXFLAGS) -c -o common/timecode/common_timecode_TimeCodeTester-TimeCodeTest.o `test -f 'common/timecode/TimeCodeTest.cpp' || echo '$(srcdir)/'`common/timecode/TimeCodeTest.cpp common/timecode/common_timecode_TimeCodeTester-TimeCodeTest.obj: common/timecode/TimeCodeTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_timecode_TimeCodeTester_CXXFLAGS) $(CXXFLAGS) -MT common/timecode/common_timecode_TimeCodeTester-TimeCodeTest.obj -MD -MP -MF common/timecode/$(DEPDIR)/common_timecode_TimeCodeTester-TimeCodeTest.Tpo -c -o common/timecode/common_timecode_TimeCodeTester-TimeCodeTest.obj `if test -f 'common/timecode/TimeCodeTest.cpp'; then $(CYGPATH_W) 'common/timecode/TimeCodeTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/timecode/TimeCodeTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/timecode/$(DEPDIR)/common_timecode_TimeCodeTester-TimeCodeTest.Tpo common/timecode/$(DEPDIR)/common_timecode_TimeCodeTester-TimeCodeTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/timecode/TimeCodeTest.cpp' object='common/timecode/common_timecode_TimeCodeTester-TimeCodeTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_timecode_TimeCodeTester_CXXFLAGS) $(CXXFLAGS) -c -o common/timecode/common_timecode_TimeCodeTester-TimeCodeTest.obj `if test -f 'common/timecode/TimeCodeTest.cpp'; then $(CYGPATH_W) 'common/timecode/TimeCodeTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/timecode/TimeCodeTest.cpp'; fi` common/utils/common_utils_UtilsTester-ActionQueueTest.o: common/utils/ActionQueueTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -MT common/utils/common_utils_UtilsTester-ActionQueueTest.o -MD -MP -MF common/utils/$(DEPDIR)/common_utils_UtilsTester-ActionQueueTest.Tpo -c -o common/utils/common_utils_UtilsTester-ActionQueueTest.o `test -f 'common/utils/ActionQueueTest.cpp' || echo '$(srcdir)/'`common/utils/ActionQueueTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/utils/$(DEPDIR)/common_utils_UtilsTester-ActionQueueTest.Tpo common/utils/$(DEPDIR)/common_utils_UtilsTester-ActionQueueTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/utils/ActionQueueTest.cpp' object='common/utils/common_utils_UtilsTester-ActionQueueTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -c -o common/utils/common_utils_UtilsTester-ActionQueueTest.o `test -f 'common/utils/ActionQueueTest.cpp' || echo '$(srcdir)/'`common/utils/ActionQueueTest.cpp common/utils/common_utils_UtilsTester-ActionQueueTest.obj: common/utils/ActionQueueTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -MT common/utils/common_utils_UtilsTester-ActionQueueTest.obj -MD -MP -MF common/utils/$(DEPDIR)/common_utils_UtilsTester-ActionQueueTest.Tpo -c -o common/utils/common_utils_UtilsTester-ActionQueueTest.obj `if test -f 'common/utils/ActionQueueTest.cpp'; then $(CYGPATH_W) 'common/utils/ActionQueueTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/utils/ActionQueueTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/utils/$(DEPDIR)/common_utils_UtilsTester-ActionQueueTest.Tpo common/utils/$(DEPDIR)/common_utils_UtilsTester-ActionQueueTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/utils/ActionQueueTest.cpp' object='common/utils/common_utils_UtilsTester-ActionQueueTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -c -o common/utils/common_utils_UtilsTester-ActionQueueTest.obj `if test -f 'common/utils/ActionQueueTest.cpp'; then $(CYGPATH_W) 'common/utils/ActionQueueTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/utils/ActionQueueTest.cpp'; fi` common/utils/common_utils_UtilsTester-BackoffTest.o: common/utils/BackoffTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -MT common/utils/common_utils_UtilsTester-BackoffTest.o -MD -MP -MF common/utils/$(DEPDIR)/common_utils_UtilsTester-BackoffTest.Tpo -c -o common/utils/common_utils_UtilsTester-BackoffTest.o `test -f 'common/utils/BackoffTest.cpp' || echo '$(srcdir)/'`common/utils/BackoffTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/utils/$(DEPDIR)/common_utils_UtilsTester-BackoffTest.Tpo common/utils/$(DEPDIR)/common_utils_UtilsTester-BackoffTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/utils/BackoffTest.cpp' object='common/utils/common_utils_UtilsTester-BackoffTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -c -o common/utils/common_utils_UtilsTester-BackoffTest.o `test -f 'common/utils/BackoffTest.cpp' || echo '$(srcdir)/'`common/utils/BackoffTest.cpp common/utils/common_utils_UtilsTester-BackoffTest.obj: common/utils/BackoffTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -MT common/utils/common_utils_UtilsTester-BackoffTest.obj -MD -MP -MF common/utils/$(DEPDIR)/common_utils_UtilsTester-BackoffTest.Tpo -c -o common/utils/common_utils_UtilsTester-BackoffTest.obj `if test -f 'common/utils/BackoffTest.cpp'; then $(CYGPATH_W) 'common/utils/BackoffTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/utils/BackoffTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/utils/$(DEPDIR)/common_utils_UtilsTester-BackoffTest.Tpo common/utils/$(DEPDIR)/common_utils_UtilsTester-BackoffTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/utils/BackoffTest.cpp' object='common/utils/common_utils_UtilsTester-BackoffTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -c -o common/utils/common_utils_UtilsTester-BackoffTest.obj `if test -f 'common/utils/BackoffTest.cpp'; then $(CYGPATH_W) 'common/utils/BackoffTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/utils/BackoffTest.cpp'; fi` common/utils/common_utils_UtilsTester-CallbackTest.o: common/utils/CallbackTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -MT common/utils/common_utils_UtilsTester-CallbackTest.o -MD -MP -MF common/utils/$(DEPDIR)/common_utils_UtilsTester-CallbackTest.Tpo -c -o common/utils/common_utils_UtilsTester-CallbackTest.o `test -f 'common/utils/CallbackTest.cpp' || echo '$(srcdir)/'`common/utils/CallbackTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/utils/$(DEPDIR)/common_utils_UtilsTester-CallbackTest.Tpo common/utils/$(DEPDIR)/common_utils_UtilsTester-CallbackTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/utils/CallbackTest.cpp' object='common/utils/common_utils_UtilsTester-CallbackTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -c -o common/utils/common_utils_UtilsTester-CallbackTest.o `test -f 'common/utils/CallbackTest.cpp' || echo '$(srcdir)/'`common/utils/CallbackTest.cpp common/utils/common_utils_UtilsTester-CallbackTest.obj: common/utils/CallbackTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -MT common/utils/common_utils_UtilsTester-CallbackTest.obj -MD -MP -MF common/utils/$(DEPDIR)/common_utils_UtilsTester-CallbackTest.Tpo -c -o common/utils/common_utils_UtilsTester-CallbackTest.obj `if test -f 'common/utils/CallbackTest.cpp'; then $(CYGPATH_W) 'common/utils/CallbackTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/utils/CallbackTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/utils/$(DEPDIR)/common_utils_UtilsTester-CallbackTest.Tpo common/utils/$(DEPDIR)/common_utils_UtilsTester-CallbackTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/utils/CallbackTest.cpp' object='common/utils/common_utils_UtilsTester-CallbackTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -c -o common/utils/common_utils_UtilsTester-CallbackTest.obj `if test -f 'common/utils/CallbackTest.cpp'; then $(CYGPATH_W) 'common/utils/CallbackTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/utils/CallbackTest.cpp'; fi` common/utils/common_utils_UtilsTester-ClockTest.o: common/utils/ClockTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -MT common/utils/common_utils_UtilsTester-ClockTest.o -MD -MP -MF common/utils/$(DEPDIR)/common_utils_UtilsTester-ClockTest.Tpo -c -o common/utils/common_utils_UtilsTester-ClockTest.o `test -f 'common/utils/ClockTest.cpp' || echo '$(srcdir)/'`common/utils/ClockTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/utils/$(DEPDIR)/common_utils_UtilsTester-ClockTest.Tpo common/utils/$(DEPDIR)/common_utils_UtilsTester-ClockTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/utils/ClockTest.cpp' object='common/utils/common_utils_UtilsTester-ClockTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -c -o common/utils/common_utils_UtilsTester-ClockTest.o `test -f 'common/utils/ClockTest.cpp' || echo '$(srcdir)/'`common/utils/ClockTest.cpp common/utils/common_utils_UtilsTester-ClockTest.obj: common/utils/ClockTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -MT common/utils/common_utils_UtilsTester-ClockTest.obj -MD -MP -MF common/utils/$(DEPDIR)/common_utils_UtilsTester-ClockTest.Tpo -c -o common/utils/common_utils_UtilsTester-ClockTest.obj `if test -f 'common/utils/ClockTest.cpp'; then $(CYGPATH_W) 'common/utils/ClockTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/utils/ClockTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/utils/$(DEPDIR)/common_utils_UtilsTester-ClockTest.Tpo common/utils/$(DEPDIR)/common_utils_UtilsTester-ClockTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/utils/ClockTest.cpp' object='common/utils/common_utils_UtilsTester-ClockTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -c -o common/utils/common_utils_UtilsTester-ClockTest.obj `if test -f 'common/utils/ClockTest.cpp'; then $(CYGPATH_W) 'common/utils/ClockTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/utils/ClockTest.cpp'; fi` common/utils/common_utils_UtilsTester-DmxBufferTest.o: common/utils/DmxBufferTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -MT common/utils/common_utils_UtilsTester-DmxBufferTest.o -MD -MP -MF common/utils/$(DEPDIR)/common_utils_UtilsTester-DmxBufferTest.Tpo -c -o common/utils/common_utils_UtilsTester-DmxBufferTest.o `test -f 'common/utils/DmxBufferTest.cpp' || echo '$(srcdir)/'`common/utils/DmxBufferTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/utils/$(DEPDIR)/common_utils_UtilsTester-DmxBufferTest.Tpo common/utils/$(DEPDIR)/common_utils_UtilsTester-DmxBufferTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/utils/DmxBufferTest.cpp' object='common/utils/common_utils_UtilsTester-DmxBufferTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -c -o common/utils/common_utils_UtilsTester-DmxBufferTest.o `test -f 'common/utils/DmxBufferTest.cpp' || echo '$(srcdir)/'`common/utils/DmxBufferTest.cpp common/utils/common_utils_UtilsTester-DmxBufferTest.obj: common/utils/DmxBufferTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -MT common/utils/common_utils_UtilsTester-DmxBufferTest.obj -MD -MP -MF common/utils/$(DEPDIR)/common_utils_UtilsTester-DmxBufferTest.Tpo -c -o common/utils/common_utils_UtilsTester-DmxBufferTest.obj `if test -f 'common/utils/DmxBufferTest.cpp'; then $(CYGPATH_W) 'common/utils/DmxBufferTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/utils/DmxBufferTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/utils/$(DEPDIR)/common_utils_UtilsTester-DmxBufferTest.Tpo common/utils/$(DEPDIR)/common_utils_UtilsTester-DmxBufferTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/utils/DmxBufferTest.cpp' object='common/utils/common_utils_UtilsTester-DmxBufferTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -c -o common/utils/common_utils_UtilsTester-DmxBufferTest.obj `if test -f 'common/utils/DmxBufferTest.cpp'; then $(CYGPATH_W) 'common/utils/DmxBufferTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/utils/DmxBufferTest.cpp'; fi` common/utils/common_utils_UtilsTester-MultiCallbackTest.o: common/utils/MultiCallbackTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -MT common/utils/common_utils_UtilsTester-MultiCallbackTest.o -MD -MP -MF common/utils/$(DEPDIR)/common_utils_UtilsTester-MultiCallbackTest.Tpo -c -o common/utils/common_utils_UtilsTester-MultiCallbackTest.o `test -f 'common/utils/MultiCallbackTest.cpp' || echo '$(srcdir)/'`common/utils/MultiCallbackTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/utils/$(DEPDIR)/common_utils_UtilsTester-MultiCallbackTest.Tpo common/utils/$(DEPDIR)/common_utils_UtilsTester-MultiCallbackTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/utils/MultiCallbackTest.cpp' object='common/utils/common_utils_UtilsTester-MultiCallbackTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -c -o common/utils/common_utils_UtilsTester-MultiCallbackTest.o `test -f 'common/utils/MultiCallbackTest.cpp' || echo '$(srcdir)/'`common/utils/MultiCallbackTest.cpp common/utils/common_utils_UtilsTester-MultiCallbackTest.obj: common/utils/MultiCallbackTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -MT common/utils/common_utils_UtilsTester-MultiCallbackTest.obj -MD -MP -MF common/utils/$(DEPDIR)/common_utils_UtilsTester-MultiCallbackTest.Tpo -c -o common/utils/common_utils_UtilsTester-MultiCallbackTest.obj `if test -f 'common/utils/MultiCallbackTest.cpp'; then $(CYGPATH_W) 'common/utils/MultiCallbackTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/utils/MultiCallbackTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/utils/$(DEPDIR)/common_utils_UtilsTester-MultiCallbackTest.Tpo common/utils/$(DEPDIR)/common_utils_UtilsTester-MultiCallbackTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/utils/MultiCallbackTest.cpp' object='common/utils/common_utils_UtilsTester-MultiCallbackTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -c -o common/utils/common_utils_UtilsTester-MultiCallbackTest.obj `if test -f 'common/utils/MultiCallbackTest.cpp'; then $(CYGPATH_W) 'common/utils/MultiCallbackTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/utils/MultiCallbackTest.cpp'; fi` common/utils/common_utils_UtilsTester-StringUtilsTest.o: common/utils/StringUtilsTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -MT common/utils/common_utils_UtilsTester-StringUtilsTest.o -MD -MP -MF common/utils/$(DEPDIR)/common_utils_UtilsTester-StringUtilsTest.Tpo -c -o common/utils/common_utils_UtilsTester-StringUtilsTest.o `test -f 'common/utils/StringUtilsTest.cpp' || echo '$(srcdir)/'`common/utils/StringUtilsTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/utils/$(DEPDIR)/common_utils_UtilsTester-StringUtilsTest.Tpo common/utils/$(DEPDIR)/common_utils_UtilsTester-StringUtilsTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/utils/StringUtilsTest.cpp' object='common/utils/common_utils_UtilsTester-StringUtilsTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -c -o common/utils/common_utils_UtilsTester-StringUtilsTest.o `test -f 'common/utils/StringUtilsTest.cpp' || echo '$(srcdir)/'`common/utils/StringUtilsTest.cpp common/utils/common_utils_UtilsTester-StringUtilsTest.obj: common/utils/StringUtilsTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -MT common/utils/common_utils_UtilsTester-StringUtilsTest.obj -MD -MP -MF common/utils/$(DEPDIR)/common_utils_UtilsTester-StringUtilsTest.Tpo -c -o common/utils/common_utils_UtilsTester-StringUtilsTest.obj `if test -f 'common/utils/StringUtilsTest.cpp'; then $(CYGPATH_W) 'common/utils/StringUtilsTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/utils/StringUtilsTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/utils/$(DEPDIR)/common_utils_UtilsTester-StringUtilsTest.Tpo common/utils/$(DEPDIR)/common_utils_UtilsTester-StringUtilsTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/utils/StringUtilsTest.cpp' object='common/utils/common_utils_UtilsTester-StringUtilsTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -c -o common/utils/common_utils_UtilsTester-StringUtilsTest.obj `if test -f 'common/utils/StringUtilsTest.cpp'; then $(CYGPATH_W) 'common/utils/StringUtilsTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/utils/StringUtilsTest.cpp'; fi` common/utils/common_utils_UtilsTester-TokenBucketTest.o: common/utils/TokenBucketTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -MT common/utils/common_utils_UtilsTester-TokenBucketTest.o -MD -MP -MF common/utils/$(DEPDIR)/common_utils_UtilsTester-TokenBucketTest.Tpo -c -o common/utils/common_utils_UtilsTester-TokenBucketTest.o `test -f 'common/utils/TokenBucketTest.cpp' || echo '$(srcdir)/'`common/utils/TokenBucketTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/utils/$(DEPDIR)/common_utils_UtilsTester-TokenBucketTest.Tpo common/utils/$(DEPDIR)/common_utils_UtilsTester-TokenBucketTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/utils/TokenBucketTest.cpp' object='common/utils/common_utils_UtilsTester-TokenBucketTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -c -o common/utils/common_utils_UtilsTester-TokenBucketTest.o `test -f 'common/utils/TokenBucketTest.cpp' || echo '$(srcdir)/'`common/utils/TokenBucketTest.cpp common/utils/common_utils_UtilsTester-TokenBucketTest.obj: common/utils/TokenBucketTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -MT common/utils/common_utils_UtilsTester-TokenBucketTest.obj -MD -MP -MF common/utils/$(DEPDIR)/common_utils_UtilsTester-TokenBucketTest.Tpo -c -o common/utils/common_utils_UtilsTester-TokenBucketTest.obj `if test -f 'common/utils/TokenBucketTest.cpp'; then $(CYGPATH_W) 'common/utils/TokenBucketTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/utils/TokenBucketTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/utils/$(DEPDIR)/common_utils_UtilsTester-TokenBucketTest.Tpo common/utils/$(DEPDIR)/common_utils_UtilsTester-TokenBucketTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/utils/TokenBucketTest.cpp' object='common/utils/common_utils_UtilsTester-TokenBucketTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -c -o common/utils/common_utils_UtilsTester-TokenBucketTest.obj `if test -f 'common/utils/TokenBucketTest.cpp'; then $(CYGPATH_W) 'common/utils/TokenBucketTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/utils/TokenBucketTest.cpp'; fi` common/utils/common_utils_UtilsTester-UtilsTest.o: common/utils/UtilsTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -MT common/utils/common_utils_UtilsTester-UtilsTest.o -MD -MP -MF common/utils/$(DEPDIR)/common_utils_UtilsTester-UtilsTest.Tpo -c -o common/utils/common_utils_UtilsTester-UtilsTest.o `test -f 'common/utils/UtilsTest.cpp' || echo '$(srcdir)/'`common/utils/UtilsTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/utils/$(DEPDIR)/common_utils_UtilsTester-UtilsTest.Tpo common/utils/$(DEPDIR)/common_utils_UtilsTester-UtilsTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/utils/UtilsTest.cpp' object='common/utils/common_utils_UtilsTester-UtilsTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -c -o common/utils/common_utils_UtilsTester-UtilsTest.o `test -f 'common/utils/UtilsTest.cpp' || echo '$(srcdir)/'`common/utils/UtilsTest.cpp common/utils/common_utils_UtilsTester-UtilsTest.obj: common/utils/UtilsTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -MT common/utils/common_utils_UtilsTester-UtilsTest.obj -MD -MP -MF common/utils/$(DEPDIR)/common_utils_UtilsTester-UtilsTest.Tpo -c -o common/utils/common_utils_UtilsTester-UtilsTest.obj `if test -f 'common/utils/UtilsTest.cpp'; then $(CYGPATH_W) 'common/utils/UtilsTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/utils/UtilsTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/utils/$(DEPDIR)/common_utils_UtilsTester-UtilsTest.Tpo common/utils/$(DEPDIR)/common_utils_UtilsTester-UtilsTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/utils/UtilsTest.cpp' object='common/utils/common_utils_UtilsTester-UtilsTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -c -o common/utils/common_utils_UtilsTester-UtilsTest.obj `if test -f 'common/utils/UtilsTest.cpp'; then $(CYGPATH_W) 'common/utils/UtilsTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/utils/UtilsTest.cpp'; fi` common/utils/common_utils_UtilsTester-WatchdogTest.o: common/utils/WatchdogTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -MT common/utils/common_utils_UtilsTester-WatchdogTest.o -MD -MP -MF common/utils/$(DEPDIR)/common_utils_UtilsTester-WatchdogTest.Tpo -c -o common/utils/common_utils_UtilsTester-WatchdogTest.o `test -f 'common/utils/WatchdogTest.cpp' || echo '$(srcdir)/'`common/utils/WatchdogTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/utils/$(DEPDIR)/common_utils_UtilsTester-WatchdogTest.Tpo common/utils/$(DEPDIR)/common_utils_UtilsTester-WatchdogTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/utils/WatchdogTest.cpp' object='common/utils/common_utils_UtilsTester-WatchdogTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -c -o common/utils/common_utils_UtilsTester-WatchdogTest.o `test -f 'common/utils/WatchdogTest.cpp' || echo '$(srcdir)/'`common/utils/WatchdogTest.cpp common/utils/common_utils_UtilsTester-WatchdogTest.obj: common/utils/WatchdogTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -MT common/utils/common_utils_UtilsTester-WatchdogTest.obj -MD -MP -MF common/utils/$(DEPDIR)/common_utils_UtilsTester-WatchdogTest.Tpo -c -o common/utils/common_utils_UtilsTester-WatchdogTest.obj `if test -f 'common/utils/WatchdogTest.cpp'; then $(CYGPATH_W) 'common/utils/WatchdogTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/utils/WatchdogTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/utils/$(DEPDIR)/common_utils_UtilsTester-WatchdogTest.Tpo common/utils/$(DEPDIR)/common_utils_UtilsTester-WatchdogTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/utils/WatchdogTest.cpp' object='common/utils/common_utils_UtilsTester-WatchdogTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_utils_UtilsTester_CXXFLAGS) $(CXXFLAGS) -c -o common/utils/common_utils_UtilsTester-WatchdogTest.obj `if test -f 'common/utils/WatchdogTest.cpp'; then $(CYGPATH_W) 'common/utils/WatchdogTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/utils/WatchdogTest.cpp'; fi` common/web/common_web_JsonTester-JsonTest.o: common/web/JsonTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_JsonTester_CXXFLAGS) $(CXXFLAGS) -MT common/web/common_web_JsonTester-JsonTest.o -MD -MP -MF common/web/$(DEPDIR)/common_web_JsonTester-JsonTest.Tpo -c -o common/web/common_web_JsonTester-JsonTest.o `test -f 'common/web/JsonTest.cpp' || echo '$(srcdir)/'`common/web/JsonTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/web/$(DEPDIR)/common_web_JsonTester-JsonTest.Tpo common/web/$(DEPDIR)/common_web_JsonTester-JsonTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/web/JsonTest.cpp' object='common/web/common_web_JsonTester-JsonTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_JsonTester_CXXFLAGS) $(CXXFLAGS) -c -o common/web/common_web_JsonTester-JsonTest.o `test -f 'common/web/JsonTest.cpp' || echo '$(srcdir)/'`common/web/JsonTest.cpp common/web/common_web_JsonTester-JsonTest.obj: common/web/JsonTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_JsonTester_CXXFLAGS) $(CXXFLAGS) -MT common/web/common_web_JsonTester-JsonTest.obj -MD -MP -MF common/web/$(DEPDIR)/common_web_JsonTester-JsonTest.Tpo -c -o common/web/common_web_JsonTester-JsonTest.obj `if test -f 'common/web/JsonTest.cpp'; then $(CYGPATH_W) 'common/web/JsonTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/web/JsonTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/web/$(DEPDIR)/common_web_JsonTester-JsonTest.Tpo common/web/$(DEPDIR)/common_web_JsonTester-JsonTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/web/JsonTest.cpp' object='common/web/common_web_JsonTester-JsonTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_JsonTester_CXXFLAGS) $(CXXFLAGS) -c -o common/web/common_web_JsonTester-JsonTest.obj `if test -f 'common/web/JsonTest.cpp'; then $(CYGPATH_W) 'common/web/JsonTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/web/JsonTest.cpp'; fi` common/web/common_web_ParserTester-ParserTest.o: common/web/ParserTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_ParserTester_CXXFLAGS) $(CXXFLAGS) -MT common/web/common_web_ParserTester-ParserTest.o -MD -MP -MF common/web/$(DEPDIR)/common_web_ParserTester-ParserTest.Tpo -c -o common/web/common_web_ParserTester-ParserTest.o `test -f 'common/web/ParserTest.cpp' || echo '$(srcdir)/'`common/web/ParserTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/web/$(DEPDIR)/common_web_ParserTester-ParserTest.Tpo common/web/$(DEPDIR)/common_web_ParserTester-ParserTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/web/ParserTest.cpp' object='common/web/common_web_ParserTester-ParserTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_ParserTester_CXXFLAGS) $(CXXFLAGS) -c -o common/web/common_web_ParserTester-ParserTest.o `test -f 'common/web/ParserTest.cpp' || echo '$(srcdir)/'`common/web/ParserTest.cpp common/web/common_web_ParserTester-ParserTest.obj: common/web/ParserTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_ParserTester_CXXFLAGS) $(CXXFLAGS) -MT common/web/common_web_ParserTester-ParserTest.obj -MD -MP -MF common/web/$(DEPDIR)/common_web_ParserTester-ParserTest.Tpo -c -o common/web/common_web_ParserTester-ParserTest.obj `if test -f 'common/web/ParserTest.cpp'; then $(CYGPATH_W) 'common/web/ParserTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/web/ParserTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/web/$(DEPDIR)/common_web_ParserTester-ParserTest.Tpo common/web/$(DEPDIR)/common_web_ParserTester-ParserTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/web/ParserTest.cpp' object='common/web/common_web_ParserTester-ParserTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_ParserTester_CXXFLAGS) $(CXXFLAGS) -c -o common/web/common_web_ParserTester-ParserTest.obj `if test -f 'common/web/ParserTest.cpp'; then $(CYGPATH_W) 'common/web/ParserTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/web/ParserTest.cpp'; fi` common/web/common_web_PointerTester-PointerTest.o: common/web/PointerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_PointerTester_CXXFLAGS) $(CXXFLAGS) -MT common/web/common_web_PointerTester-PointerTest.o -MD -MP -MF common/web/$(DEPDIR)/common_web_PointerTester-PointerTest.Tpo -c -o common/web/common_web_PointerTester-PointerTest.o `test -f 'common/web/PointerTest.cpp' || echo '$(srcdir)/'`common/web/PointerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/web/$(DEPDIR)/common_web_PointerTester-PointerTest.Tpo common/web/$(DEPDIR)/common_web_PointerTester-PointerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/web/PointerTest.cpp' object='common/web/common_web_PointerTester-PointerTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_PointerTester_CXXFLAGS) $(CXXFLAGS) -c -o common/web/common_web_PointerTester-PointerTest.o `test -f 'common/web/PointerTest.cpp' || echo '$(srcdir)/'`common/web/PointerTest.cpp common/web/common_web_PointerTester-PointerTest.obj: common/web/PointerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_PointerTester_CXXFLAGS) $(CXXFLAGS) -MT common/web/common_web_PointerTester-PointerTest.obj -MD -MP -MF common/web/$(DEPDIR)/common_web_PointerTester-PointerTest.Tpo -c -o common/web/common_web_PointerTester-PointerTest.obj `if test -f 'common/web/PointerTest.cpp'; then $(CYGPATH_W) 'common/web/PointerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/web/PointerTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/web/$(DEPDIR)/common_web_PointerTester-PointerTest.Tpo common/web/$(DEPDIR)/common_web_PointerTester-PointerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/web/PointerTest.cpp' object='common/web/common_web_PointerTester-PointerTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_PointerTester_CXXFLAGS) $(CXXFLAGS) -c -o common/web/common_web_PointerTester-PointerTest.obj `if test -f 'common/web/PointerTest.cpp'; then $(CYGPATH_W) 'common/web/PointerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/web/PointerTest.cpp'; fi` common/web/common_web_PointerTrackerTester-PointerTrackerTest.o: common/web/PointerTrackerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_PointerTrackerTester_CXXFLAGS) $(CXXFLAGS) -MT common/web/common_web_PointerTrackerTester-PointerTrackerTest.o -MD -MP -MF common/web/$(DEPDIR)/common_web_PointerTrackerTester-PointerTrackerTest.Tpo -c -o common/web/common_web_PointerTrackerTester-PointerTrackerTest.o `test -f 'common/web/PointerTrackerTest.cpp' || echo '$(srcdir)/'`common/web/PointerTrackerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/web/$(DEPDIR)/common_web_PointerTrackerTester-PointerTrackerTest.Tpo common/web/$(DEPDIR)/common_web_PointerTrackerTester-PointerTrackerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/web/PointerTrackerTest.cpp' object='common/web/common_web_PointerTrackerTester-PointerTrackerTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_PointerTrackerTester_CXXFLAGS) $(CXXFLAGS) -c -o common/web/common_web_PointerTrackerTester-PointerTrackerTest.o `test -f 'common/web/PointerTrackerTest.cpp' || echo '$(srcdir)/'`common/web/PointerTrackerTest.cpp common/web/common_web_PointerTrackerTester-PointerTrackerTest.obj: common/web/PointerTrackerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_PointerTrackerTester_CXXFLAGS) $(CXXFLAGS) -MT common/web/common_web_PointerTrackerTester-PointerTrackerTest.obj -MD -MP -MF common/web/$(DEPDIR)/common_web_PointerTrackerTester-PointerTrackerTest.Tpo -c -o common/web/common_web_PointerTrackerTester-PointerTrackerTest.obj `if test -f 'common/web/PointerTrackerTest.cpp'; then $(CYGPATH_W) 'common/web/PointerTrackerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/web/PointerTrackerTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/web/$(DEPDIR)/common_web_PointerTrackerTester-PointerTrackerTest.Tpo common/web/$(DEPDIR)/common_web_PointerTrackerTester-PointerTrackerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/web/PointerTrackerTest.cpp' object='common/web/common_web_PointerTrackerTester-PointerTrackerTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_PointerTrackerTester_CXXFLAGS) $(CXXFLAGS) -c -o common/web/common_web_PointerTrackerTester-PointerTrackerTest.obj `if test -f 'common/web/PointerTrackerTest.cpp'; then $(CYGPATH_W) 'common/web/PointerTrackerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/web/PointerTrackerTest.cpp'; fi` common/web/common_web_PtchParserTester-PatchParserTest.o: common/web/PatchParserTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_PtchParserTester_CXXFLAGS) $(CXXFLAGS) -MT common/web/common_web_PtchParserTester-PatchParserTest.o -MD -MP -MF common/web/$(DEPDIR)/common_web_PtchParserTester-PatchParserTest.Tpo -c -o common/web/common_web_PtchParserTester-PatchParserTest.o `test -f 'common/web/PatchParserTest.cpp' || echo '$(srcdir)/'`common/web/PatchParserTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/web/$(DEPDIR)/common_web_PtchParserTester-PatchParserTest.Tpo common/web/$(DEPDIR)/common_web_PtchParserTester-PatchParserTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/web/PatchParserTest.cpp' object='common/web/common_web_PtchParserTester-PatchParserTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_PtchParserTester_CXXFLAGS) $(CXXFLAGS) -c -o common/web/common_web_PtchParserTester-PatchParserTest.o `test -f 'common/web/PatchParserTest.cpp' || echo '$(srcdir)/'`common/web/PatchParserTest.cpp common/web/common_web_PtchParserTester-PatchParserTest.obj: common/web/PatchParserTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_PtchParserTester_CXXFLAGS) $(CXXFLAGS) -MT common/web/common_web_PtchParserTester-PatchParserTest.obj -MD -MP -MF common/web/$(DEPDIR)/common_web_PtchParserTester-PatchParserTest.Tpo -c -o common/web/common_web_PtchParserTester-PatchParserTest.obj `if test -f 'common/web/PatchParserTest.cpp'; then $(CYGPATH_W) 'common/web/PatchParserTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/web/PatchParserTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/web/$(DEPDIR)/common_web_PtchParserTester-PatchParserTest.Tpo common/web/$(DEPDIR)/common_web_PtchParserTester-PatchParserTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/web/PatchParserTest.cpp' object='common/web/common_web_PtchParserTester-PatchParserTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_PtchParserTester_CXXFLAGS) $(CXXFLAGS) -c -o common/web/common_web_PtchParserTester-PatchParserTest.obj `if test -f 'common/web/PatchParserTest.cpp'; then $(CYGPATH_W) 'common/web/PatchParserTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/web/PatchParserTest.cpp'; fi` common/web/common_web_PtchTester-PatchTest.o: common/web/PatchTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_PtchTester_CXXFLAGS) $(CXXFLAGS) -MT common/web/common_web_PtchTester-PatchTest.o -MD -MP -MF common/web/$(DEPDIR)/common_web_PtchTester-PatchTest.Tpo -c -o common/web/common_web_PtchTester-PatchTest.o `test -f 'common/web/PatchTest.cpp' || echo '$(srcdir)/'`common/web/PatchTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/web/$(DEPDIR)/common_web_PtchTester-PatchTest.Tpo common/web/$(DEPDIR)/common_web_PtchTester-PatchTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/web/PatchTest.cpp' object='common/web/common_web_PtchTester-PatchTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_PtchTester_CXXFLAGS) $(CXXFLAGS) -c -o common/web/common_web_PtchTester-PatchTest.o `test -f 'common/web/PatchTest.cpp' || echo '$(srcdir)/'`common/web/PatchTest.cpp common/web/common_web_PtchTester-PatchTest.obj: common/web/PatchTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_PtchTester_CXXFLAGS) $(CXXFLAGS) -MT common/web/common_web_PtchTester-PatchTest.obj -MD -MP -MF common/web/$(DEPDIR)/common_web_PtchTester-PatchTest.Tpo -c -o common/web/common_web_PtchTester-PatchTest.obj `if test -f 'common/web/PatchTest.cpp'; then $(CYGPATH_W) 'common/web/PatchTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/web/PatchTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/web/$(DEPDIR)/common_web_PtchTester-PatchTest.Tpo common/web/$(DEPDIR)/common_web_PtchTester-PatchTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/web/PatchTest.cpp' object='common/web/common_web_PtchTester-PatchTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_PtchTester_CXXFLAGS) $(CXXFLAGS) -c -o common/web/common_web_PtchTester-PatchTest.obj `if test -f 'common/web/PatchTest.cpp'; then $(CYGPATH_W) 'common/web/PatchTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/web/PatchTest.cpp'; fi` common/web/common_web_SchemaParserTester-SchemaParserTest.o: common/web/SchemaParserTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_SchemaParserTester_CXXFLAGS) $(CXXFLAGS) -MT common/web/common_web_SchemaParserTester-SchemaParserTest.o -MD -MP -MF common/web/$(DEPDIR)/common_web_SchemaParserTester-SchemaParserTest.Tpo -c -o common/web/common_web_SchemaParserTester-SchemaParserTest.o `test -f 'common/web/SchemaParserTest.cpp' || echo '$(srcdir)/'`common/web/SchemaParserTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/web/$(DEPDIR)/common_web_SchemaParserTester-SchemaParserTest.Tpo common/web/$(DEPDIR)/common_web_SchemaParserTester-SchemaParserTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/web/SchemaParserTest.cpp' object='common/web/common_web_SchemaParserTester-SchemaParserTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_SchemaParserTester_CXXFLAGS) $(CXXFLAGS) -c -o common/web/common_web_SchemaParserTester-SchemaParserTest.o `test -f 'common/web/SchemaParserTest.cpp' || echo '$(srcdir)/'`common/web/SchemaParserTest.cpp common/web/common_web_SchemaParserTester-SchemaParserTest.obj: common/web/SchemaParserTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_SchemaParserTester_CXXFLAGS) $(CXXFLAGS) -MT common/web/common_web_SchemaParserTester-SchemaParserTest.obj -MD -MP -MF common/web/$(DEPDIR)/common_web_SchemaParserTester-SchemaParserTest.Tpo -c -o common/web/common_web_SchemaParserTester-SchemaParserTest.obj `if test -f 'common/web/SchemaParserTest.cpp'; then $(CYGPATH_W) 'common/web/SchemaParserTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/web/SchemaParserTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/web/$(DEPDIR)/common_web_SchemaParserTester-SchemaParserTest.Tpo common/web/$(DEPDIR)/common_web_SchemaParserTester-SchemaParserTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/web/SchemaParserTest.cpp' object='common/web/common_web_SchemaParserTester-SchemaParserTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_SchemaParserTester_CXXFLAGS) $(CXXFLAGS) -c -o common/web/common_web_SchemaParserTester-SchemaParserTest.obj `if test -f 'common/web/SchemaParserTest.cpp'; then $(CYGPATH_W) 'common/web/SchemaParserTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/web/SchemaParserTest.cpp'; fi` common/web/common_web_SchemaTester-SchemaTest.o: common/web/SchemaTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_SchemaTester_CXXFLAGS) $(CXXFLAGS) -MT common/web/common_web_SchemaTester-SchemaTest.o -MD -MP -MF common/web/$(DEPDIR)/common_web_SchemaTester-SchemaTest.Tpo -c -o common/web/common_web_SchemaTester-SchemaTest.o `test -f 'common/web/SchemaTest.cpp' || echo '$(srcdir)/'`common/web/SchemaTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/web/$(DEPDIR)/common_web_SchemaTester-SchemaTest.Tpo common/web/$(DEPDIR)/common_web_SchemaTester-SchemaTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/web/SchemaTest.cpp' object='common/web/common_web_SchemaTester-SchemaTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_SchemaTester_CXXFLAGS) $(CXXFLAGS) -c -o common/web/common_web_SchemaTester-SchemaTest.o `test -f 'common/web/SchemaTest.cpp' || echo '$(srcdir)/'`common/web/SchemaTest.cpp common/web/common_web_SchemaTester-SchemaTest.obj: common/web/SchemaTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_SchemaTester_CXXFLAGS) $(CXXFLAGS) -MT common/web/common_web_SchemaTester-SchemaTest.obj -MD -MP -MF common/web/$(DEPDIR)/common_web_SchemaTester-SchemaTest.Tpo -c -o common/web/common_web_SchemaTester-SchemaTest.obj `if test -f 'common/web/SchemaTest.cpp'; then $(CYGPATH_W) 'common/web/SchemaTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/web/SchemaTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/web/$(DEPDIR)/common_web_SchemaTester-SchemaTest.Tpo common/web/$(DEPDIR)/common_web_SchemaTester-SchemaTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/web/SchemaTest.cpp' object='common/web/common_web_SchemaTester-SchemaTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_SchemaTester_CXXFLAGS) $(CXXFLAGS) -c -o common/web/common_web_SchemaTester-SchemaTest.obj `if test -f 'common/web/SchemaTest.cpp'; then $(CYGPATH_W) 'common/web/SchemaTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/web/SchemaTest.cpp'; fi` common/web/common_web_SectionsTester-SectionsTest.o: common/web/SectionsTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_SectionsTester_CXXFLAGS) $(CXXFLAGS) -MT common/web/common_web_SectionsTester-SectionsTest.o -MD -MP -MF common/web/$(DEPDIR)/common_web_SectionsTester-SectionsTest.Tpo -c -o common/web/common_web_SectionsTester-SectionsTest.o `test -f 'common/web/SectionsTest.cpp' || echo '$(srcdir)/'`common/web/SectionsTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/web/$(DEPDIR)/common_web_SectionsTester-SectionsTest.Tpo common/web/$(DEPDIR)/common_web_SectionsTester-SectionsTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/web/SectionsTest.cpp' object='common/web/common_web_SectionsTester-SectionsTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_SectionsTester_CXXFLAGS) $(CXXFLAGS) -c -o common/web/common_web_SectionsTester-SectionsTest.o `test -f 'common/web/SectionsTest.cpp' || echo '$(srcdir)/'`common/web/SectionsTest.cpp common/web/common_web_SectionsTester-SectionsTest.obj: common/web/SectionsTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_SectionsTester_CXXFLAGS) $(CXXFLAGS) -MT common/web/common_web_SectionsTester-SectionsTest.obj -MD -MP -MF common/web/$(DEPDIR)/common_web_SectionsTester-SectionsTest.Tpo -c -o common/web/common_web_SectionsTester-SectionsTest.obj `if test -f 'common/web/SectionsTest.cpp'; then $(CYGPATH_W) 'common/web/SectionsTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/web/SectionsTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) common/web/$(DEPDIR)/common_web_SectionsTester-SectionsTest.Tpo common/web/$(DEPDIR)/common_web_SectionsTester-SectionsTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='common/web/SectionsTest.cpp' object='common/web/common_web_SectionsTester-SectionsTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(common_web_SectionsTester_CXXFLAGS) $(CXXFLAGS) -c -o common/web/common_web_SectionsTester-SectionsTest.obj `if test -f 'common/web/SectionsTest.cpp'; then $(CYGPATH_W) 'common/web/SectionsTest.cpp'; else $(CYGPATH_W) '$(srcdir)/common/web/SectionsTest.cpp'; fi` data/rdm/data_rdm_PidDataTester-PidDataTest.o: data/rdm/PidDataTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(data_rdm_PidDataTester_CXXFLAGS) $(CXXFLAGS) -MT data/rdm/data_rdm_PidDataTester-PidDataTest.o -MD -MP -MF data/rdm/$(DEPDIR)/data_rdm_PidDataTester-PidDataTest.Tpo -c -o data/rdm/data_rdm_PidDataTester-PidDataTest.o `test -f 'data/rdm/PidDataTest.cpp' || echo '$(srcdir)/'`data/rdm/PidDataTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) data/rdm/$(DEPDIR)/data_rdm_PidDataTester-PidDataTest.Tpo data/rdm/$(DEPDIR)/data_rdm_PidDataTester-PidDataTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='data/rdm/PidDataTest.cpp' object='data/rdm/data_rdm_PidDataTester-PidDataTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(data_rdm_PidDataTester_CXXFLAGS) $(CXXFLAGS) -c -o data/rdm/data_rdm_PidDataTester-PidDataTest.o `test -f 'data/rdm/PidDataTest.cpp' || echo '$(srcdir)/'`data/rdm/PidDataTest.cpp data/rdm/data_rdm_PidDataTester-PidDataTest.obj: data/rdm/PidDataTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(data_rdm_PidDataTester_CXXFLAGS) $(CXXFLAGS) -MT data/rdm/data_rdm_PidDataTester-PidDataTest.obj -MD -MP -MF data/rdm/$(DEPDIR)/data_rdm_PidDataTester-PidDataTest.Tpo -c -o data/rdm/data_rdm_PidDataTester-PidDataTest.obj `if test -f 'data/rdm/PidDataTest.cpp'; then $(CYGPATH_W) 'data/rdm/PidDataTest.cpp'; else $(CYGPATH_W) '$(srcdir)/data/rdm/PidDataTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) data/rdm/$(DEPDIR)/data_rdm_PidDataTester-PidDataTest.Tpo data/rdm/$(DEPDIR)/data_rdm_PidDataTester-PidDataTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='data/rdm/PidDataTest.cpp' object='data/rdm/data_rdm_PidDataTester-PidDataTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(data_rdm_PidDataTester_CXXFLAGS) $(CXXFLAGS) -c -o data/rdm/data_rdm_PidDataTester-PidDataTest.obj `if test -f 'data/rdm/PidDataTest.cpp'; then $(CYGPATH_W) 'data/rdm/PidDataTest.cpp'; else $(CYGPATH_W) '$(srcdir)/data/rdm/PidDataTest.cpp'; fi` examples/examples_ola_artnet-ola-artnet.o: examples/ola-artnet.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(examples_ola_artnet_CXXFLAGS) $(CXXFLAGS) -MT examples/examples_ola_artnet-ola-artnet.o -MD -MP -MF examples/$(DEPDIR)/examples_ola_artnet-ola-artnet.Tpo -c -o examples/examples_ola_artnet-ola-artnet.o `test -f 'examples/ola-artnet.cpp' || echo '$(srcdir)/'`examples/ola-artnet.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) examples/$(DEPDIR)/examples_ola_artnet-ola-artnet.Tpo examples/$(DEPDIR)/examples_ola_artnet-ola-artnet.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='examples/ola-artnet.cpp' object='examples/examples_ola_artnet-ola-artnet.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(examples_ola_artnet_CXXFLAGS) $(CXXFLAGS) -c -o examples/examples_ola_artnet-ola-artnet.o `test -f 'examples/ola-artnet.cpp' || echo '$(srcdir)/'`examples/ola-artnet.cpp examples/examples_ola_artnet-ola-artnet.obj: examples/ola-artnet.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(examples_ola_artnet_CXXFLAGS) $(CXXFLAGS) -MT examples/examples_ola_artnet-ola-artnet.obj -MD -MP -MF examples/$(DEPDIR)/examples_ola_artnet-ola-artnet.Tpo -c -o examples/examples_ola_artnet-ola-artnet.obj `if test -f 'examples/ola-artnet.cpp'; then $(CYGPATH_W) 'examples/ola-artnet.cpp'; else $(CYGPATH_W) '$(srcdir)/examples/ola-artnet.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) examples/$(DEPDIR)/examples_ola_artnet-ola-artnet.Tpo examples/$(DEPDIR)/examples_ola_artnet-ola-artnet.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='examples/ola-artnet.cpp' object='examples/examples_ola_artnet-ola-artnet.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(examples_ola_artnet_CXXFLAGS) $(CXXFLAGS) -c -o examples/examples_ola_artnet-ola-artnet.obj `if test -f 'examples/ola-artnet.cpp'; then $(CYGPATH_W) 'examples/ola-artnet.cpp'; else $(CYGPATH_W) '$(srcdir)/examples/ola-artnet.cpp'; fi` examples/examples_ola_e131-ola-e131.o: examples/ola-e131.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(examples_ola_e131_CXXFLAGS) $(CXXFLAGS) -MT examples/examples_ola_e131-ola-e131.o -MD -MP -MF examples/$(DEPDIR)/examples_ola_e131-ola-e131.Tpo -c -o examples/examples_ola_e131-ola-e131.o `test -f 'examples/ola-e131.cpp' || echo '$(srcdir)/'`examples/ola-e131.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) examples/$(DEPDIR)/examples_ola_e131-ola-e131.Tpo examples/$(DEPDIR)/examples_ola_e131-ola-e131.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='examples/ola-e131.cpp' object='examples/examples_ola_e131-ola-e131.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(examples_ola_e131_CXXFLAGS) $(CXXFLAGS) -c -o examples/examples_ola_e131-ola-e131.o `test -f 'examples/ola-e131.cpp' || echo '$(srcdir)/'`examples/ola-e131.cpp examples/examples_ola_e131-ola-e131.obj: examples/ola-e131.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(examples_ola_e131_CXXFLAGS) $(CXXFLAGS) -MT examples/examples_ola_e131-ola-e131.obj -MD -MP -MF examples/$(DEPDIR)/examples_ola_e131-ola-e131.Tpo -c -o examples/examples_ola_e131-ola-e131.obj `if test -f 'examples/ola-e131.cpp'; then $(CYGPATH_W) 'examples/ola-e131.cpp'; else $(CYGPATH_W) '$(srcdir)/examples/ola-e131.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) examples/$(DEPDIR)/examples_ola_e131-ola-e131.Tpo examples/$(DEPDIR)/examples_ola_e131-ola-e131.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='examples/ola-e131.cpp' object='examples/examples_ola_e131-ola-e131.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(examples_ola_e131_CXXFLAGS) $(CXXFLAGS) -c -o examples/examples_ola_e131-ola-e131.obj `if test -f 'examples/ola-e131.cpp'; then $(CYGPATH_W) 'examples/ola-e131.cpp'; else $(CYGPATH_W) '$(srcdir)/examples/ola-e131.cpp'; fi` examples/examples_ola_usbpro-ola-usbpro.o: examples/ola-usbpro.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(examples_ola_usbpro_CXXFLAGS) $(CXXFLAGS) -MT examples/examples_ola_usbpro-ola-usbpro.o -MD -MP -MF examples/$(DEPDIR)/examples_ola_usbpro-ola-usbpro.Tpo -c -o examples/examples_ola_usbpro-ola-usbpro.o `test -f 'examples/ola-usbpro.cpp' || echo '$(srcdir)/'`examples/ola-usbpro.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) examples/$(DEPDIR)/examples_ola_usbpro-ola-usbpro.Tpo examples/$(DEPDIR)/examples_ola_usbpro-ola-usbpro.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='examples/ola-usbpro.cpp' object='examples/examples_ola_usbpro-ola-usbpro.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(examples_ola_usbpro_CXXFLAGS) $(CXXFLAGS) -c -o examples/examples_ola_usbpro-ola-usbpro.o `test -f 'examples/ola-usbpro.cpp' || echo '$(srcdir)/'`examples/ola-usbpro.cpp examples/examples_ola_usbpro-ola-usbpro.obj: examples/ola-usbpro.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(examples_ola_usbpro_CXXFLAGS) $(CXXFLAGS) -MT examples/examples_ola_usbpro-ola-usbpro.obj -MD -MP -MF examples/$(DEPDIR)/examples_ola_usbpro-ola-usbpro.Tpo -c -o examples/examples_ola_usbpro-ola-usbpro.obj `if test -f 'examples/ola-usbpro.cpp'; then $(CYGPATH_W) 'examples/ola-usbpro.cpp'; else $(CYGPATH_W) '$(srcdir)/examples/ola-usbpro.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) examples/$(DEPDIR)/examples_ola_usbpro-ola-usbpro.Tpo examples/$(DEPDIR)/examples_ola_usbpro-ola-usbpro.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='examples/ola-usbpro.cpp' object='examples/examples_ola_usbpro-ola-usbpro.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(examples_ola_usbpro_CXXFLAGS) $(CXXFLAGS) -c -o examples/examples_ola_usbpro-ola-usbpro.obj `if test -f 'examples/ola-usbpro.cpp'; then $(CYGPATH_W) 'examples/ola-usbpro.cpp'; else $(CYGPATH_W) '$(srcdir)/examples/ola-usbpro.cpp'; fi` libs/acn/libs_acn_E131Tester-BaseInflatorTest.o: libs/acn/BaseInflatorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_E131Tester-BaseInflatorTest.o -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_E131Tester-BaseInflatorTest.Tpo -c -o libs/acn/libs_acn_E131Tester-BaseInflatorTest.o `test -f 'libs/acn/BaseInflatorTest.cpp' || echo '$(srcdir)/'`libs/acn/BaseInflatorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_E131Tester-BaseInflatorTest.Tpo libs/acn/$(DEPDIR)/libs_acn_E131Tester-BaseInflatorTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/BaseInflatorTest.cpp' object='libs/acn/libs_acn_E131Tester-BaseInflatorTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_E131Tester-BaseInflatorTest.o `test -f 'libs/acn/BaseInflatorTest.cpp' || echo '$(srcdir)/'`libs/acn/BaseInflatorTest.cpp libs/acn/libs_acn_E131Tester-BaseInflatorTest.obj: libs/acn/BaseInflatorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_E131Tester-BaseInflatorTest.obj -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_E131Tester-BaseInflatorTest.Tpo -c -o libs/acn/libs_acn_E131Tester-BaseInflatorTest.obj `if test -f 'libs/acn/BaseInflatorTest.cpp'; then $(CYGPATH_W) 'libs/acn/BaseInflatorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/BaseInflatorTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_E131Tester-BaseInflatorTest.Tpo libs/acn/$(DEPDIR)/libs_acn_E131Tester-BaseInflatorTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/BaseInflatorTest.cpp' object='libs/acn/libs_acn_E131Tester-BaseInflatorTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_E131Tester-BaseInflatorTest.obj `if test -f 'libs/acn/BaseInflatorTest.cpp'; then $(CYGPATH_W) 'libs/acn/BaseInflatorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/BaseInflatorTest.cpp'; fi` libs/acn/libs_acn_E131Tester-CIDTest.o: libs/acn/CIDTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_E131Tester-CIDTest.o -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_E131Tester-CIDTest.Tpo -c -o libs/acn/libs_acn_E131Tester-CIDTest.o `test -f 'libs/acn/CIDTest.cpp' || echo '$(srcdir)/'`libs/acn/CIDTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_E131Tester-CIDTest.Tpo libs/acn/$(DEPDIR)/libs_acn_E131Tester-CIDTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/CIDTest.cpp' object='libs/acn/libs_acn_E131Tester-CIDTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_E131Tester-CIDTest.o `test -f 'libs/acn/CIDTest.cpp' || echo '$(srcdir)/'`libs/acn/CIDTest.cpp libs/acn/libs_acn_E131Tester-CIDTest.obj: libs/acn/CIDTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_E131Tester-CIDTest.obj -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_E131Tester-CIDTest.Tpo -c -o libs/acn/libs_acn_E131Tester-CIDTest.obj `if test -f 'libs/acn/CIDTest.cpp'; then $(CYGPATH_W) 'libs/acn/CIDTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/CIDTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_E131Tester-CIDTest.Tpo libs/acn/$(DEPDIR)/libs_acn_E131Tester-CIDTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/CIDTest.cpp' object='libs/acn/libs_acn_E131Tester-CIDTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_E131Tester-CIDTest.obj `if test -f 'libs/acn/CIDTest.cpp'; then $(CYGPATH_W) 'libs/acn/CIDTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/CIDTest.cpp'; fi` libs/acn/libs_acn_E131Tester-DMPAddressTest.o: libs/acn/DMPAddressTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_E131Tester-DMPAddressTest.o -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_E131Tester-DMPAddressTest.Tpo -c -o libs/acn/libs_acn_E131Tester-DMPAddressTest.o `test -f 'libs/acn/DMPAddressTest.cpp' || echo '$(srcdir)/'`libs/acn/DMPAddressTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_E131Tester-DMPAddressTest.Tpo libs/acn/$(DEPDIR)/libs_acn_E131Tester-DMPAddressTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/DMPAddressTest.cpp' object='libs/acn/libs_acn_E131Tester-DMPAddressTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_E131Tester-DMPAddressTest.o `test -f 'libs/acn/DMPAddressTest.cpp' || echo '$(srcdir)/'`libs/acn/DMPAddressTest.cpp libs/acn/libs_acn_E131Tester-DMPAddressTest.obj: libs/acn/DMPAddressTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_E131Tester-DMPAddressTest.obj -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_E131Tester-DMPAddressTest.Tpo -c -o libs/acn/libs_acn_E131Tester-DMPAddressTest.obj `if test -f 'libs/acn/DMPAddressTest.cpp'; then $(CYGPATH_W) 'libs/acn/DMPAddressTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/DMPAddressTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_E131Tester-DMPAddressTest.Tpo libs/acn/$(DEPDIR)/libs_acn_E131Tester-DMPAddressTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/DMPAddressTest.cpp' object='libs/acn/libs_acn_E131Tester-DMPAddressTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_E131Tester-DMPAddressTest.obj `if test -f 'libs/acn/DMPAddressTest.cpp'; then $(CYGPATH_W) 'libs/acn/DMPAddressTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/DMPAddressTest.cpp'; fi` libs/acn/libs_acn_E131Tester-DMPInflatorTest.o: libs/acn/DMPInflatorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_E131Tester-DMPInflatorTest.o -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_E131Tester-DMPInflatorTest.Tpo -c -o libs/acn/libs_acn_E131Tester-DMPInflatorTest.o `test -f 'libs/acn/DMPInflatorTest.cpp' || echo '$(srcdir)/'`libs/acn/DMPInflatorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_E131Tester-DMPInflatorTest.Tpo libs/acn/$(DEPDIR)/libs_acn_E131Tester-DMPInflatorTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/DMPInflatorTest.cpp' object='libs/acn/libs_acn_E131Tester-DMPInflatorTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_E131Tester-DMPInflatorTest.o `test -f 'libs/acn/DMPInflatorTest.cpp' || echo '$(srcdir)/'`libs/acn/DMPInflatorTest.cpp libs/acn/libs_acn_E131Tester-DMPInflatorTest.obj: libs/acn/DMPInflatorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_E131Tester-DMPInflatorTest.obj -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_E131Tester-DMPInflatorTest.Tpo -c -o libs/acn/libs_acn_E131Tester-DMPInflatorTest.obj `if test -f 'libs/acn/DMPInflatorTest.cpp'; then $(CYGPATH_W) 'libs/acn/DMPInflatorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/DMPInflatorTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_E131Tester-DMPInflatorTest.Tpo libs/acn/$(DEPDIR)/libs_acn_E131Tester-DMPInflatorTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/DMPInflatorTest.cpp' object='libs/acn/libs_acn_E131Tester-DMPInflatorTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_E131Tester-DMPInflatorTest.obj `if test -f 'libs/acn/DMPInflatorTest.cpp'; then $(CYGPATH_W) 'libs/acn/DMPInflatorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/DMPInflatorTest.cpp'; fi` libs/acn/libs_acn_E131Tester-DMPPDUTest.o: libs/acn/DMPPDUTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_E131Tester-DMPPDUTest.o -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_E131Tester-DMPPDUTest.Tpo -c -o libs/acn/libs_acn_E131Tester-DMPPDUTest.o `test -f 'libs/acn/DMPPDUTest.cpp' || echo '$(srcdir)/'`libs/acn/DMPPDUTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_E131Tester-DMPPDUTest.Tpo libs/acn/$(DEPDIR)/libs_acn_E131Tester-DMPPDUTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/DMPPDUTest.cpp' object='libs/acn/libs_acn_E131Tester-DMPPDUTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_E131Tester-DMPPDUTest.o `test -f 'libs/acn/DMPPDUTest.cpp' || echo '$(srcdir)/'`libs/acn/DMPPDUTest.cpp libs/acn/libs_acn_E131Tester-DMPPDUTest.obj: libs/acn/DMPPDUTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_E131Tester-DMPPDUTest.obj -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_E131Tester-DMPPDUTest.Tpo -c -o libs/acn/libs_acn_E131Tester-DMPPDUTest.obj `if test -f 'libs/acn/DMPPDUTest.cpp'; then $(CYGPATH_W) 'libs/acn/DMPPDUTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/DMPPDUTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_E131Tester-DMPPDUTest.Tpo libs/acn/$(DEPDIR)/libs_acn_E131Tester-DMPPDUTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/DMPPDUTest.cpp' object='libs/acn/libs_acn_E131Tester-DMPPDUTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_E131Tester-DMPPDUTest.obj `if test -f 'libs/acn/DMPPDUTest.cpp'; then $(CYGPATH_W) 'libs/acn/DMPPDUTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/DMPPDUTest.cpp'; fi` libs/acn/libs_acn_E131Tester-E131InflatorTest.o: libs/acn/E131InflatorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_E131Tester-E131InflatorTest.o -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_E131Tester-E131InflatorTest.Tpo -c -o libs/acn/libs_acn_E131Tester-E131InflatorTest.o `test -f 'libs/acn/E131InflatorTest.cpp' || echo '$(srcdir)/'`libs/acn/E131InflatorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_E131Tester-E131InflatorTest.Tpo libs/acn/$(DEPDIR)/libs_acn_E131Tester-E131InflatorTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/E131InflatorTest.cpp' object='libs/acn/libs_acn_E131Tester-E131InflatorTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_E131Tester-E131InflatorTest.o `test -f 'libs/acn/E131InflatorTest.cpp' || echo '$(srcdir)/'`libs/acn/E131InflatorTest.cpp libs/acn/libs_acn_E131Tester-E131InflatorTest.obj: libs/acn/E131InflatorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_E131Tester-E131InflatorTest.obj -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_E131Tester-E131InflatorTest.Tpo -c -o libs/acn/libs_acn_E131Tester-E131InflatorTest.obj `if test -f 'libs/acn/E131InflatorTest.cpp'; then $(CYGPATH_W) 'libs/acn/E131InflatorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/E131InflatorTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_E131Tester-E131InflatorTest.Tpo libs/acn/$(DEPDIR)/libs_acn_E131Tester-E131InflatorTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/E131InflatorTest.cpp' object='libs/acn/libs_acn_E131Tester-E131InflatorTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_E131Tester-E131InflatorTest.obj `if test -f 'libs/acn/E131InflatorTest.cpp'; then $(CYGPATH_W) 'libs/acn/E131InflatorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/E131InflatorTest.cpp'; fi` libs/acn/libs_acn_E131Tester-E131PDUTest.o: libs/acn/E131PDUTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_E131Tester-E131PDUTest.o -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_E131Tester-E131PDUTest.Tpo -c -o libs/acn/libs_acn_E131Tester-E131PDUTest.o `test -f 'libs/acn/E131PDUTest.cpp' || echo '$(srcdir)/'`libs/acn/E131PDUTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_E131Tester-E131PDUTest.Tpo libs/acn/$(DEPDIR)/libs_acn_E131Tester-E131PDUTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/E131PDUTest.cpp' object='libs/acn/libs_acn_E131Tester-E131PDUTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_E131Tester-E131PDUTest.o `test -f 'libs/acn/E131PDUTest.cpp' || echo '$(srcdir)/'`libs/acn/E131PDUTest.cpp libs/acn/libs_acn_E131Tester-E131PDUTest.obj: libs/acn/E131PDUTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_E131Tester-E131PDUTest.obj -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_E131Tester-E131PDUTest.Tpo -c -o libs/acn/libs_acn_E131Tester-E131PDUTest.obj `if test -f 'libs/acn/E131PDUTest.cpp'; then $(CYGPATH_W) 'libs/acn/E131PDUTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/E131PDUTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_E131Tester-E131PDUTest.Tpo libs/acn/$(DEPDIR)/libs_acn_E131Tester-E131PDUTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/E131PDUTest.cpp' object='libs/acn/libs_acn_E131Tester-E131PDUTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_E131Tester-E131PDUTest.obj `if test -f 'libs/acn/E131PDUTest.cpp'; then $(CYGPATH_W) 'libs/acn/E131PDUTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/E131PDUTest.cpp'; fi` libs/acn/libs_acn_E131Tester-HeaderSetTest.o: libs/acn/HeaderSetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_E131Tester-HeaderSetTest.o -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_E131Tester-HeaderSetTest.Tpo -c -o libs/acn/libs_acn_E131Tester-HeaderSetTest.o `test -f 'libs/acn/HeaderSetTest.cpp' || echo '$(srcdir)/'`libs/acn/HeaderSetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_E131Tester-HeaderSetTest.Tpo libs/acn/$(DEPDIR)/libs_acn_E131Tester-HeaderSetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/HeaderSetTest.cpp' object='libs/acn/libs_acn_E131Tester-HeaderSetTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_E131Tester-HeaderSetTest.o `test -f 'libs/acn/HeaderSetTest.cpp' || echo '$(srcdir)/'`libs/acn/HeaderSetTest.cpp libs/acn/libs_acn_E131Tester-HeaderSetTest.obj: libs/acn/HeaderSetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_E131Tester-HeaderSetTest.obj -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_E131Tester-HeaderSetTest.Tpo -c -o libs/acn/libs_acn_E131Tester-HeaderSetTest.obj `if test -f 'libs/acn/HeaderSetTest.cpp'; then $(CYGPATH_W) 'libs/acn/HeaderSetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/HeaderSetTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_E131Tester-HeaderSetTest.Tpo libs/acn/$(DEPDIR)/libs_acn_E131Tester-HeaderSetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/HeaderSetTest.cpp' object='libs/acn/libs_acn_E131Tester-HeaderSetTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_E131Tester-HeaderSetTest.obj `if test -f 'libs/acn/HeaderSetTest.cpp'; then $(CYGPATH_W) 'libs/acn/HeaderSetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/HeaderSetTest.cpp'; fi` libs/acn/libs_acn_E131Tester-PDUTest.o: libs/acn/PDUTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_E131Tester-PDUTest.o -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_E131Tester-PDUTest.Tpo -c -o libs/acn/libs_acn_E131Tester-PDUTest.o `test -f 'libs/acn/PDUTest.cpp' || echo '$(srcdir)/'`libs/acn/PDUTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_E131Tester-PDUTest.Tpo libs/acn/$(DEPDIR)/libs_acn_E131Tester-PDUTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/PDUTest.cpp' object='libs/acn/libs_acn_E131Tester-PDUTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_E131Tester-PDUTest.o `test -f 'libs/acn/PDUTest.cpp' || echo '$(srcdir)/'`libs/acn/PDUTest.cpp libs/acn/libs_acn_E131Tester-PDUTest.obj: libs/acn/PDUTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_E131Tester-PDUTest.obj -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_E131Tester-PDUTest.Tpo -c -o libs/acn/libs_acn_E131Tester-PDUTest.obj `if test -f 'libs/acn/PDUTest.cpp'; then $(CYGPATH_W) 'libs/acn/PDUTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/PDUTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_E131Tester-PDUTest.Tpo libs/acn/$(DEPDIR)/libs_acn_E131Tester-PDUTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/PDUTest.cpp' object='libs/acn/libs_acn_E131Tester-PDUTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_E131Tester-PDUTest.obj `if test -f 'libs/acn/PDUTest.cpp'; then $(CYGPATH_W) 'libs/acn/PDUTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/PDUTest.cpp'; fi` libs/acn/libs_acn_E131Tester-RootInflatorTest.o: libs/acn/RootInflatorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_E131Tester-RootInflatorTest.o -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_E131Tester-RootInflatorTest.Tpo -c -o libs/acn/libs_acn_E131Tester-RootInflatorTest.o `test -f 'libs/acn/RootInflatorTest.cpp' || echo '$(srcdir)/'`libs/acn/RootInflatorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_E131Tester-RootInflatorTest.Tpo libs/acn/$(DEPDIR)/libs_acn_E131Tester-RootInflatorTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/RootInflatorTest.cpp' object='libs/acn/libs_acn_E131Tester-RootInflatorTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_E131Tester-RootInflatorTest.o `test -f 'libs/acn/RootInflatorTest.cpp' || echo '$(srcdir)/'`libs/acn/RootInflatorTest.cpp libs/acn/libs_acn_E131Tester-RootInflatorTest.obj: libs/acn/RootInflatorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_E131Tester-RootInflatorTest.obj -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_E131Tester-RootInflatorTest.Tpo -c -o libs/acn/libs_acn_E131Tester-RootInflatorTest.obj `if test -f 'libs/acn/RootInflatorTest.cpp'; then $(CYGPATH_W) 'libs/acn/RootInflatorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/RootInflatorTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_E131Tester-RootInflatorTest.Tpo libs/acn/$(DEPDIR)/libs_acn_E131Tester-RootInflatorTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/RootInflatorTest.cpp' object='libs/acn/libs_acn_E131Tester-RootInflatorTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_E131Tester-RootInflatorTest.obj `if test -f 'libs/acn/RootInflatorTest.cpp'; then $(CYGPATH_W) 'libs/acn/RootInflatorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/RootInflatorTest.cpp'; fi` libs/acn/libs_acn_E131Tester-RootPDUTest.o: libs/acn/RootPDUTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_E131Tester-RootPDUTest.o -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_E131Tester-RootPDUTest.Tpo -c -o libs/acn/libs_acn_E131Tester-RootPDUTest.o `test -f 'libs/acn/RootPDUTest.cpp' || echo '$(srcdir)/'`libs/acn/RootPDUTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_E131Tester-RootPDUTest.Tpo libs/acn/$(DEPDIR)/libs_acn_E131Tester-RootPDUTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/RootPDUTest.cpp' object='libs/acn/libs_acn_E131Tester-RootPDUTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_E131Tester-RootPDUTest.o `test -f 'libs/acn/RootPDUTest.cpp' || echo '$(srcdir)/'`libs/acn/RootPDUTest.cpp libs/acn/libs_acn_E131Tester-RootPDUTest.obj: libs/acn/RootPDUTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_E131Tester-RootPDUTest.obj -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_E131Tester-RootPDUTest.Tpo -c -o libs/acn/libs_acn_E131Tester-RootPDUTest.obj `if test -f 'libs/acn/RootPDUTest.cpp'; then $(CYGPATH_W) 'libs/acn/RootPDUTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/RootPDUTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_E131Tester-RootPDUTest.Tpo libs/acn/$(DEPDIR)/libs_acn_E131Tester-RootPDUTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/RootPDUTest.cpp' object='libs/acn/libs_acn_E131Tester-RootPDUTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_E131Tester-RootPDUTest.obj `if test -f 'libs/acn/RootPDUTest.cpp'; then $(CYGPATH_W) 'libs/acn/RootPDUTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/RootPDUTest.cpp'; fi` libs/acn/libs_acn_E131Tester-RootSenderTest.o: libs/acn/RootSenderTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_E131Tester-RootSenderTest.o -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_E131Tester-RootSenderTest.Tpo -c -o libs/acn/libs_acn_E131Tester-RootSenderTest.o `test -f 'libs/acn/RootSenderTest.cpp' || echo '$(srcdir)/'`libs/acn/RootSenderTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_E131Tester-RootSenderTest.Tpo libs/acn/$(DEPDIR)/libs_acn_E131Tester-RootSenderTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/RootSenderTest.cpp' object='libs/acn/libs_acn_E131Tester-RootSenderTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_E131Tester-RootSenderTest.o `test -f 'libs/acn/RootSenderTest.cpp' || echo '$(srcdir)/'`libs/acn/RootSenderTest.cpp libs/acn/libs_acn_E131Tester-RootSenderTest.obj: libs/acn/RootSenderTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_E131Tester-RootSenderTest.obj -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_E131Tester-RootSenderTest.Tpo -c -o libs/acn/libs_acn_E131Tester-RootSenderTest.obj `if test -f 'libs/acn/RootSenderTest.cpp'; then $(CYGPATH_W) 'libs/acn/RootSenderTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/RootSenderTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_E131Tester-RootSenderTest.Tpo libs/acn/$(DEPDIR)/libs_acn_E131Tester-RootSenderTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/RootSenderTest.cpp' object='libs/acn/libs_acn_E131Tester-RootSenderTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E131Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_E131Tester-RootSenderTest.obj `if test -f 'libs/acn/RootSenderTest.cpp'; then $(CYGPATH_W) 'libs/acn/RootSenderTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/RootSenderTest.cpp'; fi` libs/acn/libs_acn_E133Tester-E133InflatorTest.o: libs/acn/E133InflatorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E133Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_E133Tester-E133InflatorTest.o -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_E133Tester-E133InflatorTest.Tpo -c -o libs/acn/libs_acn_E133Tester-E133InflatorTest.o `test -f 'libs/acn/E133InflatorTest.cpp' || echo '$(srcdir)/'`libs/acn/E133InflatorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_E133Tester-E133InflatorTest.Tpo libs/acn/$(DEPDIR)/libs_acn_E133Tester-E133InflatorTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/E133InflatorTest.cpp' object='libs/acn/libs_acn_E133Tester-E133InflatorTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E133Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_E133Tester-E133InflatorTest.o `test -f 'libs/acn/E133InflatorTest.cpp' || echo '$(srcdir)/'`libs/acn/E133InflatorTest.cpp libs/acn/libs_acn_E133Tester-E133InflatorTest.obj: libs/acn/E133InflatorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E133Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_E133Tester-E133InflatorTest.obj -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_E133Tester-E133InflatorTest.Tpo -c -o libs/acn/libs_acn_E133Tester-E133InflatorTest.obj `if test -f 'libs/acn/E133InflatorTest.cpp'; then $(CYGPATH_W) 'libs/acn/E133InflatorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/E133InflatorTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_E133Tester-E133InflatorTest.Tpo libs/acn/$(DEPDIR)/libs_acn_E133Tester-E133InflatorTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/E133InflatorTest.cpp' object='libs/acn/libs_acn_E133Tester-E133InflatorTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E133Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_E133Tester-E133InflatorTest.obj `if test -f 'libs/acn/E133InflatorTest.cpp'; then $(CYGPATH_W) 'libs/acn/E133InflatorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/E133InflatorTest.cpp'; fi` libs/acn/libs_acn_E133Tester-E133PDUTest.o: libs/acn/E133PDUTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E133Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_E133Tester-E133PDUTest.o -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_E133Tester-E133PDUTest.Tpo -c -o libs/acn/libs_acn_E133Tester-E133PDUTest.o `test -f 'libs/acn/E133PDUTest.cpp' || echo '$(srcdir)/'`libs/acn/E133PDUTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_E133Tester-E133PDUTest.Tpo libs/acn/$(DEPDIR)/libs_acn_E133Tester-E133PDUTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/E133PDUTest.cpp' object='libs/acn/libs_acn_E133Tester-E133PDUTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E133Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_E133Tester-E133PDUTest.o `test -f 'libs/acn/E133PDUTest.cpp' || echo '$(srcdir)/'`libs/acn/E133PDUTest.cpp libs/acn/libs_acn_E133Tester-E133PDUTest.obj: libs/acn/E133PDUTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E133Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_E133Tester-E133PDUTest.obj -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_E133Tester-E133PDUTest.Tpo -c -o libs/acn/libs_acn_E133Tester-E133PDUTest.obj `if test -f 'libs/acn/E133PDUTest.cpp'; then $(CYGPATH_W) 'libs/acn/E133PDUTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/E133PDUTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_E133Tester-E133PDUTest.Tpo libs/acn/$(DEPDIR)/libs_acn_E133Tester-E133PDUTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/E133PDUTest.cpp' object='libs/acn/libs_acn_E133Tester-E133PDUTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E133Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_E133Tester-E133PDUTest.obj `if test -f 'libs/acn/E133PDUTest.cpp'; then $(CYGPATH_W) 'libs/acn/E133PDUTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/E133PDUTest.cpp'; fi` libs/acn/libs_acn_E133Tester-RDMPDUTest.o: libs/acn/RDMPDUTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E133Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_E133Tester-RDMPDUTest.o -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_E133Tester-RDMPDUTest.Tpo -c -o libs/acn/libs_acn_E133Tester-RDMPDUTest.o `test -f 'libs/acn/RDMPDUTest.cpp' || echo '$(srcdir)/'`libs/acn/RDMPDUTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_E133Tester-RDMPDUTest.Tpo libs/acn/$(DEPDIR)/libs_acn_E133Tester-RDMPDUTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/RDMPDUTest.cpp' object='libs/acn/libs_acn_E133Tester-RDMPDUTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E133Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_E133Tester-RDMPDUTest.o `test -f 'libs/acn/RDMPDUTest.cpp' || echo '$(srcdir)/'`libs/acn/RDMPDUTest.cpp libs/acn/libs_acn_E133Tester-RDMPDUTest.obj: libs/acn/RDMPDUTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E133Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_E133Tester-RDMPDUTest.obj -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_E133Tester-RDMPDUTest.Tpo -c -o libs/acn/libs_acn_E133Tester-RDMPDUTest.obj `if test -f 'libs/acn/RDMPDUTest.cpp'; then $(CYGPATH_W) 'libs/acn/RDMPDUTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/RDMPDUTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_E133Tester-RDMPDUTest.Tpo libs/acn/$(DEPDIR)/libs_acn_E133Tester-RDMPDUTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/RDMPDUTest.cpp' object='libs/acn/libs_acn_E133Tester-RDMPDUTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_E133Tester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_E133Tester-RDMPDUTest.obj `if test -f 'libs/acn/RDMPDUTest.cpp'; then $(CYGPATH_W) 'libs/acn/RDMPDUTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/RDMPDUTest.cpp'; fi` libs/acn/libs_acn_TransportTester-TCPTransportTest.o: libs/acn/TCPTransportTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_TransportTester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_TransportTester-TCPTransportTest.o -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_TransportTester-TCPTransportTest.Tpo -c -o libs/acn/libs_acn_TransportTester-TCPTransportTest.o `test -f 'libs/acn/TCPTransportTest.cpp' || echo '$(srcdir)/'`libs/acn/TCPTransportTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_TransportTester-TCPTransportTest.Tpo libs/acn/$(DEPDIR)/libs_acn_TransportTester-TCPTransportTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/TCPTransportTest.cpp' object='libs/acn/libs_acn_TransportTester-TCPTransportTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_TransportTester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_TransportTester-TCPTransportTest.o `test -f 'libs/acn/TCPTransportTest.cpp' || echo '$(srcdir)/'`libs/acn/TCPTransportTest.cpp libs/acn/libs_acn_TransportTester-TCPTransportTest.obj: libs/acn/TCPTransportTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_TransportTester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_TransportTester-TCPTransportTest.obj -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_TransportTester-TCPTransportTest.Tpo -c -o libs/acn/libs_acn_TransportTester-TCPTransportTest.obj `if test -f 'libs/acn/TCPTransportTest.cpp'; then $(CYGPATH_W) 'libs/acn/TCPTransportTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/TCPTransportTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_TransportTester-TCPTransportTest.Tpo libs/acn/$(DEPDIR)/libs_acn_TransportTester-TCPTransportTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/TCPTransportTest.cpp' object='libs/acn/libs_acn_TransportTester-TCPTransportTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_TransportTester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_TransportTester-TCPTransportTest.obj `if test -f 'libs/acn/TCPTransportTest.cpp'; then $(CYGPATH_W) 'libs/acn/TCPTransportTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/TCPTransportTest.cpp'; fi` libs/acn/libs_acn_TransportTester-UDPTransportTest.o: libs/acn/UDPTransportTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_TransportTester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_TransportTester-UDPTransportTest.o -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_TransportTester-UDPTransportTest.Tpo -c -o libs/acn/libs_acn_TransportTester-UDPTransportTest.o `test -f 'libs/acn/UDPTransportTest.cpp' || echo '$(srcdir)/'`libs/acn/UDPTransportTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_TransportTester-UDPTransportTest.Tpo libs/acn/$(DEPDIR)/libs_acn_TransportTester-UDPTransportTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/UDPTransportTest.cpp' object='libs/acn/libs_acn_TransportTester-UDPTransportTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_TransportTester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_TransportTester-UDPTransportTest.o `test -f 'libs/acn/UDPTransportTest.cpp' || echo '$(srcdir)/'`libs/acn/UDPTransportTest.cpp libs/acn/libs_acn_TransportTester-UDPTransportTest.obj: libs/acn/UDPTransportTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_TransportTester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libs/acn/libs_acn_TransportTester-UDPTransportTest.obj -MD -MP -MF libs/acn/$(DEPDIR)/libs_acn_TransportTester-UDPTransportTest.Tpo -c -o libs/acn/libs_acn_TransportTester-UDPTransportTest.obj `if test -f 'libs/acn/UDPTransportTest.cpp'; then $(CYGPATH_W) 'libs/acn/UDPTransportTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/UDPTransportTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/acn/$(DEPDIR)/libs_acn_TransportTester-UDPTransportTest.Tpo libs/acn/$(DEPDIR)/libs_acn_TransportTester-UDPTransportTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/acn/UDPTransportTest.cpp' object='libs/acn/libs_acn_TransportTester-UDPTransportTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs_acn_TransportTester_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libs/acn/libs_acn_TransportTester-UDPTransportTest.obj `if test -f 'libs/acn/UDPTransportTest.cpp'; then $(CYGPATH_W) 'libs/acn/UDPTransportTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/acn/UDPTransportTest.cpp'; fi` libs/usb/libs_usb_LibUsbThreadTester-LibUsbThreadTest.o: libs/usb/LibUsbThreadTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_usb_LibUsbThreadTester_CXXFLAGS) $(CXXFLAGS) -MT libs/usb/libs_usb_LibUsbThreadTester-LibUsbThreadTest.o -MD -MP -MF libs/usb/$(DEPDIR)/libs_usb_LibUsbThreadTester-LibUsbThreadTest.Tpo -c -o libs/usb/libs_usb_LibUsbThreadTester-LibUsbThreadTest.o `test -f 'libs/usb/LibUsbThreadTest.cpp' || echo '$(srcdir)/'`libs/usb/LibUsbThreadTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/usb/$(DEPDIR)/libs_usb_LibUsbThreadTester-LibUsbThreadTest.Tpo libs/usb/$(DEPDIR)/libs_usb_LibUsbThreadTester-LibUsbThreadTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/usb/LibUsbThreadTest.cpp' object='libs/usb/libs_usb_LibUsbThreadTester-LibUsbThreadTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_usb_LibUsbThreadTester_CXXFLAGS) $(CXXFLAGS) -c -o libs/usb/libs_usb_LibUsbThreadTester-LibUsbThreadTest.o `test -f 'libs/usb/LibUsbThreadTest.cpp' || echo '$(srcdir)/'`libs/usb/LibUsbThreadTest.cpp libs/usb/libs_usb_LibUsbThreadTester-LibUsbThreadTest.obj: libs/usb/LibUsbThreadTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_usb_LibUsbThreadTester_CXXFLAGS) $(CXXFLAGS) -MT libs/usb/libs_usb_LibUsbThreadTester-LibUsbThreadTest.obj -MD -MP -MF libs/usb/$(DEPDIR)/libs_usb_LibUsbThreadTester-LibUsbThreadTest.Tpo -c -o libs/usb/libs_usb_LibUsbThreadTester-LibUsbThreadTest.obj `if test -f 'libs/usb/LibUsbThreadTest.cpp'; then $(CYGPATH_W) 'libs/usb/LibUsbThreadTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/usb/LibUsbThreadTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) libs/usb/$(DEPDIR)/libs_usb_LibUsbThreadTester-LibUsbThreadTest.Tpo libs/usb/$(DEPDIR)/libs_usb_LibUsbThreadTester-LibUsbThreadTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='libs/usb/LibUsbThreadTest.cpp' object='libs/usb/libs_usb_LibUsbThreadTester-LibUsbThreadTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libs_usb_LibUsbThreadTester_CXXFLAGS) $(CXXFLAGS) -c -o libs/usb/libs_usb_LibUsbThreadTester-LibUsbThreadTest.obj `if test -f 'libs/usb/LibUsbThreadTest.cpp'; then $(CYGPATH_W) 'libs/usb/LibUsbThreadTest.cpp'; else $(CYGPATH_W) '$(srcdir)/libs/usb/LibUsbThreadTest.cpp'; fi` ola/ola_OlaClientTester-OlaClientWrapperTest.o: ola/OlaClientWrapperTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ola_OlaClientTester_CXXFLAGS) $(CXXFLAGS) -MT ola/ola_OlaClientTester-OlaClientWrapperTest.o -MD -MP -MF ola/$(DEPDIR)/ola_OlaClientTester-OlaClientWrapperTest.Tpo -c -o ola/ola_OlaClientTester-OlaClientWrapperTest.o `test -f 'ola/OlaClientWrapperTest.cpp' || echo '$(srcdir)/'`ola/OlaClientWrapperTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ola/$(DEPDIR)/ola_OlaClientTester-OlaClientWrapperTest.Tpo ola/$(DEPDIR)/ola_OlaClientTester-OlaClientWrapperTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ola/OlaClientWrapperTest.cpp' object='ola/ola_OlaClientTester-OlaClientWrapperTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ola_OlaClientTester_CXXFLAGS) $(CXXFLAGS) -c -o ola/ola_OlaClientTester-OlaClientWrapperTest.o `test -f 'ola/OlaClientWrapperTest.cpp' || echo '$(srcdir)/'`ola/OlaClientWrapperTest.cpp ola/ola_OlaClientTester-OlaClientWrapperTest.obj: ola/OlaClientWrapperTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ola_OlaClientTester_CXXFLAGS) $(CXXFLAGS) -MT ola/ola_OlaClientTester-OlaClientWrapperTest.obj -MD -MP -MF ola/$(DEPDIR)/ola_OlaClientTester-OlaClientWrapperTest.Tpo -c -o ola/ola_OlaClientTester-OlaClientWrapperTest.obj `if test -f 'ola/OlaClientWrapperTest.cpp'; then $(CYGPATH_W) 'ola/OlaClientWrapperTest.cpp'; else $(CYGPATH_W) '$(srcdir)/ola/OlaClientWrapperTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ola/$(DEPDIR)/ola_OlaClientTester-OlaClientWrapperTest.Tpo ola/$(DEPDIR)/ola_OlaClientTester-OlaClientWrapperTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ola/OlaClientWrapperTest.cpp' object='ola/ola_OlaClientTester-OlaClientWrapperTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ola_OlaClientTester_CXXFLAGS) $(CXXFLAGS) -c -o ola/ola_OlaClientTester-OlaClientWrapperTest.obj `if test -f 'ola/OlaClientWrapperTest.cpp'; then $(CYGPATH_W) 'ola/OlaClientWrapperTest.cpp'; else $(CYGPATH_W) '$(srcdir)/ola/OlaClientWrapperTest.cpp'; fi` ola/ola_OlaClientTester-StreamingClientTest.o: ola/StreamingClientTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ola_OlaClientTester_CXXFLAGS) $(CXXFLAGS) -MT ola/ola_OlaClientTester-StreamingClientTest.o -MD -MP -MF ola/$(DEPDIR)/ola_OlaClientTester-StreamingClientTest.Tpo -c -o ola/ola_OlaClientTester-StreamingClientTest.o `test -f 'ola/StreamingClientTest.cpp' || echo '$(srcdir)/'`ola/StreamingClientTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ola/$(DEPDIR)/ola_OlaClientTester-StreamingClientTest.Tpo ola/$(DEPDIR)/ola_OlaClientTester-StreamingClientTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ola/StreamingClientTest.cpp' object='ola/ola_OlaClientTester-StreamingClientTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ola_OlaClientTester_CXXFLAGS) $(CXXFLAGS) -c -o ola/ola_OlaClientTester-StreamingClientTest.o `test -f 'ola/StreamingClientTest.cpp' || echo '$(srcdir)/'`ola/StreamingClientTest.cpp ola/ola_OlaClientTester-StreamingClientTest.obj: ola/StreamingClientTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ola_OlaClientTester_CXXFLAGS) $(CXXFLAGS) -MT ola/ola_OlaClientTester-StreamingClientTest.obj -MD -MP -MF ola/$(DEPDIR)/ola_OlaClientTester-StreamingClientTest.Tpo -c -o ola/ola_OlaClientTester-StreamingClientTest.obj `if test -f 'ola/StreamingClientTest.cpp'; then $(CYGPATH_W) 'ola/StreamingClientTest.cpp'; else $(CYGPATH_W) '$(srcdir)/ola/StreamingClientTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ola/$(DEPDIR)/ola_OlaClientTester-StreamingClientTest.Tpo ola/$(DEPDIR)/ola_OlaClientTester-StreamingClientTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ola/StreamingClientTest.cpp' object='ola/ola_OlaClientTester-StreamingClientTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ola_OlaClientTester_CXXFLAGS) $(CXXFLAGS) -c -o ola/ola_OlaClientTester-StreamingClientTest.obj `if test -f 'ola/StreamingClientTest.cpp'; then $(CYGPATH_W) 'ola/StreamingClientTest.cpp'; else $(CYGPATH_W) '$(srcdir)/ola/StreamingClientTest.cpp'; fi` olad/olad_OlaTester-PluginManagerTest.o: olad/PluginManagerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_OlaTester_CXXFLAGS) $(CXXFLAGS) -MT olad/olad_OlaTester-PluginManagerTest.o -MD -MP -MF olad/$(DEPDIR)/olad_OlaTester-PluginManagerTest.Tpo -c -o olad/olad_OlaTester-PluginManagerTest.o `test -f 'olad/PluginManagerTest.cpp' || echo '$(srcdir)/'`olad/PluginManagerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/$(DEPDIR)/olad_OlaTester-PluginManagerTest.Tpo olad/$(DEPDIR)/olad_OlaTester-PluginManagerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/PluginManagerTest.cpp' object='olad/olad_OlaTester-PluginManagerTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_OlaTester_CXXFLAGS) $(CXXFLAGS) -c -o olad/olad_OlaTester-PluginManagerTest.o `test -f 'olad/PluginManagerTest.cpp' || echo '$(srcdir)/'`olad/PluginManagerTest.cpp olad/olad_OlaTester-PluginManagerTest.obj: olad/PluginManagerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_OlaTester_CXXFLAGS) $(CXXFLAGS) -MT olad/olad_OlaTester-PluginManagerTest.obj -MD -MP -MF olad/$(DEPDIR)/olad_OlaTester-PluginManagerTest.Tpo -c -o olad/olad_OlaTester-PluginManagerTest.obj `if test -f 'olad/PluginManagerTest.cpp'; then $(CYGPATH_W) 'olad/PluginManagerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/olad/PluginManagerTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/$(DEPDIR)/olad_OlaTester-PluginManagerTest.Tpo olad/$(DEPDIR)/olad_OlaTester-PluginManagerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/PluginManagerTest.cpp' object='olad/olad_OlaTester-PluginManagerTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_OlaTester_CXXFLAGS) $(CXXFLAGS) -c -o olad/olad_OlaTester-PluginManagerTest.obj `if test -f 'olad/PluginManagerTest.cpp'; then $(CYGPATH_W) 'olad/PluginManagerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/olad/PluginManagerTest.cpp'; fi` olad/olad_OlaTester-OlaServerServiceImplTest.o: olad/OlaServerServiceImplTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_OlaTester_CXXFLAGS) $(CXXFLAGS) -MT olad/olad_OlaTester-OlaServerServiceImplTest.o -MD -MP -MF olad/$(DEPDIR)/olad_OlaTester-OlaServerServiceImplTest.Tpo -c -o olad/olad_OlaTester-OlaServerServiceImplTest.o `test -f 'olad/OlaServerServiceImplTest.cpp' || echo '$(srcdir)/'`olad/OlaServerServiceImplTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/$(DEPDIR)/olad_OlaTester-OlaServerServiceImplTest.Tpo olad/$(DEPDIR)/olad_OlaTester-OlaServerServiceImplTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/OlaServerServiceImplTest.cpp' object='olad/olad_OlaTester-OlaServerServiceImplTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_OlaTester_CXXFLAGS) $(CXXFLAGS) -c -o olad/olad_OlaTester-OlaServerServiceImplTest.o `test -f 'olad/OlaServerServiceImplTest.cpp' || echo '$(srcdir)/'`olad/OlaServerServiceImplTest.cpp olad/olad_OlaTester-OlaServerServiceImplTest.obj: olad/OlaServerServiceImplTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_OlaTester_CXXFLAGS) $(CXXFLAGS) -MT olad/olad_OlaTester-OlaServerServiceImplTest.obj -MD -MP -MF olad/$(DEPDIR)/olad_OlaTester-OlaServerServiceImplTest.Tpo -c -o olad/olad_OlaTester-OlaServerServiceImplTest.obj `if test -f 'olad/OlaServerServiceImplTest.cpp'; then $(CYGPATH_W) 'olad/OlaServerServiceImplTest.cpp'; else $(CYGPATH_W) '$(srcdir)/olad/OlaServerServiceImplTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/$(DEPDIR)/olad_OlaTester-OlaServerServiceImplTest.Tpo olad/$(DEPDIR)/olad_OlaTester-OlaServerServiceImplTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/OlaServerServiceImplTest.cpp' object='olad/olad_OlaTester-OlaServerServiceImplTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_OlaTester_CXXFLAGS) $(CXXFLAGS) -c -o olad/olad_OlaTester-OlaServerServiceImplTest.obj `if test -f 'olad/OlaServerServiceImplTest.cpp'; then $(CYGPATH_W) 'olad/OlaServerServiceImplTest.cpp'; else $(CYGPATH_W) '$(srcdir)/olad/OlaServerServiceImplTest.cpp'; fi` olad/plugin_api/olad_plugin_api_ClientTester-ClientTest.o: olad/plugin_api/ClientTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_ClientTester_CXXFLAGS) $(CXXFLAGS) -MT olad/plugin_api/olad_plugin_api_ClientTester-ClientTest.o -MD -MP -MF olad/plugin_api/$(DEPDIR)/olad_plugin_api_ClientTester-ClientTest.Tpo -c -o olad/plugin_api/olad_plugin_api_ClientTester-ClientTest.o `test -f 'olad/plugin_api/ClientTest.cpp' || echo '$(srcdir)/'`olad/plugin_api/ClientTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/plugin_api/$(DEPDIR)/olad_plugin_api_ClientTester-ClientTest.Tpo olad/plugin_api/$(DEPDIR)/olad_plugin_api_ClientTester-ClientTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/plugin_api/ClientTest.cpp' object='olad/plugin_api/olad_plugin_api_ClientTester-ClientTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_ClientTester_CXXFLAGS) $(CXXFLAGS) -c -o olad/plugin_api/olad_plugin_api_ClientTester-ClientTest.o `test -f 'olad/plugin_api/ClientTest.cpp' || echo '$(srcdir)/'`olad/plugin_api/ClientTest.cpp olad/plugin_api/olad_plugin_api_ClientTester-ClientTest.obj: olad/plugin_api/ClientTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_ClientTester_CXXFLAGS) $(CXXFLAGS) -MT olad/plugin_api/olad_plugin_api_ClientTester-ClientTest.obj -MD -MP -MF olad/plugin_api/$(DEPDIR)/olad_plugin_api_ClientTester-ClientTest.Tpo -c -o olad/plugin_api/olad_plugin_api_ClientTester-ClientTest.obj `if test -f 'olad/plugin_api/ClientTest.cpp'; then $(CYGPATH_W) 'olad/plugin_api/ClientTest.cpp'; else $(CYGPATH_W) '$(srcdir)/olad/plugin_api/ClientTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/plugin_api/$(DEPDIR)/olad_plugin_api_ClientTester-ClientTest.Tpo olad/plugin_api/$(DEPDIR)/olad_plugin_api_ClientTester-ClientTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/plugin_api/ClientTest.cpp' object='olad/plugin_api/olad_plugin_api_ClientTester-ClientTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_ClientTester_CXXFLAGS) $(CXXFLAGS) -c -o olad/plugin_api/olad_plugin_api_ClientTester-ClientTest.obj `if test -f 'olad/plugin_api/ClientTest.cpp'; then $(CYGPATH_W) 'olad/plugin_api/ClientTest.cpp'; else $(CYGPATH_W) '$(srcdir)/olad/plugin_api/ClientTest.cpp'; fi` olad/plugin_api/olad_plugin_api_DeviceTester-DeviceManagerTest.o: olad/plugin_api/DeviceManagerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_DeviceTester_CXXFLAGS) $(CXXFLAGS) -MT olad/plugin_api/olad_plugin_api_DeviceTester-DeviceManagerTest.o -MD -MP -MF olad/plugin_api/$(DEPDIR)/olad_plugin_api_DeviceTester-DeviceManagerTest.Tpo -c -o olad/plugin_api/olad_plugin_api_DeviceTester-DeviceManagerTest.o `test -f 'olad/plugin_api/DeviceManagerTest.cpp' || echo '$(srcdir)/'`olad/plugin_api/DeviceManagerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/plugin_api/$(DEPDIR)/olad_plugin_api_DeviceTester-DeviceManagerTest.Tpo olad/plugin_api/$(DEPDIR)/olad_plugin_api_DeviceTester-DeviceManagerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/plugin_api/DeviceManagerTest.cpp' object='olad/plugin_api/olad_plugin_api_DeviceTester-DeviceManagerTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_DeviceTester_CXXFLAGS) $(CXXFLAGS) -c -o olad/plugin_api/olad_plugin_api_DeviceTester-DeviceManagerTest.o `test -f 'olad/plugin_api/DeviceManagerTest.cpp' || echo '$(srcdir)/'`olad/plugin_api/DeviceManagerTest.cpp olad/plugin_api/olad_plugin_api_DeviceTester-DeviceManagerTest.obj: olad/plugin_api/DeviceManagerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_DeviceTester_CXXFLAGS) $(CXXFLAGS) -MT olad/plugin_api/olad_plugin_api_DeviceTester-DeviceManagerTest.obj -MD -MP -MF olad/plugin_api/$(DEPDIR)/olad_plugin_api_DeviceTester-DeviceManagerTest.Tpo -c -o olad/plugin_api/olad_plugin_api_DeviceTester-DeviceManagerTest.obj `if test -f 'olad/plugin_api/DeviceManagerTest.cpp'; then $(CYGPATH_W) 'olad/plugin_api/DeviceManagerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/olad/plugin_api/DeviceManagerTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/plugin_api/$(DEPDIR)/olad_plugin_api_DeviceTester-DeviceManagerTest.Tpo olad/plugin_api/$(DEPDIR)/olad_plugin_api_DeviceTester-DeviceManagerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/plugin_api/DeviceManagerTest.cpp' object='olad/plugin_api/olad_plugin_api_DeviceTester-DeviceManagerTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_DeviceTester_CXXFLAGS) $(CXXFLAGS) -c -o olad/plugin_api/olad_plugin_api_DeviceTester-DeviceManagerTest.obj `if test -f 'olad/plugin_api/DeviceManagerTest.cpp'; then $(CYGPATH_W) 'olad/plugin_api/DeviceManagerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/olad/plugin_api/DeviceManagerTest.cpp'; fi` olad/plugin_api/olad_plugin_api_DeviceTester-DeviceTest.o: olad/plugin_api/DeviceTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_DeviceTester_CXXFLAGS) $(CXXFLAGS) -MT olad/plugin_api/olad_plugin_api_DeviceTester-DeviceTest.o -MD -MP -MF olad/plugin_api/$(DEPDIR)/olad_plugin_api_DeviceTester-DeviceTest.Tpo -c -o olad/plugin_api/olad_plugin_api_DeviceTester-DeviceTest.o `test -f 'olad/plugin_api/DeviceTest.cpp' || echo '$(srcdir)/'`olad/plugin_api/DeviceTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/plugin_api/$(DEPDIR)/olad_plugin_api_DeviceTester-DeviceTest.Tpo olad/plugin_api/$(DEPDIR)/olad_plugin_api_DeviceTester-DeviceTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/plugin_api/DeviceTest.cpp' object='olad/plugin_api/olad_plugin_api_DeviceTester-DeviceTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_DeviceTester_CXXFLAGS) $(CXXFLAGS) -c -o olad/plugin_api/olad_plugin_api_DeviceTester-DeviceTest.o `test -f 'olad/plugin_api/DeviceTest.cpp' || echo '$(srcdir)/'`olad/plugin_api/DeviceTest.cpp olad/plugin_api/olad_plugin_api_DeviceTester-DeviceTest.obj: olad/plugin_api/DeviceTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_DeviceTester_CXXFLAGS) $(CXXFLAGS) -MT olad/plugin_api/olad_plugin_api_DeviceTester-DeviceTest.obj -MD -MP -MF olad/plugin_api/$(DEPDIR)/olad_plugin_api_DeviceTester-DeviceTest.Tpo -c -o olad/plugin_api/olad_plugin_api_DeviceTester-DeviceTest.obj `if test -f 'olad/plugin_api/DeviceTest.cpp'; then $(CYGPATH_W) 'olad/plugin_api/DeviceTest.cpp'; else $(CYGPATH_W) '$(srcdir)/olad/plugin_api/DeviceTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/plugin_api/$(DEPDIR)/olad_plugin_api_DeviceTester-DeviceTest.Tpo olad/plugin_api/$(DEPDIR)/olad_plugin_api_DeviceTester-DeviceTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/plugin_api/DeviceTest.cpp' object='olad/plugin_api/olad_plugin_api_DeviceTester-DeviceTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_DeviceTester_CXXFLAGS) $(CXXFLAGS) -c -o olad/plugin_api/olad_plugin_api_DeviceTester-DeviceTest.obj `if test -f 'olad/plugin_api/DeviceTest.cpp'; then $(CYGPATH_W) 'olad/plugin_api/DeviceTest.cpp'; else $(CYGPATH_W) '$(srcdir)/olad/plugin_api/DeviceTest.cpp'; fi` olad/plugin_api/olad_plugin_api_DmxSourceTester-DmxSourceTest.o: olad/plugin_api/DmxSourceTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_DmxSourceTester_CXXFLAGS) $(CXXFLAGS) -MT olad/plugin_api/olad_plugin_api_DmxSourceTester-DmxSourceTest.o -MD -MP -MF olad/plugin_api/$(DEPDIR)/olad_plugin_api_DmxSourceTester-DmxSourceTest.Tpo -c -o olad/plugin_api/olad_plugin_api_DmxSourceTester-DmxSourceTest.o `test -f 'olad/plugin_api/DmxSourceTest.cpp' || echo '$(srcdir)/'`olad/plugin_api/DmxSourceTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/plugin_api/$(DEPDIR)/olad_plugin_api_DmxSourceTester-DmxSourceTest.Tpo olad/plugin_api/$(DEPDIR)/olad_plugin_api_DmxSourceTester-DmxSourceTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/plugin_api/DmxSourceTest.cpp' object='olad/plugin_api/olad_plugin_api_DmxSourceTester-DmxSourceTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_DmxSourceTester_CXXFLAGS) $(CXXFLAGS) -c -o olad/plugin_api/olad_plugin_api_DmxSourceTester-DmxSourceTest.o `test -f 'olad/plugin_api/DmxSourceTest.cpp' || echo '$(srcdir)/'`olad/plugin_api/DmxSourceTest.cpp olad/plugin_api/olad_plugin_api_DmxSourceTester-DmxSourceTest.obj: olad/plugin_api/DmxSourceTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_DmxSourceTester_CXXFLAGS) $(CXXFLAGS) -MT olad/plugin_api/olad_plugin_api_DmxSourceTester-DmxSourceTest.obj -MD -MP -MF olad/plugin_api/$(DEPDIR)/olad_plugin_api_DmxSourceTester-DmxSourceTest.Tpo -c -o olad/plugin_api/olad_plugin_api_DmxSourceTester-DmxSourceTest.obj `if test -f 'olad/plugin_api/DmxSourceTest.cpp'; then $(CYGPATH_W) 'olad/plugin_api/DmxSourceTest.cpp'; else $(CYGPATH_W) '$(srcdir)/olad/plugin_api/DmxSourceTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/plugin_api/$(DEPDIR)/olad_plugin_api_DmxSourceTester-DmxSourceTest.Tpo olad/plugin_api/$(DEPDIR)/olad_plugin_api_DmxSourceTester-DmxSourceTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/plugin_api/DmxSourceTest.cpp' object='olad/plugin_api/olad_plugin_api_DmxSourceTester-DmxSourceTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_DmxSourceTester_CXXFLAGS) $(CXXFLAGS) -c -o olad/plugin_api/olad_plugin_api_DmxSourceTester-DmxSourceTest.obj `if test -f 'olad/plugin_api/DmxSourceTest.cpp'; then $(CYGPATH_W) 'olad/plugin_api/DmxSourceTest.cpp'; else $(CYGPATH_W) '$(srcdir)/olad/plugin_api/DmxSourceTest.cpp'; fi` olad/plugin_api/olad_plugin_api_PortTester-PortTest.o: olad/plugin_api/PortTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_PortTester_CXXFLAGS) $(CXXFLAGS) -MT olad/plugin_api/olad_plugin_api_PortTester-PortTest.o -MD -MP -MF olad/plugin_api/$(DEPDIR)/olad_plugin_api_PortTester-PortTest.Tpo -c -o olad/plugin_api/olad_plugin_api_PortTester-PortTest.o `test -f 'olad/plugin_api/PortTest.cpp' || echo '$(srcdir)/'`olad/plugin_api/PortTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/plugin_api/$(DEPDIR)/olad_plugin_api_PortTester-PortTest.Tpo olad/plugin_api/$(DEPDIR)/olad_plugin_api_PortTester-PortTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/plugin_api/PortTest.cpp' object='olad/plugin_api/olad_plugin_api_PortTester-PortTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_PortTester_CXXFLAGS) $(CXXFLAGS) -c -o olad/plugin_api/olad_plugin_api_PortTester-PortTest.o `test -f 'olad/plugin_api/PortTest.cpp' || echo '$(srcdir)/'`olad/plugin_api/PortTest.cpp olad/plugin_api/olad_plugin_api_PortTester-PortTest.obj: olad/plugin_api/PortTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_PortTester_CXXFLAGS) $(CXXFLAGS) -MT olad/plugin_api/olad_plugin_api_PortTester-PortTest.obj -MD -MP -MF olad/plugin_api/$(DEPDIR)/olad_plugin_api_PortTester-PortTest.Tpo -c -o olad/plugin_api/olad_plugin_api_PortTester-PortTest.obj `if test -f 'olad/plugin_api/PortTest.cpp'; then $(CYGPATH_W) 'olad/plugin_api/PortTest.cpp'; else $(CYGPATH_W) '$(srcdir)/olad/plugin_api/PortTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/plugin_api/$(DEPDIR)/olad_plugin_api_PortTester-PortTest.Tpo olad/plugin_api/$(DEPDIR)/olad_plugin_api_PortTester-PortTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/plugin_api/PortTest.cpp' object='olad/plugin_api/olad_plugin_api_PortTester-PortTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_PortTester_CXXFLAGS) $(CXXFLAGS) -c -o olad/plugin_api/olad_plugin_api_PortTester-PortTest.obj `if test -f 'olad/plugin_api/PortTest.cpp'; then $(CYGPATH_W) 'olad/plugin_api/PortTest.cpp'; else $(CYGPATH_W) '$(srcdir)/olad/plugin_api/PortTest.cpp'; fi` olad/plugin_api/olad_plugin_api_PortTester-PortManagerTest.o: olad/plugin_api/PortManagerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_PortTester_CXXFLAGS) $(CXXFLAGS) -MT olad/plugin_api/olad_plugin_api_PortTester-PortManagerTest.o -MD -MP -MF olad/plugin_api/$(DEPDIR)/olad_plugin_api_PortTester-PortManagerTest.Tpo -c -o olad/plugin_api/olad_plugin_api_PortTester-PortManagerTest.o `test -f 'olad/plugin_api/PortManagerTest.cpp' || echo '$(srcdir)/'`olad/plugin_api/PortManagerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/plugin_api/$(DEPDIR)/olad_plugin_api_PortTester-PortManagerTest.Tpo olad/plugin_api/$(DEPDIR)/olad_plugin_api_PortTester-PortManagerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/plugin_api/PortManagerTest.cpp' object='olad/plugin_api/olad_plugin_api_PortTester-PortManagerTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_PortTester_CXXFLAGS) $(CXXFLAGS) -c -o olad/plugin_api/olad_plugin_api_PortTester-PortManagerTest.o `test -f 'olad/plugin_api/PortManagerTest.cpp' || echo '$(srcdir)/'`olad/plugin_api/PortManagerTest.cpp olad/plugin_api/olad_plugin_api_PortTester-PortManagerTest.obj: olad/plugin_api/PortManagerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_PortTester_CXXFLAGS) $(CXXFLAGS) -MT olad/plugin_api/olad_plugin_api_PortTester-PortManagerTest.obj -MD -MP -MF olad/plugin_api/$(DEPDIR)/olad_plugin_api_PortTester-PortManagerTest.Tpo -c -o olad/plugin_api/olad_plugin_api_PortTester-PortManagerTest.obj `if test -f 'olad/plugin_api/PortManagerTest.cpp'; then $(CYGPATH_W) 'olad/plugin_api/PortManagerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/olad/plugin_api/PortManagerTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/plugin_api/$(DEPDIR)/olad_plugin_api_PortTester-PortManagerTest.Tpo olad/plugin_api/$(DEPDIR)/olad_plugin_api_PortTester-PortManagerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/plugin_api/PortManagerTest.cpp' object='olad/plugin_api/olad_plugin_api_PortTester-PortManagerTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_PortTester_CXXFLAGS) $(CXXFLAGS) -c -o olad/plugin_api/olad_plugin_api_PortTester-PortManagerTest.obj `if test -f 'olad/plugin_api/PortManagerTest.cpp'; then $(CYGPATH_W) 'olad/plugin_api/PortManagerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/olad/plugin_api/PortManagerTest.cpp'; fi` olad/plugin_api/olad_plugin_api_PreferencesTester-PreferencesTest.o: olad/plugin_api/PreferencesTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_PreferencesTester_CXXFLAGS) $(CXXFLAGS) -MT olad/plugin_api/olad_plugin_api_PreferencesTester-PreferencesTest.o -MD -MP -MF olad/plugin_api/$(DEPDIR)/olad_plugin_api_PreferencesTester-PreferencesTest.Tpo -c -o olad/plugin_api/olad_plugin_api_PreferencesTester-PreferencesTest.o `test -f 'olad/plugin_api/PreferencesTest.cpp' || echo '$(srcdir)/'`olad/plugin_api/PreferencesTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/plugin_api/$(DEPDIR)/olad_plugin_api_PreferencesTester-PreferencesTest.Tpo olad/plugin_api/$(DEPDIR)/olad_plugin_api_PreferencesTester-PreferencesTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/plugin_api/PreferencesTest.cpp' object='olad/plugin_api/olad_plugin_api_PreferencesTester-PreferencesTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_PreferencesTester_CXXFLAGS) $(CXXFLAGS) -c -o olad/plugin_api/olad_plugin_api_PreferencesTester-PreferencesTest.o `test -f 'olad/plugin_api/PreferencesTest.cpp' || echo '$(srcdir)/'`olad/plugin_api/PreferencesTest.cpp olad/plugin_api/olad_plugin_api_PreferencesTester-PreferencesTest.obj: olad/plugin_api/PreferencesTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_PreferencesTester_CXXFLAGS) $(CXXFLAGS) -MT olad/plugin_api/olad_plugin_api_PreferencesTester-PreferencesTest.obj -MD -MP -MF olad/plugin_api/$(DEPDIR)/olad_plugin_api_PreferencesTester-PreferencesTest.Tpo -c -o olad/plugin_api/olad_plugin_api_PreferencesTester-PreferencesTest.obj `if test -f 'olad/plugin_api/PreferencesTest.cpp'; then $(CYGPATH_W) 'olad/plugin_api/PreferencesTest.cpp'; else $(CYGPATH_W) '$(srcdir)/olad/plugin_api/PreferencesTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/plugin_api/$(DEPDIR)/olad_plugin_api_PreferencesTester-PreferencesTest.Tpo olad/plugin_api/$(DEPDIR)/olad_plugin_api_PreferencesTester-PreferencesTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/plugin_api/PreferencesTest.cpp' object='olad/plugin_api/olad_plugin_api_PreferencesTester-PreferencesTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_PreferencesTester_CXXFLAGS) $(CXXFLAGS) -c -o olad/plugin_api/olad_plugin_api_PreferencesTester-PreferencesTest.obj `if test -f 'olad/plugin_api/PreferencesTest.cpp'; then $(CYGPATH_W) 'olad/plugin_api/PreferencesTest.cpp'; else $(CYGPATH_W) '$(srcdir)/olad/plugin_api/PreferencesTest.cpp'; fi` olad/plugin_api/olad_plugin_api_UniverseTester-UniverseTest.o: olad/plugin_api/UniverseTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_UniverseTester_CXXFLAGS) $(CXXFLAGS) -MT olad/plugin_api/olad_plugin_api_UniverseTester-UniverseTest.o -MD -MP -MF olad/plugin_api/$(DEPDIR)/olad_plugin_api_UniverseTester-UniverseTest.Tpo -c -o olad/plugin_api/olad_plugin_api_UniverseTester-UniverseTest.o `test -f 'olad/plugin_api/UniverseTest.cpp' || echo '$(srcdir)/'`olad/plugin_api/UniverseTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/plugin_api/$(DEPDIR)/olad_plugin_api_UniverseTester-UniverseTest.Tpo olad/plugin_api/$(DEPDIR)/olad_plugin_api_UniverseTester-UniverseTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/plugin_api/UniverseTest.cpp' object='olad/plugin_api/olad_plugin_api_UniverseTester-UniverseTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_UniverseTester_CXXFLAGS) $(CXXFLAGS) -c -o olad/plugin_api/olad_plugin_api_UniverseTester-UniverseTest.o `test -f 'olad/plugin_api/UniverseTest.cpp' || echo '$(srcdir)/'`olad/plugin_api/UniverseTest.cpp olad/plugin_api/olad_plugin_api_UniverseTester-UniverseTest.obj: olad/plugin_api/UniverseTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_UniverseTester_CXXFLAGS) $(CXXFLAGS) -MT olad/plugin_api/olad_plugin_api_UniverseTester-UniverseTest.obj -MD -MP -MF olad/plugin_api/$(DEPDIR)/olad_plugin_api_UniverseTester-UniverseTest.Tpo -c -o olad/plugin_api/olad_plugin_api_UniverseTester-UniverseTest.obj `if test -f 'olad/plugin_api/UniverseTest.cpp'; then $(CYGPATH_W) 'olad/plugin_api/UniverseTest.cpp'; else $(CYGPATH_W) '$(srcdir)/olad/plugin_api/UniverseTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) olad/plugin_api/$(DEPDIR)/olad_plugin_api_UniverseTester-UniverseTest.Tpo olad/plugin_api/$(DEPDIR)/olad_plugin_api_UniverseTester-UniverseTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='olad/plugin_api/UniverseTest.cpp' object='olad/plugin_api/olad_plugin_api_UniverseTester-UniverseTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(olad_plugin_api_UniverseTester_CXXFLAGS) $(CXXFLAGS) -c -o olad/plugin_api/olad_plugin_api_UniverseTester-UniverseTest.obj `if test -f 'olad/plugin_api/UniverseTest.cpp'; then $(CYGPATH_W) 'olad/plugin_api/UniverseTest.cpp'; else $(CYGPATH_W) '$(srcdir)/olad/plugin_api/UniverseTest.cpp'; fi` plugins/artnet/plugins_artnet_ArtNetTester-ArtNetNodeTest.o: plugins/artnet/ArtNetNodeTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_artnet_ArtNetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/artnet/plugins_artnet_ArtNetTester-ArtNetNodeTest.o -MD -MP -MF plugins/artnet/$(DEPDIR)/plugins_artnet_ArtNetTester-ArtNetNodeTest.Tpo -c -o plugins/artnet/plugins_artnet_ArtNetTester-ArtNetNodeTest.o `test -f 'plugins/artnet/ArtNetNodeTest.cpp' || echo '$(srcdir)/'`plugins/artnet/ArtNetNodeTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/artnet/$(DEPDIR)/plugins_artnet_ArtNetTester-ArtNetNodeTest.Tpo plugins/artnet/$(DEPDIR)/plugins_artnet_ArtNetTester-ArtNetNodeTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/artnet/ArtNetNodeTest.cpp' object='plugins/artnet/plugins_artnet_ArtNetTester-ArtNetNodeTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_artnet_ArtNetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/artnet/plugins_artnet_ArtNetTester-ArtNetNodeTest.o `test -f 'plugins/artnet/ArtNetNodeTest.cpp' || echo '$(srcdir)/'`plugins/artnet/ArtNetNodeTest.cpp plugins/artnet/plugins_artnet_ArtNetTester-ArtNetNodeTest.obj: plugins/artnet/ArtNetNodeTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_artnet_ArtNetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/artnet/plugins_artnet_ArtNetTester-ArtNetNodeTest.obj -MD -MP -MF plugins/artnet/$(DEPDIR)/plugins_artnet_ArtNetTester-ArtNetNodeTest.Tpo -c -o plugins/artnet/plugins_artnet_ArtNetTester-ArtNetNodeTest.obj `if test -f 'plugins/artnet/ArtNetNodeTest.cpp'; then $(CYGPATH_W) 'plugins/artnet/ArtNetNodeTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/artnet/ArtNetNodeTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/artnet/$(DEPDIR)/plugins_artnet_ArtNetTester-ArtNetNodeTest.Tpo plugins/artnet/$(DEPDIR)/plugins_artnet_ArtNetTester-ArtNetNodeTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/artnet/ArtNetNodeTest.cpp' object='plugins/artnet/plugins_artnet_ArtNetTester-ArtNetNodeTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_artnet_ArtNetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/artnet/plugins_artnet_ArtNetTester-ArtNetNodeTest.obj `if test -f 'plugins/artnet/ArtNetNodeTest.cpp'; then $(CYGPATH_W) 'plugins/artnet/ArtNetNodeTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/artnet/ArtNetNodeTest.cpp'; fi` plugins/dummy/plugins_dummy_DummyPluginTester-DummyPortTest.o: plugins/dummy/DummyPortTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_dummy_DummyPluginTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/dummy/plugins_dummy_DummyPluginTester-DummyPortTest.o -MD -MP -MF plugins/dummy/$(DEPDIR)/plugins_dummy_DummyPluginTester-DummyPortTest.Tpo -c -o plugins/dummy/plugins_dummy_DummyPluginTester-DummyPortTest.o `test -f 'plugins/dummy/DummyPortTest.cpp' || echo '$(srcdir)/'`plugins/dummy/DummyPortTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/dummy/$(DEPDIR)/plugins_dummy_DummyPluginTester-DummyPortTest.Tpo plugins/dummy/$(DEPDIR)/plugins_dummy_DummyPluginTester-DummyPortTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/dummy/DummyPortTest.cpp' object='plugins/dummy/plugins_dummy_DummyPluginTester-DummyPortTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_dummy_DummyPluginTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/dummy/plugins_dummy_DummyPluginTester-DummyPortTest.o `test -f 'plugins/dummy/DummyPortTest.cpp' || echo '$(srcdir)/'`plugins/dummy/DummyPortTest.cpp plugins/dummy/plugins_dummy_DummyPluginTester-DummyPortTest.obj: plugins/dummy/DummyPortTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_dummy_DummyPluginTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/dummy/plugins_dummy_DummyPluginTester-DummyPortTest.obj -MD -MP -MF plugins/dummy/$(DEPDIR)/plugins_dummy_DummyPluginTester-DummyPortTest.Tpo -c -o plugins/dummy/plugins_dummy_DummyPluginTester-DummyPortTest.obj `if test -f 'plugins/dummy/DummyPortTest.cpp'; then $(CYGPATH_W) 'plugins/dummy/DummyPortTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/dummy/DummyPortTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/dummy/$(DEPDIR)/plugins_dummy_DummyPluginTester-DummyPortTest.Tpo plugins/dummy/$(DEPDIR)/plugins_dummy_DummyPluginTester-DummyPortTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/dummy/DummyPortTest.cpp' object='plugins/dummy/plugins_dummy_DummyPluginTester-DummyPortTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_dummy_DummyPluginTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/dummy/plugins_dummy_DummyPluginTester-DummyPortTest.obj `if test -f 'plugins/dummy/DummyPortTest.cpp'; then $(CYGPATH_W) 'plugins/dummy/DummyPortTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/dummy/DummyPortTest.cpp'; fi` plugins/espnet/plugins_espnet_EspNetTester-RunLengthDecoderTest.o: plugins/espnet/RunLengthDecoderTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_espnet_EspNetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/espnet/plugins_espnet_EspNetTester-RunLengthDecoderTest.o -MD -MP -MF plugins/espnet/$(DEPDIR)/plugins_espnet_EspNetTester-RunLengthDecoderTest.Tpo -c -o plugins/espnet/plugins_espnet_EspNetTester-RunLengthDecoderTest.o `test -f 'plugins/espnet/RunLengthDecoderTest.cpp' || echo '$(srcdir)/'`plugins/espnet/RunLengthDecoderTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/espnet/$(DEPDIR)/plugins_espnet_EspNetTester-RunLengthDecoderTest.Tpo plugins/espnet/$(DEPDIR)/plugins_espnet_EspNetTester-RunLengthDecoderTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/espnet/RunLengthDecoderTest.cpp' object='plugins/espnet/plugins_espnet_EspNetTester-RunLengthDecoderTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_espnet_EspNetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/espnet/plugins_espnet_EspNetTester-RunLengthDecoderTest.o `test -f 'plugins/espnet/RunLengthDecoderTest.cpp' || echo '$(srcdir)/'`plugins/espnet/RunLengthDecoderTest.cpp plugins/espnet/plugins_espnet_EspNetTester-RunLengthDecoderTest.obj: plugins/espnet/RunLengthDecoderTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_espnet_EspNetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/espnet/plugins_espnet_EspNetTester-RunLengthDecoderTest.obj -MD -MP -MF plugins/espnet/$(DEPDIR)/plugins_espnet_EspNetTester-RunLengthDecoderTest.Tpo -c -o plugins/espnet/plugins_espnet_EspNetTester-RunLengthDecoderTest.obj `if test -f 'plugins/espnet/RunLengthDecoderTest.cpp'; then $(CYGPATH_W) 'plugins/espnet/RunLengthDecoderTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/espnet/RunLengthDecoderTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/espnet/$(DEPDIR)/plugins_espnet_EspNetTester-RunLengthDecoderTest.Tpo plugins/espnet/$(DEPDIR)/plugins_espnet_EspNetTester-RunLengthDecoderTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/espnet/RunLengthDecoderTest.cpp' object='plugins/espnet/plugins_espnet_EspNetTester-RunLengthDecoderTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_espnet_EspNetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/espnet/plugins_espnet_EspNetTester-RunLengthDecoderTest.obj `if test -f 'plugins/espnet/RunLengthDecoderTest.cpp'; then $(CYGPATH_W) 'plugins/espnet/RunLengthDecoderTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/espnet/RunLengthDecoderTest.cpp'; fi` plugins/espnet/plugins_espnet_EspNetTester-RunLengthDecoder.o: plugins/espnet/RunLengthDecoder.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_espnet_EspNetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/espnet/plugins_espnet_EspNetTester-RunLengthDecoder.o -MD -MP -MF plugins/espnet/$(DEPDIR)/plugins_espnet_EspNetTester-RunLengthDecoder.Tpo -c -o plugins/espnet/plugins_espnet_EspNetTester-RunLengthDecoder.o `test -f 'plugins/espnet/RunLengthDecoder.cpp' || echo '$(srcdir)/'`plugins/espnet/RunLengthDecoder.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/espnet/$(DEPDIR)/plugins_espnet_EspNetTester-RunLengthDecoder.Tpo plugins/espnet/$(DEPDIR)/plugins_espnet_EspNetTester-RunLengthDecoder.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/espnet/RunLengthDecoder.cpp' object='plugins/espnet/plugins_espnet_EspNetTester-RunLengthDecoder.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_espnet_EspNetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/espnet/plugins_espnet_EspNetTester-RunLengthDecoder.o `test -f 'plugins/espnet/RunLengthDecoder.cpp' || echo '$(srcdir)/'`plugins/espnet/RunLengthDecoder.cpp plugins/espnet/plugins_espnet_EspNetTester-RunLengthDecoder.obj: plugins/espnet/RunLengthDecoder.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_espnet_EspNetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/espnet/plugins_espnet_EspNetTester-RunLengthDecoder.obj -MD -MP -MF plugins/espnet/$(DEPDIR)/plugins_espnet_EspNetTester-RunLengthDecoder.Tpo -c -o plugins/espnet/plugins_espnet_EspNetTester-RunLengthDecoder.obj `if test -f 'plugins/espnet/RunLengthDecoder.cpp'; then $(CYGPATH_W) 'plugins/espnet/RunLengthDecoder.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/espnet/RunLengthDecoder.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/espnet/$(DEPDIR)/plugins_espnet_EspNetTester-RunLengthDecoder.Tpo plugins/espnet/$(DEPDIR)/plugins_espnet_EspNetTester-RunLengthDecoder.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/espnet/RunLengthDecoder.cpp' object='plugins/espnet/plugins_espnet_EspNetTester-RunLengthDecoder.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_espnet_EspNetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/espnet/plugins_espnet_EspNetTester-RunLengthDecoder.obj `if test -f 'plugins/espnet/RunLengthDecoder.cpp'; then $(CYGPATH_W) 'plugins/espnet/RunLengthDecoder.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/espnet/RunLengthDecoder.cpp'; fi` plugins/kinet/plugins_kinet_KiNetTester-KiNetNodeTest.o: plugins/kinet/KiNetNodeTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_kinet_KiNetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/kinet/plugins_kinet_KiNetTester-KiNetNodeTest.o -MD -MP -MF plugins/kinet/$(DEPDIR)/plugins_kinet_KiNetTester-KiNetNodeTest.Tpo -c -o plugins/kinet/plugins_kinet_KiNetTester-KiNetNodeTest.o `test -f 'plugins/kinet/KiNetNodeTest.cpp' || echo '$(srcdir)/'`plugins/kinet/KiNetNodeTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/kinet/$(DEPDIR)/plugins_kinet_KiNetTester-KiNetNodeTest.Tpo plugins/kinet/$(DEPDIR)/plugins_kinet_KiNetTester-KiNetNodeTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/kinet/KiNetNodeTest.cpp' object='plugins/kinet/plugins_kinet_KiNetTester-KiNetNodeTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_kinet_KiNetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/kinet/plugins_kinet_KiNetTester-KiNetNodeTest.o `test -f 'plugins/kinet/KiNetNodeTest.cpp' || echo '$(srcdir)/'`plugins/kinet/KiNetNodeTest.cpp plugins/kinet/plugins_kinet_KiNetTester-KiNetNodeTest.obj: plugins/kinet/KiNetNodeTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_kinet_KiNetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/kinet/plugins_kinet_KiNetTester-KiNetNodeTest.obj -MD -MP -MF plugins/kinet/$(DEPDIR)/plugins_kinet_KiNetTester-KiNetNodeTest.Tpo -c -o plugins/kinet/plugins_kinet_KiNetTester-KiNetNodeTest.obj `if test -f 'plugins/kinet/KiNetNodeTest.cpp'; then $(CYGPATH_W) 'plugins/kinet/KiNetNodeTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/kinet/KiNetNodeTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/kinet/$(DEPDIR)/plugins_kinet_KiNetTester-KiNetNodeTest.Tpo plugins/kinet/$(DEPDIR)/plugins_kinet_KiNetTester-KiNetNodeTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/kinet/KiNetNodeTest.cpp' object='plugins/kinet/plugins_kinet_KiNetTester-KiNetNodeTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_kinet_KiNetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/kinet/plugins_kinet_KiNetTester-KiNetNodeTest.obj `if test -f 'plugins/kinet/KiNetNodeTest.cpp'; then $(CYGPATH_W) 'plugins/kinet/KiNetNodeTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/kinet/KiNetNodeTest.cpp'; fi` plugins/openpixelcontrol/plugins_openpixelcontrol_OPCClientTester-OPCClientTest.o: plugins/openpixelcontrol/OPCClientTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_openpixelcontrol_OPCClientTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/openpixelcontrol/plugins_openpixelcontrol_OPCClientTester-OPCClientTest.o -MD -MP -MF plugins/openpixelcontrol/$(DEPDIR)/plugins_openpixelcontrol_OPCClientTester-OPCClientTest.Tpo -c -o plugins/openpixelcontrol/plugins_openpixelcontrol_OPCClientTester-OPCClientTest.o `test -f 'plugins/openpixelcontrol/OPCClientTest.cpp' || echo '$(srcdir)/'`plugins/openpixelcontrol/OPCClientTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/openpixelcontrol/$(DEPDIR)/plugins_openpixelcontrol_OPCClientTester-OPCClientTest.Tpo plugins/openpixelcontrol/$(DEPDIR)/plugins_openpixelcontrol_OPCClientTester-OPCClientTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/openpixelcontrol/OPCClientTest.cpp' object='plugins/openpixelcontrol/plugins_openpixelcontrol_OPCClientTester-OPCClientTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_openpixelcontrol_OPCClientTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/openpixelcontrol/plugins_openpixelcontrol_OPCClientTester-OPCClientTest.o `test -f 'plugins/openpixelcontrol/OPCClientTest.cpp' || echo '$(srcdir)/'`plugins/openpixelcontrol/OPCClientTest.cpp plugins/openpixelcontrol/plugins_openpixelcontrol_OPCClientTester-OPCClientTest.obj: plugins/openpixelcontrol/OPCClientTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_openpixelcontrol_OPCClientTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/openpixelcontrol/plugins_openpixelcontrol_OPCClientTester-OPCClientTest.obj -MD -MP -MF plugins/openpixelcontrol/$(DEPDIR)/plugins_openpixelcontrol_OPCClientTester-OPCClientTest.Tpo -c -o plugins/openpixelcontrol/plugins_openpixelcontrol_OPCClientTester-OPCClientTest.obj `if test -f 'plugins/openpixelcontrol/OPCClientTest.cpp'; then $(CYGPATH_W) 'plugins/openpixelcontrol/OPCClientTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/openpixelcontrol/OPCClientTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/openpixelcontrol/$(DEPDIR)/plugins_openpixelcontrol_OPCClientTester-OPCClientTest.Tpo plugins/openpixelcontrol/$(DEPDIR)/plugins_openpixelcontrol_OPCClientTester-OPCClientTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/openpixelcontrol/OPCClientTest.cpp' object='plugins/openpixelcontrol/plugins_openpixelcontrol_OPCClientTester-OPCClientTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_openpixelcontrol_OPCClientTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/openpixelcontrol/plugins_openpixelcontrol_OPCClientTester-OPCClientTest.obj `if test -f 'plugins/openpixelcontrol/OPCClientTest.cpp'; then $(CYGPATH_W) 'plugins/openpixelcontrol/OPCClientTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/openpixelcontrol/OPCClientTest.cpp'; fi` plugins/openpixelcontrol/plugins_openpixelcontrol_OPCServerTester-OPCServerTest.o: plugins/openpixelcontrol/OPCServerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_openpixelcontrol_OPCServerTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/openpixelcontrol/plugins_openpixelcontrol_OPCServerTester-OPCServerTest.o -MD -MP -MF plugins/openpixelcontrol/$(DEPDIR)/plugins_openpixelcontrol_OPCServerTester-OPCServerTest.Tpo -c -o plugins/openpixelcontrol/plugins_openpixelcontrol_OPCServerTester-OPCServerTest.o `test -f 'plugins/openpixelcontrol/OPCServerTest.cpp' || echo '$(srcdir)/'`plugins/openpixelcontrol/OPCServerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/openpixelcontrol/$(DEPDIR)/plugins_openpixelcontrol_OPCServerTester-OPCServerTest.Tpo plugins/openpixelcontrol/$(DEPDIR)/plugins_openpixelcontrol_OPCServerTester-OPCServerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/openpixelcontrol/OPCServerTest.cpp' object='plugins/openpixelcontrol/plugins_openpixelcontrol_OPCServerTester-OPCServerTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_openpixelcontrol_OPCServerTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/openpixelcontrol/plugins_openpixelcontrol_OPCServerTester-OPCServerTest.o `test -f 'plugins/openpixelcontrol/OPCServerTest.cpp' || echo '$(srcdir)/'`plugins/openpixelcontrol/OPCServerTest.cpp plugins/openpixelcontrol/plugins_openpixelcontrol_OPCServerTester-OPCServerTest.obj: plugins/openpixelcontrol/OPCServerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_openpixelcontrol_OPCServerTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/openpixelcontrol/plugins_openpixelcontrol_OPCServerTester-OPCServerTest.obj -MD -MP -MF plugins/openpixelcontrol/$(DEPDIR)/plugins_openpixelcontrol_OPCServerTester-OPCServerTest.Tpo -c -o plugins/openpixelcontrol/plugins_openpixelcontrol_OPCServerTester-OPCServerTest.obj `if test -f 'plugins/openpixelcontrol/OPCServerTest.cpp'; then $(CYGPATH_W) 'plugins/openpixelcontrol/OPCServerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/openpixelcontrol/OPCServerTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/openpixelcontrol/$(DEPDIR)/plugins_openpixelcontrol_OPCServerTester-OPCServerTest.Tpo plugins/openpixelcontrol/$(DEPDIR)/plugins_openpixelcontrol_OPCServerTester-OPCServerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/openpixelcontrol/OPCServerTest.cpp' object='plugins/openpixelcontrol/plugins_openpixelcontrol_OPCServerTester-OPCServerTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_openpixelcontrol_OPCServerTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/openpixelcontrol/plugins_openpixelcontrol_OPCServerTester-OPCServerTest.obj `if test -f 'plugins/openpixelcontrol/OPCServerTest.cpp'; then $(CYGPATH_W) 'plugins/openpixelcontrol/OPCServerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/openpixelcontrol/OPCServerTest.cpp'; fi` plugins/osc/plugins_osc_OSCTester-OSCAddressTemplateTest.o: plugins/osc/OSCAddressTemplateTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_osc_OSCTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/osc/plugins_osc_OSCTester-OSCAddressTemplateTest.o -MD -MP -MF plugins/osc/$(DEPDIR)/plugins_osc_OSCTester-OSCAddressTemplateTest.Tpo -c -o plugins/osc/plugins_osc_OSCTester-OSCAddressTemplateTest.o `test -f 'plugins/osc/OSCAddressTemplateTest.cpp' || echo '$(srcdir)/'`plugins/osc/OSCAddressTemplateTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/osc/$(DEPDIR)/plugins_osc_OSCTester-OSCAddressTemplateTest.Tpo plugins/osc/$(DEPDIR)/plugins_osc_OSCTester-OSCAddressTemplateTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/osc/OSCAddressTemplateTest.cpp' object='plugins/osc/plugins_osc_OSCTester-OSCAddressTemplateTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_osc_OSCTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/osc/plugins_osc_OSCTester-OSCAddressTemplateTest.o `test -f 'plugins/osc/OSCAddressTemplateTest.cpp' || echo '$(srcdir)/'`plugins/osc/OSCAddressTemplateTest.cpp plugins/osc/plugins_osc_OSCTester-OSCAddressTemplateTest.obj: plugins/osc/OSCAddressTemplateTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_osc_OSCTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/osc/plugins_osc_OSCTester-OSCAddressTemplateTest.obj -MD -MP -MF plugins/osc/$(DEPDIR)/plugins_osc_OSCTester-OSCAddressTemplateTest.Tpo -c -o plugins/osc/plugins_osc_OSCTester-OSCAddressTemplateTest.obj `if test -f 'plugins/osc/OSCAddressTemplateTest.cpp'; then $(CYGPATH_W) 'plugins/osc/OSCAddressTemplateTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/osc/OSCAddressTemplateTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/osc/$(DEPDIR)/plugins_osc_OSCTester-OSCAddressTemplateTest.Tpo plugins/osc/$(DEPDIR)/plugins_osc_OSCTester-OSCAddressTemplateTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/osc/OSCAddressTemplateTest.cpp' object='plugins/osc/plugins_osc_OSCTester-OSCAddressTemplateTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_osc_OSCTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/osc/plugins_osc_OSCTester-OSCAddressTemplateTest.obj `if test -f 'plugins/osc/OSCAddressTemplateTest.cpp'; then $(CYGPATH_W) 'plugins/osc/OSCAddressTemplateTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/osc/OSCAddressTemplateTest.cpp'; fi` plugins/osc/plugins_osc_OSCTester-OSCNodeTest.o: plugins/osc/OSCNodeTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_osc_OSCTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/osc/plugins_osc_OSCTester-OSCNodeTest.o -MD -MP -MF plugins/osc/$(DEPDIR)/plugins_osc_OSCTester-OSCNodeTest.Tpo -c -o plugins/osc/plugins_osc_OSCTester-OSCNodeTest.o `test -f 'plugins/osc/OSCNodeTest.cpp' || echo '$(srcdir)/'`plugins/osc/OSCNodeTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/osc/$(DEPDIR)/plugins_osc_OSCTester-OSCNodeTest.Tpo plugins/osc/$(DEPDIR)/plugins_osc_OSCTester-OSCNodeTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/osc/OSCNodeTest.cpp' object='plugins/osc/plugins_osc_OSCTester-OSCNodeTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_osc_OSCTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/osc/plugins_osc_OSCTester-OSCNodeTest.o `test -f 'plugins/osc/OSCNodeTest.cpp' || echo '$(srcdir)/'`plugins/osc/OSCNodeTest.cpp plugins/osc/plugins_osc_OSCTester-OSCNodeTest.obj: plugins/osc/OSCNodeTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_osc_OSCTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/osc/plugins_osc_OSCTester-OSCNodeTest.obj -MD -MP -MF plugins/osc/$(DEPDIR)/plugins_osc_OSCTester-OSCNodeTest.Tpo -c -o plugins/osc/plugins_osc_OSCTester-OSCNodeTest.obj `if test -f 'plugins/osc/OSCNodeTest.cpp'; then $(CYGPATH_W) 'plugins/osc/OSCNodeTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/osc/OSCNodeTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/osc/$(DEPDIR)/plugins_osc_OSCTester-OSCNodeTest.Tpo plugins/osc/$(DEPDIR)/plugins_osc_OSCTester-OSCNodeTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/osc/OSCNodeTest.cpp' object='plugins/osc/plugins_osc_OSCTester-OSCNodeTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_osc_OSCTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/osc/plugins_osc_OSCTester-OSCNodeTest.obj `if test -f 'plugins/osc/OSCNodeTest.cpp'; then $(CYGPATH_W) 'plugins/osc/OSCNodeTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/osc/OSCNodeTest.cpp'; fi` plugins/shownet/plugins_shownet_ShowNetTester-ShowNetNode.o: plugins/shownet/ShowNetNode.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_shownet_ShowNetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/shownet/plugins_shownet_ShowNetTester-ShowNetNode.o -MD -MP -MF plugins/shownet/$(DEPDIR)/plugins_shownet_ShowNetTester-ShowNetNode.Tpo -c -o plugins/shownet/plugins_shownet_ShowNetTester-ShowNetNode.o `test -f 'plugins/shownet/ShowNetNode.cpp' || echo '$(srcdir)/'`plugins/shownet/ShowNetNode.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/shownet/$(DEPDIR)/plugins_shownet_ShowNetTester-ShowNetNode.Tpo plugins/shownet/$(DEPDIR)/plugins_shownet_ShowNetTester-ShowNetNode.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/shownet/ShowNetNode.cpp' object='plugins/shownet/plugins_shownet_ShowNetTester-ShowNetNode.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_shownet_ShowNetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/shownet/plugins_shownet_ShowNetTester-ShowNetNode.o `test -f 'plugins/shownet/ShowNetNode.cpp' || echo '$(srcdir)/'`plugins/shownet/ShowNetNode.cpp plugins/shownet/plugins_shownet_ShowNetTester-ShowNetNode.obj: plugins/shownet/ShowNetNode.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_shownet_ShowNetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/shownet/plugins_shownet_ShowNetTester-ShowNetNode.obj -MD -MP -MF plugins/shownet/$(DEPDIR)/plugins_shownet_ShowNetTester-ShowNetNode.Tpo -c -o plugins/shownet/plugins_shownet_ShowNetTester-ShowNetNode.obj `if test -f 'plugins/shownet/ShowNetNode.cpp'; then $(CYGPATH_W) 'plugins/shownet/ShowNetNode.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/shownet/ShowNetNode.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/shownet/$(DEPDIR)/plugins_shownet_ShowNetTester-ShowNetNode.Tpo plugins/shownet/$(DEPDIR)/plugins_shownet_ShowNetTester-ShowNetNode.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/shownet/ShowNetNode.cpp' object='plugins/shownet/plugins_shownet_ShowNetTester-ShowNetNode.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_shownet_ShowNetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/shownet/plugins_shownet_ShowNetTester-ShowNetNode.obj `if test -f 'plugins/shownet/ShowNetNode.cpp'; then $(CYGPATH_W) 'plugins/shownet/ShowNetNode.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/shownet/ShowNetNode.cpp'; fi` plugins/shownet/plugins_shownet_ShowNetTester-ShowNetNodeTest.o: plugins/shownet/ShowNetNodeTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_shownet_ShowNetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/shownet/plugins_shownet_ShowNetTester-ShowNetNodeTest.o -MD -MP -MF plugins/shownet/$(DEPDIR)/plugins_shownet_ShowNetTester-ShowNetNodeTest.Tpo -c -o plugins/shownet/plugins_shownet_ShowNetTester-ShowNetNodeTest.o `test -f 'plugins/shownet/ShowNetNodeTest.cpp' || echo '$(srcdir)/'`plugins/shownet/ShowNetNodeTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/shownet/$(DEPDIR)/plugins_shownet_ShowNetTester-ShowNetNodeTest.Tpo plugins/shownet/$(DEPDIR)/plugins_shownet_ShowNetTester-ShowNetNodeTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/shownet/ShowNetNodeTest.cpp' object='plugins/shownet/plugins_shownet_ShowNetTester-ShowNetNodeTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_shownet_ShowNetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/shownet/plugins_shownet_ShowNetTester-ShowNetNodeTest.o `test -f 'plugins/shownet/ShowNetNodeTest.cpp' || echo '$(srcdir)/'`plugins/shownet/ShowNetNodeTest.cpp plugins/shownet/plugins_shownet_ShowNetTester-ShowNetNodeTest.obj: plugins/shownet/ShowNetNodeTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_shownet_ShowNetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/shownet/plugins_shownet_ShowNetTester-ShowNetNodeTest.obj -MD -MP -MF plugins/shownet/$(DEPDIR)/plugins_shownet_ShowNetTester-ShowNetNodeTest.Tpo -c -o plugins/shownet/plugins_shownet_ShowNetTester-ShowNetNodeTest.obj `if test -f 'plugins/shownet/ShowNetNodeTest.cpp'; then $(CYGPATH_W) 'plugins/shownet/ShowNetNodeTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/shownet/ShowNetNodeTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/shownet/$(DEPDIR)/plugins_shownet_ShowNetTester-ShowNetNodeTest.Tpo plugins/shownet/$(DEPDIR)/plugins_shownet_ShowNetTester-ShowNetNodeTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/shownet/ShowNetNodeTest.cpp' object='plugins/shownet/plugins_shownet_ShowNetTester-ShowNetNodeTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_shownet_ShowNetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/shownet/plugins_shownet_ShowNetTester-ShowNetNodeTest.obj `if test -f 'plugins/shownet/ShowNetNodeTest.cpp'; then $(CYGPATH_W) 'plugins/shownet/ShowNetNodeTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/shownet/ShowNetNodeTest.cpp'; fi` plugins/spi/plugins_spi_SPITester-SPIBackendTest.o: plugins/spi/SPIBackendTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_spi_SPITester_CXXFLAGS) $(CXXFLAGS) -MT plugins/spi/plugins_spi_SPITester-SPIBackendTest.o -MD -MP -MF plugins/spi/$(DEPDIR)/plugins_spi_SPITester-SPIBackendTest.Tpo -c -o plugins/spi/plugins_spi_SPITester-SPIBackendTest.o `test -f 'plugins/spi/SPIBackendTest.cpp' || echo '$(srcdir)/'`plugins/spi/SPIBackendTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/spi/$(DEPDIR)/plugins_spi_SPITester-SPIBackendTest.Tpo plugins/spi/$(DEPDIR)/plugins_spi_SPITester-SPIBackendTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/spi/SPIBackendTest.cpp' object='plugins/spi/plugins_spi_SPITester-SPIBackendTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_spi_SPITester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/spi/plugins_spi_SPITester-SPIBackendTest.o `test -f 'plugins/spi/SPIBackendTest.cpp' || echo '$(srcdir)/'`plugins/spi/SPIBackendTest.cpp plugins/spi/plugins_spi_SPITester-SPIBackendTest.obj: plugins/spi/SPIBackendTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_spi_SPITester_CXXFLAGS) $(CXXFLAGS) -MT plugins/spi/plugins_spi_SPITester-SPIBackendTest.obj -MD -MP -MF plugins/spi/$(DEPDIR)/plugins_spi_SPITester-SPIBackendTest.Tpo -c -o plugins/spi/plugins_spi_SPITester-SPIBackendTest.obj `if test -f 'plugins/spi/SPIBackendTest.cpp'; then $(CYGPATH_W) 'plugins/spi/SPIBackendTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/spi/SPIBackendTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/spi/$(DEPDIR)/plugins_spi_SPITester-SPIBackendTest.Tpo plugins/spi/$(DEPDIR)/plugins_spi_SPITester-SPIBackendTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/spi/SPIBackendTest.cpp' object='plugins/spi/plugins_spi_SPITester-SPIBackendTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_spi_SPITester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/spi/plugins_spi_SPITester-SPIBackendTest.obj `if test -f 'plugins/spi/SPIBackendTest.cpp'; then $(CYGPATH_W) 'plugins/spi/SPIBackendTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/spi/SPIBackendTest.cpp'; fi` plugins/spi/plugins_spi_SPITester-SPIOutputTest.o: plugins/spi/SPIOutputTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_spi_SPITester_CXXFLAGS) $(CXXFLAGS) -MT plugins/spi/plugins_spi_SPITester-SPIOutputTest.o -MD -MP -MF plugins/spi/$(DEPDIR)/plugins_spi_SPITester-SPIOutputTest.Tpo -c -o plugins/spi/plugins_spi_SPITester-SPIOutputTest.o `test -f 'plugins/spi/SPIOutputTest.cpp' || echo '$(srcdir)/'`plugins/spi/SPIOutputTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/spi/$(DEPDIR)/plugins_spi_SPITester-SPIOutputTest.Tpo plugins/spi/$(DEPDIR)/plugins_spi_SPITester-SPIOutputTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/spi/SPIOutputTest.cpp' object='plugins/spi/plugins_spi_SPITester-SPIOutputTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_spi_SPITester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/spi/plugins_spi_SPITester-SPIOutputTest.o `test -f 'plugins/spi/SPIOutputTest.cpp' || echo '$(srcdir)/'`plugins/spi/SPIOutputTest.cpp plugins/spi/plugins_spi_SPITester-SPIOutputTest.obj: plugins/spi/SPIOutputTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_spi_SPITester_CXXFLAGS) $(CXXFLAGS) -MT plugins/spi/plugins_spi_SPITester-SPIOutputTest.obj -MD -MP -MF plugins/spi/$(DEPDIR)/plugins_spi_SPITester-SPIOutputTest.Tpo -c -o plugins/spi/plugins_spi_SPITester-SPIOutputTest.obj `if test -f 'plugins/spi/SPIOutputTest.cpp'; then $(CYGPATH_W) 'plugins/spi/SPIOutputTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/spi/SPIOutputTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/spi/$(DEPDIR)/plugins_spi_SPITester-SPIOutputTest.Tpo plugins/spi/$(DEPDIR)/plugins_spi_SPITester-SPIOutputTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/spi/SPIOutputTest.cpp' object='plugins/spi/plugins_spi_SPITester-SPIOutputTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_spi_SPITester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/spi/plugins_spi_SPITester-SPIOutputTest.obj `if test -f 'plugins/spi/SPIOutputTest.cpp'; then $(CYGPATH_W) 'plugins/spi/SPIOutputTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/spi/SPIOutputTest.cpp'; fi` plugins/spi/plugins_spi_SPITester-FakeSPIWriter.o: plugins/spi/FakeSPIWriter.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_spi_SPITester_CXXFLAGS) $(CXXFLAGS) -MT plugins/spi/plugins_spi_SPITester-FakeSPIWriter.o -MD -MP -MF plugins/spi/$(DEPDIR)/plugins_spi_SPITester-FakeSPIWriter.Tpo -c -o plugins/spi/plugins_spi_SPITester-FakeSPIWriter.o `test -f 'plugins/spi/FakeSPIWriter.cpp' || echo '$(srcdir)/'`plugins/spi/FakeSPIWriter.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/spi/$(DEPDIR)/plugins_spi_SPITester-FakeSPIWriter.Tpo plugins/spi/$(DEPDIR)/plugins_spi_SPITester-FakeSPIWriter.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/spi/FakeSPIWriter.cpp' object='plugins/spi/plugins_spi_SPITester-FakeSPIWriter.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_spi_SPITester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/spi/plugins_spi_SPITester-FakeSPIWriter.o `test -f 'plugins/spi/FakeSPIWriter.cpp' || echo '$(srcdir)/'`plugins/spi/FakeSPIWriter.cpp plugins/spi/plugins_spi_SPITester-FakeSPIWriter.obj: plugins/spi/FakeSPIWriter.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_spi_SPITester_CXXFLAGS) $(CXXFLAGS) -MT plugins/spi/plugins_spi_SPITester-FakeSPIWriter.obj -MD -MP -MF plugins/spi/$(DEPDIR)/plugins_spi_SPITester-FakeSPIWriter.Tpo -c -o plugins/spi/plugins_spi_SPITester-FakeSPIWriter.obj `if test -f 'plugins/spi/FakeSPIWriter.cpp'; then $(CYGPATH_W) 'plugins/spi/FakeSPIWriter.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/spi/FakeSPIWriter.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/spi/$(DEPDIR)/plugins_spi_SPITester-FakeSPIWriter.Tpo plugins/spi/$(DEPDIR)/plugins_spi_SPITester-FakeSPIWriter.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/spi/FakeSPIWriter.cpp' object='plugins/spi/plugins_spi_SPITester-FakeSPIWriter.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_spi_SPITester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/spi/plugins_spi_SPITester-FakeSPIWriter.obj `if test -f 'plugins/spi/FakeSPIWriter.cpp'; then $(CYGPATH_W) 'plugins/spi/FakeSPIWriter.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/spi/FakeSPIWriter.cpp'; fi` plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-ArduinoWidgetTest.o: plugins/usbpro/ArduinoWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_ArduinoWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-ArduinoWidgetTest.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_ArduinoWidgetTester-ArduinoWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-ArduinoWidgetTest.o `test -f 'plugins/usbpro/ArduinoWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/ArduinoWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_ArduinoWidgetTester-ArduinoWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_ArduinoWidgetTester-ArduinoWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/ArduinoWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-ArduinoWidgetTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_ArduinoWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-ArduinoWidgetTest.o `test -f 'plugins/usbpro/ArduinoWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/ArduinoWidgetTest.cpp plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-ArduinoWidgetTest.obj: plugins/usbpro/ArduinoWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_ArduinoWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-ArduinoWidgetTest.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_ArduinoWidgetTester-ArduinoWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-ArduinoWidgetTest.obj `if test -f 'plugins/usbpro/ArduinoWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/ArduinoWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/ArduinoWidgetTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_ArduinoWidgetTester-ArduinoWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_ArduinoWidgetTester-ArduinoWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/ArduinoWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-ArduinoWidgetTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_ArduinoWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-ArduinoWidgetTest.obj `if test -f 'plugins/usbpro/ArduinoWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/ArduinoWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/ArduinoWidgetTest.cpp'; fi` plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-CommonWidgetTest.o: plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_ArduinoWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-CommonWidgetTest.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_ArduinoWidgetTester-CommonWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-CommonWidgetTest.o `test -f 'plugins/usbpro/CommonWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_ArduinoWidgetTester-CommonWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_ArduinoWidgetTester-CommonWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/CommonWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-CommonWidgetTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_ArduinoWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-CommonWidgetTest.o `test -f 'plugins/usbpro/CommonWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/CommonWidgetTest.cpp plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-CommonWidgetTest.obj: plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_ArduinoWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-CommonWidgetTest.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_ArduinoWidgetTester-CommonWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-CommonWidgetTest.obj `if test -f 'plugins/usbpro/CommonWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/CommonWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/CommonWidgetTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_ArduinoWidgetTester-CommonWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_ArduinoWidgetTester-CommonWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/CommonWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-CommonWidgetTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_ArduinoWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-CommonWidgetTest.obj `if test -f 'plugins/usbpro/CommonWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/CommonWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/CommonWidgetTest.cpp'; fi` plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-MockEndpoint.o: plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_ArduinoWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-MockEndpoint.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_ArduinoWidgetTester-MockEndpoint.Tpo -c -o plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-MockEndpoint.o `test -f 'plugins/usbpro/MockEndpoint.cpp' || echo '$(srcdir)/'`plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_ArduinoWidgetTester-MockEndpoint.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_ArduinoWidgetTester-MockEndpoint.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/MockEndpoint.cpp' object='plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-MockEndpoint.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_ArduinoWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-MockEndpoint.o `test -f 'plugins/usbpro/MockEndpoint.cpp' || echo '$(srcdir)/'`plugins/usbpro/MockEndpoint.cpp plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-MockEndpoint.obj: plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_ArduinoWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-MockEndpoint.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_ArduinoWidgetTester-MockEndpoint.Tpo -c -o plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-MockEndpoint.obj `if test -f 'plugins/usbpro/MockEndpoint.cpp'; then $(CYGPATH_W) 'plugins/usbpro/MockEndpoint.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/MockEndpoint.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_ArduinoWidgetTester-MockEndpoint.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_ArduinoWidgetTester-MockEndpoint.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/MockEndpoint.cpp' object='plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-MockEndpoint.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_ArduinoWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_ArduinoWidgetTester-MockEndpoint.obj `if test -f 'plugins/usbpro/MockEndpoint.cpp'; then $(CYGPATH_W) 'plugins/usbpro/MockEndpoint.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/MockEndpoint.cpp'; fi` plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-BaseRobeWidgetTest.o: plugins/usbpro/BaseRobeWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_BaseRobeWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-BaseRobeWidgetTest.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseRobeWidgetTester-BaseRobeWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-BaseRobeWidgetTest.o `test -f 'plugins/usbpro/BaseRobeWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/BaseRobeWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseRobeWidgetTester-BaseRobeWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseRobeWidgetTester-BaseRobeWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/BaseRobeWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-BaseRobeWidgetTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_BaseRobeWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-BaseRobeWidgetTest.o `test -f 'plugins/usbpro/BaseRobeWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/BaseRobeWidgetTest.cpp plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-BaseRobeWidgetTest.obj: plugins/usbpro/BaseRobeWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_BaseRobeWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-BaseRobeWidgetTest.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseRobeWidgetTester-BaseRobeWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-BaseRobeWidgetTest.obj `if test -f 'plugins/usbpro/BaseRobeWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/BaseRobeWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/BaseRobeWidgetTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseRobeWidgetTester-BaseRobeWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseRobeWidgetTester-BaseRobeWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/BaseRobeWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-BaseRobeWidgetTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_BaseRobeWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-BaseRobeWidgetTest.obj `if test -f 'plugins/usbpro/BaseRobeWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/BaseRobeWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/BaseRobeWidgetTest.cpp'; fi` plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-CommonWidgetTest.o: plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_BaseRobeWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-CommonWidgetTest.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseRobeWidgetTester-CommonWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-CommonWidgetTest.o `test -f 'plugins/usbpro/CommonWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseRobeWidgetTester-CommonWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseRobeWidgetTester-CommonWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/CommonWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-CommonWidgetTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_BaseRobeWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-CommonWidgetTest.o `test -f 'plugins/usbpro/CommonWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/CommonWidgetTest.cpp plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-CommonWidgetTest.obj: plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_BaseRobeWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-CommonWidgetTest.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseRobeWidgetTester-CommonWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-CommonWidgetTest.obj `if test -f 'plugins/usbpro/CommonWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/CommonWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/CommonWidgetTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseRobeWidgetTester-CommonWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseRobeWidgetTester-CommonWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/CommonWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-CommonWidgetTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_BaseRobeWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-CommonWidgetTest.obj `if test -f 'plugins/usbpro/CommonWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/CommonWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/CommonWidgetTest.cpp'; fi` plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-MockEndpoint.o: plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_BaseRobeWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-MockEndpoint.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseRobeWidgetTester-MockEndpoint.Tpo -c -o plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-MockEndpoint.o `test -f 'plugins/usbpro/MockEndpoint.cpp' || echo '$(srcdir)/'`plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseRobeWidgetTester-MockEndpoint.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseRobeWidgetTester-MockEndpoint.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/MockEndpoint.cpp' object='plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-MockEndpoint.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_BaseRobeWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-MockEndpoint.o `test -f 'plugins/usbpro/MockEndpoint.cpp' || echo '$(srcdir)/'`plugins/usbpro/MockEndpoint.cpp plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-MockEndpoint.obj: plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_BaseRobeWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-MockEndpoint.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseRobeWidgetTester-MockEndpoint.Tpo -c -o plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-MockEndpoint.obj `if test -f 'plugins/usbpro/MockEndpoint.cpp'; then $(CYGPATH_W) 'plugins/usbpro/MockEndpoint.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/MockEndpoint.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseRobeWidgetTester-MockEndpoint.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseRobeWidgetTester-MockEndpoint.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/MockEndpoint.cpp' object='plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-MockEndpoint.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_BaseRobeWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_BaseRobeWidgetTester-MockEndpoint.obj `if test -f 'plugins/usbpro/MockEndpoint.cpp'; then $(CYGPATH_W) 'plugins/usbpro/MockEndpoint.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/MockEndpoint.cpp'; fi` plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-BaseUsbProWidgetTest.o: plugins/usbpro/BaseUsbProWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_BaseUsbProWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-BaseUsbProWidgetTest.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseUsbProWidgetTester-BaseUsbProWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-BaseUsbProWidgetTest.o `test -f 'plugins/usbpro/BaseUsbProWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/BaseUsbProWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseUsbProWidgetTester-BaseUsbProWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseUsbProWidgetTester-BaseUsbProWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/BaseUsbProWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-BaseUsbProWidgetTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_BaseUsbProWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-BaseUsbProWidgetTest.o `test -f 'plugins/usbpro/BaseUsbProWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/BaseUsbProWidgetTest.cpp plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-BaseUsbProWidgetTest.obj: plugins/usbpro/BaseUsbProWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_BaseUsbProWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-BaseUsbProWidgetTest.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseUsbProWidgetTester-BaseUsbProWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-BaseUsbProWidgetTest.obj `if test -f 'plugins/usbpro/BaseUsbProWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/BaseUsbProWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/BaseUsbProWidgetTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseUsbProWidgetTester-BaseUsbProWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseUsbProWidgetTester-BaseUsbProWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/BaseUsbProWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-BaseUsbProWidgetTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_BaseUsbProWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-BaseUsbProWidgetTest.obj `if test -f 'plugins/usbpro/BaseUsbProWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/BaseUsbProWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/BaseUsbProWidgetTest.cpp'; fi` plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-CommonWidgetTest.o: plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_BaseUsbProWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-CommonWidgetTest.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseUsbProWidgetTester-CommonWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-CommonWidgetTest.o `test -f 'plugins/usbpro/CommonWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseUsbProWidgetTester-CommonWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseUsbProWidgetTester-CommonWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/CommonWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-CommonWidgetTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_BaseUsbProWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-CommonWidgetTest.o `test -f 'plugins/usbpro/CommonWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/CommonWidgetTest.cpp plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-CommonWidgetTest.obj: plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_BaseUsbProWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-CommonWidgetTest.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseUsbProWidgetTester-CommonWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-CommonWidgetTest.obj `if test -f 'plugins/usbpro/CommonWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/CommonWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/CommonWidgetTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseUsbProWidgetTester-CommonWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseUsbProWidgetTester-CommonWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/CommonWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-CommonWidgetTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_BaseUsbProWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-CommonWidgetTest.obj `if test -f 'plugins/usbpro/CommonWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/CommonWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/CommonWidgetTest.cpp'; fi` plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-MockEndpoint.o: plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_BaseUsbProWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-MockEndpoint.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseUsbProWidgetTester-MockEndpoint.Tpo -c -o plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-MockEndpoint.o `test -f 'plugins/usbpro/MockEndpoint.cpp' || echo '$(srcdir)/'`plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseUsbProWidgetTester-MockEndpoint.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseUsbProWidgetTester-MockEndpoint.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/MockEndpoint.cpp' object='plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-MockEndpoint.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_BaseUsbProWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-MockEndpoint.o `test -f 'plugins/usbpro/MockEndpoint.cpp' || echo '$(srcdir)/'`plugins/usbpro/MockEndpoint.cpp plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-MockEndpoint.obj: plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_BaseUsbProWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-MockEndpoint.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseUsbProWidgetTester-MockEndpoint.Tpo -c -o plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-MockEndpoint.obj `if test -f 'plugins/usbpro/MockEndpoint.cpp'; then $(CYGPATH_W) 'plugins/usbpro/MockEndpoint.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/MockEndpoint.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseUsbProWidgetTester-MockEndpoint.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_BaseUsbProWidgetTester-MockEndpoint.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/MockEndpoint.cpp' object='plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-MockEndpoint.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_BaseUsbProWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_BaseUsbProWidgetTester-MockEndpoint.obj `if test -f 'plugins/usbpro/MockEndpoint.cpp'; then $(CYGPATH_W) 'plugins/usbpro/MockEndpoint.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/MockEndpoint.cpp'; fi` plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-DmxTriWidgetTest.o: plugins/usbpro/DmxTriWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_DmxTriWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-DmxTriWidgetTest.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxTriWidgetTester-DmxTriWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-DmxTriWidgetTest.o `test -f 'plugins/usbpro/DmxTriWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/DmxTriWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxTriWidgetTester-DmxTriWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxTriWidgetTester-DmxTriWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/DmxTriWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-DmxTriWidgetTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_DmxTriWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-DmxTriWidgetTest.o `test -f 'plugins/usbpro/DmxTriWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/DmxTriWidgetTest.cpp plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-DmxTriWidgetTest.obj: plugins/usbpro/DmxTriWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_DmxTriWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-DmxTriWidgetTest.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxTriWidgetTester-DmxTriWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-DmxTriWidgetTest.obj `if test -f 'plugins/usbpro/DmxTriWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/DmxTriWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/DmxTriWidgetTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxTriWidgetTester-DmxTriWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxTriWidgetTester-DmxTriWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/DmxTriWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-DmxTriWidgetTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_DmxTriWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-DmxTriWidgetTest.obj `if test -f 'plugins/usbpro/DmxTriWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/DmxTriWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/DmxTriWidgetTest.cpp'; fi` plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-CommonWidgetTest.o: plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_DmxTriWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-CommonWidgetTest.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxTriWidgetTester-CommonWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-CommonWidgetTest.o `test -f 'plugins/usbpro/CommonWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxTriWidgetTester-CommonWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxTriWidgetTester-CommonWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/CommonWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-CommonWidgetTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_DmxTriWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-CommonWidgetTest.o `test -f 'plugins/usbpro/CommonWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/CommonWidgetTest.cpp plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-CommonWidgetTest.obj: plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_DmxTriWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-CommonWidgetTest.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxTriWidgetTester-CommonWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-CommonWidgetTest.obj `if test -f 'plugins/usbpro/CommonWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/CommonWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/CommonWidgetTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxTriWidgetTester-CommonWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxTriWidgetTester-CommonWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/CommonWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-CommonWidgetTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_DmxTriWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-CommonWidgetTest.obj `if test -f 'plugins/usbpro/CommonWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/CommonWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/CommonWidgetTest.cpp'; fi` plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-MockEndpoint.o: plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_DmxTriWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-MockEndpoint.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxTriWidgetTester-MockEndpoint.Tpo -c -o plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-MockEndpoint.o `test -f 'plugins/usbpro/MockEndpoint.cpp' || echo '$(srcdir)/'`plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxTriWidgetTester-MockEndpoint.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxTriWidgetTester-MockEndpoint.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/MockEndpoint.cpp' object='plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-MockEndpoint.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_DmxTriWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-MockEndpoint.o `test -f 'plugins/usbpro/MockEndpoint.cpp' || echo '$(srcdir)/'`plugins/usbpro/MockEndpoint.cpp plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-MockEndpoint.obj: plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_DmxTriWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-MockEndpoint.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxTriWidgetTester-MockEndpoint.Tpo -c -o plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-MockEndpoint.obj `if test -f 'plugins/usbpro/MockEndpoint.cpp'; then $(CYGPATH_W) 'plugins/usbpro/MockEndpoint.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/MockEndpoint.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxTriWidgetTester-MockEndpoint.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxTriWidgetTester-MockEndpoint.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/MockEndpoint.cpp' object='plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-MockEndpoint.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_DmxTriWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_DmxTriWidgetTester-MockEndpoint.obj `if test -f 'plugins/usbpro/MockEndpoint.cpp'; then $(CYGPATH_W) 'plugins/usbpro/MockEndpoint.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/MockEndpoint.cpp'; fi` plugins/usbpro/plugins_usbpro_DmxterWidgetTester-DmxterWidgetTest.o: plugins/usbpro/DmxterWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_DmxterWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_DmxterWidgetTester-DmxterWidgetTest.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxterWidgetTester-DmxterWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_DmxterWidgetTester-DmxterWidgetTest.o `test -f 'plugins/usbpro/DmxterWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/DmxterWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxterWidgetTester-DmxterWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxterWidgetTester-DmxterWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/DmxterWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_DmxterWidgetTester-DmxterWidgetTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_DmxterWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_DmxterWidgetTester-DmxterWidgetTest.o `test -f 'plugins/usbpro/DmxterWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/DmxterWidgetTest.cpp plugins/usbpro/plugins_usbpro_DmxterWidgetTester-DmxterWidgetTest.obj: plugins/usbpro/DmxterWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_DmxterWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_DmxterWidgetTester-DmxterWidgetTest.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxterWidgetTester-DmxterWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_DmxterWidgetTester-DmxterWidgetTest.obj `if test -f 'plugins/usbpro/DmxterWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/DmxterWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/DmxterWidgetTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxterWidgetTester-DmxterWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxterWidgetTester-DmxterWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/DmxterWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_DmxterWidgetTester-DmxterWidgetTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_DmxterWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_DmxterWidgetTester-DmxterWidgetTest.obj `if test -f 'plugins/usbpro/DmxterWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/DmxterWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/DmxterWidgetTest.cpp'; fi` plugins/usbpro/plugins_usbpro_DmxterWidgetTester-CommonWidgetTest.o: plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_DmxterWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_DmxterWidgetTester-CommonWidgetTest.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxterWidgetTester-CommonWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_DmxterWidgetTester-CommonWidgetTest.o `test -f 'plugins/usbpro/CommonWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxterWidgetTester-CommonWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxterWidgetTester-CommonWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/CommonWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_DmxterWidgetTester-CommonWidgetTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_DmxterWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_DmxterWidgetTester-CommonWidgetTest.o `test -f 'plugins/usbpro/CommonWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/CommonWidgetTest.cpp plugins/usbpro/plugins_usbpro_DmxterWidgetTester-CommonWidgetTest.obj: plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_DmxterWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_DmxterWidgetTester-CommonWidgetTest.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxterWidgetTester-CommonWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_DmxterWidgetTester-CommonWidgetTest.obj `if test -f 'plugins/usbpro/CommonWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/CommonWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/CommonWidgetTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxterWidgetTester-CommonWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxterWidgetTester-CommonWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/CommonWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_DmxterWidgetTester-CommonWidgetTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_DmxterWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_DmxterWidgetTester-CommonWidgetTest.obj `if test -f 'plugins/usbpro/CommonWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/CommonWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/CommonWidgetTest.cpp'; fi` plugins/usbpro/plugins_usbpro_DmxterWidgetTester-MockEndpoint.o: plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_DmxterWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_DmxterWidgetTester-MockEndpoint.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxterWidgetTester-MockEndpoint.Tpo -c -o plugins/usbpro/plugins_usbpro_DmxterWidgetTester-MockEndpoint.o `test -f 'plugins/usbpro/MockEndpoint.cpp' || echo '$(srcdir)/'`plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxterWidgetTester-MockEndpoint.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxterWidgetTester-MockEndpoint.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/MockEndpoint.cpp' object='plugins/usbpro/plugins_usbpro_DmxterWidgetTester-MockEndpoint.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_DmxterWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_DmxterWidgetTester-MockEndpoint.o `test -f 'plugins/usbpro/MockEndpoint.cpp' || echo '$(srcdir)/'`plugins/usbpro/MockEndpoint.cpp plugins/usbpro/plugins_usbpro_DmxterWidgetTester-MockEndpoint.obj: plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_DmxterWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_DmxterWidgetTester-MockEndpoint.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxterWidgetTester-MockEndpoint.Tpo -c -o plugins/usbpro/plugins_usbpro_DmxterWidgetTester-MockEndpoint.obj `if test -f 'plugins/usbpro/MockEndpoint.cpp'; then $(CYGPATH_W) 'plugins/usbpro/MockEndpoint.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/MockEndpoint.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxterWidgetTester-MockEndpoint.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_DmxterWidgetTester-MockEndpoint.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/MockEndpoint.cpp' object='plugins/usbpro/plugins_usbpro_DmxterWidgetTester-MockEndpoint.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_DmxterWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_DmxterWidgetTester-MockEndpoint.obj `if test -f 'plugins/usbpro/MockEndpoint.cpp'; then $(CYGPATH_W) 'plugins/usbpro/MockEndpoint.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/MockEndpoint.cpp'; fi` plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-EnttecUsbProWidgetTest.o: plugins/usbpro/EnttecUsbProWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_EnttecUsbProWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-EnttecUsbProWidgetTest.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_EnttecUsbProWidgetTester-EnttecUsbProWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-EnttecUsbProWidgetTest.o `test -f 'plugins/usbpro/EnttecUsbProWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/EnttecUsbProWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_EnttecUsbProWidgetTester-EnttecUsbProWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_EnttecUsbProWidgetTester-EnttecUsbProWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/EnttecUsbProWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-EnttecUsbProWidgetTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_EnttecUsbProWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-EnttecUsbProWidgetTest.o `test -f 'plugins/usbpro/EnttecUsbProWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/EnttecUsbProWidgetTest.cpp plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-EnttecUsbProWidgetTest.obj: plugins/usbpro/EnttecUsbProWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_EnttecUsbProWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-EnttecUsbProWidgetTest.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_EnttecUsbProWidgetTester-EnttecUsbProWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-EnttecUsbProWidgetTest.obj `if test -f 'plugins/usbpro/EnttecUsbProWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/EnttecUsbProWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/EnttecUsbProWidgetTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_EnttecUsbProWidgetTester-EnttecUsbProWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_EnttecUsbProWidgetTester-EnttecUsbProWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/EnttecUsbProWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-EnttecUsbProWidgetTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_EnttecUsbProWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-EnttecUsbProWidgetTest.obj `if test -f 'plugins/usbpro/EnttecUsbProWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/EnttecUsbProWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/EnttecUsbProWidgetTest.cpp'; fi` plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-CommonWidgetTest.o: plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_EnttecUsbProWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-CommonWidgetTest.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_EnttecUsbProWidgetTester-CommonWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-CommonWidgetTest.o `test -f 'plugins/usbpro/CommonWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_EnttecUsbProWidgetTester-CommonWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_EnttecUsbProWidgetTester-CommonWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/CommonWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-CommonWidgetTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_EnttecUsbProWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-CommonWidgetTest.o `test -f 'plugins/usbpro/CommonWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/CommonWidgetTest.cpp plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-CommonWidgetTest.obj: plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_EnttecUsbProWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-CommonWidgetTest.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_EnttecUsbProWidgetTester-CommonWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-CommonWidgetTest.obj `if test -f 'plugins/usbpro/CommonWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/CommonWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/CommonWidgetTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_EnttecUsbProWidgetTester-CommonWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_EnttecUsbProWidgetTester-CommonWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/CommonWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-CommonWidgetTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_EnttecUsbProWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-CommonWidgetTest.obj `if test -f 'plugins/usbpro/CommonWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/CommonWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/CommonWidgetTest.cpp'; fi` plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-MockEndpoint.o: plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_EnttecUsbProWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-MockEndpoint.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_EnttecUsbProWidgetTester-MockEndpoint.Tpo -c -o plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-MockEndpoint.o `test -f 'plugins/usbpro/MockEndpoint.cpp' || echo '$(srcdir)/'`plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_EnttecUsbProWidgetTester-MockEndpoint.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_EnttecUsbProWidgetTester-MockEndpoint.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/MockEndpoint.cpp' object='plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-MockEndpoint.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_EnttecUsbProWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-MockEndpoint.o `test -f 'plugins/usbpro/MockEndpoint.cpp' || echo '$(srcdir)/'`plugins/usbpro/MockEndpoint.cpp plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-MockEndpoint.obj: plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_EnttecUsbProWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-MockEndpoint.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_EnttecUsbProWidgetTester-MockEndpoint.Tpo -c -o plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-MockEndpoint.obj `if test -f 'plugins/usbpro/MockEndpoint.cpp'; then $(CYGPATH_W) 'plugins/usbpro/MockEndpoint.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/MockEndpoint.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_EnttecUsbProWidgetTester-MockEndpoint.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_EnttecUsbProWidgetTester-MockEndpoint.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/MockEndpoint.cpp' object='plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-MockEndpoint.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_EnttecUsbProWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_EnttecUsbProWidgetTester-MockEndpoint.obj `if test -f 'plugins/usbpro/MockEndpoint.cpp'; then $(CYGPATH_W) 'plugins/usbpro/MockEndpoint.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/MockEndpoint.cpp'; fi` plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-RobeWidgetDetectorTest.o: plugins/usbpro/RobeWidgetDetectorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_RobeWidgetDetectorTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-RobeWidgetDetectorTest.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetDetectorTester-RobeWidgetDetectorTest.Tpo -c -o plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-RobeWidgetDetectorTest.o `test -f 'plugins/usbpro/RobeWidgetDetectorTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/RobeWidgetDetectorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetDetectorTester-RobeWidgetDetectorTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetDetectorTester-RobeWidgetDetectorTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/RobeWidgetDetectorTest.cpp' object='plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-RobeWidgetDetectorTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_RobeWidgetDetectorTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-RobeWidgetDetectorTest.o `test -f 'plugins/usbpro/RobeWidgetDetectorTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/RobeWidgetDetectorTest.cpp plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-RobeWidgetDetectorTest.obj: plugins/usbpro/RobeWidgetDetectorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_RobeWidgetDetectorTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-RobeWidgetDetectorTest.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetDetectorTester-RobeWidgetDetectorTest.Tpo -c -o plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-RobeWidgetDetectorTest.obj `if test -f 'plugins/usbpro/RobeWidgetDetectorTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/RobeWidgetDetectorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/RobeWidgetDetectorTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetDetectorTester-RobeWidgetDetectorTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetDetectorTester-RobeWidgetDetectorTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/RobeWidgetDetectorTest.cpp' object='plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-RobeWidgetDetectorTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_RobeWidgetDetectorTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-RobeWidgetDetectorTest.obj `if test -f 'plugins/usbpro/RobeWidgetDetectorTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/RobeWidgetDetectorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/RobeWidgetDetectorTest.cpp'; fi` plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-CommonWidgetTest.o: plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_RobeWidgetDetectorTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-CommonWidgetTest.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetDetectorTester-CommonWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-CommonWidgetTest.o `test -f 'plugins/usbpro/CommonWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetDetectorTester-CommonWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetDetectorTester-CommonWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/CommonWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-CommonWidgetTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_RobeWidgetDetectorTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-CommonWidgetTest.o `test -f 'plugins/usbpro/CommonWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/CommonWidgetTest.cpp plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-CommonWidgetTest.obj: plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_RobeWidgetDetectorTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-CommonWidgetTest.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetDetectorTester-CommonWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-CommonWidgetTest.obj `if test -f 'plugins/usbpro/CommonWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/CommonWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/CommonWidgetTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetDetectorTester-CommonWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetDetectorTester-CommonWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/CommonWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-CommonWidgetTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_RobeWidgetDetectorTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-CommonWidgetTest.obj `if test -f 'plugins/usbpro/CommonWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/CommonWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/CommonWidgetTest.cpp'; fi` plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-MockEndpoint.o: plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_RobeWidgetDetectorTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-MockEndpoint.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetDetectorTester-MockEndpoint.Tpo -c -o plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-MockEndpoint.o `test -f 'plugins/usbpro/MockEndpoint.cpp' || echo '$(srcdir)/'`plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetDetectorTester-MockEndpoint.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetDetectorTester-MockEndpoint.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/MockEndpoint.cpp' object='plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-MockEndpoint.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_RobeWidgetDetectorTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-MockEndpoint.o `test -f 'plugins/usbpro/MockEndpoint.cpp' || echo '$(srcdir)/'`plugins/usbpro/MockEndpoint.cpp plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-MockEndpoint.obj: plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_RobeWidgetDetectorTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-MockEndpoint.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetDetectorTester-MockEndpoint.Tpo -c -o plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-MockEndpoint.obj `if test -f 'plugins/usbpro/MockEndpoint.cpp'; then $(CYGPATH_W) 'plugins/usbpro/MockEndpoint.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/MockEndpoint.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetDetectorTester-MockEndpoint.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetDetectorTester-MockEndpoint.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/MockEndpoint.cpp' object='plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-MockEndpoint.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_RobeWidgetDetectorTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_RobeWidgetDetectorTester-MockEndpoint.obj `if test -f 'plugins/usbpro/MockEndpoint.cpp'; then $(CYGPATH_W) 'plugins/usbpro/MockEndpoint.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/MockEndpoint.cpp'; fi` plugins/usbpro/plugins_usbpro_RobeWidgetTester-RobeWidgetTest.o: plugins/usbpro/RobeWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_RobeWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_RobeWidgetTester-RobeWidgetTest.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetTester-RobeWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_RobeWidgetTester-RobeWidgetTest.o `test -f 'plugins/usbpro/RobeWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/RobeWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetTester-RobeWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetTester-RobeWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/RobeWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_RobeWidgetTester-RobeWidgetTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_RobeWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_RobeWidgetTester-RobeWidgetTest.o `test -f 'plugins/usbpro/RobeWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/RobeWidgetTest.cpp plugins/usbpro/plugins_usbpro_RobeWidgetTester-RobeWidgetTest.obj: plugins/usbpro/RobeWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_RobeWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_RobeWidgetTester-RobeWidgetTest.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetTester-RobeWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_RobeWidgetTester-RobeWidgetTest.obj `if test -f 'plugins/usbpro/RobeWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/RobeWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/RobeWidgetTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetTester-RobeWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetTester-RobeWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/RobeWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_RobeWidgetTester-RobeWidgetTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_RobeWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_RobeWidgetTester-RobeWidgetTest.obj `if test -f 'plugins/usbpro/RobeWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/RobeWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/RobeWidgetTest.cpp'; fi` plugins/usbpro/plugins_usbpro_RobeWidgetTester-CommonWidgetTest.o: plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_RobeWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_RobeWidgetTester-CommonWidgetTest.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetTester-CommonWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_RobeWidgetTester-CommonWidgetTest.o `test -f 'plugins/usbpro/CommonWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetTester-CommonWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetTester-CommonWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/CommonWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_RobeWidgetTester-CommonWidgetTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_RobeWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_RobeWidgetTester-CommonWidgetTest.o `test -f 'plugins/usbpro/CommonWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/CommonWidgetTest.cpp plugins/usbpro/plugins_usbpro_RobeWidgetTester-CommonWidgetTest.obj: plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_RobeWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_RobeWidgetTester-CommonWidgetTest.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetTester-CommonWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_RobeWidgetTester-CommonWidgetTest.obj `if test -f 'plugins/usbpro/CommonWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/CommonWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/CommonWidgetTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetTester-CommonWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetTester-CommonWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/CommonWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_RobeWidgetTester-CommonWidgetTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_RobeWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_RobeWidgetTester-CommonWidgetTest.obj `if test -f 'plugins/usbpro/CommonWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/CommonWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/CommonWidgetTest.cpp'; fi` plugins/usbpro/plugins_usbpro_RobeWidgetTester-MockEndpoint.o: plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_RobeWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_RobeWidgetTester-MockEndpoint.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetTester-MockEndpoint.Tpo -c -o plugins/usbpro/plugins_usbpro_RobeWidgetTester-MockEndpoint.o `test -f 'plugins/usbpro/MockEndpoint.cpp' || echo '$(srcdir)/'`plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetTester-MockEndpoint.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetTester-MockEndpoint.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/MockEndpoint.cpp' object='plugins/usbpro/plugins_usbpro_RobeWidgetTester-MockEndpoint.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_RobeWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_RobeWidgetTester-MockEndpoint.o `test -f 'plugins/usbpro/MockEndpoint.cpp' || echo '$(srcdir)/'`plugins/usbpro/MockEndpoint.cpp plugins/usbpro/plugins_usbpro_RobeWidgetTester-MockEndpoint.obj: plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_RobeWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_RobeWidgetTester-MockEndpoint.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetTester-MockEndpoint.Tpo -c -o plugins/usbpro/plugins_usbpro_RobeWidgetTester-MockEndpoint.obj `if test -f 'plugins/usbpro/MockEndpoint.cpp'; then $(CYGPATH_W) 'plugins/usbpro/MockEndpoint.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/MockEndpoint.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetTester-MockEndpoint.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_RobeWidgetTester-MockEndpoint.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/MockEndpoint.cpp' object='plugins/usbpro/plugins_usbpro_RobeWidgetTester-MockEndpoint.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_RobeWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_RobeWidgetTester-MockEndpoint.obj `if test -f 'plugins/usbpro/MockEndpoint.cpp'; then $(CYGPATH_W) 'plugins/usbpro/MockEndpoint.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/MockEndpoint.cpp'; fi` plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-UltraDMXProWidgetTest.o: plugins/usbpro/UltraDMXProWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_UltraDMXProWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-UltraDMXProWidgetTest.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_UltraDMXProWidgetTester-UltraDMXProWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-UltraDMXProWidgetTest.o `test -f 'plugins/usbpro/UltraDMXProWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/UltraDMXProWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_UltraDMXProWidgetTester-UltraDMXProWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_UltraDMXProWidgetTester-UltraDMXProWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/UltraDMXProWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-UltraDMXProWidgetTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_UltraDMXProWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-UltraDMXProWidgetTest.o `test -f 'plugins/usbpro/UltraDMXProWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/UltraDMXProWidgetTest.cpp plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-UltraDMXProWidgetTest.obj: plugins/usbpro/UltraDMXProWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_UltraDMXProWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-UltraDMXProWidgetTest.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_UltraDMXProWidgetTester-UltraDMXProWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-UltraDMXProWidgetTest.obj `if test -f 'plugins/usbpro/UltraDMXProWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/UltraDMXProWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/UltraDMXProWidgetTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_UltraDMXProWidgetTester-UltraDMXProWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_UltraDMXProWidgetTester-UltraDMXProWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/UltraDMXProWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-UltraDMXProWidgetTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_UltraDMXProWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-UltraDMXProWidgetTest.obj `if test -f 'plugins/usbpro/UltraDMXProWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/UltraDMXProWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/UltraDMXProWidgetTest.cpp'; fi` plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-CommonWidgetTest.o: plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_UltraDMXProWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-CommonWidgetTest.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_UltraDMXProWidgetTester-CommonWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-CommonWidgetTest.o `test -f 'plugins/usbpro/CommonWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_UltraDMXProWidgetTester-CommonWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_UltraDMXProWidgetTester-CommonWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/CommonWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-CommonWidgetTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_UltraDMXProWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-CommonWidgetTest.o `test -f 'plugins/usbpro/CommonWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/CommonWidgetTest.cpp plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-CommonWidgetTest.obj: plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_UltraDMXProWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-CommonWidgetTest.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_UltraDMXProWidgetTester-CommonWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-CommonWidgetTest.obj `if test -f 'plugins/usbpro/CommonWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/CommonWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/CommonWidgetTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_UltraDMXProWidgetTester-CommonWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_UltraDMXProWidgetTester-CommonWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/CommonWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-CommonWidgetTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_UltraDMXProWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-CommonWidgetTest.obj `if test -f 'plugins/usbpro/CommonWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/CommonWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/CommonWidgetTest.cpp'; fi` plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-MockEndpoint.o: plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_UltraDMXProWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-MockEndpoint.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_UltraDMXProWidgetTester-MockEndpoint.Tpo -c -o plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-MockEndpoint.o `test -f 'plugins/usbpro/MockEndpoint.cpp' || echo '$(srcdir)/'`plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_UltraDMXProWidgetTester-MockEndpoint.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_UltraDMXProWidgetTester-MockEndpoint.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/MockEndpoint.cpp' object='plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-MockEndpoint.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_UltraDMXProWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-MockEndpoint.o `test -f 'plugins/usbpro/MockEndpoint.cpp' || echo '$(srcdir)/'`plugins/usbpro/MockEndpoint.cpp plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-MockEndpoint.obj: plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_UltraDMXProWidgetTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-MockEndpoint.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_UltraDMXProWidgetTester-MockEndpoint.Tpo -c -o plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-MockEndpoint.obj `if test -f 'plugins/usbpro/MockEndpoint.cpp'; then $(CYGPATH_W) 'plugins/usbpro/MockEndpoint.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/MockEndpoint.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_UltraDMXProWidgetTester-MockEndpoint.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_UltraDMXProWidgetTester-MockEndpoint.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/MockEndpoint.cpp' object='plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-MockEndpoint.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_UltraDMXProWidgetTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_UltraDMXProWidgetTester-MockEndpoint.obj `if test -f 'plugins/usbpro/MockEndpoint.cpp'; then $(CYGPATH_W) 'plugins/usbpro/MockEndpoint.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/MockEndpoint.cpp'; fi` plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-UsbProWidgetDetectorTest.o: plugins/usbpro/UsbProWidgetDetectorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_UsbProWidgetDetectorTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-UsbProWidgetDetectorTest.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_UsbProWidgetDetectorTester-UsbProWidgetDetectorTest.Tpo -c -o plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-UsbProWidgetDetectorTest.o `test -f 'plugins/usbpro/UsbProWidgetDetectorTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/UsbProWidgetDetectorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_UsbProWidgetDetectorTester-UsbProWidgetDetectorTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_UsbProWidgetDetectorTester-UsbProWidgetDetectorTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/UsbProWidgetDetectorTest.cpp' object='plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-UsbProWidgetDetectorTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_UsbProWidgetDetectorTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-UsbProWidgetDetectorTest.o `test -f 'plugins/usbpro/UsbProWidgetDetectorTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/UsbProWidgetDetectorTest.cpp plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-UsbProWidgetDetectorTest.obj: plugins/usbpro/UsbProWidgetDetectorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_UsbProWidgetDetectorTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-UsbProWidgetDetectorTest.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_UsbProWidgetDetectorTester-UsbProWidgetDetectorTest.Tpo -c -o plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-UsbProWidgetDetectorTest.obj `if test -f 'plugins/usbpro/UsbProWidgetDetectorTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/UsbProWidgetDetectorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/UsbProWidgetDetectorTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_UsbProWidgetDetectorTester-UsbProWidgetDetectorTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_UsbProWidgetDetectorTester-UsbProWidgetDetectorTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/UsbProWidgetDetectorTest.cpp' object='plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-UsbProWidgetDetectorTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_UsbProWidgetDetectorTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-UsbProWidgetDetectorTest.obj `if test -f 'plugins/usbpro/UsbProWidgetDetectorTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/UsbProWidgetDetectorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/UsbProWidgetDetectorTest.cpp'; fi` plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-CommonWidgetTest.o: plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_UsbProWidgetDetectorTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-CommonWidgetTest.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_UsbProWidgetDetectorTester-CommonWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-CommonWidgetTest.o `test -f 'plugins/usbpro/CommonWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_UsbProWidgetDetectorTester-CommonWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_UsbProWidgetDetectorTester-CommonWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/CommonWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-CommonWidgetTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_UsbProWidgetDetectorTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-CommonWidgetTest.o `test -f 'plugins/usbpro/CommonWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/CommonWidgetTest.cpp plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-CommonWidgetTest.obj: plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_UsbProWidgetDetectorTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-CommonWidgetTest.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_UsbProWidgetDetectorTester-CommonWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-CommonWidgetTest.obj `if test -f 'plugins/usbpro/CommonWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/CommonWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/CommonWidgetTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_UsbProWidgetDetectorTester-CommonWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_UsbProWidgetDetectorTester-CommonWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/CommonWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-CommonWidgetTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_UsbProWidgetDetectorTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-CommonWidgetTest.obj `if test -f 'plugins/usbpro/CommonWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/CommonWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/CommonWidgetTest.cpp'; fi` plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-MockEndpoint.o: plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_UsbProWidgetDetectorTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-MockEndpoint.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_UsbProWidgetDetectorTester-MockEndpoint.Tpo -c -o plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-MockEndpoint.o `test -f 'plugins/usbpro/MockEndpoint.cpp' || echo '$(srcdir)/'`plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_UsbProWidgetDetectorTester-MockEndpoint.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_UsbProWidgetDetectorTester-MockEndpoint.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/MockEndpoint.cpp' object='plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-MockEndpoint.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_UsbProWidgetDetectorTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-MockEndpoint.o `test -f 'plugins/usbpro/MockEndpoint.cpp' || echo '$(srcdir)/'`plugins/usbpro/MockEndpoint.cpp plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-MockEndpoint.obj: plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_UsbProWidgetDetectorTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-MockEndpoint.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_UsbProWidgetDetectorTester-MockEndpoint.Tpo -c -o plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-MockEndpoint.obj `if test -f 'plugins/usbpro/MockEndpoint.cpp'; then $(CYGPATH_W) 'plugins/usbpro/MockEndpoint.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/MockEndpoint.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_UsbProWidgetDetectorTester-MockEndpoint.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_UsbProWidgetDetectorTester-MockEndpoint.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/MockEndpoint.cpp' object='plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-MockEndpoint.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_UsbProWidgetDetectorTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_UsbProWidgetDetectorTester-MockEndpoint.obj `if test -f 'plugins/usbpro/MockEndpoint.cpp'; then $(CYGPATH_W) 'plugins/usbpro/MockEndpoint.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/MockEndpoint.cpp'; fi` plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-WidgetDetectorThreadTest.o: plugins/usbpro/WidgetDetectorThreadTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_WidgetDetectorThreadTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-WidgetDetectorThreadTest.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_WidgetDetectorThreadTester-WidgetDetectorThreadTest.Tpo -c -o plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-WidgetDetectorThreadTest.o `test -f 'plugins/usbpro/WidgetDetectorThreadTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/WidgetDetectorThreadTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_WidgetDetectorThreadTester-WidgetDetectorThreadTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_WidgetDetectorThreadTester-WidgetDetectorThreadTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/WidgetDetectorThreadTest.cpp' object='plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-WidgetDetectorThreadTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_WidgetDetectorThreadTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-WidgetDetectorThreadTest.o `test -f 'plugins/usbpro/WidgetDetectorThreadTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/WidgetDetectorThreadTest.cpp plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-WidgetDetectorThreadTest.obj: plugins/usbpro/WidgetDetectorThreadTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_WidgetDetectorThreadTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-WidgetDetectorThreadTest.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_WidgetDetectorThreadTester-WidgetDetectorThreadTest.Tpo -c -o plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-WidgetDetectorThreadTest.obj `if test -f 'plugins/usbpro/WidgetDetectorThreadTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/WidgetDetectorThreadTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/WidgetDetectorThreadTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_WidgetDetectorThreadTester-WidgetDetectorThreadTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_WidgetDetectorThreadTester-WidgetDetectorThreadTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/WidgetDetectorThreadTest.cpp' object='plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-WidgetDetectorThreadTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_WidgetDetectorThreadTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-WidgetDetectorThreadTest.obj `if test -f 'plugins/usbpro/WidgetDetectorThreadTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/WidgetDetectorThreadTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/WidgetDetectorThreadTest.cpp'; fi` plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-CommonWidgetTest.o: plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_WidgetDetectorThreadTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-CommonWidgetTest.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_WidgetDetectorThreadTester-CommonWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-CommonWidgetTest.o `test -f 'plugins/usbpro/CommonWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_WidgetDetectorThreadTester-CommonWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_WidgetDetectorThreadTester-CommonWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/CommonWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-CommonWidgetTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_WidgetDetectorThreadTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-CommonWidgetTest.o `test -f 'plugins/usbpro/CommonWidgetTest.cpp' || echo '$(srcdir)/'`plugins/usbpro/CommonWidgetTest.cpp plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-CommonWidgetTest.obj: plugins/usbpro/CommonWidgetTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_WidgetDetectorThreadTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-CommonWidgetTest.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_WidgetDetectorThreadTester-CommonWidgetTest.Tpo -c -o plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-CommonWidgetTest.obj `if test -f 'plugins/usbpro/CommonWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/CommonWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/CommonWidgetTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_WidgetDetectorThreadTester-CommonWidgetTest.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_WidgetDetectorThreadTester-CommonWidgetTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/CommonWidgetTest.cpp' object='plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-CommonWidgetTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_WidgetDetectorThreadTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-CommonWidgetTest.obj `if test -f 'plugins/usbpro/CommonWidgetTest.cpp'; then $(CYGPATH_W) 'plugins/usbpro/CommonWidgetTest.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/CommonWidgetTest.cpp'; fi` plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-MockEndpoint.o: plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_WidgetDetectorThreadTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-MockEndpoint.o -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_WidgetDetectorThreadTester-MockEndpoint.Tpo -c -o plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-MockEndpoint.o `test -f 'plugins/usbpro/MockEndpoint.cpp' || echo '$(srcdir)/'`plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_WidgetDetectorThreadTester-MockEndpoint.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_WidgetDetectorThreadTester-MockEndpoint.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/MockEndpoint.cpp' object='plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-MockEndpoint.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_WidgetDetectorThreadTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-MockEndpoint.o `test -f 'plugins/usbpro/MockEndpoint.cpp' || echo '$(srcdir)/'`plugins/usbpro/MockEndpoint.cpp plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-MockEndpoint.obj: plugins/usbpro/MockEndpoint.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_WidgetDetectorThreadTester_CXXFLAGS) $(CXXFLAGS) -MT plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-MockEndpoint.obj -MD -MP -MF plugins/usbpro/$(DEPDIR)/plugins_usbpro_WidgetDetectorThreadTester-MockEndpoint.Tpo -c -o plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-MockEndpoint.obj `if test -f 'plugins/usbpro/MockEndpoint.cpp'; then $(CYGPATH_W) 'plugins/usbpro/MockEndpoint.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/MockEndpoint.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) plugins/usbpro/$(DEPDIR)/plugins_usbpro_WidgetDetectorThreadTester-MockEndpoint.Tpo plugins/usbpro/$(DEPDIR)/plugins_usbpro_WidgetDetectorThreadTester-MockEndpoint.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='plugins/usbpro/MockEndpoint.cpp' object='plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-MockEndpoint.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(plugins_usbpro_WidgetDetectorThreadTester_CXXFLAGS) $(CXXFLAGS) -c -o plugins/usbpro/plugins_usbpro_WidgetDetectorThreadTester-MockEndpoint.obj `if test -f 'plugins/usbpro/MockEndpoint.cpp'; then $(CYGPATH_W) 'plugins/usbpro/MockEndpoint.cpp'; else $(CYGPATH_W) '$(srcdir)/plugins/usbpro/MockEndpoint.cpp'; fi` protoc/protoc_ola_protoc_plugin-CppFileGenerator.o: protoc/CppFileGenerator.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protoc_ola_protoc_plugin_CXXFLAGS) $(CXXFLAGS) -MT protoc/protoc_ola_protoc_plugin-CppFileGenerator.o -MD -MP -MF protoc/$(DEPDIR)/protoc_ola_protoc_plugin-CppFileGenerator.Tpo -c -o protoc/protoc_ola_protoc_plugin-CppFileGenerator.o `test -f 'protoc/CppFileGenerator.cpp' || echo '$(srcdir)/'`protoc/CppFileGenerator.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) protoc/$(DEPDIR)/protoc_ola_protoc_plugin-CppFileGenerator.Tpo protoc/$(DEPDIR)/protoc_ola_protoc_plugin-CppFileGenerator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='protoc/CppFileGenerator.cpp' object='protoc/protoc_ola_protoc_plugin-CppFileGenerator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protoc_ola_protoc_plugin_CXXFLAGS) $(CXXFLAGS) -c -o protoc/protoc_ola_protoc_plugin-CppFileGenerator.o `test -f 'protoc/CppFileGenerator.cpp' || echo '$(srcdir)/'`protoc/CppFileGenerator.cpp protoc/protoc_ola_protoc_plugin-CppFileGenerator.obj: protoc/CppFileGenerator.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protoc_ola_protoc_plugin_CXXFLAGS) $(CXXFLAGS) -MT protoc/protoc_ola_protoc_plugin-CppFileGenerator.obj -MD -MP -MF protoc/$(DEPDIR)/protoc_ola_protoc_plugin-CppFileGenerator.Tpo -c -o protoc/protoc_ola_protoc_plugin-CppFileGenerator.obj `if test -f 'protoc/CppFileGenerator.cpp'; then $(CYGPATH_W) 'protoc/CppFileGenerator.cpp'; else $(CYGPATH_W) '$(srcdir)/protoc/CppFileGenerator.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) protoc/$(DEPDIR)/protoc_ola_protoc_plugin-CppFileGenerator.Tpo protoc/$(DEPDIR)/protoc_ola_protoc_plugin-CppFileGenerator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='protoc/CppFileGenerator.cpp' object='protoc/protoc_ola_protoc_plugin-CppFileGenerator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protoc_ola_protoc_plugin_CXXFLAGS) $(CXXFLAGS) -c -o protoc/protoc_ola_protoc_plugin-CppFileGenerator.obj `if test -f 'protoc/CppFileGenerator.cpp'; then $(CYGPATH_W) 'protoc/CppFileGenerator.cpp'; else $(CYGPATH_W) '$(srcdir)/protoc/CppFileGenerator.cpp'; fi` protoc/protoc_ola_protoc_plugin-CppGenerator.o: protoc/CppGenerator.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protoc_ola_protoc_plugin_CXXFLAGS) $(CXXFLAGS) -MT protoc/protoc_ola_protoc_plugin-CppGenerator.o -MD -MP -MF protoc/$(DEPDIR)/protoc_ola_protoc_plugin-CppGenerator.Tpo -c -o protoc/protoc_ola_protoc_plugin-CppGenerator.o `test -f 'protoc/CppGenerator.cpp' || echo '$(srcdir)/'`protoc/CppGenerator.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) protoc/$(DEPDIR)/protoc_ola_protoc_plugin-CppGenerator.Tpo protoc/$(DEPDIR)/protoc_ola_protoc_plugin-CppGenerator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='protoc/CppGenerator.cpp' object='protoc/protoc_ola_protoc_plugin-CppGenerator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protoc_ola_protoc_plugin_CXXFLAGS) $(CXXFLAGS) -c -o protoc/protoc_ola_protoc_plugin-CppGenerator.o `test -f 'protoc/CppGenerator.cpp' || echo '$(srcdir)/'`protoc/CppGenerator.cpp protoc/protoc_ola_protoc_plugin-CppGenerator.obj: protoc/CppGenerator.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protoc_ola_protoc_plugin_CXXFLAGS) $(CXXFLAGS) -MT protoc/protoc_ola_protoc_plugin-CppGenerator.obj -MD -MP -MF protoc/$(DEPDIR)/protoc_ola_protoc_plugin-CppGenerator.Tpo -c -o protoc/protoc_ola_protoc_plugin-CppGenerator.obj `if test -f 'protoc/CppGenerator.cpp'; then $(CYGPATH_W) 'protoc/CppGenerator.cpp'; else $(CYGPATH_W) '$(srcdir)/protoc/CppGenerator.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) protoc/$(DEPDIR)/protoc_ola_protoc_plugin-CppGenerator.Tpo protoc/$(DEPDIR)/protoc_ola_protoc_plugin-CppGenerator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='protoc/CppGenerator.cpp' object='protoc/protoc_ola_protoc_plugin-CppGenerator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protoc_ola_protoc_plugin_CXXFLAGS) $(CXXFLAGS) -c -o protoc/protoc_ola_protoc_plugin-CppGenerator.obj `if test -f 'protoc/CppGenerator.cpp'; then $(CYGPATH_W) 'protoc/CppGenerator.cpp'; else $(CYGPATH_W) '$(srcdir)/protoc/CppGenerator.cpp'; fi` protoc/protoc_ola_protoc_plugin-GeneratorHelpers.o: protoc/GeneratorHelpers.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protoc_ola_protoc_plugin_CXXFLAGS) $(CXXFLAGS) -MT protoc/protoc_ola_protoc_plugin-GeneratorHelpers.o -MD -MP -MF protoc/$(DEPDIR)/protoc_ola_protoc_plugin-GeneratorHelpers.Tpo -c -o protoc/protoc_ola_protoc_plugin-GeneratorHelpers.o `test -f 'protoc/GeneratorHelpers.cpp' || echo '$(srcdir)/'`protoc/GeneratorHelpers.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) protoc/$(DEPDIR)/protoc_ola_protoc_plugin-GeneratorHelpers.Tpo protoc/$(DEPDIR)/protoc_ola_protoc_plugin-GeneratorHelpers.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='protoc/GeneratorHelpers.cpp' object='protoc/protoc_ola_protoc_plugin-GeneratorHelpers.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protoc_ola_protoc_plugin_CXXFLAGS) $(CXXFLAGS) -c -o protoc/protoc_ola_protoc_plugin-GeneratorHelpers.o `test -f 'protoc/GeneratorHelpers.cpp' || echo '$(srcdir)/'`protoc/GeneratorHelpers.cpp protoc/protoc_ola_protoc_plugin-GeneratorHelpers.obj: protoc/GeneratorHelpers.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protoc_ola_protoc_plugin_CXXFLAGS) $(CXXFLAGS) -MT protoc/protoc_ola_protoc_plugin-GeneratorHelpers.obj -MD -MP -MF protoc/$(DEPDIR)/protoc_ola_protoc_plugin-GeneratorHelpers.Tpo -c -o protoc/protoc_ola_protoc_plugin-GeneratorHelpers.obj `if test -f 'protoc/GeneratorHelpers.cpp'; then $(CYGPATH_W) 'protoc/GeneratorHelpers.cpp'; else $(CYGPATH_W) '$(srcdir)/protoc/GeneratorHelpers.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) protoc/$(DEPDIR)/protoc_ola_protoc_plugin-GeneratorHelpers.Tpo protoc/$(DEPDIR)/protoc_ola_protoc_plugin-GeneratorHelpers.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='protoc/GeneratorHelpers.cpp' object='protoc/protoc_ola_protoc_plugin-GeneratorHelpers.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protoc_ola_protoc_plugin_CXXFLAGS) $(CXXFLAGS) -c -o protoc/protoc_ola_protoc_plugin-GeneratorHelpers.obj `if test -f 'protoc/GeneratorHelpers.cpp'; then $(CYGPATH_W) 'protoc/GeneratorHelpers.cpp'; else $(CYGPATH_W) '$(srcdir)/protoc/GeneratorHelpers.cpp'; fi` protoc/protoc_ola_protoc_plugin-ServiceGenerator.o: protoc/ServiceGenerator.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protoc_ola_protoc_plugin_CXXFLAGS) $(CXXFLAGS) -MT protoc/protoc_ola_protoc_plugin-ServiceGenerator.o -MD -MP -MF protoc/$(DEPDIR)/protoc_ola_protoc_plugin-ServiceGenerator.Tpo -c -o protoc/protoc_ola_protoc_plugin-ServiceGenerator.o `test -f 'protoc/ServiceGenerator.cpp' || echo '$(srcdir)/'`protoc/ServiceGenerator.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) protoc/$(DEPDIR)/protoc_ola_protoc_plugin-ServiceGenerator.Tpo protoc/$(DEPDIR)/protoc_ola_protoc_plugin-ServiceGenerator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='protoc/ServiceGenerator.cpp' object='protoc/protoc_ola_protoc_plugin-ServiceGenerator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protoc_ola_protoc_plugin_CXXFLAGS) $(CXXFLAGS) -c -o protoc/protoc_ola_protoc_plugin-ServiceGenerator.o `test -f 'protoc/ServiceGenerator.cpp' || echo '$(srcdir)/'`protoc/ServiceGenerator.cpp protoc/protoc_ola_protoc_plugin-ServiceGenerator.obj: protoc/ServiceGenerator.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protoc_ola_protoc_plugin_CXXFLAGS) $(CXXFLAGS) -MT protoc/protoc_ola_protoc_plugin-ServiceGenerator.obj -MD -MP -MF protoc/$(DEPDIR)/protoc_ola_protoc_plugin-ServiceGenerator.Tpo -c -o protoc/protoc_ola_protoc_plugin-ServiceGenerator.obj `if test -f 'protoc/ServiceGenerator.cpp'; then $(CYGPATH_W) 'protoc/ServiceGenerator.cpp'; else $(CYGPATH_W) '$(srcdir)/protoc/ServiceGenerator.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) protoc/$(DEPDIR)/protoc_ola_protoc_plugin-ServiceGenerator.Tpo protoc/$(DEPDIR)/protoc_ola_protoc_plugin-ServiceGenerator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='protoc/ServiceGenerator.cpp' object='protoc/protoc_ola_protoc_plugin-ServiceGenerator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protoc_ola_protoc_plugin_CXXFLAGS) $(CXXFLAGS) -c -o protoc/protoc_ola_protoc_plugin-ServiceGenerator.obj `if test -f 'protoc/ServiceGenerator.cpp'; then $(CYGPATH_W) 'protoc/ServiceGenerator.cpp'; else $(CYGPATH_W) '$(srcdir)/protoc/ServiceGenerator.cpp'; fi` protoc/protoc_ola_protoc_plugin-StrUtil.o: protoc/StrUtil.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protoc_ola_protoc_plugin_CXXFLAGS) $(CXXFLAGS) -MT protoc/protoc_ola_protoc_plugin-StrUtil.o -MD -MP -MF protoc/$(DEPDIR)/protoc_ola_protoc_plugin-StrUtil.Tpo -c -o protoc/protoc_ola_protoc_plugin-StrUtil.o `test -f 'protoc/StrUtil.cpp' || echo '$(srcdir)/'`protoc/StrUtil.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) protoc/$(DEPDIR)/protoc_ola_protoc_plugin-StrUtil.Tpo protoc/$(DEPDIR)/protoc_ola_protoc_plugin-StrUtil.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='protoc/StrUtil.cpp' object='protoc/protoc_ola_protoc_plugin-StrUtil.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protoc_ola_protoc_plugin_CXXFLAGS) $(CXXFLAGS) -c -o protoc/protoc_ola_protoc_plugin-StrUtil.o `test -f 'protoc/StrUtil.cpp' || echo '$(srcdir)/'`protoc/StrUtil.cpp protoc/protoc_ola_protoc_plugin-StrUtil.obj: protoc/StrUtil.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protoc_ola_protoc_plugin_CXXFLAGS) $(CXXFLAGS) -MT protoc/protoc_ola_protoc_plugin-StrUtil.obj -MD -MP -MF protoc/$(DEPDIR)/protoc_ola_protoc_plugin-StrUtil.Tpo -c -o protoc/protoc_ola_protoc_plugin-StrUtil.obj `if test -f 'protoc/StrUtil.cpp'; then $(CYGPATH_W) 'protoc/StrUtil.cpp'; else $(CYGPATH_W) '$(srcdir)/protoc/StrUtil.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) protoc/$(DEPDIR)/protoc_ola_protoc_plugin-StrUtil.Tpo protoc/$(DEPDIR)/protoc_ola_protoc_plugin-StrUtil.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='protoc/StrUtil.cpp' object='protoc/protoc_ola_protoc_plugin-StrUtil.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protoc_ola_protoc_plugin_CXXFLAGS) $(CXXFLAGS) -c -o protoc/protoc_ola_protoc_plugin-StrUtil.obj `if test -f 'protoc/StrUtil.cpp'; then $(CYGPATH_W) 'protoc/StrUtil.cpp'; else $(CYGPATH_W) '$(srcdir)/protoc/StrUtil.cpp'; fi` protoc/protoc_ola_protoc_plugin-ola-protoc-generator-plugin.o: protoc/ola-protoc-generator-plugin.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protoc_ola_protoc_plugin_CXXFLAGS) $(CXXFLAGS) -MT protoc/protoc_ola_protoc_plugin-ola-protoc-generator-plugin.o -MD -MP -MF protoc/$(DEPDIR)/protoc_ola_protoc_plugin-ola-protoc-generator-plugin.Tpo -c -o protoc/protoc_ola_protoc_plugin-ola-protoc-generator-plugin.o `test -f 'protoc/ola-protoc-generator-plugin.cpp' || echo '$(srcdir)/'`protoc/ola-protoc-generator-plugin.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) protoc/$(DEPDIR)/protoc_ola_protoc_plugin-ola-protoc-generator-plugin.Tpo protoc/$(DEPDIR)/protoc_ola_protoc_plugin-ola-protoc-generator-plugin.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='protoc/ola-protoc-generator-plugin.cpp' object='protoc/protoc_ola_protoc_plugin-ola-protoc-generator-plugin.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protoc_ola_protoc_plugin_CXXFLAGS) $(CXXFLAGS) -c -o protoc/protoc_ola_protoc_plugin-ola-protoc-generator-plugin.o `test -f 'protoc/ola-protoc-generator-plugin.cpp' || echo '$(srcdir)/'`protoc/ola-protoc-generator-plugin.cpp protoc/protoc_ola_protoc_plugin-ola-protoc-generator-plugin.obj: protoc/ola-protoc-generator-plugin.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protoc_ola_protoc_plugin_CXXFLAGS) $(CXXFLAGS) -MT protoc/protoc_ola_protoc_plugin-ola-protoc-generator-plugin.obj -MD -MP -MF protoc/$(DEPDIR)/protoc_ola_protoc_plugin-ola-protoc-generator-plugin.Tpo -c -o protoc/protoc_ola_protoc_plugin-ola-protoc-generator-plugin.obj `if test -f 'protoc/ola-protoc-generator-plugin.cpp'; then $(CYGPATH_W) 'protoc/ola-protoc-generator-plugin.cpp'; else $(CYGPATH_W) '$(srcdir)/protoc/ola-protoc-generator-plugin.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) protoc/$(DEPDIR)/protoc_ola_protoc_plugin-ola-protoc-generator-plugin.Tpo protoc/$(DEPDIR)/protoc_ola_protoc_plugin-ola-protoc-generator-plugin.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='protoc/ola-protoc-generator-plugin.cpp' object='protoc/protoc_ola_protoc_plugin-ola-protoc-generator-plugin.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(protoc_ola_protoc_plugin_CXXFLAGS) $(CXXFLAGS) -c -o protoc/protoc_ola_protoc_plugin-ola-protoc-generator-plugin.obj `if test -f 'protoc/ola-protoc-generator-plugin.cpp'; then $(CYGPATH_W) 'protoc/ola-protoc-generator-plugin.cpp'; else $(CYGPATH_W) '$(srcdir)/protoc/ola-protoc-generator-plugin.cpp'; fi` tools/ja-rule/tools_ja_rule_ja_rule-USBDeviceManager.o: tools/ja-rule/USBDeviceManager.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ja_rule_ja_rule_CXXFLAGS) $(CXXFLAGS) -MT tools/ja-rule/tools_ja_rule_ja_rule-USBDeviceManager.o -MD -MP -MF tools/ja-rule/$(DEPDIR)/tools_ja_rule_ja_rule-USBDeviceManager.Tpo -c -o tools/ja-rule/tools_ja_rule_ja_rule-USBDeviceManager.o `test -f 'tools/ja-rule/USBDeviceManager.cpp' || echo '$(srcdir)/'`tools/ja-rule/USBDeviceManager.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) tools/ja-rule/$(DEPDIR)/tools_ja_rule_ja_rule-USBDeviceManager.Tpo tools/ja-rule/$(DEPDIR)/tools_ja_rule_ja_rule-USBDeviceManager.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tools/ja-rule/USBDeviceManager.cpp' object='tools/ja-rule/tools_ja_rule_ja_rule-USBDeviceManager.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ja_rule_ja_rule_CXXFLAGS) $(CXXFLAGS) -c -o tools/ja-rule/tools_ja_rule_ja_rule-USBDeviceManager.o `test -f 'tools/ja-rule/USBDeviceManager.cpp' || echo '$(srcdir)/'`tools/ja-rule/USBDeviceManager.cpp tools/ja-rule/tools_ja_rule_ja_rule-USBDeviceManager.obj: tools/ja-rule/USBDeviceManager.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ja_rule_ja_rule_CXXFLAGS) $(CXXFLAGS) -MT tools/ja-rule/tools_ja_rule_ja_rule-USBDeviceManager.obj -MD -MP -MF tools/ja-rule/$(DEPDIR)/tools_ja_rule_ja_rule-USBDeviceManager.Tpo -c -o tools/ja-rule/tools_ja_rule_ja_rule-USBDeviceManager.obj `if test -f 'tools/ja-rule/USBDeviceManager.cpp'; then $(CYGPATH_W) 'tools/ja-rule/USBDeviceManager.cpp'; else $(CYGPATH_W) '$(srcdir)/tools/ja-rule/USBDeviceManager.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) tools/ja-rule/$(DEPDIR)/tools_ja_rule_ja_rule-USBDeviceManager.Tpo tools/ja-rule/$(DEPDIR)/tools_ja_rule_ja_rule-USBDeviceManager.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tools/ja-rule/USBDeviceManager.cpp' object='tools/ja-rule/tools_ja_rule_ja_rule-USBDeviceManager.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ja_rule_ja_rule_CXXFLAGS) $(CXXFLAGS) -c -o tools/ja-rule/tools_ja_rule_ja_rule-USBDeviceManager.obj `if test -f 'tools/ja-rule/USBDeviceManager.cpp'; then $(CYGPATH_W) 'tools/ja-rule/USBDeviceManager.cpp'; else $(CYGPATH_W) '$(srcdir)/tools/ja-rule/USBDeviceManager.cpp'; fi` tools/ja-rule/tools_ja_rule_ja_rule-ja-rule.o: tools/ja-rule/ja-rule.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ja_rule_ja_rule_CXXFLAGS) $(CXXFLAGS) -MT tools/ja-rule/tools_ja_rule_ja_rule-ja-rule.o -MD -MP -MF tools/ja-rule/$(DEPDIR)/tools_ja_rule_ja_rule-ja-rule.Tpo -c -o tools/ja-rule/tools_ja_rule_ja_rule-ja-rule.o `test -f 'tools/ja-rule/ja-rule.cpp' || echo '$(srcdir)/'`tools/ja-rule/ja-rule.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) tools/ja-rule/$(DEPDIR)/tools_ja_rule_ja_rule-ja-rule.Tpo tools/ja-rule/$(DEPDIR)/tools_ja_rule_ja_rule-ja-rule.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tools/ja-rule/ja-rule.cpp' object='tools/ja-rule/tools_ja_rule_ja_rule-ja-rule.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ja_rule_ja_rule_CXXFLAGS) $(CXXFLAGS) -c -o tools/ja-rule/tools_ja_rule_ja_rule-ja-rule.o `test -f 'tools/ja-rule/ja-rule.cpp' || echo '$(srcdir)/'`tools/ja-rule/ja-rule.cpp tools/ja-rule/tools_ja_rule_ja_rule-ja-rule.obj: tools/ja-rule/ja-rule.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ja_rule_ja_rule_CXXFLAGS) $(CXXFLAGS) -MT tools/ja-rule/tools_ja_rule_ja_rule-ja-rule.obj -MD -MP -MF tools/ja-rule/$(DEPDIR)/tools_ja_rule_ja_rule-ja-rule.Tpo -c -o tools/ja-rule/tools_ja_rule_ja_rule-ja-rule.obj `if test -f 'tools/ja-rule/ja-rule.cpp'; then $(CYGPATH_W) 'tools/ja-rule/ja-rule.cpp'; else $(CYGPATH_W) '$(srcdir)/tools/ja-rule/ja-rule.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) tools/ja-rule/$(DEPDIR)/tools_ja_rule_ja_rule-ja-rule.Tpo tools/ja-rule/$(DEPDIR)/tools_ja_rule_ja_rule-ja-rule.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tools/ja-rule/ja-rule.cpp' object='tools/ja-rule/tools_ja_rule_ja_rule-ja-rule.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ja_rule_ja_rule_CXXFLAGS) $(CXXFLAGS) -c -o tools/ja-rule/tools_ja_rule_ja_rule-ja-rule.obj `if test -f 'tools/ja-rule/ja-rule.cpp'; then $(CYGPATH_W) 'tools/ja-rule/ja-rule.cpp'; else $(CYGPATH_W) '$(srcdir)/tools/ja-rule/ja-rule.cpp'; fi` tools/ja-rule/tools_ja_rule_ja_rule_controller-USBDeviceManager.o: tools/ja-rule/USBDeviceManager.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ja_rule_ja_rule_controller_CXXFLAGS) $(CXXFLAGS) -MT tools/ja-rule/tools_ja_rule_ja_rule_controller-USBDeviceManager.o -MD -MP -MF tools/ja-rule/$(DEPDIR)/tools_ja_rule_ja_rule_controller-USBDeviceManager.Tpo -c -o tools/ja-rule/tools_ja_rule_ja_rule_controller-USBDeviceManager.o `test -f 'tools/ja-rule/USBDeviceManager.cpp' || echo '$(srcdir)/'`tools/ja-rule/USBDeviceManager.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) tools/ja-rule/$(DEPDIR)/tools_ja_rule_ja_rule_controller-USBDeviceManager.Tpo tools/ja-rule/$(DEPDIR)/tools_ja_rule_ja_rule_controller-USBDeviceManager.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tools/ja-rule/USBDeviceManager.cpp' object='tools/ja-rule/tools_ja_rule_ja_rule_controller-USBDeviceManager.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ja_rule_ja_rule_controller_CXXFLAGS) $(CXXFLAGS) -c -o tools/ja-rule/tools_ja_rule_ja_rule_controller-USBDeviceManager.o `test -f 'tools/ja-rule/USBDeviceManager.cpp' || echo '$(srcdir)/'`tools/ja-rule/USBDeviceManager.cpp tools/ja-rule/tools_ja_rule_ja_rule_controller-USBDeviceManager.obj: tools/ja-rule/USBDeviceManager.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ja_rule_ja_rule_controller_CXXFLAGS) $(CXXFLAGS) -MT tools/ja-rule/tools_ja_rule_ja_rule_controller-USBDeviceManager.obj -MD -MP -MF tools/ja-rule/$(DEPDIR)/tools_ja_rule_ja_rule_controller-USBDeviceManager.Tpo -c -o tools/ja-rule/tools_ja_rule_ja_rule_controller-USBDeviceManager.obj `if test -f 'tools/ja-rule/USBDeviceManager.cpp'; then $(CYGPATH_W) 'tools/ja-rule/USBDeviceManager.cpp'; else $(CYGPATH_W) '$(srcdir)/tools/ja-rule/USBDeviceManager.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) tools/ja-rule/$(DEPDIR)/tools_ja_rule_ja_rule_controller-USBDeviceManager.Tpo tools/ja-rule/$(DEPDIR)/tools_ja_rule_ja_rule_controller-USBDeviceManager.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tools/ja-rule/USBDeviceManager.cpp' object='tools/ja-rule/tools_ja_rule_ja_rule_controller-USBDeviceManager.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ja_rule_ja_rule_controller_CXXFLAGS) $(CXXFLAGS) -c -o tools/ja-rule/tools_ja_rule_ja_rule_controller-USBDeviceManager.obj `if test -f 'tools/ja-rule/USBDeviceManager.cpp'; then $(CYGPATH_W) 'tools/ja-rule/USBDeviceManager.cpp'; else $(CYGPATH_W) '$(srcdir)/tools/ja-rule/USBDeviceManager.cpp'; fi` tools/ja-rule/tools_ja_rule_ja_rule_controller-ja-rule-controller.o: tools/ja-rule/ja-rule-controller.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ja_rule_ja_rule_controller_CXXFLAGS) $(CXXFLAGS) -MT tools/ja-rule/tools_ja_rule_ja_rule_controller-ja-rule-controller.o -MD -MP -MF tools/ja-rule/$(DEPDIR)/tools_ja_rule_ja_rule_controller-ja-rule-controller.Tpo -c -o tools/ja-rule/tools_ja_rule_ja_rule_controller-ja-rule-controller.o `test -f 'tools/ja-rule/ja-rule-controller.cpp' || echo '$(srcdir)/'`tools/ja-rule/ja-rule-controller.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) tools/ja-rule/$(DEPDIR)/tools_ja_rule_ja_rule_controller-ja-rule-controller.Tpo tools/ja-rule/$(DEPDIR)/tools_ja_rule_ja_rule_controller-ja-rule-controller.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tools/ja-rule/ja-rule-controller.cpp' object='tools/ja-rule/tools_ja_rule_ja_rule_controller-ja-rule-controller.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ja_rule_ja_rule_controller_CXXFLAGS) $(CXXFLAGS) -c -o tools/ja-rule/tools_ja_rule_ja_rule_controller-ja-rule-controller.o `test -f 'tools/ja-rule/ja-rule-controller.cpp' || echo '$(srcdir)/'`tools/ja-rule/ja-rule-controller.cpp tools/ja-rule/tools_ja_rule_ja_rule_controller-ja-rule-controller.obj: tools/ja-rule/ja-rule-controller.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ja_rule_ja_rule_controller_CXXFLAGS) $(CXXFLAGS) -MT tools/ja-rule/tools_ja_rule_ja_rule_controller-ja-rule-controller.obj -MD -MP -MF tools/ja-rule/$(DEPDIR)/tools_ja_rule_ja_rule_controller-ja-rule-controller.Tpo -c -o tools/ja-rule/tools_ja_rule_ja_rule_controller-ja-rule-controller.obj `if test -f 'tools/ja-rule/ja-rule-controller.cpp'; then $(CYGPATH_W) 'tools/ja-rule/ja-rule-controller.cpp'; else $(CYGPATH_W) '$(srcdir)/tools/ja-rule/ja-rule-controller.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) tools/ja-rule/$(DEPDIR)/tools_ja_rule_ja_rule_controller-ja-rule-controller.Tpo tools/ja-rule/$(DEPDIR)/tools_ja_rule_ja_rule_controller-ja-rule-controller.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tools/ja-rule/ja-rule-controller.cpp' object='tools/ja-rule/tools_ja_rule_ja_rule_controller-ja-rule-controller.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ja_rule_ja_rule_controller_CXXFLAGS) $(CXXFLAGS) -c -o tools/ja-rule/tools_ja_rule_ja_rule_controller-ja-rule-controller.obj `if test -f 'tools/ja-rule/ja-rule-controller.cpp'; then $(CYGPATH_W) 'tools/ja-rule/ja-rule-controller.cpp'; else $(CYGPATH_W) '$(srcdir)/tools/ja-rule/ja-rule-controller.cpp'; fi` tools/ola_trigger/tools_ola_trigger_ActionTester-ActionTest.o: tools/ola_trigger/ActionTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ActionTester_CXXFLAGS) $(CXXFLAGS) -MT tools/ola_trigger/tools_ola_trigger_ActionTester-ActionTest.o -MD -MP -MF tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-ActionTest.Tpo -c -o tools/ola_trigger/tools_ola_trigger_ActionTester-ActionTest.o `test -f 'tools/ola_trigger/ActionTest.cpp' || echo '$(srcdir)/'`tools/ola_trigger/ActionTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-ActionTest.Tpo tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-ActionTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tools/ola_trigger/ActionTest.cpp' object='tools/ola_trigger/tools_ola_trigger_ActionTester-ActionTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ActionTester_CXXFLAGS) $(CXXFLAGS) -c -o tools/ola_trigger/tools_ola_trigger_ActionTester-ActionTest.o `test -f 'tools/ola_trigger/ActionTest.cpp' || echo '$(srcdir)/'`tools/ola_trigger/ActionTest.cpp tools/ola_trigger/tools_ola_trigger_ActionTester-ActionTest.obj: tools/ola_trigger/ActionTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ActionTester_CXXFLAGS) $(CXXFLAGS) -MT tools/ola_trigger/tools_ola_trigger_ActionTester-ActionTest.obj -MD -MP -MF tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-ActionTest.Tpo -c -o tools/ola_trigger/tools_ola_trigger_ActionTester-ActionTest.obj `if test -f 'tools/ola_trigger/ActionTest.cpp'; then $(CYGPATH_W) 'tools/ola_trigger/ActionTest.cpp'; else $(CYGPATH_W) '$(srcdir)/tools/ola_trigger/ActionTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-ActionTest.Tpo tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-ActionTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tools/ola_trigger/ActionTest.cpp' object='tools/ola_trigger/tools_ola_trigger_ActionTester-ActionTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ActionTester_CXXFLAGS) $(CXXFLAGS) -c -o tools/ola_trigger/tools_ola_trigger_ActionTester-ActionTest.obj `if test -f 'tools/ola_trigger/ActionTest.cpp'; then $(CYGPATH_W) 'tools/ola_trigger/ActionTest.cpp'; else $(CYGPATH_W) '$(srcdir)/tools/ola_trigger/ActionTest.cpp'; fi` tools/ola_trigger/tools_ola_trigger_ActionTester-ContextTest.o: tools/ola_trigger/ContextTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ActionTester_CXXFLAGS) $(CXXFLAGS) -MT tools/ola_trigger/tools_ola_trigger_ActionTester-ContextTest.o -MD -MP -MF tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-ContextTest.Tpo -c -o tools/ola_trigger/tools_ola_trigger_ActionTester-ContextTest.o `test -f 'tools/ola_trigger/ContextTest.cpp' || echo '$(srcdir)/'`tools/ola_trigger/ContextTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-ContextTest.Tpo tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-ContextTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tools/ola_trigger/ContextTest.cpp' object='tools/ola_trigger/tools_ola_trigger_ActionTester-ContextTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ActionTester_CXXFLAGS) $(CXXFLAGS) -c -o tools/ola_trigger/tools_ola_trigger_ActionTester-ContextTest.o `test -f 'tools/ola_trigger/ContextTest.cpp' || echo '$(srcdir)/'`tools/ola_trigger/ContextTest.cpp tools/ola_trigger/tools_ola_trigger_ActionTester-ContextTest.obj: tools/ola_trigger/ContextTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ActionTester_CXXFLAGS) $(CXXFLAGS) -MT tools/ola_trigger/tools_ola_trigger_ActionTester-ContextTest.obj -MD -MP -MF tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-ContextTest.Tpo -c -o tools/ola_trigger/tools_ola_trigger_ActionTester-ContextTest.obj `if test -f 'tools/ola_trigger/ContextTest.cpp'; then $(CYGPATH_W) 'tools/ola_trigger/ContextTest.cpp'; else $(CYGPATH_W) '$(srcdir)/tools/ola_trigger/ContextTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-ContextTest.Tpo tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-ContextTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tools/ola_trigger/ContextTest.cpp' object='tools/ola_trigger/tools_ola_trigger_ActionTester-ContextTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ActionTester_CXXFLAGS) $(CXXFLAGS) -c -o tools/ola_trigger/tools_ola_trigger_ActionTester-ContextTest.obj `if test -f 'tools/ola_trigger/ContextTest.cpp'; then $(CYGPATH_W) 'tools/ola_trigger/ContextTest.cpp'; else $(CYGPATH_W) '$(srcdir)/tools/ola_trigger/ContextTest.cpp'; fi` tools/ola_trigger/tools_ola_trigger_ActionTester-DMXTriggerTest.o: tools/ola_trigger/DMXTriggerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ActionTester_CXXFLAGS) $(CXXFLAGS) -MT tools/ola_trigger/tools_ola_trigger_ActionTester-DMXTriggerTest.o -MD -MP -MF tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-DMXTriggerTest.Tpo -c -o tools/ola_trigger/tools_ola_trigger_ActionTester-DMXTriggerTest.o `test -f 'tools/ola_trigger/DMXTriggerTest.cpp' || echo '$(srcdir)/'`tools/ola_trigger/DMXTriggerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-DMXTriggerTest.Tpo tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-DMXTriggerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tools/ola_trigger/DMXTriggerTest.cpp' object='tools/ola_trigger/tools_ola_trigger_ActionTester-DMXTriggerTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ActionTester_CXXFLAGS) $(CXXFLAGS) -c -o tools/ola_trigger/tools_ola_trigger_ActionTester-DMXTriggerTest.o `test -f 'tools/ola_trigger/DMXTriggerTest.cpp' || echo '$(srcdir)/'`tools/ola_trigger/DMXTriggerTest.cpp tools/ola_trigger/tools_ola_trigger_ActionTester-DMXTriggerTest.obj: tools/ola_trigger/DMXTriggerTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ActionTester_CXXFLAGS) $(CXXFLAGS) -MT tools/ola_trigger/tools_ola_trigger_ActionTester-DMXTriggerTest.obj -MD -MP -MF tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-DMXTriggerTest.Tpo -c -o tools/ola_trigger/tools_ola_trigger_ActionTester-DMXTriggerTest.obj `if test -f 'tools/ola_trigger/DMXTriggerTest.cpp'; then $(CYGPATH_W) 'tools/ola_trigger/DMXTriggerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/tools/ola_trigger/DMXTriggerTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-DMXTriggerTest.Tpo tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-DMXTriggerTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tools/ola_trigger/DMXTriggerTest.cpp' object='tools/ola_trigger/tools_ola_trigger_ActionTester-DMXTriggerTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ActionTester_CXXFLAGS) $(CXXFLAGS) -c -o tools/ola_trigger/tools_ola_trigger_ActionTester-DMXTriggerTest.obj `if test -f 'tools/ola_trigger/DMXTriggerTest.cpp'; then $(CYGPATH_W) 'tools/ola_trigger/DMXTriggerTest.cpp'; else $(CYGPATH_W) '$(srcdir)/tools/ola_trigger/DMXTriggerTest.cpp'; fi` tools/ola_trigger/tools_ola_trigger_ActionTester-IntervalTest.o: tools/ola_trigger/IntervalTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ActionTester_CXXFLAGS) $(CXXFLAGS) -MT tools/ola_trigger/tools_ola_trigger_ActionTester-IntervalTest.o -MD -MP -MF tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-IntervalTest.Tpo -c -o tools/ola_trigger/tools_ola_trigger_ActionTester-IntervalTest.o `test -f 'tools/ola_trigger/IntervalTest.cpp' || echo '$(srcdir)/'`tools/ola_trigger/IntervalTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-IntervalTest.Tpo tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-IntervalTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tools/ola_trigger/IntervalTest.cpp' object='tools/ola_trigger/tools_ola_trigger_ActionTester-IntervalTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ActionTester_CXXFLAGS) $(CXXFLAGS) -c -o tools/ola_trigger/tools_ola_trigger_ActionTester-IntervalTest.o `test -f 'tools/ola_trigger/IntervalTest.cpp' || echo '$(srcdir)/'`tools/ola_trigger/IntervalTest.cpp tools/ola_trigger/tools_ola_trigger_ActionTester-IntervalTest.obj: tools/ola_trigger/IntervalTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ActionTester_CXXFLAGS) $(CXXFLAGS) -MT tools/ola_trigger/tools_ola_trigger_ActionTester-IntervalTest.obj -MD -MP -MF tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-IntervalTest.Tpo -c -o tools/ola_trigger/tools_ola_trigger_ActionTester-IntervalTest.obj `if test -f 'tools/ola_trigger/IntervalTest.cpp'; then $(CYGPATH_W) 'tools/ola_trigger/IntervalTest.cpp'; else $(CYGPATH_W) '$(srcdir)/tools/ola_trigger/IntervalTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-IntervalTest.Tpo tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-IntervalTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tools/ola_trigger/IntervalTest.cpp' object='tools/ola_trigger/tools_ola_trigger_ActionTester-IntervalTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ActionTester_CXXFLAGS) $(CXXFLAGS) -c -o tools/ola_trigger/tools_ola_trigger_ActionTester-IntervalTest.obj `if test -f 'tools/ola_trigger/IntervalTest.cpp'; then $(CYGPATH_W) 'tools/ola_trigger/IntervalTest.cpp'; else $(CYGPATH_W) '$(srcdir)/tools/ola_trigger/IntervalTest.cpp'; fi` tools/ola_trigger/tools_ola_trigger_ActionTester-SlotTest.o: tools/ola_trigger/SlotTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ActionTester_CXXFLAGS) $(CXXFLAGS) -MT tools/ola_trigger/tools_ola_trigger_ActionTester-SlotTest.o -MD -MP -MF tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-SlotTest.Tpo -c -o tools/ola_trigger/tools_ola_trigger_ActionTester-SlotTest.o `test -f 'tools/ola_trigger/SlotTest.cpp' || echo '$(srcdir)/'`tools/ola_trigger/SlotTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-SlotTest.Tpo tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-SlotTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tools/ola_trigger/SlotTest.cpp' object='tools/ola_trigger/tools_ola_trigger_ActionTester-SlotTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ActionTester_CXXFLAGS) $(CXXFLAGS) -c -o tools/ola_trigger/tools_ola_trigger_ActionTester-SlotTest.o `test -f 'tools/ola_trigger/SlotTest.cpp' || echo '$(srcdir)/'`tools/ola_trigger/SlotTest.cpp tools/ola_trigger/tools_ola_trigger_ActionTester-SlotTest.obj: tools/ola_trigger/SlotTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ActionTester_CXXFLAGS) $(CXXFLAGS) -MT tools/ola_trigger/tools_ola_trigger_ActionTester-SlotTest.obj -MD -MP -MF tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-SlotTest.Tpo -c -o tools/ola_trigger/tools_ola_trigger_ActionTester-SlotTest.obj `if test -f 'tools/ola_trigger/SlotTest.cpp'; then $(CYGPATH_W) 'tools/ola_trigger/SlotTest.cpp'; else $(CYGPATH_W) '$(srcdir)/tools/ola_trigger/SlotTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-SlotTest.Tpo tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-SlotTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tools/ola_trigger/SlotTest.cpp' object='tools/ola_trigger/tools_ola_trigger_ActionTester-SlotTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ActionTester_CXXFLAGS) $(CXXFLAGS) -c -o tools/ola_trigger/tools_ola_trigger_ActionTester-SlotTest.obj `if test -f 'tools/ola_trigger/SlotTest.cpp'; then $(CYGPATH_W) 'tools/ola_trigger/SlotTest.cpp'; else $(CYGPATH_W) '$(srcdir)/tools/ola_trigger/SlotTest.cpp'; fi` tools/ola_trigger/tools_ola_trigger_ActionTester-VariableInterpolatorTest.o: tools/ola_trigger/VariableInterpolatorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ActionTester_CXXFLAGS) $(CXXFLAGS) -MT tools/ola_trigger/tools_ola_trigger_ActionTester-VariableInterpolatorTest.o -MD -MP -MF tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-VariableInterpolatorTest.Tpo -c -o tools/ola_trigger/tools_ola_trigger_ActionTester-VariableInterpolatorTest.o `test -f 'tools/ola_trigger/VariableInterpolatorTest.cpp' || echo '$(srcdir)/'`tools/ola_trigger/VariableInterpolatorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-VariableInterpolatorTest.Tpo tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-VariableInterpolatorTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tools/ola_trigger/VariableInterpolatorTest.cpp' object='tools/ola_trigger/tools_ola_trigger_ActionTester-VariableInterpolatorTest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ActionTester_CXXFLAGS) $(CXXFLAGS) -c -o tools/ola_trigger/tools_ola_trigger_ActionTester-VariableInterpolatorTest.o `test -f 'tools/ola_trigger/VariableInterpolatorTest.cpp' || echo '$(srcdir)/'`tools/ola_trigger/VariableInterpolatorTest.cpp tools/ola_trigger/tools_ola_trigger_ActionTester-VariableInterpolatorTest.obj: tools/ola_trigger/VariableInterpolatorTest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ActionTester_CXXFLAGS) $(CXXFLAGS) -MT tools/ola_trigger/tools_ola_trigger_ActionTester-VariableInterpolatorTest.obj -MD -MP -MF tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-VariableInterpolatorTest.Tpo -c -o tools/ola_trigger/tools_ola_trigger_ActionTester-VariableInterpolatorTest.obj `if test -f 'tools/ola_trigger/VariableInterpolatorTest.cpp'; then $(CYGPATH_W) 'tools/ola_trigger/VariableInterpolatorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/tools/ola_trigger/VariableInterpolatorTest.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-VariableInterpolatorTest.Tpo tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ActionTester-VariableInterpolatorTest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tools/ola_trigger/VariableInterpolatorTest.cpp' object='tools/ola_trigger/tools_ola_trigger_ActionTester-VariableInterpolatorTest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ActionTester_CXXFLAGS) $(CXXFLAGS) -c -o tools/ola_trigger/tools_ola_trigger_ActionTester-VariableInterpolatorTest.obj `if test -f 'tools/ola_trigger/VariableInterpolatorTest.cpp'; then $(CYGPATH_W) 'tools/ola_trigger/VariableInterpolatorTest.cpp'; else $(CYGPATH_W) '$(srcdir)/tools/ola_trigger/VariableInterpolatorTest.cpp'; fi` tools/ola_trigger/tools_ola_trigger_ola_trigger-ParserActions.o: tools/ola_trigger/ParserActions.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ola_trigger_CXXFLAGS) $(CXXFLAGS) -MT tools/ola_trigger/tools_ola_trigger_ola_trigger-ParserActions.o -MD -MP -MF tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ola_trigger-ParserActions.Tpo -c -o tools/ola_trigger/tools_ola_trigger_ola_trigger-ParserActions.o `test -f 'tools/ola_trigger/ParserActions.cpp' || echo '$(srcdir)/'`tools/ola_trigger/ParserActions.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ola_trigger-ParserActions.Tpo tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ola_trigger-ParserActions.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tools/ola_trigger/ParserActions.cpp' object='tools/ola_trigger/tools_ola_trigger_ola_trigger-ParserActions.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ola_trigger_CXXFLAGS) $(CXXFLAGS) -c -o tools/ola_trigger/tools_ola_trigger_ola_trigger-ParserActions.o `test -f 'tools/ola_trigger/ParserActions.cpp' || echo '$(srcdir)/'`tools/ola_trigger/ParserActions.cpp tools/ola_trigger/tools_ola_trigger_ola_trigger-ParserActions.obj: tools/ola_trigger/ParserActions.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ola_trigger_CXXFLAGS) $(CXXFLAGS) -MT tools/ola_trigger/tools_ola_trigger_ola_trigger-ParserActions.obj -MD -MP -MF tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ola_trigger-ParserActions.Tpo -c -o tools/ola_trigger/tools_ola_trigger_ola_trigger-ParserActions.obj `if test -f 'tools/ola_trigger/ParserActions.cpp'; then $(CYGPATH_W) 'tools/ola_trigger/ParserActions.cpp'; else $(CYGPATH_W) '$(srcdir)/tools/ola_trigger/ParserActions.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ola_trigger-ParserActions.Tpo tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ola_trigger-ParserActions.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tools/ola_trigger/ParserActions.cpp' object='tools/ola_trigger/tools_ola_trigger_ola_trigger-ParserActions.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ola_trigger_CXXFLAGS) $(CXXFLAGS) -c -o tools/ola_trigger/tools_ola_trigger_ola_trigger-ParserActions.obj `if test -f 'tools/ola_trigger/ParserActions.cpp'; then $(CYGPATH_W) 'tools/ola_trigger/ParserActions.cpp'; else $(CYGPATH_W) '$(srcdir)/tools/ola_trigger/ParserActions.cpp'; fi` tools/ola_trigger/tools_ola_trigger_ola_trigger-ola-trigger.o: tools/ola_trigger/ola-trigger.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ola_trigger_CXXFLAGS) $(CXXFLAGS) -MT tools/ola_trigger/tools_ola_trigger_ola_trigger-ola-trigger.o -MD -MP -MF tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ola_trigger-ola-trigger.Tpo -c -o tools/ola_trigger/tools_ola_trigger_ola_trigger-ola-trigger.o `test -f 'tools/ola_trigger/ola-trigger.cpp' || echo '$(srcdir)/'`tools/ola_trigger/ola-trigger.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ola_trigger-ola-trigger.Tpo tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ola_trigger-ola-trigger.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tools/ola_trigger/ola-trigger.cpp' object='tools/ola_trigger/tools_ola_trigger_ola_trigger-ola-trigger.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ola_trigger_CXXFLAGS) $(CXXFLAGS) -c -o tools/ola_trigger/tools_ola_trigger_ola_trigger-ola-trigger.o `test -f 'tools/ola_trigger/ola-trigger.cpp' || echo '$(srcdir)/'`tools/ola_trigger/ola-trigger.cpp tools/ola_trigger/tools_ola_trigger_ola_trigger-ola-trigger.obj: tools/ola_trigger/ola-trigger.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ola_trigger_CXXFLAGS) $(CXXFLAGS) -MT tools/ola_trigger/tools_ola_trigger_ola_trigger-ola-trigger.obj -MD -MP -MF tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ola_trigger-ola-trigger.Tpo -c -o tools/ola_trigger/tools_ola_trigger_ola_trigger-ola-trigger.obj `if test -f 'tools/ola_trigger/ola-trigger.cpp'; then $(CYGPATH_W) 'tools/ola_trigger/ola-trigger.cpp'; else $(CYGPATH_W) '$(srcdir)/tools/ola_trigger/ola-trigger.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ola_trigger-ola-trigger.Tpo tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ola_trigger-ola-trigger.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tools/ola_trigger/ola-trigger.cpp' object='tools/ola_trigger/tools_ola_trigger_ola_trigger-ola-trigger.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ola_trigger_CXXFLAGS) $(CXXFLAGS) -c -o tools/ola_trigger/tools_ola_trigger_ola_trigger-ola-trigger.obj `if test -f 'tools/ola_trigger/ola-trigger.cpp'; then $(CYGPATH_W) 'tools/ola_trigger/ola-trigger.cpp'; else $(CYGPATH_W) '$(srcdir)/tools/ola_trigger/ola-trigger.cpp'; fi` tools/ola_trigger/tools_ola_trigger_ola_trigger-config.tab.o: tools/ola_trigger/config.tab.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ola_trigger_CXXFLAGS) $(CXXFLAGS) -MT tools/ola_trigger/tools_ola_trigger_ola_trigger-config.tab.o -MD -MP -MF tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ola_trigger-config.tab.Tpo -c -o tools/ola_trigger/tools_ola_trigger_ola_trigger-config.tab.o `test -f 'tools/ola_trigger/config.tab.cpp' || echo '$(srcdir)/'`tools/ola_trigger/config.tab.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ola_trigger-config.tab.Tpo tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ola_trigger-config.tab.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tools/ola_trigger/config.tab.cpp' object='tools/ola_trigger/tools_ola_trigger_ola_trigger-config.tab.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ola_trigger_CXXFLAGS) $(CXXFLAGS) -c -o tools/ola_trigger/tools_ola_trigger_ola_trigger-config.tab.o `test -f 'tools/ola_trigger/config.tab.cpp' || echo '$(srcdir)/'`tools/ola_trigger/config.tab.cpp tools/ola_trigger/tools_ola_trigger_ola_trigger-config.tab.obj: tools/ola_trigger/config.tab.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ola_trigger_CXXFLAGS) $(CXXFLAGS) -MT tools/ola_trigger/tools_ola_trigger_ola_trigger-config.tab.obj -MD -MP -MF tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ola_trigger-config.tab.Tpo -c -o tools/ola_trigger/tools_ola_trigger_ola_trigger-config.tab.obj `if test -f 'tools/ola_trigger/config.tab.cpp'; then $(CYGPATH_W) 'tools/ola_trigger/config.tab.cpp'; else $(CYGPATH_W) '$(srcdir)/tools/ola_trigger/config.tab.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ola_trigger-config.tab.Tpo tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ola_trigger-config.tab.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tools/ola_trigger/config.tab.cpp' object='tools/ola_trigger/tools_ola_trigger_ola_trigger-config.tab.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ola_trigger_CXXFLAGS) $(CXXFLAGS) -c -o tools/ola_trigger/tools_ola_trigger_ola_trigger-config.tab.obj `if test -f 'tools/ola_trigger/config.tab.cpp'; then $(CYGPATH_W) 'tools/ola_trigger/config.tab.cpp'; else $(CYGPATH_W) '$(srcdir)/tools/ola_trigger/config.tab.cpp'; fi` tools/ola_trigger/tools_ola_trigger_ola_trigger-lex.yy.o: tools/ola_trigger/lex.yy.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ola_trigger_CXXFLAGS) $(CXXFLAGS) -MT tools/ola_trigger/tools_ola_trigger_ola_trigger-lex.yy.o -MD -MP -MF tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ola_trigger-lex.yy.Tpo -c -o tools/ola_trigger/tools_ola_trigger_ola_trigger-lex.yy.o `test -f 'tools/ola_trigger/lex.yy.cpp' || echo '$(srcdir)/'`tools/ola_trigger/lex.yy.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ola_trigger-lex.yy.Tpo tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ola_trigger-lex.yy.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tools/ola_trigger/lex.yy.cpp' object='tools/ola_trigger/tools_ola_trigger_ola_trigger-lex.yy.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ola_trigger_CXXFLAGS) $(CXXFLAGS) -c -o tools/ola_trigger/tools_ola_trigger_ola_trigger-lex.yy.o `test -f 'tools/ola_trigger/lex.yy.cpp' || echo '$(srcdir)/'`tools/ola_trigger/lex.yy.cpp tools/ola_trigger/tools_ola_trigger_ola_trigger-lex.yy.obj: tools/ola_trigger/lex.yy.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ola_trigger_CXXFLAGS) $(CXXFLAGS) -MT tools/ola_trigger/tools_ola_trigger_ola_trigger-lex.yy.obj -MD -MP -MF tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ola_trigger-lex.yy.Tpo -c -o tools/ola_trigger/tools_ola_trigger_ola_trigger-lex.yy.obj `if test -f 'tools/ola_trigger/lex.yy.cpp'; then $(CYGPATH_W) 'tools/ola_trigger/lex.yy.cpp'; else $(CYGPATH_W) '$(srcdir)/tools/ola_trigger/lex.yy.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ola_trigger-lex.yy.Tpo tools/ola_trigger/$(DEPDIR)/tools_ola_trigger_ola_trigger-lex.yy.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tools/ola_trigger/lex.yy.cpp' object='tools/ola_trigger/tools_ola_trigger_ola_trigger-lex.yy.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_ola_trigger_ola_trigger_CXXFLAGS) $(CXXFLAGS) -c -o tools/ola_trigger/tools_ola_trigger_ola_trigger-lex.yy.obj `if test -f 'tools/ola_trigger/lex.yy.cpp'; then $(CYGPATH_W) 'tools/ola_trigger/lex.yy.cpp'; else $(CYGPATH_W) '$(srcdir)/tools/ola_trigger/lex.yy.cpp'; fi` .cpp.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs -rm -rf common/.libs common/_libs -rm -rf common/base/.libs common/base/_libs -rm -rf common/dmx/.libs common/dmx/_libs -rm -rf common/export_map/.libs common/export_map/_libs -rm -rf common/file/.libs common/file/_libs -rm -rf common/http/.libs common/http/_libs -rm -rf common/io/.libs common/io/_libs -rm -rf common/math/.libs common/math/_libs -rm -rf common/messaging/.libs common/messaging/_libs -rm -rf common/network/.libs common/network/_libs -rm -rf common/protocol/.libs common/protocol/_libs -rm -rf common/rdm/.libs common/rdm/_libs -rm -rf common/rpc/.libs common/rpc/_libs -rm -rf common/strings/.libs common/strings/_libs -rm -rf common/system/.libs common/system/_libs -rm -rf common/testing/.libs common/testing/_libs -rm -rf common/thread/.libs common/thread/_libs -rm -rf common/timecode/.libs common/timecode/_libs -rm -rf common/utils/.libs common/utils/_libs -rm -rf common/web/.libs common/web/_libs -rm -rf data/rdm/.libs data/rdm/_libs -rm -rf doxygen/examples/.libs doxygen/examples/_libs -rm -rf examples/.libs examples/_libs -rm -rf libs/acn/.libs libs/acn/_libs -rm -rf libs/usb/.libs libs/usb/_libs -rm -rf ola/.libs ola/_libs -rm -rf olad/.libs olad/_libs -rm -rf olad/plugin_api/.libs olad/plugin_api/_libs -rm -rf plugins/artnet/.libs plugins/artnet/_libs -rm -rf plugins/artnet/messages/.libs plugins/artnet/messages/_libs -rm -rf plugins/dmx4linux/.libs plugins/dmx4linux/_libs -rm -rf plugins/dummy/.libs plugins/dummy/_libs -rm -rf plugins/e131/.libs plugins/e131/_libs -rm -rf plugins/e131/messages/.libs plugins/e131/messages/_libs -rm -rf plugins/espnet/.libs plugins/espnet/_libs -rm -rf plugins/ftdidmx/.libs plugins/ftdidmx/_libs -rm -rf plugins/gpio/.libs plugins/gpio/_libs -rm -rf plugins/karate/.libs plugins/karate/_libs -rm -rf plugins/kinet/.libs plugins/kinet/_libs -rm -rf plugins/milinst/.libs plugins/milinst/_libs -rm -rf plugins/opendmx/.libs plugins/opendmx/_libs -rm -rf plugins/openpixelcontrol/.libs plugins/openpixelcontrol/_libs -rm -rf plugins/osc/.libs plugins/osc/_libs -rm -rf plugins/pathport/.libs plugins/pathport/_libs -rm -rf plugins/renard/.libs plugins/renard/_libs -rm -rf plugins/sandnet/.libs plugins/sandnet/_libs -rm -rf plugins/shownet/.libs plugins/shownet/_libs -rm -rf plugins/spi/.libs plugins/spi/_libs -rm -rf plugins/stageprofi/.libs plugins/stageprofi/_libs -rm -rf plugins/uartdmx/.libs plugins/uartdmx/_libs -rm -rf plugins/usbdmx/.libs plugins/usbdmx/_libs -rm -rf plugins/usbpro/.libs plugins/usbpro/_libs -rm -rf plugins/usbpro/messages/.libs plugins/usbpro/messages/_libs -rm -rf protoc/.libs protoc/_libs -rm -rf tools/e133/.libs tools/e133/_libs -rm -rf tools/ja-rule/.libs tools/ja-rule/_libs -rm -rf tools/logic/.libs tools/logic/_libs -rm -rf tools/ola_trigger/.libs tools/ola_trigger/_libs -rm -rf tools/rdmpro/.libs tools/rdmpro/_libs -rm -rf tools/usbpro/.libs tools/usbpro/_libs distclean-libtool: -rm -f libtool config.lt install-nodist_pkgpythonPYTHON: $(nodist_pkgpython_PYTHON) @$(NORMAL_INSTALL) @list='$(nodist_pkgpython_PYTHON)'; dlist=; list2=; test -n "$(pkgpythondir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgpythondir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgpythondir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \ if test -f $$b$$p; then \ $(am__strip_dir) \ dlist="$$dlist $$f"; \ list2="$$list2 $$b$$p"; \ else :; fi; \ done; \ for file in $$list2; do echo $$file; done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgpythondir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgpythondir)" || exit $$?; \ done || exit $$?; \ if test -n "$$dlist"; then \ $(am__py_compile) --destdir "$(DESTDIR)" \ --basedir "$(pkgpythondir)" $$dlist; \ else :; fi uninstall-nodist_pkgpythonPYTHON: @$(NORMAL_UNINSTALL) @list='$(nodist_pkgpython_PYTHON)'; test -n "$(pkgpythondir)" || list=; \ py_files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$py_files" || exit 0; \ dir='$(DESTDIR)$(pkgpythondir)'; \ pyc_files=`echo "$$py_files" | sed 's|$$|c|'`; \ pyo_files=`echo "$$py_files" | sed 's|$$|o|'`; \ py_files_pep3147=`echo "$$py_files" | $(am__pep3147_tweak)`; \ echo "$$py_files_pep3147";\ pyc_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|c|'`; \ pyo_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|o|'`; \ st=0; \ for files in \ "$$py_files" \ "$$pyc_files" \ "$$pyo_files" \ "$$pyc_files_pep3147" \ "$$pyo_files_pep3147" \ ; do \ $(am__uninstall_files_from_dir) || st=$$?; \ done; \ exit $$st install-nodist_rdmtestsPYTHON: $(nodist_rdmtests_PYTHON) @$(NORMAL_INSTALL) @list='$(nodist_rdmtests_PYTHON)'; dlist=; list2=; test -n "$(rdmtestsdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(rdmtestsdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(rdmtestsdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \ if test -f $$b$$p; then \ $(am__strip_dir) \ dlist="$$dlist $$f"; \ list2="$$list2 $$b$$p"; \ else :; fi; \ done; \ for file in $$list2; do echo $$file; done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(rdmtestsdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(rdmtestsdir)" || exit $$?; \ done || exit $$?; \ if test -n "$$dlist"; then \ $(am__py_compile) --destdir "$(DESTDIR)" \ --basedir "$(rdmtestsdir)" $$dlist; \ else :; fi uninstall-nodist_rdmtestsPYTHON: @$(NORMAL_UNINSTALL) @list='$(nodist_rdmtests_PYTHON)'; test -n "$(rdmtestsdir)" || list=; \ py_files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$py_files" || exit 0; \ dir='$(DESTDIR)$(rdmtestsdir)'; \ pyc_files=`echo "$$py_files" | sed 's|$$|c|'`; \ pyo_files=`echo "$$py_files" | sed 's|$$|o|'`; \ py_files_pep3147=`echo "$$py_files" | $(am__pep3147_tweak)`; \ echo "$$py_files_pep3147";\ pyc_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|c|'`; \ pyo_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|o|'`; \ st=0; \ for files in \ "$$py_files" \ "$$pyc_files" \ "$$pyo_files" \ "$$pyc_files_pep3147" \ "$$pyo_files_pep3147" \ ; do \ $(am__uninstall_files_from_dir) || st=$$?; \ done; \ exit $$st install-nodist_rpcpythonPYTHON: $(nodist_rpcpython_PYTHON) @$(NORMAL_INSTALL) @list='$(nodist_rpcpython_PYTHON)'; dlist=; list2=; test -n "$(rpcpythondir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(rpcpythondir)'"; \ $(MKDIR_P) "$(DESTDIR)$(rpcpythondir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \ if test -f $$b$$p; then \ $(am__strip_dir) \ dlist="$$dlist $$f"; \ list2="$$list2 $$b$$p"; \ else :; fi; \ done; \ for file in $$list2; do echo $$file; done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(rpcpythondir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(rpcpythondir)" || exit $$?; \ done || exit $$?; \ if test -n "$$dlist"; then \ $(am__py_compile) --destdir "$(DESTDIR)" \ --basedir "$(rpcpythondir)" $$dlist; \ else :; fi uninstall-nodist_rpcpythonPYTHON: @$(NORMAL_UNINSTALL) @list='$(nodist_rpcpython_PYTHON)'; test -n "$(rpcpythondir)" || list=; \ py_files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$py_files" || exit 0; \ dir='$(DESTDIR)$(rpcpythondir)'; \ pyc_files=`echo "$$py_files" | sed 's|$$|c|'`; \ pyo_files=`echo "$$py_files" | sed 's|$$|o|'`; \ py_files_pep3147=`echo "$$py_files" | $(am__pep3147_tweak)`; \ echo "$$py_files_pep3147";\ pyc_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|c|'`; \ pyo_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|o|'`; \ st=0; \ for files in \ "$$py_files" \ "$$pyc_files" \ "$$pyo_files" \ "$$pyc_files_pep3147" \ "$$pyo_files_pep3147" \ ; do \ $(am__uninstall_files_from_dir) || st=$$?; \ done; \ exit $$st install-pkgpythonPYTHON: $(pkgpython_PYTHON) @$(NORMAL_INSTALL) @list='$(pkgpython_PYTHON)'; dlist=; list2=; test -n "$(pkgpythondir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgpythondir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgpythondir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \ if test -f $$b$$p; then \ $(am__strip_dir) \ dlist="$$dlist $$f"; \ list2="$$list2 $$b$$p"; \ else :; fi; \ done; \ for file in $$list2; do echo $$file; done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgpythondir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgpythondir)" || exit $$?; \ done || exit $$?; \ if test -n "$$dlist"; then \ $(am__py_compile) --destdir "$(DESTDIR)" \ --basedir "$(pkgpythondir)" $$dlist; \ else :; fi uninstall-pkgpythonPYTHON: @$(NORMAL_UNINSTALL) @list='$(pkgpython_PYTHON)'; test -n "$(pkgpythondir)" || list=; \ py_files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$py_files" || exit 0; \ dir='$(DESTDIR)$(pkgpythondir)'; \ pyc_files=`echo "$$py_files" | sed 's|$$|c|'`; \ pyo_files=`echo "$$py_files" | sed 's|$$|o|'`; \ py_files_pep3147=`echo "$$py_files" | $(am__pep3147_tweak)`; \ echo "$$py_files_pep3147";\ pyc_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|c|'`; \ pyo_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|o|'`; \ st=0; \ for files in \ "$$py_files" \ "$$pyc_files" \ "$$pyo_files" \ "$$pyc_files_pep3147" \ "$$pyo_files_pep3147" \ ; do \ $(am__uninstall_files_from_dir) || st=$$?; \ done; \ exit $$st install-rdminitPYTHON: $(rdminit_PYTHON) @$(NORMAL_INSTALL) @list='$(rdminit_PYTHON)'; dlist=; list2=; test -n "$(rdminitdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(rdminitdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(rdminitdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \ if test -f $$b$$p; then \ $(am__strip_dir) \ dlist="$$dlist $$f"; \ list2="$$list2 $$b$$p"; \ else :; fi; \ done; \ for file in $$list2; do echo $$file; done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(rdminitdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(rdminitdir)" || exit $$?; \ done || exit $$?; \ if test -n "$$dlist"; then \ $(am__py_compile) --destdir "$(DESTDIR)" \ --basedir "$(rdminitdir)" $$dlist; \ else :; fi uninstall-rdminitPYTHON: @$(NORMAL_UNINSTALL) @list='$(rdminit_PYTHON)'; test -n "$(rdminitdir)" || list=; \ py_files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$py_files" || exit 0; \ dir='$(DESTDIR)$(rdminitdir)'; \ pyc_files=`echo "$$py_files" | sed 's|$$|c|'`; \ pyo_files=`echo "$$py_files" | sed 's|$$|o|'`; \ py_files_pep3147=`echo "$$py_files" | $(am__pep3147_tweak)`; \ echo "$$py_files_pep3147";\ pyc_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|c|'`; \ pyo_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|o|'`; \ st=0; \ for files in \ "$$py_files" \ "$$pyc_files" \ "$$pyo_files" \ "$$pyc_files_pep3147" \ "$$pyo_files_pep3147" \ ; do \ $(am__uninstall_files_from_dir) || st=$$?; \ done; \ exit $$st install-rdmtestsPYTHON: $(rdmtests_PYTHON) @$(NORMAL_INSTALL) @list='$(rdmtests_PYTHON)'; dlist=; list2=; test -n "$(rdmtestsdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(rdmtestsdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(rdmtestsdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \ if test -f $$b$$p; then \ $(am__strip_dir) \ dlist="$$dlist $$f"; \ list2="$$list2 $$b$$p"; \ else :; fi; \ done; \ for file in $$list2; do echo $$file; done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(rdmtestsdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(rdmtestsdir)" || exit $$?; \ done || exit $$?; \ if test -n "$$dlist"; then \ $(am__py_compile) --destdir "$(DESTDIR)" \ --basedir "$(rdmtestsdir)" $$dlist; \ else :; fi uninstall-rdmtestsPYTHON: @$(NORMAL_UNINSTALL) @list='$(rdmtests_PYTHON)'; test -n "$(rdmtestsdir)" || list=; \ py_files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$py_files" || exit 0; \ dir='$(DESTDIR)$(rdmtestsdir)'; \ pyc_files=`echo "$$py_files" | sed 's|$$|c|'`; \ pyo_files=`echo "$$py_files" | sed 's|$$|o|'`; \ py_files_pep3147=`echo "$$py_files" | $(am__pep3147_tweak)`; \ echo "$$py_files_pep3147";\ pyc_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|c|'`; \ pyo_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|o|'`; \ st=0; \ for files in \ "$$py_files" \ "$$pyc_files" \ "$$pyo_files" \ "$$pyc_files_pep3147" \ "$$pyo_files_pep3147" \ ; do \ $(am__uninstall_files_from_dir) || st=$$?; \ done; \ exit $$st install-rpcpythonPYTHON: $(rpcpython_PYTHON) @$(NORMAL_INSTALL) @list='$(rpcpython_PYTHON)'; dlist=; list2=; test -n "$(rpcpythondir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(rpcpythondir)'"; \ $(MKDIR_P) "$(DESTDIR)$(rpcpythondir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \ if test -f $$b$$p; then \ $(am__strip_dir) \ dlist="$$dlist $$f"; \ list2="$$list2 $$b$$p"; \ else :; fi; \ done; \ for file in $$list2; do echo $$file; done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(rpcpythondir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(rpcpythondir)" || exit $$?; \ done || exit $$?; \ if test -n "$$dlist"; then \ $(am__py_compile) --destdir "$(DESTDIR)" \ --basedir "$(rpcpythondir)" $$dlist; \ else :; fi uninstall-rpcpythonPYTHON: @$(NORMAL_UNINSTALL) @list='$(rpcpython_PYTHON)'; test -n "$(rpcpythondir)" || list=; \ py_files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$py_files" || exit 0; \ dir='$(DESTDIR)$(rpcpythondir)'; \ pyc_files=`echo "$$py_files" | sed 's|$$|c|'`; \ pyo_files=`echo "$$py_files" | sed 's|$$|o|'`; \ py_files_pep3147=`echo "$$py_files" | $(am__pep3147_tweak)`; \ echo "$$py_files_pep3147";\ pyc_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|c|'`; \ pyo_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|o|'`; \ st=0; \ for files in \ "$$py_files" \ "$$pyc_files" \ "$$pyo_files" \ "$$pyc_files_pep3147" \ "$$pyo_files_pep3147" \ ; do \ $(am__uninstall_files_from_dir) || st=$$?; \ done; \ exit $$st install-man1: $(dist_man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(dist_man_MANS)'; \ test -n "$(man1dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.1[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ done; } uninstall-man1: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man1dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.1[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) install-dist_angularDATA: $(dist_angular_DATA) @$(NORMAL_INSTALL) @list='$(dist_angular_DATA)'; test -n "$(angulardir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(angulardir)'"; \ $(MKDIR_P) "$(DESTDIR)$(angulardir)" || 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)$(angulardir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(angulardir)" || exit $$?; \ done uninstall-dist_angularDATA: @$(NORMAL_UNINSTALL) @list='$(dist_angular_DATA)'; test -n "$(angulardir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(angulardir)'; $(am__uninstall_files_from_dir) install-dist_angularrouteDATA: $(dist_angularroute_DATA) @$(NORMAL_INSTALL) @list='$(dist_angularroute_DATA)'; test -n "$(angularroutedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(angularroutedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(angularroutedir)" || 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)$(angularroutedir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(angularroutedir)" || exit $$?; \ done uninstall-dist_angularrouteDATA: @$(NORMAL_UNINSTALL) @list='$(dist_angularroute_DATA)'; test -n "$(angularroutedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(angularroutedir)'; $(am__uninstall_files_from_dir) install-dist_bootcssDATA: $(dist_bootcss_DATA) @$(NORMAL_INSTALL) @list='$(dist_bootcss_DATA)'; test -n "$(bootcssdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bootcssdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bootcssdir)" || 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)$(bootcssdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(bootcssdir)" || exit $$?; \ done uninstall-dist_bootcssDATA: @$(NORMAL_UNINSTALL) @list='$(dist_bootcss_DATA)'; test -n "$(bootcssdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(bootcssdir)'; $(am__uninstall_files_from_dir) install-dist_bootfontsDATA: $(dist_bootfonts_DATA) @$(NORMAL_INSTALL) @list='$(dist_bootfonts_DATA)'; test -n "$(bootfontsdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bootfontsdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bootfontsdir)" || 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)$(bootfontsdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(bootfontsdir)" || exit $$?; \ done uninstall-dist_bootfontsDATA: @$(NORMAL_UNINSTALL) @list='$(dist_bootfonts_DATA)'; test -n "$(bootfontsdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(bootfontsdir)'; $(am__uninstall_files_from_dir) install-dist_bootjsDATA: $(dist_bootjs_DATA) @$(NORMAL_INSTALL) @list='$(dist_bootjs_DATA)'; test -n "$(bootjsdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bootjsdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bootjsdir)" || 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)$(bootjsdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(bootjsdir)" || exit $$?; \ done uninstall-dist_bootjsDATA: @$(NORMAL_UNINSTALL) @list='$(dist_bootjs_DATA)'; test -n "$(bootjsdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(bootjsdir)'; $(am__uninstall_files_from_dir) install-dist_cssDATA: $(dist_css_DATA) @$(NORMAL_INSTALL) @list='$(dist_css_DATA)'; test -n "$(cssdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(cssdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(cssdir)" || 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)$(cssdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(cssdir)" || exit $$?; \ done uninstall-dist_cssDATA: @$(NORMAL_UNINSTALL) @list='$(dist_css_DATA)'; test -n "$(cssdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(cssdir)'; $(am__uninstall_files_from_dir) install-dist_imgDATA: $(dist_img_DATA) @$(NORMAL_INSTALL) @list='$(dist_img_DATA)'; test -n "$(imgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(imgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(imgdir)" || 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)$(imgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(imgdir)" || exit $$?; \ done uninstall-dist_imgDATA: @$(NORMAL_UNINSTALL) @list='$(dist_img_DATA)'; test -n "$(imgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(imgdir)'; $(am__uninstall_files_from_dir) install-dist_jqueryDATA: $(dist_jquery_DATA) @$(NORMAL_INSTALL) @list='$(dist_jquery_DATA)'; test -n "$(jquerydir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(jquerydir)'"; \ $(MKDIR_P) "$(DESTDIR)$(jquerydir)" || 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)$(jquerydir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(jquerydir)" || exit $$?; \ done uninstall-dist_jqueryDATA: @$(NORMAL_UNINSTALL) @list='$(dist_jquery_DATA)'; test -n "$(jquerydir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(jquerydir)'; $(am__uninstall_files_from_dir) install-dist_jsDATA: $(dist_js_DATA) @$(NORMAL_INSTALL) @list='$(dist_js_DATA)'; test -n "$(jsdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(jsdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(jsdir)" || 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)$(jsdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(jsdir)" || exit $$?; \ done uninstall-dist_jsDATA: @$(NORMAL_UNINSTALL) @list='$(dist_js_DATA)'; test -n "$(jsdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(jsdir)'; $(am__uninstall_files_from_dir) install-dist_newDATA: $(dist_new_DATA) @$(NORMAL_INSTALL) @list='$(dist_new_DATA)'; test -n "$(newdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(newdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(newdir)" || 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)$(newdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(newdir)" || exit $$?; \ done uninstall-dist_newDATA: @$(NORMAL_UNINSTALL) @list='$(dist_new_DATA)'; test -n "$(newdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(newdir)'; $(am__uninstall_files_from_dir) install-dist_piddataDATA: $(dist_piddata_DATA) @$(NORMAL_INSTALL) @list='$(dist_piddata_DATA)'; test -n "$(piddatadir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(piddatadir)'"; \ $(MKDIR_P) "$(DESTDIR)$(piddatadir)" || 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)$(piddatadir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(piddatadir)" || exit $$?; \ done uninstall-dist_piddataDATA: @$(NORMAL_UNINSTALL) @list='$(dist_piddata_DATA)'; test -n "$(piddatadir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(piddatadir)'; $(am__uninstall_files_from_dir) install-dist_tools_rdm_testserver_imagesDATA: $(dist_tools_rdm_testserver_images_DATA) @$(NORMAL_INSTALL) @list='$(dist_tools_rdm_testserver_images_DATA)'; test -n "$(tools_rdm_testserver_imagesdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(tools_rdm_testserver_imagesdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(tools_rdm_testserver_imagesdir)" || 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)$(tools_rdm_testserver_imagesdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(tools_rdm_testserver_imagesdir)" || exit $$?; \ done uninstall-dist_tools_rdm_testserver_imagesDATA: @$(NORMAL_UNINSTALL) @list='$(dist_tools_rdm_testserver_images_DATA)'; test -n "$(tools_rdm_testserver_imagesdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(tools_rdm_testserver_imagesdir)'; $(am__uninstall_files_from_dir) install-dist_tools_rdm_testserver_staticDATA: $(dist_tools_rdm_testserver_static_DATA) @$(NORMAL_INSTALL) @list='$(dist_tools_rdm_testserver_static_DATA)'; test -n "$(tools_rdm_testserver_staticdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(tools_rdm_testserver_staticdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(tools_rdm_testserver_staticdir)" || 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)$(tools_rdm_testserver_staticdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(tools_rdm_testserver_staticdir)" || exit $$?; \ done uninstall-dist_tools_rdm_testserver_staticDATA: @$(NORMAL_UNINSTALL) @list='$(dist_tools_rdm_testserver_static_DATA)'; test -n "$(tools_rdm_testserver_staticdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(tools_rdm_testserver_staticdir)'; $(am__uninstall_files_from_dir) install-dist_viewsDATA: $(dist_views_DATA) @$(NORMAL_INSTALL) @list='$(dist_views_DATA)'; test -n "$(viewsdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(viewsdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(viewsdir)" || 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)$(viewsdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(viewsdir)" || exit $$?; \ done uninstall-dist_viewsDATA: @$(NORMAL_UNINSTALL) @list='$(dist_views_DATA)'; test -n "$(viewsdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(viewsdir)'; $(am__uninstall_files_from_dir) install-dist_wwwDATA: $(dist_www_DATA) @$(NORMAL_INSTALL) @list='$(dist_www_DATA)'; test -n "$(wwwdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(wwwdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(wwwdir)" || 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)$(wwwdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(wwwdir)" || exit $$?; \ done uninstall-dist_wwwDATA: @$(NORMAL_UNINSTALL) @list='$(dist_www_DATA)'; test -n "$(wwwdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(wwwdir)'; $(am__uninstall_files_from_dir) install-pkgconfigDATA: $(pkgconfig_DATA) @$(NORMAL_INSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || 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)$(pkgconfigdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ done uninstall-pkgconfigDATA: @$(NORMAL_UNINSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) install-nodist_artnetincludeHEADERS: $(nodist_artnetinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(nodist_artnetinclude_HEADERS)'; test -n "$(artnetincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(artnetincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(artnetincludedir)" || 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_HEADER) $$files '$(DESTDIR)$(artnetincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(artnetincludedir)" || exit $$?; \ done uninstall-nodist_artnetincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(nodist_artnetinclude_HEADERS)'; test -n "$(artnetincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(artnetincludedir)'; $(am__uninstall_files_from_dir) install-nodist_e131includeHEADERS: $(nodist_e131include_HEADERS) @$(NORMAL_INSTALL) @list='$(nodist_e131include_HEADERS)'; test -n "$(e131includedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(e131includedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(e131includedir)" || 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_HEADER) $$files '$(DESTDIR)$(e131includedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(e131includedir)" || exit $$?; \ done uninstall-nodist_e131includeHEADERS: @$(NORMAL_UNINSTALL) @list='$(nodist_e131include_HEADERS)'; test -n "$(e131includedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(e131includedir)'; $(am__uninstall_files_from_dir) install-nodist_olabaseincludeHEADERS: $(nodist_olabaseinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(nodist_olabaseinclude_HEADERS)'; test -n "$(olabaseincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(olabaseincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(olabaseincludedir)" || 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_HEADER) $$files '$(DESTDIR)$(olabaseincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(olabaseincludedir)" || exit $$?; \ done uninstall-nodist_olabaseincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(nodist_olabaseinclude_HEADERS)'; test -n "$(olabaseincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(olabaseincludedir)'; $(am__uninstall_files_from_dir) install-nodist_olardmincludeHEADERS: $(nodist_olardminclude_HEADERS) @$(NORMAL_INSTALL) @list='$(nodist_olardminclude_HEADERS)'; test -n "$(olardmincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(olardmincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(olardmincludedir)" || 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_HEADER) $$files '$(DESTDIR)$(olardmincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(olardmincludedir)" || exit $$?; \ done uninstall-nodist_olardmincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(nodist_olardminclude_HEADERS)'; test -n "$(olardmincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(olardmincludedir)'; $(am__uninstall_files_from_dir) install-nodist_olatimecodeincludeHEADERS: $(nodist_olatimecodeinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(nodist_olatimecodeinclude_HEADERS)'; test -n "$(olatimecodeincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(olatimecodeincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(olatimecodeincludedir)" || 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_HEADER) $$files '$(DESTDIR)$(olatimecodeincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(olatimecodeincludedir)" || exit $$?; \ done uninstall-nodist_olatimecodeincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(nodist_olatimecodeinclude_HEADERS)'; test -n "$(olatimecodeincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(olatimecodeincludedir)'; $(am__uninstall_files_from_dir) install-nodist_pkgincludeHEADERS: $(nodist_pkginclude_HEADERS) @$(NORMAL_INSTALL) @list='$(nodist_pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" || 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_HEADER) $$files '$(DESTDIR)$(pkgincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkgincludedir)" || exit $$?; \ done uninstall-nodist_pkgincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(nodist_pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgincludedir)'; $(am__uninstall_files_from_dir) install-nodist_usbproincludeHEADERS: $(nodist_usbproinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(nodist_usbproinclude_HEADERS)'; test -n "$(usbproincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(usbproincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(usbproincludedir)" || 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_HEADER) $$files '$(DESTDIR)$(usbproincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(usbproincludedir)" || exit $$?; \ done uninstall-nodist_usbproincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(nodist_usbproinclude_HEADERS)'; test -n "$(usbproincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(usbproincludedir)'; $(am__uninstall_files_from_dir) install-olaacnincludeHEADERS: $(olaacninclude_HEADERS) @$(NORMAL_INSTALL) @list='$(olaacninclude_HEADERS)'; test -n "$(olaacnincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(olaacnincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(olaacnincludedir)" || 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_HEADER) $$files '$(DESTDIR)$(olaacnincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(olaacnincludedir)" || exit $$?; \ done uninstall-olaacnincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(olaacninclude_HEADERS)'; test -n "$(olaacnincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(olaacnincludedir)'; $(am__uninstall_files_from_dir) install-olabaseincludeHEADERS: $(olabaseinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(olabaseinclude_HEADERS)'; test -n "$(olabaseincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(olabaseincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(olabaseincludedir)" || 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_HEADER) $$files '$(DESTDIR)$(olabaseincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(olabaseincludedir)" || exit $$?; \ done uninstall-olabaseincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(olabaseinclude_HEADERS)'; test -n "$(olabaseincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(olabaseincludedir)'; $(am__uninstall_files_from_dir) install-olaclientincludeHEADERS: $(olaclientinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(olaclientinclude_HEADERS)'; test -n "$(olaclientincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(olaclientincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(olaclientincludedir)" || 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_HEADER) $$files '$(DESTDIR)$(olaclientincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(olaclientincludedir)" || exit $$?; \ done uninstall-olaclientincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(olaclientinclude_HEADERS)'; test -n "$(olaclientincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(olaclientincludedir)'; $(am__uninstall_files_from_dir) install-oladincludeHEADERS: $(oladinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(oladinclude_HEADERS)'; test -n "$(oladincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(oladincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(oladincludedir)" || 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_HEADER) $$files '$(DESTDIR)$(oladincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(oladincludedir)" || exit $$?; \ done uninstall-oladincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(oladinclude_HEADERS)'; test -n "$(oladincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(oladincludedir)'; $(am__uninstall_files_from_dir) install-oladmxincludeHEADERS: $(oladmxinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(oladmxinclude_HEADERS)'; test -n "$(oladmxincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(oladmxincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(oladmxincludedir)" || 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_HEADER) $$files '$(DESTDIR)$(oladmxincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(oladmxincludedir)" || exit $$?; \ done uninstall-oladmxincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(oladmxinclude_HEADERS)'; test -n "$(oladmxincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(oladmxincludedir)'; $(am__uninstall_files_from_dir) install-olae133includeHEADERS: $(olae133include_HEADERS) @$(NORMAL_INSTALL) @list='$(olae133include_HEADERS)'; test -n "$(olae133includedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(olae133includedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(olae133includedir)" || 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_HEADER) $$files '$(DESTDIR)$(olae133includedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(olae133includedir)" || exit $$?; \ done uninstall-olae133includeHEADERS: @$(NORMAL_UNINSTALL) @list='$(olae133include_HEADERS)'; test -n "$(olae133includedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(olae133includedir)'; $(am__uninstall_files_from_dir) install-olafileincludeHEADERS: $(olafileinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(olafileinclude_HEADERS)'; test -n "$(olafileincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(olafileincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(olafileincludedir)" || 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_HEADER) $$files '$(DESTDIR)$(olafileincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(olafileincludedir)" || exit $$?; \ done uninstall-olafileincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(olafileinclude_HEADERS)'; test -n "$(olafileincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(olafileincludedir)'; $(am__uninstall_files_from_dir) install-olahttpincludeHEADERS: $(olahttpinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(olahttpinclude_HEADERS)'; test -n "$(olahttpincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(olahttpincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(olahttpincludedir)" || 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_HEADER) $$files '$(DESTDIR)$(olahttpincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(olahttpincludedir)" || exit $$?; \ done uninstall-olahttpincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(olahttpinclude_HEADERS)'; test -n "$(olahttpincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(olahttpincludedir)'; $(am__uninstall_files_from_dir) install-olaioincludeHEADERS: $(olaioinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(olaioinclude_HEADERS)'; test -n "$(olaioincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(olaioincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(olaioincludedir)" || 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_HEADER) $$files '$(DESTDIR)$(olaioincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(olaioincludedir)" || exit $$?; \ done uninstall-olaioincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(olaioinclude_HEADERS)'; test -n "$(olaioincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(olaioincludedir)'; $(am__uninstall_files_from_dir) install-olamathincludeHEADERS: $(olamathinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(olamathinclude_HEADERS)'; test -n "$(olamathincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(olamathincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(olamathincludedir)" || 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_HEADER) $$files '$(DESTDIR)$(olamathincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(olamathincludedir)" || exit $$?; \ done uninstall-olamathincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(olamathinclude_HEADERS)'; test -n "$(olamathincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(olamathincludedir)'; $(am__uninstall_files_from_dir) install-olamessagingincludeHEADERS: $(olamessaginginclude_HEADERS) @$(NORMAL_INSTALL) @list='$(olamessaginginclude_HEADERS)'; test -n "$(olamessagingincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(olamessagingincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(olamessagingincludedir)" || 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_HEADER) $$files '$(DESTDIR)$(olamessagingincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(olamessagingincludedir)" || exit $$?; \ done uninstall-olamessagingincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(olamessaginginclude_HEADERS)'; test -n "$(olamessagingincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(olamessagingincludedir)'; $(am__uninstall_files_from_dir) install-olanetworkincludeHEADERS: $(olanetworkinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(olanetworkinclude_HEADERS)'; test -n "$(olanetworkincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(olanetworkincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(olanetworkincludedir)" || 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_HEADER) $$files '$(DESTDIR)$(olanetworkincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(olanetworkincludedir)" || exit $$?; \ done uninstall-olanetworkincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(olanetworkinclude_HEADERS)'; test -n "$(olanetworkincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(olanetworkincludedir)'; $(am__uninstall_files_from_dir) install-olardmincludeHEADERS: $(olardminclude_HEADERS) @$(NORMAL_INSTALL) @list='$(olardminclude_HEADERS)'; test -n "$(olardmincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(olardmincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(olardmincludedir)" || 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_HEADER) $$files '$(DESTDIR)$(olardmincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(olardmincludedir)" || exit $$?; \ done uninstall-olardmincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(olardminclude_HEADERS)'; test -n "$(olardmincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(olardmincludedir)'; $(am__uninstall_files_from_dir) install-olarpcincludeHEADERS: $(olarpcinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(olarpcinclude_HEADERS)'; test -n "$(olarpcincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(olarpcincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(olarpcincludedir)" || 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_HEADER) $$files '$(DESTDIR)$(olarpcincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(olarpcincludedir)" || exit $$?; \ done uninstall-olarpcincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(olarpcinclude_HEADERS)'; test -n "$(olarpcincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(olarpcincludedir)'; $(am__uninstall_files_from_dir) install-olastlincludeHEADERS: $(olastlinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(olastlinclude_HEADERS)'; test -n "$(olastlincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(olastlincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(olastlincludedir)" || 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_HEADER) $$files '$(DESTDIR)$(olastlincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(olastlincludedir)" || exit $$?; \ done uninstall-olastlincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(olastlinclude_HEADERS)'; test -n "$(olastlincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(olastlincludedir)'; $(am__uninstall_files_from_dir) install-olastringsincludeHEADERS: $(olastringsinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(olastringsinclude_HEADERS)'; test -n "$(olastringsincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(olastringsincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(olastringsincludedir)" || 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_HEADER) $$files '$(DESTDIR)$(olastringsincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(olastringsincludedir)" || exit $$?; \ done uninstall-olastringsincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(olastringsinclude_HEADERS)'; test -n "$(olastringsincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(olastringsincludedir)'; $(am__uninstall_files_from_dir) install-olasystemincludeHEADERS: $(olasysteminclude_HEADERS) @$(NORMAL_INSTALL) @list='$(olasysteminclude_HEADERS)'; test -n "$(olasystemincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(olasystemincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(olasystemincludedir)" || 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_HEADER) $$files '$(DESTDIR)$(olasystemincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(olasystemincludedir)" || exit $$?; \ done uninstall-olasystemincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(olasysteminclude_HEADERS)'; test -n "$(olasystemincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(olasystemincludedir)'; $(am__uninstall_files_from_dir) install-olathreadincludeHEADERS: $(olathreadinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(olathreadinclude_HEADERS)'; test -n "$(olathreadincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(olathreadincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(olathreadincludedir)" || 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_HEADER) $$files '$(DESTDIR)$(olathreadincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(olathreadincludedir)" || exit $$?; \ done uninstall-olathreadincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(olathreadinclude_HEADERS)'; test -n "$(olathreadincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(olathreadincludedir)'; $(am__uninstall_files_from_dir) install-olatimecodeincludeHEADERS: $(olatimecodeinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(olatimecodeinclude_HEADERS)'; test -n "$(olatimecodeincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(olatimecodeincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(olatimecodeincludedir)" || 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_HEADER) $$files '$(DESTDIR)$(olatimecodeincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(olatimecodeincludedir)" || exit $$?; \ done uninstall-olatimecodeincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(olatimecodeinclude_HEADERS)'; test -n "$(olatimecodeincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(olatimecodeincludedir)'; $(am__uninstall_files_from_dir) install-olautilincludeHEADERS: $(olautilinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(olautilinclude_HEADERS)'; test -n "$(olautilincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(olautilincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(olautilincludedir)" || 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_HEADER) $$files '$(DESTDIR)$(olautilincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(olautilincludedir)" || exit $$?; \ done uninstall-olautilincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(olautilinclude_HEADERS)'; test -n "$(olautilincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(olautilincludedir)'; $(am__uninstall_files_from_dir) install-olawebincludeHEADERS: $(olawebinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(olawebinclude_HEADERS)'; test -n "$(olawebincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(olawebincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(olawebincludedir)" || 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_HEADER) $$files '$(DESTDIR)$(olawebincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(olawebincludedir)" || exit $$?; \ done uninstall-olawebincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(olawebinclude_HEADERS)'; test -n "$(olawebincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(olawebincludedir)'; $(am__uninstall_files_from_dir) install-olawinincludeHEADERS: $(olawininclude_HEADERS) @$(NORMAL_INSTALL) @list='$(olawininclude_HEADERS)'; test -n "$(olawinincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(olawinincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(olawinincludedir)" || 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_HEADER) $$files '$(DESTDIR)$(olawinincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(olawinincludedir)" || exit $$?; \ done uninstall-olawinincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(olawininclude_HEADERS)'; test -n "$(olawinincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(olawinincludedir)'; $(am__uninstall_files_from_dir) install-pkgincludeHEADERS: $(pkginclude_HEADERS) @$(NORMAL_INSTALL) @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" || 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_HEADER) $$files '$(DESTDIR)$(pkgincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkgincludedir)" || exit $$?; \ done uninstall-pkgincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgincludedir)'; $(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. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ 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" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) 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; \ $(am__define_uniq_tagged_files); \ 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-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ elif test -n "$$redo_logs"; then \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) $(check_SCRIPTS) $(dist_check_SCRIPTS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? common/base/CredentialsTester.log: common/base/CredentialsTester$(EXEEXT) @p='common/base/CredentialsTester$(EXEEXT)'; \ b='common/base/CredentialsTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/base/FlagsTester.log: common/base/FlagsTester$(EXEEXT) @p='common/base/FlagsTester$(EXEEXT)'; \ b='common/base/FlagsTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/base/LoggingTester.log: common/base/LoggingTester$(EXEEXT) @p='common/base/LoggingTester$(EXEEXT)'; \ b='common/base/LoggingTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/dmx/RunLengthEncoderTester.log: common/dmx/RunLengthEncoderTester$(EXEEXT) @p='common/dmx/RunLengthEncoderTester$(EXEEXT)'; \ b='common/dmx/RunLengthEncoderTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/export_map/ExportMapTester.log: common/export_map/ExportMapTester$(EXEEXT) @p='common/export_map/ExportMapTester$(EXEEXT)'; \ b='common/export_map/ExportMapTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/file/UtilTester.log: common/file/UtilTester$(EXEEXT) @p='common/file/UtilTester$(EXEEXT)'; \ b='common/file/UtilTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/io/DescriptorTester.log: common/io/DescriptorTester$(EXEEXT) @p='common/io/DescriptorTester$(EXEEXT)'; \ b='common/io/DescriptorTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/io/IOQueueTester.log: common/io/IOQueueTester$(EXEEXT) @p='common/io/IOQueueTester$(EXEEXT)'; \ b='common/io/IOQueueTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/io/IOStackTester.log: common/io/IOStackTester$(EXEEXT) @p='common/io/IOStackTester$(EXEEXT)'; \ b='common/io/IOStackTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/io/MemoryBlockTester.log: common/io/MemoryBlockTester$(EXEEXT) @p='common/io/MemoryBlockTester$(EXEEXT)'; \ b='common/io/MemoryBlockTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/io/SelectServerTester.log: common/io/SelectServerTester$(EXEEXT) @p='common/io/SelectServerTester$(EXEEXT)'; \ b='common/io/SelectServerTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/io/StreamTester.log: common/io/StreamTester$(EXEEXT) @p='common/io/StreamTester$(EXEEXT)'; \ b='common/io/StreamTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/io/TimeoutManagerTester.log: common/io/TimeoutManagerTester$(EXEEXT) @p='common/io/TimeoutManagerTester$(EXEEXT)'; \ b='common/io/TimeoutManagerTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/messaging/DescriptorTester.log: common/messaging/DescriptorTester$(EXEEXT) @p='common/messaging/DescriptorTester$(EXEEXT)'; \ b='common/messaging/DescriptorTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/network/HealthCheckedConnectionTester.log: common/network/HealthCheckedConnectionTester$(EXEEXT) @p='common/network/HealthCheckedConnectionTester$(EXEEXT)'; \ b='common/network/HealthCheckedConnectionTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/network/NetworkTester.log: common/network/NetworkTester$(EXEEXT) @p='common/network/NetworkTester$(EXEEXT)'; \ b='common/network/NetworkTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/network/TCPConnectorTester.log: common/network/TCPConnectorTester$(EXEEXT) @p='common/network/TCPConnectorTester$(EXEEXT)'; \ b='common/network/TCPConnectorTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/rdm/DiscoveryAgentTester.log: common/rdm/DiscoveryAgentTester$(EXEEXT) @p='common/rdm/DiscoveryAgentTester$(EXEEXT)'; \ b='common/rdm/DiscoveryAgentTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/rdm/PidStoreTester.log: common/rdm/PidStoreTester$(EXEEXT) @p='common/rdm/PidStoreTester$(EXEEXT)'; \ b='common/rdm/PidStoreTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/rdm/QueueingRDMControllerTester.log: common/rdm/QueueingRDMControllerTester$(EXEEXT) @p='common/rdm/QueueingRDMControllerTester$(EXEEXT)'; \ b='common/rdm/QueueingRDMControllerTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/rdm/RDMAPITester.log: common/rdm/RDMAPITester$(EXEEXT) @p='common/rdm/RDMAPITester$(EXEEXT)'; \ b='common/rdm/RDMAPITester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/rdm/RDMCommandSerializerTester.log: common/rdm/RDMCommandSerializerTester$(EXEEXT) @p='common/rdm/RDMCommandSerializerTester$(EXEEXT)'; \ b='common/rdm/RDMCommandSerializerTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/rdm/RDMCommandTester.log: common/rdm/RDMCommandTester$(EXEEXT) @p='common/rdm/RDMCommandTester$(EXEEXT)'; \ b='common/rdm/RDMCommandTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/rdm/RDMFrameTester.log: common/rdm/RDMFrameTester$(EXEEXT) @p='common/rdm/RDMFrameTester$(EXEEXT)'; \ b='common/rdm/RDMFrameTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/rdm/RDMHelperTester.log: common/rdm/RDMHelperTester$(EXEEXT) @p='common/rdm/RDMHelperTester$(EXEEXT)'; \ b='common/rdm/RDMHelperTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/rdm/RDMMessageTester.log: common/rdm/RDMMessageTester$(EXEEXT) @p='common/rdm/RDMMessageTester$(EXEEXT)'; \ b='common/rdm/RDMMessageTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/rdm/RDMReplyTester.log: common/rdm/RDMReplyTester$(EXEEXT) @p='common/rdm/RDMReplyTester$(EXEEXT)'; \ b='common/rdm/RDMReplyTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/rdm/UIDAllocatorTester.log: common/rdm/UIDAllocatorTester$(EXEEXT) @p='common/rdm/UIDAllocatorTester$(EXEEXT)'; \ b='common/rdm/UIDAllocatorTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/rdm/UIDTester.log: common/rdm/UIDTester$(EXEEXT) @p='common/rdm/UIDTester$(EXEEXT)'; \ b='common/rdm/UIDTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/rpc/RpcTester.log: common/rpc/RpcTester$(EXEEXT) @p='common/rpc/RpcTester$(EXEEXT)'; \ b='common/rpc/RpcTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/rpc/RpcServerTester.log: common/rpc/RpcServerTester$(EXEEXT) @p='common/rpc/RpcServerTester$(EXEEXT)'; \ b='common/rpc/RpcServerTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/strings/UtilsTester.log: common/strings/UtilsTester$(EXEEXT) @p='common/strings/UtilsTester$(EXEEXT)'; \ b='common/strings/UtilsTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/thread/ExecutorThreadTester.log: common/thread/ExecutorThreadTester$(EXEEXT) @p='common/thread/ExecutorThreadTester$(EXEEXT)'; \ b='common/thread/ExecutorThreadTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/thread/ThreadTester.log: common/thread/ThreadTester$(EXEEXT) @p='common/thread/ThreadTester$(EXEEXT)'; \ b='common/thread/ThreadTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/thread/FutureTester.log: common/thread/FutureTester$(EXEEXT) @p='common/thread/FutureTester$(EXEEXT)'; \ b='common/thread/FutureTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/timecode/TimeCodeTester.log: common/timecode/TimeCodeTester$(EXEEXT) @p='common/timecode/TimeCodeTester$(EXEEXT)'; \ b='common/timecode/TimeCodeTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/utils/UtilsTester.log: common/utils/UtilsTester$(EXEEXT) @p='common/utils/UtilsTester$(EXEEXT)'; \ b='common/utils/UtilsTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/web/JsonTester.log: common/web/JsonTester$(EXEEXT) @p='common/web/JsonTester$(EXEEXT)'; \ b='common/web/JsonTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/web/ParserTester.log: common/web/ParserTester$(EXEEXT) @p='common/web/ParserTester$(EXEEXT)'; \ b='common/web/ParserTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/web/PtchParserTester.log: common/web/PtchParserTester$(EXEEXT) @p='common/web/PtchParserTester$(EXEEXT)'; \ b='common/web/PtchParserTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/web/PtchTester.log: common/web/PtchTester$(EXEEXT) @p='common/web/PtchTester$(EXEEXT)'; \ b='common/web/PtchTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/web/PointerTester.log: common/web/PointerTester$(EXEEXT) @p='common/web/PointerTester$(EXEEXT)'; \ b='common/web/PointerTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/web/PointerTrackerTester.log: common/web/PointerTrackerTester$(EXEEXT) @p='common/web/PointerTrackerTester$(EXEEXT)'; \ b='common/web/PointerTrackerTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/web/SchemaParserTester.log: common/web/SchemaParserTester$(EXEEXT) @p='common/web/SchemaParserTester$(EXEEXT)'; \ b='common/web/SchemaParserTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/web/SchemaTester.log: common/web/SchemaTester$(EXEEXT) @p='common/web/SchemaTester$(EXEEXT)'; \ b='common/web/SchemaTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) common/web/SectionsTester.log: common/web/SectionsTester$(EXEEXT) @p='common/web/SectionsTester$(EXEEXT)'; \ b='common/web/SectionsTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) data/rdm/PidDataTester.log: data/rdm/PidDataTester$(EXEEXT) @p='data/rdm/PidDataTester$(EXEEXT)'; \ b='data/rdm/PidDataTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) libs/acn/E131Tester.log: libs/acn/E131Tester$(EXEEXT) @p='libs/acn/E131Tester$(EXEEXT)'; \ b='libs/acn/E131Tester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) libs/acn/E133Tester.log: libs/acn/E133Tester$(EXEEXT) @p='libs/acn/E133Tester$(EXEEXT)'; \ b='libs/acn/E133Tester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) libs/acn/TransportTester.log: libs/acn/TransportTester$(EXEEXT) @p='libs/acn/TransportTester$(EXEEXT)'; \ b='libs/acn/TransportTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) libs/usb/LibUsbThreadTester.log: libs/usb/LibUsbThreadTester$(EXEEXT) @p='libs/usb/LibUsbThreadTester$(EXEEXT)'; \ b='libs/usb/LibUsbThreadTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) ola/OlaClientTester.log: ola/OlaClientTester$(EXEEXT) @p='ola/OlaClientTester$(EXEEXT)'; \ b='ola/OlaClientTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) olad/plugin_api/ClientTester.log: olad/plugin_api/ClientTester$(EXEEXT) @p='olad/plugin_api/ClientTester$(EXEEXT)'; \ b='olad/plugin_api/ClientTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) olad/plugin_api/DeviceTester.log: olad/plugin_api/DeviceTester$(EXEEXT) @p='olad/plugin_api/DeviceTester$(EXEEXT)'; \ b='olad/plugin_api/DeviceTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) olad/plugin_api/DmxSourceTester.log: olad/plugin_api/DmxSourceTester$(EXEEXT) @p='olad/plugin_api/DmxSourceTester$(EXEEXT)'; \ b='olad/plugin_api/DmxSourceTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) olad/plugin_api/PortTester.log: olad/plugin_api/PortTester$(EXEEXT) @p='olad/plugin_api/PortTester$(EXEEXT)'; \ b='olad/plugin_api/PortTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) olad/plugin_api/PreferencesTester.log: olad/plugin_api/PreferencesTester$(EXEEXT) @p='olad/plugin_api/PreferencesTester$(EXEEXT)'; \ b='olad/plugin_api/PreferencesTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) olad/plugin_api/UniverseTester.log: olad/plugin_api/UniverseTester$(EXEEXT) @p='olad/plugin_api/UniverseTester$(EXEEXT)'; \ b='olad/plugin_api/UniverseTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) plugins/artnet/ArtNetTester.log: plugins/artnet/ArtNetTester$(EXEEXT) @p='plugins/artnet/ArtNetTester$(EXEEXT)'; \ b='plugins/artnet/ArtNetTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) plugins/dummy/DummyPluginTester.log: plugins/dummy/DummyPluginTester$(EXEEXT) @p='plugins/dummy/DummyPluginTester$(EXEEXT)'; \ b='plugins/dummy/DummyPluginTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) plugins/espnet/EspNetTester.log: plugins/espnet/EspNetTester$(EXEEXT) @p='plugins/espnet/EspNetTester$(EXEEXT)'; \ b='plugins/espnet/EspNetTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) plugins/kinet/KiNetTester.log: plugins/kinet/KiNetTester$(EXEEXT) @p='plugins/kinet/KiNetTester$(EXEEXT)'; \ b='plugins/kinet/KiNetTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) plugins/openpixelcontrol/OPCClientTester.log: plugins/openpixelcontrol/OPCClientTester$(EXEEXT) @p='plugins/openpixelcontrol/OPCClientTester$(EXEEXT)'; \ b='plugins/openpixelcontrol/OPCClientTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) plugins/openpixelcontrol/OPCServerTester.log: plugins/openpixelcontrol/OPCServerTester$(EXEEXT) @p='plugins/openpixelcontrol/OPCServerTester$(EXEEXT)'; \ b='plugins/openpixelcontrol/OPCServerTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) plugins/osc/OSCTester.log: plugins/osc/OSCTester$(EXEEXT) @p='plugins/osc/OSCTester$(EXEEXT)'; \ b='plugins/osc/OSCTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) plugins/shownet/ShowNetTester.log: plugins/shownet/ShowNetTester$(EXEEXT) @p='plugins/shownet/ShowNetTester$(EXEEXT)'; \ b='plugins/shownet/ShowNetTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) plugins/spi/SPITester.log: plugins/spi/SPITester$(EXEEXT) @p='plugins/spi/SPITester$(EXEEXT)'; \ b='plugins/spi/SPITester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) plugins/usbpro/ArduinoWidgetTester.log: plugins/usbpro/ArduinoWidgetTester$(EXEEXT) @p='plugins/usbpro/ArduinoWidgetTester$(EXEEXT)'; \ b='plugins/usbpro/ArduinoWidgetTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) plugins/usbpro/BaseRobeWidgetTester.log: plugins/usbpro/BaseRobeWidgetTester$(EXEEXT) @p='plugins/usbpro/BaseRobeWidgetTester$(EXEEXT)'; \ b='plugins/usbpro/BaseRobeWidgetTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) plugins/usbpro/BaseUsbProWidgetTester.log: plugins/usbpro/BaseUsbProWidgetTester$(EXEEXT) @p='plugins/usbpro/BaseUsbProWidgetTester$(EXEEXT)'; \ b='plugins/usbpro/BaseUsbProWidgetTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) plugins/usbpro/DmxTriWidgetTester.log: plugins/usbpro/DmxTriWidgetTester$(EXEEXT) @p='plugins/usbpro/DmxTriWidgetTester$(EXEEXT)'; \ b='plugins/usbpro/DmxTriWidgetTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) plugins/usbpro/DmxterWidgetTester.log: plugins/usbpro/DmxterWidgetTester$(EXEEXT) @p='plugins/usbpro/DmxterWidgetTester$(EXEEXT)'; \ b='plugins/usbpro/DmxterWidgetTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) plugins/usbpro/EnttecUsbProWidgetTester.log: plugins/usbpro/EnttecUsbProWidgetTester$(EXEEXT) @p='plugins/usbpro/EnttecUsbProWidgetTester$(EXEEXT)'; \ b='plugins/usbpro/EnttecUsbProWidgetTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) plugins/usbpro/RobeWidgetDetectorTester.log: plugins/usbpro/RobeWidgetDetectorTester$(EXEEXT) @p='plugins/usbpro/RobeWidgetDetectorTester$(EXEEXT)'; \ b='plugins/usbpro/RobeWidgetDetectorTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) plugins/usbpro/RobeWidgetTester.log: plugins/usbpro/RobeWidgetTester$(EXEEXT) @p='plugins/usbpro/RobeWidgetTester$(EXEEXT)'; \ b='plugins/usbpro/RobeWidgetTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) plugins/usbpro/UltraDMXProWidgetTester.log: plugins/usbpro/UltraDMXProWidgetTester$(EXEEXT) @p='plugins/usbpro/UltraDMXProWidgetTester$(EXEEXT)'; \ b='plugins/usbpro/UltraDMXProWidgetTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) plugins/usbpro/UsbProWidgetDetectorTester.log: plugins/usbpro/UsbProWidgetDetectorTester$(EXEEXT) @p='plugins/usbpro/UsbProWidgetDetectorTester$(EXEEXT)'; \ b='plugins/usbpro/UsbProWidgetDetectorTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) plugins/usbpro/WidgetDetectorThreadTester.log: plugins/usbpro/WidgetDetectorThreadTester$(EXEEXT) @p='plugins/usbpro/WidgetDetectorThreadTester$(EXEEXT)'; \ b='plugins/usbpro/WidgetDetectorThreadTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) olad/OlaTester.log: olad/OlaTester$(EXEEXT) @p='olad/OlaTester$(EXEEXT)'; \ b='olad/OlaTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) tools/ola_trigger/ActionTester.log: tools/ola_trigger/ActionTester$(EXEEXT) @p='tools/ola_trigger/ActionTester$(EXEEXT)'; \ b='tools/ola_trigger/ActionTester'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) data/rdm/PidDataTest.sh.log: data/rdm/PidDataTest.sh @p='data/rdm/PidDataTest.sh'; \ b='data/rdm/PidDataTest.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) examples/RecorderVerifyTest.sh.log: examples/RecorderVerifyTest.sh @p='examples/RecorderVerifyTest.sh'; \ b='examples/RecorderVerifyTest.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) python/ola/rpc/SimpleRpcControllerTest.sh.log: python/ola/rpc/SimpleRpcControllerTest.sh @p='python/ola/rpc/SimpleRpcControllerTest.sh'; \ b='python/ola/rpc/SimpleRpcControllerTest.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) tools/ola_trigger/FileValidateTest.sh.log: tools/ola_trigger/FileValidateTest.sh @p='tools/ola_trigger/FileValidateTest.sh'; \ b='tools/ola_trigger/FileValidateTest.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .py.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(PY_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_PY_LOG_DRIVER_FLAGS) $(PY_LOG_DRIVER_FLAGS) -- $(PY_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.py$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(PY_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_PY_LOG_DRIVER_FLAGS) $(PY_LOG_DRIVER_FLAGS) -- $(PY_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) 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__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) dist-tarZ: distdir @echo WARNING: "Support for distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__post_remove_distdir) dist dist-all: $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_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.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 $(distdir)/_build/sub $(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/sub \ && ../../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ --srcdir=../.. --prefix="$$dc_install_base" \ && $(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__post_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 $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(check_SCRIPTS) \ $(dist_check_SCRIPTS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-recursive all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(SCRIPTS) $(MANS) $(DATA) \ $(HEADERS) config.h install-binPROGRAMS: install-libLTLIBRARIES installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(rdmtestsexecdir)" "$(DESTDIR)$(pkgpythondir)" "$(DESTDIR)$(rdmtestsdir)" "$(DESTDIR)$(rpcpythondir)" "$(DESTDIR)$(pkgpythondir)" "$(DESTDIR)$(rdminitdir)" "$(DESTDIR)$(rdmtestsdir)" "$(DESTDIR)$(rpcpythondir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(angulardir)" "$(DESTDIR)$(angularroutedir)" "$(DESTDIR)$(bootcssdir)" "$(DESTDIR)$(bootfontsdir)" "$(DESTDIR)$(bootjsdir)" "$(DESTDIR)$(cssdir)" "$(DESTDIR)$(imgdir)" "$(DESTDIR)$(jquerydir)" "$(DESTDIR)$(jsdir)" "$(DESTDIR)$(newdir)" "$(DESTDIR)$(piddatadir)" "$(DESTDIR)$(tools_rdm_testserver_imagesdir)" "$(DESTDIR)$(tools_rdm_testserver_staticdir)" "$(DESTDIR)$(viewsdir)" "$(DESTDIR)$(wwwdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(artnetincludedir)" "$(DESTDIR)$(e131includedir)" "$(DESTDIR)$(olabaseincludedir)" "$(DESTDIR)$(olardmincludedir)" "$(DESTDIR)$(olatimecodeincludedir)" "$(DESTDIR)$(pkgincludedir)" "$(DESTDIR)$(usbproincludedir)" "$(DESTDIR)$(olaacnincludedir)" "$(DESTDIR)$(olabaseincludedir)" "$(DESTDIR)$(olaclientincludedir)" "$(DESTDIR)$(oladincludedir)" "$(DESTDIR)$(oladmxincludedir)" "$(DESTDIR)$(olae133includedir)" "$(DESTDIR)$(olafileincludedir)" "$(DESTDIR)$(olahttpincludedir)" "$(DESTDIR)$(olaioincludedir)" "$(DESTDIR)$(olamathincludedir)" "$(DESTDIR)$(olamessagingincludedir)" "$(DESTDIR)$(olanetworkincludedir)" "$(DESTDIR)$(olardmincludedir)" "$(DESTDIR)$(olarpcincludedir)" "$(DESTDIR)$(olastlincludedir)" "$(DESTDIR)$(olastringsincludedir)" "$(DESTDIR)$(olasystemincludedir)" "$(DESTDIR)$(olathreadincludedir)" "$(DESTDIR)$(olatimecodeincludedir)" "$(DESTDIR)$(olautilincludedir)" "$(DESTDIR)$(olawebincludedir)" "$(DESTDIR)$(olawinincludedir)" "$(DESTDIR)$(pkgincludedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) 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: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) 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) -rm -f common/$(am__dirstamp) -rm -f common/base/$(DEPDIR)/$(am__dirstamp) -rm -f common/base/$(am__dirstamp) -rm -f common/dmx/$(DEPDIR)/$(am__dirstamp) -rm -f common/dmx/$(am__dirstamp) -rm -f common/export_map/$(DEPDIR)/$(am__dirstamp) -rm -f common/export_map/$(am__dirstamp) -rm -f common/file/$(DEPDIR)/$(am__dirstamp) -rm -f common/file/$(am__dirstamp) -rm -f common/http/$(DEPDIR)/$(am__dirstamp) -rm -f common/http/$(am__dirstamp) -rm -f common/io/$(DEPDIR)/$(am__dirstamp) -rm -f common/io/$(am__dirstamp) -rm -f common/math/$(DEPDIR)/$(am__dirstamp) -rm -f common/math/$(am__dirstamp) -rm -f common/messaging/$(DEPDIR)/$(am__dirstamp) -rm -f common/messaging/$(am__dirstamp) -rm -f common/network/$(DEPDIR)/$(am__dirstamp) -rm -f common/network/$(am__dirstamp) -rm -f common/protocol/$(DEPDIR)/$(am__dirstamp) -rm -f common/protocol/$(am__dirstamp) -rm -f common/rdm/$(DEPDIR)/$(am__dirstamp) -rm -f common/rdm/$(am__dirstamp) -rm -f common/rpc/$(DEPDIR)/$(am__dirstamp) -rm -f common/rpc/$(am__dirstamp) -rm -f common/strings/$(DEPDIR)/$(am__dirstamp) -rm -f common/strings/$(am__dirstamp) -rm -f common/system/$(DEPDIR)/$(am__dirstamp) -rm -f common/system/$(am__dirstamp) -rm -f common/testing/$(DEPDIR)/$(am__dirstamp) -rm -f common/testing/$(am__dirstamp) -rm -f common/thread/$(DEPDIR)/$(am__dirstamp) -rm -f common/thread/$(am__dirstamp) -rm -f common/timecode/$(DEPDIR)/$(am__dirstamp) -rm -f common/timecode/$(am__dirstamp) -rm -f common/utils/$(DEPDIR)/$(am__dirstamp) -rm -f common/utils/$(am__dirstamp) -rm -f common/web/$(DEPDIR)/$(am__dirstamp) -rm -f common/web/$(am__dirstamp) -rm -f data/rdm/$(DEPDIR)/$(am__dirstamp) -rm -f data/rdm/$(am__dirstamp) -rm -f doxygen/examples/$(DEPDIR)/$(am__dirstamp) -rm -f doxygen/examples/$(am__dirstamp) -rm -f examples/$(DEPDIR)/$(am__dirstamp) -rm -f examples/$(am__dirstamp) -rm -f libs/acn/$(DEPDIR)/$(am__dirstamp) -rm -f libs/acn/$(am__dirstamp) -rm -f libs/usb/$(DEPDIR)/$(am__dirstamp) -rm -f libs/usb/$(am__dirstamp) -rm -f ola/$(DEPDIR)/$(am__dirstamp) -rm -f ola/$(am__dirstamp) -rm -f olad/$(DEPDIR)/$(am__dirstamp) -rm -f olad/$(am__dirstamp) -rm -f olad/plugin_api/$(DEPDIR)/$(am__dirstamp) -rm -f olad/plugin_api/$(am__dirstamp) -rm -f plugins/artnet/$(DEPDIR)/$(am__dirstamp) -rm -f plugins/artnet/$(am__dirstamp) -rm -f plugins/artnet/messages/$(DEPDIR)/$(am__dirstamp) -rm -f plugins/artnet/messages/$(am__dirstamp) -rm -f plugins/dmx4linux/$(DEPDIR)/$(am__dirstamp) -rm -f plugins/dmx4linux/$(am__dirstamp) -rm -f plugins/dummy/$(DEPDIR)/$(am__dirstamp) -rm -f plugins/dummy/$(am__dirstamp) -rm -f plugins/e131/$(DEPDIR)/$(am__dirstamp) -rm -f plugins/e131/$(am__dirstamp) -rm -f plugins/e131/messages/$(DEPDIR)/$(am__dirstamp) -rm -f plugins/e131/messages/$(am__dirstamp) -rm -f plugins/espnet/$(DEPDIR)/$(am__dirstamp) -rm -f plugins/espnet/$(am__dirstamp) -rm -f plugins/ftdidmx/$(DEPDIR)/$(am__dirstamp) -rm -f plugins/ftdidmx/$(am__dirstamp) -rm -f plugins/gpio/$(DEPDIR)/$(am__dirstamp) -rm -f plugins/gpio/$(am__dirstamp) -rm -f plugins/karate/$(DEPDIR)/$(am__dirstamp) -rm -f plugins/karate/$(am__dirstamp) -rm -f plugins/kinet/$(DEPDIR)/$(am__dirstamp) -rm -f plugins/kinet/$(am__dirstamp) -rm -f plugins/milinst/$(DEPDIR)/$(am__dirstamp) -rm -f plugins/milinst/$(am__dirstamp) -rm -f plugins/opendmx/$(DEPDIR)/$(am__dirstamp) -rm -f plugins/opendmx/$(am__dirstamp) -rm -f plugins/openpixelcontrol/$(DEPDIR)/$(am__dirstamp) -rm -f plugins/openpixelcontrol/$(am__dirstamp) -rm -f plugins/osc/$(DEPDIR)/$(am__dirstamp) -rm -f plugins/osc/$(am__dirstamp) -rm -f plugins/pathport/$(DEPDIR)/$(am__dirstamp) -rm -f plugins/pathport/$(am__dirstamp) -rm -f plugins/renard/$(DEPDIR)/$(am__dirstamp) -rm -f plugins/renard/$(am__dirstamp) -rm -f plugins/sandnet/$(DEPDIR)/$(am__dirstamp) -rm -f plugins/sandnet/$(am__dirstamp) -rm -f plugins/shownet/$(DEPDIR)/$(am__dirstamp) -rm -f plugins/shownet/$(am__dirstamp) -rm -f plugins/spi/$(DEPDIR)/$(am__dirstamp) -rm -f plugins/spi/$(am__dirstamp) -rm -f plugins/stageprofi/$(DEPDIR)/$(am__dirstamp) -rm -f plugins/stageprofi/$(am__dirstamp) -rm -f plugins/uartdmx/$(DEPDIR)/$(am__dirstamp) -rm -f plugins/uartdmx/$(am__dirstamp) -rm -f plugins/usbdmx/$(DEPDIR)/$(am__dirstamp) -rm -f plugins/usbdmx/$(am__dirstamp) -rm -f plugins/usbpro/$(DEPDIR)/$(am__dirstamp) -rm -f plugins/usbpro/$(am__dirstamp) -rm -f plugins/usbpro/messages/$(DEPDIR)/$(am__dirstamp) -rm -f plugins/usbpro/messages/$(am__dirstamp) -rm -f protoc/$(DEPDIR)/$(am__dirstamp) -rm -f protoc/$(am__dirstamp) -rm -f tools/e133/$(DEPDIR)/$(am__dirstamp) -rm -f tools/e133/$(am__dirstamp) -rm -f tools/ja-rule/$(DEPDIR)/$(am__dirstamp) -rm -f tools/ja-rule/$(am__dirstamp) -rm -f tools/logic/$(DEPDIR)/$(am__dirstamp) -rm -f tools/logic/$(am__dirstamp) -rm -f tools/ola_trigger/$(DEPDIR)/$(am__dirstamp) -rm -f tools/ola_trigger/$(am__dirstamp) -rm -f tools/rdmpro/$(DEPDIR)/$(am__dirstamp) -rm -f tools/rdmpro/$(am__dirstamp) -rm -f tools/usbpro/$(DEPDIR)/$(am__dirstamp) -rm -f tools/usbpro/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-recursive clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libtool clean-noinstLTLIBRARIES \ clean-noinstPROGRAMS mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf common/base/$(DEPDIR) common/dmx/$(DEPDIR) common/export_map/$(DEPDIR) common/file/$(DEPDIR) common/http/$(DEPDIR) common/io/$(DEPDIR) common/math/$(DEPDIR) common/messaging/$(DEPDIR) common/network/$(DEPDIR) common/protocol/$(DEPDIR) common/rdm/$(DEPDIR) common/rpc/$(DEPDIR) common/strings/$(DEPDIR) common/system/$(DEPDIR) common/testing/$(DEPDIR) common/thread/$(DEPDIR) common/timecode/$(DEPDIR) common/utils/$(DEPDIR) common/web/$(DEPDIR) data/rdm/$(DEPDIR) doxygen/examples/$(DEPDIR) examples/$(DEPDIR) libs/acn/$(DEPDIR) libs/usb/$(DEPDIR) ola/$(DEPDIR) olad/$(DEPDIR) olad/plugin_api/$(DEPDIR) plugins/artnet/$(DEPDIR) plugins/artnet/messages/$(DEPDIR) plugins/dmx4linux/$(DEPDIR) plugins/dummy/$(DEPDIR) plugins/e131/$(DEPDIR) plugins/e131/messages/$(DEPDIR) plugins/espnet/$(DEPDIR) plugins/ftdidmx/$(DEPDIR) plugins/gpio/$(DEPDIR) plugins/karate/$(DEPDIR) plugins/kinet/$(DEPDIR) plugins/milinst/$(DEPDIR) plugins/opendmx/$(DEPDIR) plugins/openpixelcontrol/$(DEPDIR) plugins/osc/$(DEPDIR) plugins/pathport/$(DEPDIR) plugins/renard/$(DEPDIR) plugins/sandnet/$(DEPDIR) plugins/shownet/$(DEPDIR) plugins/spi/$(DEPDIR) plugins/stageprofi/$(DEPDIR) plugins/uartdmx/$(DEPDIR) plugins/usbdmx/$(DEPDIR) plugins/usbpro/$(DEPDIR) plugins/usbpro/messages/$(DEPDIR) protoc/$(DEPDIR) tools/e133/$(DEPDIR) tools/ja-rule/$(DEPDIR) tools/logic/$(DEPDIR) tools/ola_trigger/$(DEPDIR) tools/rdmpro/$(DEPDIR) tools/usbpro/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr distclean-libtool distclean-tags dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dist_angularDATA \ install-dist_angularrouteDATA install-dist_bootcssDATA \ install-dist_bootfontsDATA install-dist_bootjsDATA \ install-dist_cssDATA install-dist_imgDATA \ install-dist_jqueryDATA install-dist_jsDATA \ install-dist_newDATA install-dist_piddataDATA \ install-dist_tools_rdm_testserver_imagesDATA \ install-dist_tools_rdm_testserver_staticDATA \ install-dist_viewsDATA install-dist_wwwDATA install-man \ install-nodist_artnetincludeHEADERS \ install-nodist_e131includeHEADERS \ install-nodist_olabaseincludeHEADERS \ install-nodist_olardmincludeHEADERS \ install-nodist_olatimecodeincludeHEADERS \ install-nodist_pkgincludeHEADERS \ install-nodist_pkgpythonPYTHON install-nodist_rdmtestsPYTHON \ install-nodist_rpcpythonPYTHON \ install-nodist_usbproincludeHEADERS \ install-olaacnincludeHEADERS install-olabaseincludeHEADERS \ install-olaclientincludeHEADERS install-oladincludeHEADERS \ install-oladmxincludeHEADERS install-olae133includeHEADERS \ install-olafileincludeHEADERS install-olahttpincludeHEADERS \ install-olaioincludeHEADERS install-olamathincludeHEADERS \ install-olamessagingincludeHEADERS \ install-olanetworkincludeHEADERS install-olardmincludeHEADERS \ install-olarpcincludeHEADERS install-olastlincludeHEADERS \ install-olastringsincludeHEADERS \ install-olasystemincludeHEADERS \ install-olathreadincludeHEADERS \ install-olatimecodeincludeHEADERS \ install-olautilincludeHEADERS install-olawebincludeHEADERS \ install-olawinincludeHEADERS install-pkgconfigDATA \ install-pkgincludeHEADERS install-pkgpythonPYTHON \ install-rdminitPYTHON install-rdmtestsPYTHON \ install-rpcpythonPYTHON install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-binPROGRAMS install-dist_rdmtestsexecSCRIPTS \ install-libLTLIBRARIES @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-exec-hook install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-man1 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 -rf common/base/$(DEPDIR) common/dmx/$(DEPDIR) common/export_map/$(DEPDIR) common/file/$(DEPDIR) common/http/$(DEPDIR) common/io/$(DEPDIR) common/math/$(DEPDIR) common/messaging/$(DEPDIR) common/network/$(DEPDIR) common/protocol/$(DEPDIR) common/rdm/$(DEPDIR) common/rpc/$(DEPDIR) common/strings/$(DEPDIR) common/system/$(DEPDIR) common/testing/$(DEPDIR) common/thread/$(DEPDIR) common/timecode/$(DEPDIR) common/utils/$(DEPDIR) common/web/$(DEPDIR) data/rdm/$(DEPDIR) doxygen/examples/$(DEPDIR) examples/$(DEPDIR) libs/acn/$(DEPDIR) libs/usb/$(DEPDIR) ola/$(DEPDIR) olad/$(DEPDIR) olad/plugin_api/$(DEPDIR) plugins/artnet/$(DEPDIR) plugins/artnet/messages/$(DEPDIR) plugins/dmx4linux/$(DEPDIR) plugins/dummy/$(DEPDIR) plugins/e131/$(DEPDIR) plugins/e131/messages/$(DEPDIR) plugins/espnet/$(DEPDIR) plugins/ftdidmx/$(DEPDIR) plugins/gpio/$(DEPDIR) plugins/karate/$(DEPDIR) plugins/kinet/$(DEPDIR) plugins/milinst/$(DEPDIR) plugins/opendmx/$(DEPDIR) plugins/openpixelcontrol/$(DEPDIR) plugins/osc/$(DEPDIR) plugins/pathport/$(DEPDIR) plugins/renard/$(DEPDIR) plugins/sandnet/$(DEPDIR) plugins/shownet/$(DEPDIR) plugins/spi/$(DEPDIR) plugins/stageprofi/$(DEPDIR) plugins/uartdmx/$(DEPDIR) plugins/usbdmx/$(DEPDIR) plugins/usbpro/$(DEPDIR) plugins/usbpro/messages/$(DEPDIR) protoc/$(DEPDIR) tools/e133/$(DEPDIR) tools/ja-rule/$(DEPDIR) tools/logic/$(DEPDIR) tools/ola_trigger/$(DEPDIR) tools/rdmpro/$(DEPDIR) tools/usbpro/$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-dist_angularDATA \ uninstall-dist_angularrouteDATA uninstall-dist_bootcssDATA \ uninstall-dist_bootfontsDATA uninstall-dist_bootjsDATA \ uninstall-dist_cssDATA uninstall-dist_imgDATA \ uninstall-dist_jqueryDATA uninstall-dist_jsDATA \ uninstall-dist_newDATA uninstall-dist_piddataDATA \ uninstall-dist_rdmtestsexecSCRIPTS \ uninstall-dist_tools_rdm_testserver_imagesDATA \ uninstall-dist_tools_rdm_testserver_staticDATA \ uninstall-dist_viewsDATA uninstall-dist_wwwDATA \ uninstall-libLTLIBRARIES uninstall-man \ uninstall-nodist_artnetincludeHEADERS \ uninstall-nodist_e131includeHEADERS \ uninstall-nodist_olabaseincludeHEADERS \ uninstall-nodist_olardmincludeHEADERS \ uninstall-nodist_olatimecodeincludeHEADERS \ uninstall-nodist_pkgincludeHEADERS \ uninstall-nodist_pkgpythonPYTHON \ uninstall-nodist_rdmtestsPYTHON \ uninstall-nodist_rpcpythonPYTHON \ uninstall-nodist_usbproincludeHEADERS \ uninstall-olaacnincludeHEADERS uninstall-olabaseincludeHEADERS \ uninstall-olaclientincludeHEADERS uninstall-oladincludeHEADERS \ uninstall-oladmxincludeHEADERS uninstall-olae133includeHEADERS \ uninstall-olafileincludeHEADERS \ uninstall-olahttpincludeHEADERS uninstall-olaioincludeHEADERS \ uninstall-olamathincludeHEADERS \ uninstall-olamessagingincludeHEADERS \ uninstall-olanetworkincludeHEADERS \ uninstall-olardmincludeHEADERS uninstall-olarpcincludeHEADERS \ uninstall-olastlincludeHEADERS \ uninstall-olastringsincludeHEADERS \ uninstall-olasystemincludeHEADERS \ uninstall-olathreadincludeHEADERS \ uninstall-olatimecodeincludeHEADERS \ uninstall-olautilincludeHEADERS uninstall-olawebincludeHEADERS \ uninstall-olawinincludeHEADERS uninstall-pkgconfigDATA \ uninstall-pkgincludeHEADERS uninstall-pkgpythonPYTHON \ uninstall-rdminitPYTHON uninstall-rdmtestsPYTHON \ uninstall-rpcpythonPYTHON uninstall-man: uninstall-man1 .MAKE: $(am__recursive_targets) all check check-am install install-am \ install-exec-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--refresh check check-TESTS check-am clean clean-binPROGRAMS \ clean-checkPROGRAMS clean-cscope clean-generic \ clean-libLTLIBRARIES clean-libtool clean-noinstLTLIBRARIES \ clean-noinstPROGRAMS cscope cscopelist-am ctags ctags-am dist \ dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \ dist-xz dist-zip distcheck distclean distclean-compile \ distclean-generic distclean-hdr distclean-libtool \ distclean-tags distcleancheck distdir distuninstallcheck dvi \ dvi-am html html-am info info-am install install-am \ install-binPROGRAMS install-data install-data-am \ install-dist_angularDATA install-dist_angularrouteDATA \ install-dist_bootcssDATA install-dist_bootfontsDATA \ install-dist_bootjsDATA install-dist_cssDATA \ install-dist_imgDATA install-dist_jqueryDATA \ install-dist_jsDATA install-dist_newDATA \ install-dist_piddataDATA install-dist_rdmtestsexecSCRIPTS \ install-dist_tools_rdm_testserver_imagesDATA \ install-dist_tools_rdm_testserver_staticDATA \ install-dist_viewsDATA install-dist_wwwDATA install-dvi \ install-dvi-am install-exec install-exec-am install-exec-hook \ install-html install-html-am install-info install-info-am \ install-libLTLIBRARIES install-man install-man1 \ install-nodist_artnetincludeHEADERS \ install-nodist_e131includeHEADERS \ install-nodist_olabaseincludeHEADERS \ install-nodist_olardmincludeHEADERS \ install-nodist_olatimecodeincludeHEADERS \ install-nodist_pkgincludeHEADERS \ install-nodist_pkgpythonPYTHON install-nodist_rdmtestsPYTHON \ install-nodist_rpcpythonPYTHON \ install-nodist_usbproincludeHEADERS \ install-olaacnincludeHEADERS install-olabaseincludeHEADERS \ install-olaclientincludeHEADERS install-oladincludeHEADERS \ install-oladmxincludeHEADERS install-olae133includeHEADERS \ install-olafileincludeHEADERS install-olahttpincludeHEADERS \ install-olaioincludeHEADERS install-olamathincludeHEADERS \ install-olamessagingincludeHEADERS \ install-olanetworkincludeHEADERS install-olardmincludeHEADERS \ install-olarpcincludeHEADERS install-olastlincludeHEADERS \ install-olastringsincludeHEADERS \ install-olasystemincludeHEADERS \ install-olathreadincludeHEADERS \ install-olatimecodeincludeHEADERS \ install-olautilincludeHEADERS install-olawebincludeHEADERS \ install-olawinincludeHEADERS install-pdf install-pdf-am \ install-pkgconfigDATA install-pkgincludeHEADERS \ install-pkgpythonPYTHON install-ps install-ps-am \ install-rdminitPYTHON install-rdmtestsPYTHON \ install-rpcpythonPYTHON install-strip installcheck \ installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ recheck tags tags-am uninstall uninstall-am \ uninstall-binPROGRAMS uninstall-dist_angularDATA \ uninstall-dist_angularrouteDATA uninstall-dist_bootcssDATA \ uninstall-dist_bootfontsDATA uninstall-dist_bootjsDATA \ uninstall-dist_cssDATA uninstall-dist_imgDATA \ uninstall-dist_jqueryDATA uninstall-dist_jsDATA \ uninstall-dist_newDATA uninstall-dist_piddataDATA \ uninstall-dist_rdmtestsexecSCRIPTS \ uninstall-dist_tools_rdm_testserver_imagesDATA \ uninstall-dist_tools_rdm_testserver_staticDATA \ uninstall-dist_viewsDATA uninstall-dist_wwwDATA \ uninstall-libLTLIBRARIES uninstall-man uninstall-man1 \ uninstall-nodist_artnetincludeHEADERS \ uninstall-nodist_e131includeHEADERS \ uninstall-nodist_olabaseincludeHEADERS \ uninstall-nodist_olardmincludeHEADERS \ uninstall-nodist_olatimecodeincludeHEADERS \ uninstall-nodist_pkgincludeHEADERS \ uninstall-nodist_pkgpythonPYTHON \ uninstall-nodist_rdmtestsPYTHON \ uninstall-nodist_rpcpythonPYTHON \ uninstall-nodist_usbproincludeHEADERS \ uninstall-olaacnincludeHEADERS uninstall-olabaseincludeHEADERS \ uninstall-olaclientincludeHEADERS uninstall-oladincludeHEADERS \ uninstall-oladmxincludeHEADERS uninstall-olae133includeHEADERS \ uninstall-olafileincludeHEADERS \ uninstall-olahttpincludeHEADERS uninstall-olaioincludeHEADERS \ uninstall-olamathincludeHEADERS \ uninstall-olamessagingincludeHEADERS \ uninstall-olanetworkincludeHEADERS \ uninstall-olardmincludeHEADERS uninstall-olarpcincludeHEADERS \ uninstall-olastlincludeHEADERS \ uninstall-olastringsincludeHEADERS \ uninstall-olasystemincludeHEADERS \ uninstall-olathreadincludeHEADERS \ uninstall-olatimecodeincludeHEADERS \ uninstall-olautilincludeHEADERS uninstall-olawebincludeHEADERS \ uninstall-olawinincludeHEADERS uninstall-pkgconfigDATA \ uninstall-pkgincludeHEADERS uninstall-pkgpythonPYTHON \ uninstall-rdminitPYTHON uninstall-rdmtestsPYTHON \ uninstall-rpcpythonPYTHON .PRECIOUS: Makefile @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@doxygen-ps: @DX_DOCDIR@/@PACKAGE@.ps @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@@DX_DOCDIR@/@PACKAGE@.ps: @DX_DOCDIR@/@PACKAGE@.tag @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@ cd @DX_DOCDIR@/latex; \ @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@ rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \ @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@ $(DX_LATEX) refman.tex; \ @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@ $(MAKEINDEX_PATH) refman.idx; \ @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@ $(DX_LATEX) refman.tex; \ @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@ countdown=5; \ @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@ while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \ @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@ refman.log > /dev/null 2>&1 \ @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@ && test $$countdown -gt 0; do \ @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@ $(DX_LATEX) refman.tex; \ @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@ countdown=`expr $$countdown - 1`; \ @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@ done; \ @DX_COND_doc_TRUE@@DX_COND_ps_TRUE@ $(DX_DVIPS) -o ../@PACKAGE@.ps refman.dvi @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@doxygen-pdf: @DX_DOCDIR@/@PACKAGE@.pdf @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@@DX_DOCDIR@/@PACKAGE@.pdf: @DX_DOCDIR@/@PACKAGE@.tag @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@ cd @DX_DOCDIR@/latex; \ @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@ rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \ @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@ $(DX_PDFLATEX) refman.tex; \ @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@ $(DX_MAKEINDEX) refman.idx; \ @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@ $(DX_PDFLATEX) refman.tex; \ @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@ countdown=5; \ @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@ while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \ @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@ refman.log > /dev/null 2>&1 \ @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@ && test $$countdown -gt 0; do \ @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@ $(DX_PDFLATEX) refman.tex; \ @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@ countdown=`expr $$countdown - 1`; \ @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@ done; \ @DX_COND_doc_TRUE@@DX_COND_pdf_TRUE@ mv refman.pdf ../@PACKAGE@.pdf @DX_COND_doc_TRUE@.PHONY: doxygen-run doxygen-doc $(DX_PS_GOAL) $(DX_PDF_GOAL) @DX_COND_doc_TRUE@.INTERMEDIATE: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL) @DX_COND_doc_TRUE@doxygen-run: @DX_DOCDIR@/@PACKAGE@.tag @DX_COND_doc_TRUE@doxygen-doc: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL) @DX_COND_doc_TRUE@@DX_DOCDIR@/@PACKAGE@.tag: $(DX_CONFIG) $(pkginclude_HEADERS) @DX_COND_doc_TRUE@ rm -rf @DX_DOCDIR@ @DX_COND_doc_TRUE@ $(DX_ENV) $(DX_DOXYGEN) $(srcdir)/$(DX_CONFIG) common/protocol/Ola.pb.cc common/protocol/Ola.pb.h: common/protocol/Makefile.mk common/protocol/Ola.proto $(PROTOC) --cpp_out common/protocol --proto_path $(srcdir)/common/protocol $(srcdir)/common/protocol/Ola.proto common/protocol/OlaService.pb.cpp common/protocol/OlaService.pb.h: common/protocol/Makefile.mk common/protocol/Ola.proto protoc/ola_protoc_plugin$(EXEEXT) $(OLA_PROTOC) --cppservice_out common/protocol --proto_path $(srcdir)/common/protocol $(srcdir)/common/protocol/Ola.proto common/rdm/Pids.pb.cc common/rdm/Pids.pb.h: common/rdm/Makefile.mk common/rdm/Pids.proto $(PROTOC) --cpp_out common/rdm --proto_path $(srcdir)/common/rdm $(srcdir)/common/rdm/Pids.proto common/rpc/Rpc.pb.cc common/rpc/Rpc.pb.h: common/rpc/Makefile.mk common/rpc/Rpc.proto $(PROTOC) --cpp_out common/rpc --proto_path $(srcdir)/common/rpc $(srcdir)/common/rpc/Rpc.proto common/rpc/TestService.pb.cc common/rpc/TestService.pb.h: common/rpc/Makefile.mk common/rpc/TestService.proto $(PROTOC) --cpp_out common/rpc --proto_path $(srcdir)/common/rpc $(srcdir)/common/rpc/TestService.proto common/rpc/TestServiceService.pb.cpp common/rpc/TestServiceService.pb.h: common/rpc/Makefile.mk common/rpc/TestService.proto protoc/ola_protoc_plugin$(EXEEXT) $(OLA_PROTOC) --cppservice_out common/rpc --proto_path $(srcdir)/common/rpc $(srcdir)/common/rpc/TestService.proto data/rdm/PidDataTest.sh: data/rdm/Makefile.mk echo "PYTHONPATH=${top_builddir}/python PIDDATA=${srcdir}/data/rdm $(PYTHON) ${srcdir}/data/rdm/PidDataTest.py; exit \$$?" > data/rdm/PidDataTest.sh chmod +x data/rdm/PidDataTest.sh # Many of the example programs are just symlinks to ola_dev_info @BUILD_EXAMPLES_TRUE@install-exec-hook-examples: @BUILD_EXAMPLES_TRUE@ $(LN_S) -f $(bindir)/ola_dev_info $(DESTDIR)$(bindir)/$(OLA_PATCH_NAME) @BUILD_EXAMPLES_TRUE@ $(LN_S) -f $(bindir)/ola_dev_info $(DESTDIR)$(bindir)/ola_plugin_info @BUILD_EXAMPLES_TRUE@ $(LN_S) -f $(bindir)/ola_dev_info $(DESTDIR)$(bindir)/ola_set_dmx @BUILD_EXAMPLES_TRUE@ $(LN_S) -f $(bindir)/ola_dev_info $(DESTDIR)$(bindir)/ola_set_priority @BUILD_EXAMPLES_TRUE@ $(LN_S) -f $(bindir)/ola_dev_info $(DESTDIR)$(bindir)/ola_uni_info @BUILD_EXAMPLES_TRUE@ $(LN_S) -f $(bindir)/ola_dev_info $(DESTDIR)$(bindir)/ola_uni_merge @BUILD_EXAMPLES_TRUE@ $(LN_S) -f $(bindir)/ola_dev_info $(DESTDIR)$(bindir)/ola_uni_name @BUILD_EXAMPLES_TRUE@ $(LN_S) -f $(bindir)/ola_dev_info $(DESTDIR)$(bindir)/ola_plugin_state @BUILD_EXAMPLES_TRUE@ $(LN_S) -f $(bindir)/ola_rdm_get $(DESTDIR)$(bindir)/ola_rdm_set @BUILD_EXAMPLES_TRUE@examples/RecorderVerifyTest.sh: examples/Makefile.mk @BUILD_EXAMPLES_TRUE@ echo "for FILE in ${srcdir}/examples/testdata/dos_line_endings ${srcdir}/examples/testdata/multiple_unis ${srcdir}/examples/testdata/partial_frames ${srcdir}/examples/testdata/single_uni ${srcdir}/examples/testdata/trailing_timeout; do echo \"Checking \$$FILE\"; ${top_builddir}/examples/ola_recorder${EXEEXT} --verify \$$FILE; STATUS=\$$?; if [ \$$STATUS -ne 0 ]; then echo \"FAIL: \$$FILE caused ola_recorder to exit with status \$$STATUS\"; exit \$$STATUS; fi; done; exit 0" > examples/RecorderVerifyTest.sh @BUILD_EXAMPLES_TRUE@ chmod +x examples/RecorderVerifyTest.sh include/ola/rdm/RDMResponseCodes.h: include/ola/rdm/Makefile.mk include/ola/rdm/make_rdm_codes.sh common/protocol/Ola.proto mkdir -p $(top_builddir)/include/ola/rdm sh $(top_srcdir)/include/ola/rdm/make_rdm_codes.sh $(top_srcdir)/common/protocol/Ola.proto > $(top_builddir)/include/ola/rdm/RDMResponseCodes.h include/ola/timecode/TimeCodeEnums.h: include/ola/timecode/Makefile.mk include/ola/timecode/make_timecode.sh common/protocol/Ola.proto mkdir -p $(top_builddir)/include/ola/timecode sh $(top_srcdir)/include/ola/timecode/make_timecode.sh $(top_srcdir)/common/protocol/Ola.proto > $(top_builddir)/include/ola/timecode/TimeCodeEnums.h include/ola/plugin_id.h: include/ola/Makefile.mk include/ola/make_plugin_id.sh common/protocol/Ola.proto mkdir -p $(top_builddir)/include/ola sh $(top_srcdir)/include/ola/make_plugin_id.sh $(top_srcdir)/common/protocol/Ola.proto > $(top_builddir)/include/ola/plugin_id.h @USE_ARTNET_TRUE@plugins/artnet/messages/ArtNetConfigMessages.pb.cc plugins/artnet/messages/ArtNetConfigMessages.pb.h: plugins/artnet/messages/Makefile.mk plugins/artnet/messages/ArtNetConfigMessages.proto @USE_ARTNET_TRUE@ $(PROTOC) --cpp_out plugins/artnet/messages/ --proto_path $(srcdir)/plugins/artnet/messages $(srcdir)/plugins/artnet/messages/ArtNetConfigMessages.proto @USING_WIN32_FALSE@plugins/usbpro/messages/UsbProConfigMessages.pb.cc plugins/usbpro/messages/UsbProConfigMessages.pb.h: plugins/usbpro/messages/Makefile.mk plugins/usbpro/messages/UsbProConfigMessages.proto @USING_WIN32_FALSE@ $(PROTOC) --cpp_out plugins/usbpro/messages/ --proto_path $(srcdir)/plugins/usbpro/messages/ $(srcdir)/plugins/usbpro/messages/UsbProConfigMessages.proto @USE_E131_TRUE@@USING_WIN32_FALSE@plugins/e131/messages/E131ConfigMessages.pb.cc plugins/e131/messages/E131ConfigMessages.pb.h: plugins/e131/messages/Makefile.mk plugins/e131/messages/E131ConfigMessages.proto @USE_E131_TRUE@@USING_WIN32_FALSE@ $(PROTOC) --cpp_out plugins/e131/messages/ --proto_path $(srcdir)/plugins/e131/messages/ $(srcdir)/plugins/e131/messages/E131ConfigMessages.proto # If we're using a different ola_protoc_plugin, we need to provide a rule to # create this file since the generated service configs depend on it. @BUILD_OLA_PROTOC_PLUGIN_FALSE@protoc/ola_protoc_plugin$(EXEEXT): @BUILD_OLA_PROTOC_PLUGIN_FALSE@ touch protoc/ola_protoc_plugin$(EXEEXT) python/ola/rpc/Rpc_pb2.py: common/rpc/Rpc.proto mkdir -p python/ola/rpc $(PROTOC) --python_out python/ola/rpc -I ${top_srcdir}/common/rpc/ ${top_srcdir}/common/rpc/Rpc.proto python/ola/rpc/SimpleRpcControllerTest.sh: python/ola/rpc/Makefile.mk mkdir -p python/ola/rpc echo "export PYTHONPATH=${top_builddir}/python:${top_srcdir}/python; $(PYTHON) ${srcdir}/python/ola/rpc/SimpleRpcControllerTest.py; exit \$$?" > python/ola/rpc/SimpleRpcControllerTest.sh chmod +x python/ola/rpc/SimpleRpcControllerTest.sh python/ola/ArtNetConfigMessages_pb2.py: $(artnet_proto) $(PROTOC) --python_out python/ola/ -I $(artnet_path) $(artnet_proto) python/ola/Ola_pb2.py: $(ola_proto) $(PROTOC) --python_out python/ola/ -I $(ola_path) $(ola_proto) python/ola/Pids_pb2.py: $(pids_proto) $(PROTOC) --python_out python/ola/ -I $(pids_path) $(pids_proto) python/ola/UsbProConfigMessages_pb2.py: $(usbpro_proto) $(PROTOC) --python_out python/ola/ -I $(usbpro_path) $(usbpro_proto) python/ola/PidStoreLocation.py: python/ola/Makefile.mk configure.ac echo "location = '${piddatadir}'" > python/ola/PidStoreLocation.py python/ola/Version.py: python/ola/Makefile.mk configure.ac config/ola_version.m4 echo "version = '${VERSION}'" > python/ola/Version.py tools/ola_trigger/lex.yy.cpp: tools/ola_trigger/Makefile.mk tools/ola_trigger/config.lex $(LEX) -otools/ola_trigger/lex.yy.cpp $(srcdir)/tools/ola_trigger/config.lex tools/ola_trigger/config.tab.cpp tools/ola_trigger/config.tab.h: tools/ola_trigger/Makefile.mk tools/ola_trigger/config.ypp $(BISON) --defines=tools/ola_trigger/config.tab.h --output-file=tools/ola_trigger/config.tab.cpp $(srcdir)/tools/ola_trigger/config.ypp tools/ola_trigger/FileValidateTest.sh: tools/ola_trigger/Makefile.mk echo "for FILE in ${srcdir}/tools/ola_trigger/example.conf ${srcdir}/tools/ola_trigger/test_file.conf ${srcdir}/tools/ola_trigger/contrib/mac_volume.conf ${srcdir}/tools/ola_trigger/contrib/mac_itunes.conf ${srcdir}/tools/ola_trigger/contrib/philips_hue_osram_lightify.conf; do echo \"Checking \$$FILE\"; ${top_builddir}/tools/ola_trigger/ola_trigger${EXEEXT} --validate \$$FILE; STATUS=\$$?; if [ \$$STATUS -ne 0 ]; then echo \"FAIL: \$$FILE caused ola_trigger to exit with status \$$STATUS\"; exit \$$STATUS; fi; done; exit 0" > tools/ola_trigger/FileValidateTest.sh chmod +x tools/ola_trigger/FileValidateTest.sh # Create DataLocation.py with the directory of the static files. @INSTALL_RDM_TESTS_TRUE@tools/rdm/DataLocation.py: tools/rdm/Makefile.mk @INSTALL_RDM_TESTS_TRUE@ mkdir -p $(top_builddir)/tools/rdm @INSTALL_RDM_TESTS_TRUE@ echo "location = '${datadir}/ola/rdm-server'" > $(top_builddir)/tools/rdm/DataLocation.py install-exec-hook: $(INSTALL_EXEC_HOOKS) # ----------------------------------------------------------------------------- # This gives us a rather hacky method to build the files normally built during # the build, so they are present for Doxygen to run against builtfiles : Makefile.am $(built_sources) .PHONY : builtfiles # dvi is run from make distcheck. Do nothing. dvi: # 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: ola-0.10.5.nojsmin/libs/0000755000175000017500000000000013155164170014414 5ustar wouterwouterola-0.10.5.nojsmin/libs/Makefile.mk0000644000175000017500000000007213023355232016454 0ustar wouterwouterinclude libs/acn/Makefile.mk include libs/usb/Makefile.mk ola-0.10.5.nojsmin/libs/usb/0000755000175000017500000000000013134123610015174 5ustar wouterwouterola-0.10.5.nojsmin/libs/usb/JaRulePortHandleImpl.h0000644000175000017500000001262413023355232021343 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * JaRulePortHandleImpl.h * The implementation of the Ja Rule Port Handle. * Copyright (C) 2015 Simon Newton */ #ifndef LIBS_USB_JARULEPORTHANDLEIMPL_H_ #define LIBS_USB_JARULEPORTHANDLEIMPL_H_ #include #include #include #include #include #include #include #include #include #include "libs/usb/JaRuleConstants.h" namespace ola { namespace usb { /** * @brief The internal implementation of a Ja Rule Port Handle. * * This class is responsible for translating high level intent, e.g. "send RDM * command" to the binary messages that can then be passed to a JaRuleWidget. */ class JaRulePortHandleImpl : public ola::rdm::DiscoveryTargetInterface, public ola::rdm::DiscoverableRDMControllerInterface { public: /** * @brief Create a new JaRulePortHandleImpl. */ JaRulePortHandleImpl(class JaRuleWidgetPort *parent_port, const ola::rdm::UID &uid, uint8_t physical_port); ~JaRulePortHandleImpl(); // From DiscoverableRDMControllerInterface void RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback); void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback); void SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *on_complete); // From DiscoveryTargetInterface void MuteDevice(const ola::rdm::UID &target, MuteDeviceCallback *mute_complete); void UnMuteAll(UnMuteDeviceCallback *unmute_complete); void Branch(const ola::rdm::UID &lower, const ola::rdm::UID &upper, BranchCallback *branch_complete); /** * @brief Send DMX data from this widget * @param buffer The DmxBuffer containing the data to send. * @returns true if the data was sent, false otherwise. */ bool SendDMX(const DmxBuffer &buffer); /** * @brief Change the mode of this port. */ bool SetPortMode(JaRulePortMode new_mode); private: PACK( struct DUBTiming { uint16_t start; //!< The start of the discovery response. uint16_t end; //!< The end of the discovery response. }); PACK( struct GetSetTiming { uint16_t break_start; //!< The start of the break. uint16_t mark_start; //!< The start of the mark / end of the break. uint16_t mark_end; //!< The end of the mark. }); class JaRuleWidgetPort* const m_port; // not owned const ola::rdm::UID m_uid; const uint8_t m_physical_port; bool m_in_shutdown; // DMX members DmxBuffer m_dmx; bool m_dmx_in_progress; bool m_dmx_queued; CommandCompleteCallback *m_dmx_callback; // RDM members ola::rdm::DiscoveryAgent m_discovery_agent; ola::SequenceNumber m_transaction_number; ola::rdm::UIDSet m_uids; void CheckStatusFlags(uint8_t flags); void DMXComplete(USBCommandResult result, JaRuleReturnCode return_code, uint8_t status_flags, const ola::io::ByteString &payload); void MuteDeviceComplete(MuteDeviceCallback *mute_complete, USBCommandResult result, JaRuleReturnCode return_code, uint8_t status_flags, const ola::io::ByteString &payload); void UnMuteDeviceComplete(UnMuteDeviceCallback *unmute_complete, USBCommandResult result, JaRuleReturnCode return_code, uint8_t status_flags, const ola::io::ByteString &payload); void DUBComplete(BranchCallback *callback, USBCommandResult status, JaRuleReturnCode return_code, uint8_t status_flags, const ola::io::ByteString &payload); void RDMComplete(const ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *m_rdm_callback, USBCommandResult result, JaRuleReturnCode return_code, uint8_t status_flags, const ola::io::ByteString &payload); ola::rdm::RDMResponse* UnpackRDMResponse( const ola::rdm::RDMRequest *request, const ola::io::ByteString &payload, ola::rdm::RDMStatusCode *status_code); void DiscoveryComplete(ola::rdm::RDMDiscoveryCallback *callback, OLA_UNUSED bool ok, const ola::rdm::UIDSet &uids); CommandClass GetCommandFromRequest(const ola::rdm::RDMRequest *request); DISALLOW_COPY_AND_ASSIGN(JaRulePortHandleImpl); }; } // namespace usb } // namespace ola #endif // LIBS_USB_JARULEPORTHANDLEIMPL_H_ ola-0.10.5.nojsmin/libs/usb/Types.cpp0000644000175000017500000000301413023355232017006 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Types.cpp * Types used with the USB subsystem. * Copyright (C) 2015 Simon Newton */ #include "libs/usb/Types.h" #include #include "ola/strings/Format.h" namespace ola { namespace usb { using std::ostream; USBDeviceID::USBDeviceID(uint8_t bus_number, uint8_t device_address) : bus_number(bus_number), device_address(device_address) { } bool USBDeviceID::operator<(const USBDeviceID &id) const { if (bus_number < id.bus_number) { return true; } else if (bus_number == id.bus_number) { return device_address < id.device_address; } return false; } ostream& operator<<(ostream& os, const USBDeviceID &id) { return os << ola::strings::IntToString(id.bus_number) << ":" << ola::strings::IntToString(id.device_address); } } // namespace usb } // namespace ola ola-0.10.5.nojsmin/libs/usb/JaRuleWidget.cpp0000644000175000017500000001725013023355232020237 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * JaRuleWidget.cpp * A Ja Rule widget. * Copyright (C) 2015 Simon Newton */ #include "libs/usb/JaRuleWidget.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "libs/usb/JaRulePortHandle.h" #include "libs/usb/JaRuleWidgetPort.h" namespace ola { namespace usb { using ola::io::ByteString; using ola::rdm::UID; using std::auto_ptr; using std::string; namespace { struct EndpointCapabilties { EndpointCapabilties() : in_supported(false), out_supported(false), in_interface(0), out_interface(0) {} bool in_supported; bool out_supported; int in_interface; int out_interface; }; } // namespace JaRuleWidget::JaRuleWidget(ola::thread::ExecutorInterface *executor, AsyncronousLibUsbAdaptor *adaptor, libusb_device *usb_device) : m_executor(executor), m_adaptor(adaptor), m_device(usb_device), m_usb_handle(NULL), m_uid(0, 0) { m_adaptor->RefDevice(m_device); } JaRuleWidget::~JaRuleWidget() { STLDeleteElements(&m_ports); if (m_usb_handle) { m_adaptor->Close(m_usb_handle); } m_adaptor->UnrefDevice(m_device); } bool JaRuleWidget::Init() { bool ok = InternalInit(); if (!ok) { STLDeleteElements(&m_ports); if (m_usb_handle) { m_adaptor->Close(m_usb_handle); m_usb_handle = NULL; } } return ok; } USBDeviceID JaRuleWidget::GetDeviceId() const { return m_adaptor->GetDeviceId(m_device); } void JaRuleWidget::CancelAll(uint8_t port_index) { if (port_index > m_ports.size() - 1) { return; } JaRuleWidgetPort *port_info = m_ports[port_index]; port_info->CancelAll(); } uint8_t JaRuleWidget::PortCount() const { return m_ports.size(); } UID JaRuleWidget::GetUID() const { return m_uid; } string JaRuleWidget::ManufacturerString() const { return m_manufacturer; } string JaRuleWidget::ProductString() const { return m_product; } JaRulePortHandle* JaRuleWidget::ClaimPort(uint8_t port_index) { if (port_index > m_ports.size() - 1) { return NULL; } return m_ports[port_index]->ClaimPort(); } void JaRuleWidget::ReleasePort(uint8_t port_index) { if (port_index > m_ports.size() - 1) { return; } m_ports[port_index]->ReleasePort(); } void JaRuleWidget::SendCommand(uint8_t port_index, CommandClass command, const uint8_t *data, unsigned int size, CommandCompleteCallback *callback) { if (port_index > m_ports.size() - 1) { OLA_WARN << "Invalid JaRule Port " << static_cast(port_index); if (callback) { callback->Run(COMMAND_RESULT_INVALID_PORT, RC_UNKNOWN, 0, ByteString()); } return; } m_ports[port_index]->SendCommand(command, data, size, callback); } // Private Methods // ---------------------------------------------------------------------------- bool JaRuleWidget::InternalInit() { struct libusb_config_descriptor *config; int error = m_adaptor->GetActiveConfigDescriptor(m_device, &config); if (error) { return false; } // Each endpoint address is 8 bits. Bit 7 is the endpoint direction (in/out). // The lower 4 bits are the endpoint number. We try to find bulk endpoints // with matching numbers. typedef std::map EndpointMap; EndpointMap endpoint_map; for (uint8_t iface_index = 0; iface_index < config->bNumInterfaces; iface_index++) { const struct libusb_interface &iface = config->interface[iface_index]; // We don't support alt settings. if (iface.num_altsetting != 1) { continue; } const struct libusb_interface_descriptor &iface_descriptor = iface.altsetting[0]; if (iface_descriptor.bInterfaceClass == LIBUSB_CLASS_VENDOR_SPEC && iface_descriptor.bInterfaceSubClass == SUBCLASS_VALUE && iface_descriptor.bInterfaceProtocol == PROTOCOL_VALUE) { // Vendor class, subclass & protocol for (uint8_t endpoint_index = 0; endpoint_index < iface_descriptor.bNumEndpoints; endpoint_index++) { const struct libusb_endpoint_descriptor &endpoint = iface_descriptor.endpoint[endpoint_index]; if ((endpoint.bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) != LIBUSB_TRANSFER_TYPE_BULK) { continue; } uint8_t endpoint_address = endpoint.bEndpointAddress; uint8_t endpoint_number = ( endpoint_address & LIBUSB_ENDPOINT_ADDRESS_MASK); uint8_t endpoint_direction = ( endpoint_address & LIBUSB_ENDPOINT_DIR_MASK); if (endpoint_direction == LIBUSB_ENDPOINT_IN) { endpoint_map[endpoint_number].in_supported = true; endpoint_map[endpoint_number].in_interface = iface_index; } if (endpoint_direction == LIBUSB_ENDPOINT_OUT) { endpoint_map[endpoint_number].out_supported = true; endpoint_map[endpoint_number].out_interface = iface_index; } } } } m_adaptor->FreeConfigDescriptor(config); if (!m_adaptor->OpenDevice(m_device, &m_usb_handle)) { return false; } // Get the serial number (UID) of the device. libusb_device_descriptor device_descriptor; if (m_adaptor->GetDeviceDescriptor(m_device, &device_descriptor)) { return false; } AsyncronousLibUsbAdaptor::DeviceInformation device_info; if (!m_adaptor->GetDeviceInfo(m_device, device_descriptor, &device_info)) { return false; } auto_ptr uid(UID::FromString(device_info.serial)); if (!uid.get() || uid->IsBroadcast()) { OLA_WARN << "Invalid JaRule serial number: " << device_info.serial; return false; } m_uid = *uid; m_manufacturer = device_info.manufacturer; m_product = device_info.product; std::set interfaces_to_claim; EndpointMap::const_iterator endpoint_iter = endpoint_map.begin(); uint8_t port_index = 0; for (; endpoint_iter != endpoint_map.end(); ++endpoint_iter) { const EndpointCapabilties &capabilites = endpoint_iter->second; if (capabilites.in_supported && capabilites.out_supported) { interfaces_to_claim.insert(capabilites.in_interface); interfaces_to_claim.insert(capabilites.out_interface); OLA_INFO << "Found Ja Rule port at " << static_cast(endpoint_iter->first); m_ports.push_back(new JaRuleWidgetPort( m_executor, m_adaptor, m_usb_handle, endpoint_iter->first, m_uid, port_index++)); } } std::set::const_iterator iface_iter = interfaces_to_claim.begin(); for (; iface_iter != interfaces_to_claim.end(); ++iface_iter) { if (m_adaptor->ClaimInterface(m_usb_handle, *iface_iter)) { return false; } } OLA_INFO << "Found JaRule device : " << m_uid; return true; } } // namespace usb } // namespace ola ola-0.10.5.nojsmin/libs/usb/Makefile.mk0000644000175000017500000000264113023355232017251 0ustar wouterwouter# LIBRARIES ################################################## if USE_LIBUSB noinst_LTLIBRARIES += libs/usb/libolausb.la libs_usb_libolausb_la_SOURCES = \ libs/usb/HotplugAgent.cpp \ libs/usb/HotplugAgent.h \ libs/usb/JaRuleConstants.h \ libs/usb/JaRuleConstants.cpp \ libs/usb/JaRulePortHandle.cpp \ libs/usb/JaRulePortHandle.h \ libs/usb/JaRulePortHandleImpl.cpp \ libs/usb/JaRulePortHandleImpl.h \ libs/usb/JaRuleWidget.cpp \ libs/usb/JaRuleWidget.h \ libs/usb/JaRuleWidgetPort.cpp \ libs/usb/JaRuleWidgetPort.h \ libs/usb/LibUsbAdaptor.cpp \ libs/usb/LibUsbAdaptor.h \ libs/usb/LibUsbThread.cpp \ libs/usb/LibUsbThread.h \ libs/usb/Types.cpp \ libs/usb/Types.h libs_usb_libolausb_la_CXXFLAGS = $(COMMON_CXXFLAGS) \ $(libusb_CFLAGS) libs_usb_libolausb_la_LIBADD = $(libusb_LIBS) \ common/libolacommon.la # TESTS ################################################## test_programs += libs/usb/LibUsbThreadTester LIBS_USB_TEST_LDADD = $(COMMON_TESTING_LIBS) \ $(libusb_LIBS) \ libs/usb/libolausb.la libs_usb_LibUsbThreadTester_SOURCES = \ libs/usb/LibUsbThreadTest.cpp libs_usb_LibUsbThreadTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) \ $(libusb_CFLAGS) libs_usb_LibUsbThreadTester_LDADD = $(LIBS_USB_TEST_LDADD) endif ola-0.10.5.nojsmin/libs/usb/JaRulePortHandleImpl.cpp0000644000175000017500000003233713134123277021706 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * JaRulePortHandleImpl.cpp * The implementation of the Ja Rule Widget. * Copyright (C) 2015 Simon Newton */ #include "libs/usb/JaRulePortHandleImpl.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "libs/usb/JaRuleWidgetPort.h" namespace ola { namespace usb { using ola::NewSingleCallback; using ola::io::ByteString; using ola::rdm::DiscoveryAgent; using ola::rdm::DiscoverableQueueingRDMController; using ola::rdm::RDMCallback; using ola::rdm::RDMCommand; using ola::rdm::RDMCommandSerializer; using ola::rdm::RDMDiscoveryCallback; using ola::rdm::RDMDiscoveryResponse; using ola::rdm::RDMReply; using ola::rdm::RDMRequest; using ola::rdm::RDMResponse; using ola::rdm::RDMSetRequest; using ola::rdm::RunRDMCallback; using ola::rdm::UID; using ola::rdm::UIDSet; using ola::rdm::RDMStatusCode; using ola::strings::ToHex; using std::auto_ptr; using std::vector; JaRulePortHandleImpl::JaRulePortHandleImpl(JaRuleWidgetPort *parent_port, const ola::rdm::UID &uid, uint8_t physical_port) : m_port(parent_port), m_uid(uid), m_physical_port(physical_port), m_in_shutdown(false), m_dmx_in_progress(false), m_dmx_queued(false), m_dmx_callback(NewCallback(this, &JaRulePortHandleImpl::DMXComplete)), m_discovery_agent(this) { } JaRulePortHandleImpl::~JaRulePortHandleImpl() { m_in_shutdown = true; m_discovery_agent.Abort(); m_port->CancelAll(); delete m_dmx_callback; } void JaRulePortHandleImpl::RunFullDiscovery(RDMDiscoveryCallback *callback) { OLA_INFO << "Full discovery triggered"; m_discovery_agent.StartFullDiscovery( NewSingleCallback(this, &JaRulePortHandleImpl::DiscoveryComplete, callback)); } void JaRulePortHandleImpl::RunIncrementalDiscovery( RDMDiscoveryCallback *callback) { OLA_INFO << "Incremental discovery triggered"; m_discovery_agent.StartIncrementalDiscovery( NewSingleCallback(this, &JaRulePortHandleImpl::DiscoveryComplete, callback)); } void JaRulePortHandleImpl::SendRDMRequest(RDMRequest *request, ola::rdm::RDMCallback *on_complete) { request->SetSourceUID(m_uid); request->SetPortId(m_physical_port + 1); request->SetTransactionNumber(m_transaction_number.Next()); ByteString frame; if (!RDMCommandSerializer::Pack(*request, &frame)) { RunRDMCallback(on_complete, ola::rdm::RDM_FAILED_TO_SEND); delete request; return; } m_port->SendCommand( GetCommandFromRequest(request), frame.data(), frame.size(), NewSingleCallback(this, &JaRulePortHandleImpl::RDMComplete, static_cast(request), on_complete)); } void JaRulePortHandleImpl::MuteDevice(const UID &target, MuteDeviceCallback *mute_complete) { auto_ptr request( ola::rdm::NewMuteRequest(m_uid, target, m_transaction_number.Next(), m_physical_port + 1)); ByteString frame; RDMCommandSerializer::Pack(*request, &frame); m_port->SendCommand( JARULE_CMD_RDM_REQUEST, frame.data(), frame.size(), NewSingleCallback(this, &JaRulePortHandleImpl::MuteDeviceComplete, mute_complete)); } void JaRulePortHandleImpl::UnMuteAll(UnMuteDeviceCallback *unmute_complete) { auto_ptr request( ola::rdm::NewUnMuteRequest(m_uid, UID::AllDevices(), m_transaction_number.Next(), m_physical_port + 1)); ByteString frame; RDMCommandSerializer::Pack(*request, &frame); m_port->SendCommand( JARULE_CMD_RDM_BROADCAST_REQUEST, frame.data(), frame.size(), NewSingleCallback(this, &JaRulePortHandleImpl::UnMuteDeviceComplete, unmute_complete)); } void JaRulePortHandleImpl::Branch(const UID &lower, const UID &upper, BranchCallback *branch_complete) { auto_ptr request( ola::rdm::NewDiscoveryUniqueBranchRequest(m_uid, lower, upper, m_transaction_number.Next())); ByteString frame; RDMCommandSerializer::Pack(*request, &frame); OLA_INFO << "Sending RDM DUB: " << lower << " - " << upper; m_port->SendCommand( JARULE_CMD_RDM_DUB_REQUEST, frame.data(), frame.size(), NewSingleCallback(this, &JaRulePortHandleImpl::DUBComplete, branch_complete)); } bool JaRulePortHandleImpl::SendDMX(const DmxBuffer &buffer) { if (m_dmx_in_progress) { m_dmx = buffer; m_dmx_queued = true; } else { m_dmx_in_progress = true; m_port->SendCommand(JARULE_CMD_TX_DMX, buffer.GetRaw(), buffer.Size(), m_dmx_callback); } return true; } bool JaRulePortHandleImpl::SetPortMode(JaRulePortMode new_mode) { uint8_t port_mode = new_mode; m_port->SendCommand(JARULE_CMD_SET_MODE, &port_mode, sizeof(port_mode), NULL); return true; } void JaRulePortHandleImpl::CheckStatusFlags(uint8_t flags) { if (flags & FLAGS_CHANGED_FLAG) { OLA_INFO << "Flags changed!"; } if (flags & MSG_TRUNCATED_FLAG) { OLA_INFO << "Message truncated"; } } void JaRulePortHandleImpl::DMXComplete( OLA_UNUSED USBCommandResult result, OLA_UNUSED JaRuleReturnCode return_code, uint8_t status_flags, OLA_UNUSED const ola::io::ByteString &payload) { CheckStatusFlags(status_flags); // We ignore status and return_code, since DMX is streaming. if (m_dmx_queued && !m_in_shutdown) { m_port->SendCommand(JARULE_CMD_TX_DMX, m_dmx.GetRaw(), m_dmx.Size(), m_dmx_callback); m_dmx_queued = false; } else { m_dmx_in_progress = false; } } void JaRulePortHandleImpl::MuteDeviceComplete( MuteDeviceCallback *mute_complete, USBCommandResult result, JaRuleReturnCode return_code, uint8_t status_flags, const ola::io::ByteString &payload) { CheckStatusFlags(status_flags); bool muted_ok = false; if (result == COMMAND_RESULT_OK && return_code == RC_OK && payload.size() > sizeof(GetSetTiming)) { // Skip the timing data & the start code. ola::rdm::RDMStatusCode status_code = rdm::RDM_INVALID_RESPONSE; auto_ptr response(RDMResponse::InflateFromData( payload.substr(sizeof(GetSetTiming) + 1), &status_code)); // TODO(simon): I guess we could ack timer the MUTE. Handle this case // someday. muted_ok = ( status_code == rdm::RDM_COMPLETED_OK && response.get() && response->CommandClass() == RDMCommand::DISCOVER_COMMAND_RESPONSE && response->ResponseType() == rdm::RDM_ACK); } else { OLA_INFO << "Mute failed! Result: " << result << ", RC: " << return_code << ", payload size: " << payload.size(); } mute_complete->Run(muted_ok); } void JaRulePortHandleImpl::UnMuteDeviceComplete( UnMuteDeviceCallback *unmute_complete, OLA_UNUSED USBCommandResult result, OLA_UNUSED JaRuleReturnCode return_code, OLA_UNUSED uint8_t status_flags, OLA_UNUSED const ola::io::ByteString &payload) { CheckStatusFlags(status_flags); if (result != COMMAND_RESULT_OK) { OLA_INFO << "JaRule Unmute failed!"; } // TODO(simon): At some point we need to account for failures here. unmute_complete->Run(); } void JaRulePortHandleImpl::DUBComplete(BranchCallback *callback, USBCommandResult result, JaRuleReturnCode return_code, uint8_t status_flags, const ola::io::ByteString &payload) { CheckStatusFlags(status_flags); ByteString discovery_data; if (payload.size() >= sizeof(DUBTiming)) { discovery_data = payload.substr(sizeof(DUBTiming)); } if (result == COMMAND_RESULT_OK && return_code == RC_OK) { callback->Run(discovery_data.data(), discovery_data.size()); } else { callback->Run(NULL, 0); } } void JaRulePortHandleImpl::RDMComplete(const ola::rdm::RDMRequest *request_ptr, ola::rdm::RDMCallback *callback, USBCommandResult result, JaRuleReturnCode return_code, uint8_t status_flags, const ola::io::ByteString &payload) { CheckStatusFlags(status_flags); auto_ptr request(request_ptr); ola::rdm::RDMFrames frames; if (result != COMMAND_RESULT_OK) { RunRDMCallback(callback, rdm::RDM_FAILED_TO_SEND); } CommandClass command = GetCommandFromRequest(request.get()); ola::rdm::RDMStatusCode status_code = rdm::RDM_INVALID_RESPONSE; ola::rdm::RDMResponse *response = NULL; if (command == JARULE_CMD_RDM_DUB_REQUEST && return_code == RC_OK) { if (payload.size() > sizeof(DUBTiming)) { DUBTiming timing; memcpy(reinterpret_cast(&timing), payload.data(), sizeof(timing)); OLA_INFO << "Start time " << (timing.start / 10.0) << "uS, End: " << (timing.end / 10.0) << "uS"; ola::rdm::RDMFrame frame(payload.substr(sizeof(DUBTiming))); frame.timing.response_time = 100 * timing.start; frame.timing.data_time = 100 * (timing.end - timing.start); frames.push_back(frame); } status_code = rdm::RDM_DUB_RESPONSE; } else if (command == JARULE_CMD_RDM_BROADCAST_REQUEST && return_code == RC_OK) { status_code = rdm::RDM_WAS_BROADCAST; } else if (command == JARULE_CMD_RDM_BROADCAST_REQUEST && return_code == RC_RDM_BCAST_RESPONSE) { if (payload.size() > sizeof(GetSetTiming)) { response = UnpackRDMResponse( request.get(), payload.substr(sizeof(GetSetTiming)), &status_code); } } else if (command == JARULE_CMD_RDM_REQUEST && return_code == RC_OK) { if (payload.size() > sizeof(GetSetTiming)) { GetSetTiming timing; memcpy(reinterpret_cast(&timing), payload.data(), sizeof(timing)); OLA_INFO << "Response time " << (timing.break_start / 10.0) << "uS, Break: " << (timing.mark_start - timing.break_start) / 10.0 << "uS, Mark: " << (timing.mark_end - timing.mark_start) / 10.0 << "uS"; response = UnpackRDMResponse( request.get(), payload.substr(sizeof(GetSetTiming)), &status_code); ola::rdm::RDMFrame frame(payload.substr(sizeof(GetSetTiming))); frame.timing.response_time = 100 * timing.break_start; frame.timing.break_time = 100 * (timing.mark_start - timing.break_start); frame.timing.mark_time = 100 * (timing.mark_end - timing.mark_start); frames.push_back(frame); } } else if (return_code == RC_RDM_TIMEOUT) { status_code = rdm::RDM_TIMEOUT; } else if (return_code == RC_TX_ERROR || return_code == RC_BUFFER_FULL) { status_code = rdm::RDM_FAILED_TO_SEND; } else { OLA_WARN << "Unknown Ja Rule RDM RC: " << ToHex(return_code); status_code = rdm::RDM_FAILED_TO_SEND; } RDMReply reply(status_code, response, frames); callback->Run(&reply); } ola::rdm::RDMResponse* JaRulePortHandleImpl::UnpackRDMResponse( const RDMRequest *request, const ByteString &payload, ola::rdm::RDMStatusCode *status_code) { if (payload.empty() || payload[0] != RDMCommand::START_CODE) { *status_code = rdm::RDM_INVALID_RESPONSE; return NULL; } return ola::rdm::RDMResponse::InflateFromData( payload.data() + 1, payload.size() - 1, status_code, request); } void JaRulePortHandleImpl::DiscoveryComplete(RDMDiscoveryCallback *callback, OLA_UNUSED bool ok, const UIDSet& uids) { m_uids = uids; if (callback) { callback->Run(m_uids); } } CommandClass JaRulePortHandleImpl::GetCommandFromRequest( const ola::rdm::RDMRequest *request) { if (request->IsDUB()) { return JARULE_CMD_RDM_DUB_REQUEST; } return request->DestinationUID().IsBroadcast() ? JARULE_CMD_RDM_BROADCAST_REQUEST : JARULE_CMD_RDM_REQUEST; } } // namespace usb } // namespace ola ola-0.10.5.nojsmin/libs/usb/JaRuleWidgetPort.h0000644000175000017500000001450213023355232020546 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * JaRuleWidgetPort.h * A Ja Rule widget port. * Copyright (C) 2015 Simon Newton */ #ifndef LIBS_USB_JARULEWIDGETPORT_H_ #define LIBS_USB_JARULEWIDGETPORT_H_ #include #include #include #include #include #include #include #include #include "libs/usb/JaRulePortHandle.h" #include "libs/usb/LibUsbAdaptor.h" #include "libs/usb/JaRuleWidget.h" namespace ola { namespace usb { /** * @brief The internal model of a port on a JaRule device. * * Each port has its own libusb transfers as well as a command queue. This * avoids slow commands on one port blocking another. */ class JaRuleWidgetPort { public: /** * @brief Create a new JaRuleWidgetPort. * @param executor The Executor to run the callbacks on. * @param adaptor The LibUsbAdaptor to use. * @param usb_handle the libusb_device_handle for the Ja Rule widget. * @param endpoint_number The endpoint to use for transfers. * @param uid The device's UID. * @param physical_port The physical port index. */ JaRuleWidgetPort(ola::thread::ExecutorInterface *executor, LibUsbAdaptor *adaptor, libusb_device_handle *usb_handle, uint8_t endpoint_number, const ola::rdm::UID &uid, uint8_t physical_port); /** * @brief Destructor */ ~JaRuleWidgetPort(); /** * @brief Claim the handle to this port. * @returns a port handle, ownership is not transferred. Will return NULL if * the port is already claimed. */ JaRulePortHandle* ClaimPort(); /** * @brief Release a handle to a port. * @returns a port handle, ownership is not transferred. */ void ReleasePort(); /** * @brief Cancel all commands for this port. */ void CancelAll(); /** * @brief Send a command on this port. * @param command the Command type. * @param data the payload data. The data is copied and can be freed once the * method returns. * @param size the payload size. * @param callback The callback to run when the command completes. * This may be run immediately in some conditions. * * SendCommand() can be called from any thread, and messages will be queued. */ void SendCommand(CommandClass command, const uint8_t *data, unsigned int size, CommandCompleteCallback *callback); /** * @brief Called by the libusb callback when the transfer completes or is * cancelled. */ void _OutTransferComplete(); /** * @brief Called by the libusb callback when the transfer completes or is * cancelled. */ void _InTransferComplete(); private: // This must be a multiple of the USB packet size otherwise we can experience // overflows. A message can be a maximum of 640 bytes, so we'll use 1k here // to be safe. enum { IN_BUFFER_SIZE = 1024 }; enum { OUT_BUFFER_SIZE = 1024 }; // The arguments passed to the user supplied callback. typedef struct { USBCommandResult result; JaRuleReturnCode return_code; uint8_t status_flags; const ola::io::ByteString payload; } CallbackArgs; class PendingCommand { public: PendingCommand(CommandClass command, CommandCompleteCallback *callback, const ola::io::ByteString &payload) : command(command), callback(callback), payload(payload) { } CommandClass command; CommandCompleteCallback *callback; ola::io::ByteString payload; TimeStamp out_time; // When this cmd was sent }; typedef std::map PendingCommandMap; typedef std::queue CommandQueue; ola::Clock m_clock; ola::thread::ExecutorInterface* const m_executor; LibUsbAdaptor* const m_adaptor; libusb_device_handle* const m_usb_handle; const uint8_t m_endpoint_number; const ola::rdm::UID m_uid; const uint8_t m_physical_port; JaRulePortHandle *m_handle; // NULL if the port isn't claimed ola::SequenceNumber m_token; ola::thread::Mutex m_mutex; CommandQueue m_queued_commands; // GUARDED_BY(m_mutex); PendingCommandMap m_pending_commands; // GUARDED_BY(m_mutex); libusb_transfer *m_out_transfer; // GUARDED_BY(m_mutex); bool m_out_in_progress; // GUARDED_BY(m_mutex); uint8_t m_in_buffer[IN_BUFFER_SIZE]; // GUARDED_BY(m_mutex); libusb_transfer *m_in_transfer; // GUARDED_BY(m_mutex); bool m_in_in_progress; // GUARDED_BY(m_mutex); void MaybeSendCommand(); // LOCK_REQUIRED(m_mutex); bool SubmitInTransfer(); // LOCK_REQUIRED(m_mutex); void HandleResponse(const uint8_t *data, unsigned int size); // LOCK_REQUIRED(m_mutex); void ScheduleCallback(CommandCompleteCallback *callback, USBCommandResult result, JaRuleReturnCode return_code, uint8_t status_flags, const ola::io::ByteString &payload); void RunCallback(CommandCompleteCallback *callback, CallbackArgs args); static const uint8_t EOF_IDENTIFIER = 0xa5; static const uint8_t SOF_IDENTIFIER = 0x5a; static const unsigned int MAX_PAYLOAD_SIZE = 513; static const unsigned int MIN_RESPONSE_SIZE = 9; static const unsigned int USB_PACKET_SIZE = 64; static const unsigned int MAX_IN_FLIGHT = 2; static const unsigned int MAX_QUEUED_MESSAGES = 10; static const unsigned int ENDPOINT_TIMEOUT_MS = 1000; DISALLOW_COPY_AND_ASSIGN(JaRuleWidgetPort); }; } // namespace usb } // namespace ola #endif // LIBS_USB_JARULEWIDGETPORT_H_ ola-0.10.5.nojsmin/libs/usb/LibUsbThread.cpp0000644000175000017500000000707713134123277020234 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * LibUsbThread.cpp * The thread for asynchronous libusb communication. * Copyright (C) 2014 Simon Newton */ #include "libs/usb/LibUsbThread.h" #include "libs/usb/LibUsbAdaptor.h" #include "ola/Logging.h" #include "ola/StringUtils.h" #include "ola/stl/STLUtils.h" namespace ola { namespace usb { // LibUsbThread // ----------------------------------------------------------------------------- void *LibUsbThread::Run() { OLA_INFO << "----libusb event thread is running"; while (1) { { ola::thread::MutexLocker locker(&m_term_mutex); if (m_term) { break; } } libusb_handle_events(m_context); } OLA_INFO << "----libusb thread exiting"; return NULL; } void LibUsbThread::LaunchThread() { OLA_INFO << "-- Starting libusb thread"; Start(); } void LibUsbThread::JoinThread() { OLA_INFO << "-- Stopping libusb thread"; Join(); m_term = false; } // LibUsbHotplugThread // ----------------------------------------------------------------------------- #if HAVE_LIBUSB_HOTPLUG_API LibUsbHotplugThread::LibUsbHotplugThread(libusb_context *context, libusb_hotplug_callback_fn callback_fn, void *user_data) : LibUsbThread(context), m_hotplug_handle(0), m_callback_fn(callback_fn), m_user_data(user_data) { } bool LibUsbHotplugThread::Init() { /* check for hotplug support */ if (!LibUsbAdaptor::HotplugSupported()) { OLA_WARN << "No hotplug capability, giving up trying to start this thread"; return false; } int rc = libusb_hotplug_register_callback( NULL, static_cast(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT), LIBUSB_HOTPLUG_ENUMERATE, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY, m_callback_fn, m_user_data, &m_hotplug_handle); if (LIBUSB_SUCCESS != rc) { OLA_WARN << "Error creating a hotplug callback " << LibUsbAdaptor::ErrorCodeToString(rc); return false; } LaunchThread(); return true; } void LibUsbHotplugThread::Shutdown() { SetTerminate(); libusb_hotplug_deregister_callback(Context(), m_hotplug_handle); JoinThread(); } void LibUsbHotplugThread::CloseHandle(libusb_device_handle *handle) { libusb_close(handle); } #endif // HAVE_LIBUSB_HOTPLUG_API // LibUsbSimpleThread // ----------------------------------------------------------------------------- void LibUsbSimpleThread::OpenHandle() { m_device_count++; if (m_device_count == 1) { LaunchThread(); } } void LibUsbSimpleThread::CloseHandle(libusb_device_handle *handle) { if (m_device_count == 1) { SetTerminate(); } libusb_close(handle); if (m_device_count == 1) { JoinThread(); } m_device_count--; } } // namespace usb } // namespace ola ola-0.10.5.nojsmin/libs/usb/JaRuleWidgetPort.cpp0000644000175000017500000003137313023355232021106 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * JaRuleWidgetPort.cpp * A Ja Rule Widget Port. * Copyright (C) 2015 Simon Newton */ #include "libs/usb/JaRuleWidgetPort.h" #include #include #include #include #include #include #include #include #include #include namespace ola { namespace usb { using ola::NewSingleCallback; using ola::io::ByteString; using ola::strings::ToHex; using ola::thread::MutexLocker; using ola::utils::JoinUInt8; using ola::utils::SplitUInt16; using std::cerr; using std::string; using std::auto_ptr; namespace { #ifdef _WIN32 __attribute__((__stdcall__)) #endif // _WIN32 void InTransferCompleteHandler(struct libusb_transfer *transfer) { JaRuleWidgetPort *port = static_cast(transfer->user_data); return port->_InTransferComplete(); } #ifdef _WIN32 __attribute__((__stdcall__)) #endif // _WIN32 void OutTransferCompleteHandler(struct libusb_transfer *transfer) { JaRuleWidgetPort *port = static_cast(transfer->user_data); return port->_OutTransferComplete(); } } // namespace JaRuleWidgetPort::JaRuleWidgetPort(ola::thread::ExecutorInterface *executor, LibUsbAdaptor *adaptor, libusb_device_handle *usb_handle, uint8_t endpoint_number, const ola::rdm::UID &uid, uint8_t physical_port) : m_executor(executor), m_adaptor(adaptor), m_usb_handle(usb_handle), m_endpoint_number(endpoint_number), m_uid(uid), m_physical_port(physical_port), m_handle(NULL), m_out_transfer(adaptor->AllocTransfer(0)), m_out_in_progress(false), m_in_transfer(adaptor->AllocTransfer(0)), m_in_in_progress(false) { } JaRuleWidgetPort::~JaRuleWidgetPort() { if (m_handle) { OLA_WARN << "JaRulePortHandle is still claimed!"; delete m_handle; } { MutexLocker locker(&m_mutex); if (!m_queued_commands.empty()) { OLA_WARN << "Queued commands remain, did we forget to call " "CancelTransfer()?"; } if (!m_pending_commands.empty()) { OLA_WARN << "Pending commands remain, did we forget to call " "CancelTransfer()?"; } // Cancelling may take up to a second if the endpoint has stalled. I can't // really see a way to speed this up. if (m_out_in_progress) { m_adaptor->CancelTransfer(m_out_transfer); } if (m_in_in_progress) { m_adaptor->CancelTransfer(m_in_transfer); } } OLA_DEBUG << "Waiting for transfers to complete"; bool transfers_pending = true; while (transfers_pending) { // Spin waiting for the transfers to complete. MutexLocker locker(&m_mutex); transfers_pending = m_out_in_progress || m_in_in_progress; } if (m_out_transfer) { m_adaptor->FreeTransfer(m_out_transfer); } if (m_in_transfer) { m_adaptor->FreeTransfer(m_in_transfer); } } JaRulePortHandle* JaRuleWidgetPort::ClaimPort() { if (m_handle) { return NULL; } m_handle = new JaRulePortHandle(this, m_uid, m_physical_port); return m_handle; } void JaRuleWidgetPort::ReleasePort() { if (m_handle) { delete m_handle; m_handle = NULL; } } void JaRuleWidgetPort::CancelAll() { CommandQueue queued_commands; PendingCommandMap pending_commands; { MutexLocker locker(&m_mutex); queued_commands = m_queued_commands; while (!m_queued_commands.empty()) { m_queued_commands.pop(); } pending_commands.swap(m_pending_commands); } while (!queued_commands.empty()) { auto_ptr command(queued_commands.front()); if (command->callback) { command->callback->Run(COMMAND_RESULT_CANCELLED, RC_UNKNOWN, 0, ByteString()); } queued_commands.pop(); } PendingCommandMap::iterator iter = pending_commands.begin(); for (; iter != pending_commands.end(); ++iter) { if (iter->second->callback) { iter->second->callback->Run(COMMAND_RESULT_CANCELLED, RC_UNKNOWN, 0, ByteString()); delete iter->second; } } { MutexLocker locker(&m_mutex); if (!(m_queued_commands.empty() && m_pending_commands.empty())) { OLA_WARN << "Some commands have not been cancelled"; } } } void JaRuleWidgetPort::SendCommand( CommandClass command_class, const uint8_t *data, unsigned int size, CommandCompleteCallback *callback) { if (size > MAX_PAYLOAD_SIZE) { OLA_WARN << "JaRule message exceeds max payload size"; if (callback) { callback->Run(COMMAND_RESULT_MALFORMED, RC_UNKNOWN, 0, ByteString()); } return; } if (size != 0 && data == NULL) { OLA_WARN << "JaRule data is NULL, size was " << size; callback->Run(COMMAND_RESULT_MALFORMED, RC_UNKNOWN, 0, ByteString()); return; } // Create the payload ByteString payload; payload.reserve(size + MIN_RESPONSE_SIZE); payload.push_back(SOF_IDENTIFIER); payload.push_back(0); // token, will be set on TX payload.push_back(command_class & 0xff); payload.push_back(command_class >> 8); payload.push_back(size & 0xff); payload.push_back(size >> 8); payload.append(data, size); payload.push_back(EOF_IDENTIFIER); if (payload.size() % USB_PACKET_SIZE == 0) { // We need to pad the message so that the transfer completes on the // Device side. We could use LIBUSB_TRANSFER_ADD_ZERO_PACKET instead but // that isn't avaiable on all platforms. payload.push_back(0); } auto_ptr command(new PendingCommand( command_class, callback, payload)); OLA_INFO << "Adding new command " << ToHex(command_class); MutexLocker locker(&m_mutex); if (m_queued_commands.size() > MAX_QUEUED_MESSAGES) { locker.Release(); OLA_WARN << "JaRule outbound queue is full"; if (callback) { callback->Run(COMMAND_RESULT_QUEUE_FULL, RC_UNKNOWN, 0, ByteString()); } return; } m_queued_commands.push(command.release()); MaybeSendCommand(); } void JaRuleWidgetPort::_OutTransferComplete() { OLA_DEBUG << "Out Command status is " << LibUsbAdaptor::ErrorCodeToString(m_in_transfer->status); if (m_out_transfer->status == LIBUSB_TRANSFER_COMPLETED) { if (m_out_transfer->actual_length != m_out_transfer->length) { // TODO(simon): Decide what to do here OLA_WARN << "Only sent " << m_out_transfer->actual_length << " / " << m_out_transfer->length << " bytes"; } } MutexLocker locker(&m_mutex); m_out_in_progress = false; MaybeSendCommand(); } void JaRuleWidgetPort::_InTransferComplete() { OLA_DEBUG << "In transfer completed status is " << LibUsbAdaptor::ErrorCodeToString(m_in_transfer->status); MutexLocker locker(&m_mutex); m_in_in_progress = false; if (m_in_transfer->status == LIBUSB_TRANSFER_COMPLETED) { HandleResponse(m_in_transfer->buffer, m_in_transfer->actual_length); } PendingCommandMap::iterator iter = m_pending_commands.begin(); TimeStamp time_limit; m_clock.CurrentTime(&time_limit); time_limit -= TimeInterval(1, 0); while (iter != m_pending_commands.end()) { PendingCommand *command = iter->second; if (command->out_time < time_limit) { ScheduleCallback(command->callback, COMMAND_RESULT_TIMEOUT, RC_UNKNOWN, 0, ByteString()); delete command; m_pending_commands.erase(iter++); } else { iter++; } } if (!m_pending_commands.empty()) { SubmitInTransfer(); } } void JaRuleWidgetPort::MaybeSendCommand() { if (m_out_in_progress || m_pending_commands.size() > MAX_IN_FLIGHT || m_queued_commands.empty()) { return; } PendingCommand *command = m_queued_commands.front(); m_queued_commands.pop(); uint8_t token = m_token.Next(); command->payload[1] = token; m_adaptor->FillBulkTransfer( m_out_transfer, m_usb_handle, m_endpoint_number | LIBUSB_ENDPOINT_OUT, const_cast(command->payload.data()), command->payload.size(), OutTransferCompleteHandler, static_cast(this), ENDPOINT_TIMEOUT_MS); int r = m_adaptor->SubmitTransfer(m_out_transfer); if (r) { OLA_WARN << "Failed to submit outbound transfer: " << LibUsbAdaptor::ErrorCodeToString(r); ScheduleCallback(command->callback, COMMAND_RESULT_SEND_ERROR, RC_UNKNOWN, 0, ByteString()); delete command; return; } m_clock.CurrentTime(&command->out_time); std::pair p = m_pending_commands.insert( PendingCommandMap::value_type(token, command)); if (!p.second) { // We had an old entry, cancel it. ScheduleCallback(p.first->second->callback, COMMAND_RESULT_CANCELLED, RC_UNKNOWN, 0, ByteString()); delete p.first->second; p.first->second = command; } m_out_in_progress = true; if (!m_in_in_progress) { SubmitInTransfer(); } return; } bool JaRuleWidgetPort::SubmitInTransfer() { if (m_in_in_progress) { OLA_WARN << "Read already pending"; return true; } m_adaptor->FillBulkTransfer(m_in_transfer, m_usb_handle, m_endpoint_number | LIBUSB_ENDPOINT_IN, m_in_buffer, IN_BUFFER_SIZE, InTransferCompleteHandler, static_cast(this), ENDPOINT_TIMEOUT_MS); int r = m_adaptor->SubmitTransfer(m_in_transfer); if (r) { OLA_WARN << "Failed to submit input transfer: " << LibUsbAdaptor::ErrorCodeToString(r); return false; } m_in_in_progress = true; return true; } /* * */ void JaRuleWidgetPort::HandleResponse(const uint8_t *data, unsigned int size) { if (size < MIN_RESPONSE_SIZE) { OLA_WARN << "Response was too small, " << size << " bytes, min was " << MIN_RESPONSE_SIZE; return; } if (data[0] != SOF_IDENTIFIER) { OLA_WARN << "SOF_IDENTIFIER mismatch, was " << ToHex(data[0]); return; } uint8_t token = data[1]; uint16_t command_class = JoinUInt8(data[3], data[2]); uint16_t payload_size = JoinUInt8(data[5], data[4]); JaRuleReturnCode return_code = RC_UNKNOWN; if (data[6] < RC_LAST) { return_code = static_cast(data[6]); } uint8_t status_flags = data[7]; if (payload_size + MIN_RESPONSE_SIZE > size) { OLA_WARN << "Message size of " << (payload_size + MIN_RESPONSE_SIZE) << " is greater than rx size of " << size; return; } // TODO(simon): Remove this. if (LogLevel() >= OLA_LOG_INFO) { ola::strings::FormatData(&std::cerr, data, size); } if (data[MIN_RESPONSE_SIZE + payload_size - 1] != EOF_IDENTIFIER) { OLA_WARN << "EOF_IDENTIFIER mismatch, was " << ToHex(data[payload_size + MIN_RESPONSE_SIZE - 1]); return; } PendingCommand *command; if (!STLLookupAndRemove(&m_pending_commands, token, &command)) { return; } USBCommandResult status = COMMAND_RESULT_OK; if (command->command != command_class) { status = COMMAND_RESULT_CLASS_MISMATCH; } ByteString payload; if (payload_size) { payload.assign(data + MIN_RESPONSE_SIZE - 1, payload_size); } ScheduleCallback( command->callback, status, return_code, status_flags, payload); delete command; } /* * @brief Schedule a callback to be run on the Executor. */ void JaRuleWidgetPort::ScheduleCallback( CommandCompleteCallback *callback, USBCommandResult result, JaRuleReturnCode return_code, uint8_t status_flags, const ByteString &payload) { if (!callback) { return; } CallbackArgs args = { result, return_code, status_flags, payload }; if (callback) { m_executor->Execute(NewSingleCallback( this, &JaRuleWidgetPort::RunCallback, callback, args)); } } /* * @brief Only ever run in the Executor thread. */ void JaRuleWidgetPort::RunCallback(CommandCompleteCallback *callback, CallbackArgs args) { callback->Run(args.result, args.return_code, args.status_flags, args.payload); } } // namespace usb } // namespace ola ola-0.10.5.nojsmin/libs/usb/JaRulePortHandle.h0000644000175000017500000000476113023355232020524 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * JaRulePortHandle.h * A Ja Rule Port Handle. * Copyright (C) 2015 Simon Newton */ #ifndef LIBS_USB_JARULEPORTHANDLE_H_ #define LIBS_USB_JARULEPORTHANDLE_H_ #include #include #include #include #include #include #include "libs/usb/JaRuleConstants.h" namespace ola { namespace usb { /** * @brief Represents a DMX/RDM port on a Ja Rule device. */ class JaRulePortHandle : public ola::rdm::DiscoverableRDMControllerInterface { public: /** * @brief Create a new Ja Rule Port Handle. */ JaRulePortHandle(class JaRuleWidgetPort *parent_port, const ola::rdm::UID &uid, uint8_t physical_port); ~JaRulePortHandle(); void SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *on_complete); void RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback); void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback); /** * @brief Send DMX data from this widget * @param buffer The DmxBuffer containing the data to send. * @returns true if the data was sent, false otherwise. */ bool SendDMX(const DmxBuffer &buffer); /** * @brief Change the mode of the port. * * @todo I need to think about how to return errors from this since it's * async. */ bool SetPortMode(JaRulePortMode new_mode); private: // Order of destruction is important. std::auto_ptr m_impl; ola::rdm::DiscoverableQueueingRDMController m_queueing_controller; static const unsigned int RDM_QUEUE_SIZE = 50; DISALLOW_COPY_AND_ASSIGN(JaRulePortHandle); }; } // namespace usb } // namespace ola #endif // LIBS_USB_JARULEPORTHANDLE_H_ ola-0.10.5.nojsmin/libs/usb/LibUsbAdaptor.h0000644000175000017500000005561713134123277020067 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * LibUsbAdaptor.h * The wrapper around libusb calls. * Copyright (C) 2014 Simon Newton */ #ifndef LIBS_USB_LIBUSBADAPTOR_H_ #define LIBS_USB_LIBUSBADAPTOR_H_ #include #include #include "ola/base/Macro.h" #include "libs/usb/Types.h" namespace ola { namespace usb { /** * @brief Wraps calls to libusb so we can test the code. */ class LibUsbAdaptor { public: struct DeviceInformation { std::string manufacturer; std::string product; std::string serial; }; virtual ~LibUsbAdaptor() {} // Device handling and enumeration /** * @brief Wraps libusb_ref_device. * @param dev the device to reference * @returns the same device */ virtual libusb_device* RefDevice(libusb_device *dev) = 0; /** * @brief Wraps libusb_unref_device. * @param dev the device to unreference. */ virtual void UnrefDevice(libusb_device *dev) = 0; /** * @brief Open a libusb device. * @param usb_device The usb device to open. * @param[out] usb_handle the new device handle. * @returns true if the device was opened, false otherwise. */ virtual bool OpenDevice(libusb_device *usb_device, libusb_device_handle **usb_handle) = 0; /** * @brief Open a libusb device and claim an interface. * @param usb_device The usb device to open. * @param interface the interface index to claim. * @param[out] usb_handle the new device handle. * @returns true if the device was opened and the interface claimed, * false otherwise. */ virtual bool OpenDeviceAndClaimInterface( libusb_device *usb_device, int interface, libusb_device_handle **usb_handle) = 0; /** * @brief Close a libusb handle. * @param usb_handle the handle to close. */ virtual void Close(libusb_device_handle *usb_handle) = 0; /** * @brief Wraps libusb_set_configuration. * @param dev a device handle * @param configuration the bConfigurationValue of the configuration you * wish to activate, or -1 if you wish to put the device in an unconfigured * state. * @returns 0 on success * @returns LIBUSB_ERROR_NOT_FOUND if the requested configuration does not * exist. * @returns LIBUSB_ERROR_BUSY if interfaces are currently claimed * @returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected * @returns another LIBUSB_ERROR code on other failure */ virtual int SetConfiguration(libusb_device_handle *dev, int configuration) = 0; /** * @brief Wraps libusb_claim_interface. * @param dev a device handle * @param interface_number the bInterfaceNumber of the interface you * wish to claim * @returns 0 on success * @returns LIBUSB_ERROR_NOT_FOUND if the requested interface does not exist * @returns LIBUSB_ERROR_BUSY if another program or driver has claimed the * interface * @returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected * @returns a LIBUSB_ERROR code on other failure */ virtual int ClaimInterface(libusb_device_handle *dev, int interface_number) = 0; /** * @brief Detatch a kernel driver. * @param dev a device handle * @param interface_number the interface to detach the driver from * @returns 0 on success * @returns LIBUSB_ERROR_NOT_FOUND if no kernel driver was active * @returns LIBUSB_ERROR_INVALID_PARAM if the interface does not exist * @returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected * @returns LIBUSB_ERROR_NOT_SUPPORTED on platforms where the functionality * is not available * @returns another LIBUSB_ERROR code on other failure * */ virtual int DetachKernelDriver(libusb_device_handle *dev, int interface_number) = 0; // USB descriptors /** * @brief Wraps libusb_get_device_descriptor. * @param dev a device * @param[out] descriptor The device descriptor. * @returns 0 on success * @returns another LIBUSB_ERROR code on error */ virtual int GetDeviceDescriptor( libusb_device *dev, struct libusb_device_descriptor *descriptor) = 0; /** * @brief Wraps libusb_get_active_config_descriptor. * @param dev a device * @param[out] config output location for the USB configuration descriptor. * Only valid if 0 was returned. Must be freed with * libusb_free_config_descriptor() after use. * @returns 0 on success * @returns LIBUSB_ERROR_NOT_FOUND if the device is in unconfigured state * @returns another LIBUSB_ERROR code on error */ virtual int GetActiveConfigDescriptor( libusb_device *dev, struct libusb_config_descriptor **config) = 0; /** * @brief Wraps libusb_get_config_descriptor. * @param dev a device * @param config_index the index of the configuration you wish to retrieve * @param[out] config output location for the USB configuration descriptor. * Only valid if 0 was returned. Must be freed with * libusb_free_config_descriptor() after use. * @returns 0 on success * @returns LIBUSB_ERROR_NOT_FOUND if the configuration does not exist * @returns another LIBUSB_ERROR code on error */ virtual int GetConfigDescriptor(libusb_device *dev, uint8_t config_index, struct libusb_config_descriptor **config) = 0; /** * @brief Wraps busb_free_config_descriptor. * @param config the configuration descriptor to free */ virtual void FreeConfigDescriptor( struct libusb_config_descriptor *config) = 0; /** * @brief Get the value of a string descriptor. * @param usb_handle The USB device handle * @param descriptor_index The index of the string descriptor to fetch. * @param[out] data The value of the string descriptor. * @returns true if the string descriptor was retrieved, false otherwise. */ virtual bool GetStringDescriptor(libusb_device_handle *usb_handle, uint8_t descriptor_index, std::string *data) = 0; // Asynchronous device I/O /** * @brief Wraps libusb_alloc_transfer * @param iso_packets number of isochronous packet descriptors to allocate * @returns a newly allocated transfer, or NULL on error */ virtual struct libusb_transfer* AllocTransfer(int iso_packets) = 0; /** * @brief Wraps libusb_free_transfer. * @param transfer the transfer to free */ virtual void FreeTransfer(struct libusb_transfer *transfer) = 0; /** * @brief Wraps libusb_submit_transfer. * @param transfer the transfer to submit * @returns 0 on success * @returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected * @returns LIBUSB_ERROR_BUSY if the transfer has already been submitted. * @returns LIBUSB_ERROR_NOT_SUPPORTED if the transfer flags are not supported * by the operating system. * @returns another LIBUSB_ERROR code on other failure */ virtual int SubmitTransfer(struct libusb_transfer *transfer) = 0; /** * @brief Wraps libusb_cancel_transfer * @param transfer the transfer to cancel * @returns 0 on success * @returns LIBUSB_ERROR_NOT_FOUND if the transfer is already complete or * cancelled. * @returns a LIBUSB_ERROR code on failure */ virtual int CancelTransfer(struct libusb_transfer *transfer) = 0; /** * @brief Wraps libusb_fill_control_setup * @param[out] buffer buffer to output the setup packet into * This pointer must be aligned to at least 2 bytes boundary. * @param bmRequestType the request type field for the setup packet * @param bRequest the request field for the setup packet * @param wValue the value field for the setup packet * @param wIndex the index field for the setup packet * @param wLength the length field for the setup packet. The data buffer * should be at least this size. */ virtual void FillControlSetup(unsigned char *buffer, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint16_t wLength) = 0; /** * @brief Wraps libusb_fill_control_transfer * @param[out] transfer the transfer to populate * @param dev_handle handle of the device that will handle the transfer * @param buffer data buffer. If provided, this function will interpret the * first 8 bytes as a setup packet and infer the transfer length from that. * This pointer must be aligned to at least 2 bytes boundary. * @param callback callback function to be invoked on transfer completion * @param user_data user data to pass to callback function * @param timeout timeout for the transfer in milliseconds */ virtual void FillControlTransfer(struct libusb_transfer *transfer, libusb_device_handle *dev_handle, unsigned char *buffer, libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout) = 0; /** * @brief Wraps libusb_fill_bulk_transfer. * @param[out] transfer the transfer to populate * @param dev_handle handle of the device that will handle the transfer * @param endpoint address of the endpoint where this transfer will be sent * @param buffer data buffer. If provided, this function will interpret the * first 8 bytes as a setup packet and infer the transfer length from that. * This pointer must be aligned to at least 2 bytes boundary. * @param length length of data buffer * @param callback callback function to be invoked on transfer completion * @param user_data user data to pass to callback function * @param timeout timeout for the transfer in milliseconds */ virtual void FillBulkTransfer(struct libusb_transfer *transfer, libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *buffer, int length, libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout) = 0; /** * @brief Wraps libusb_fill_interrupt_transfer. * @param[out] transfer the transfer to populate * @param dev_handle handle of the device that will handle the transfer * @param endpoint address of the endpoint where this transfer will be sent * @param buffer data buffer * @param length length of data buffer * @param callback callback function to be invoked on transfer completion * @param user_data user data to pass to callback function * @param timeout timeout for the transfer in milliseconds */ virtual void FillInterruptTransfer(struct libusb_transfer *transfer, libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *buffer, int length, libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout) = 0; // Synchronous device I/O /** * @brief Wraps libusb_control_transfer(). * @param dev_handle a handle for the device to communicate with * @param bmRequestType the request type field for the setup packet * @param bRequest the request field for the setup packet * @param wValue the value field for the setup packet * @param wIndex the index field for the setup packet * @param [in,out] data a suitably-sized data buffer for either input or * output (depending on direction bits within bmRequestType) * @param wLength the length field for the setup packet. The data buffer * should be at least this size. * @param timeout timeout (in millseconds) that this function should wait * before giving up due to no response being received. For an unlimited * timeout, use value 0. * @returns on success, the number of bytes actually transferred * */ virtual int ControlTransfer(libusb_device_handle *dev_handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned char *data, uint16_t wLength, unsigned int timeout) = 0; /** * @brief Wraps libusb_bulk_transfer. * @returns 0 on success and populates transferred * @returns LIBUSB_ERROR_TIMEOUT if the transfer timed out (and populates * transferred) * @returns LIBUSB_ERROR_PIPE if the endpoint halted * @returns LIBUSB_ERROR_OVERFLOW if the device offered more data, see * @returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected * @returns another LIBUSB_ERROR code on other failures */ virtual int BulkTransfer(struct libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *data, int length, int *transferred, unsigned int timeout) = 0; /** * @brief Wraps libusb_interrupt_transfer * @returns 0 on success and populates transferred * @returns LIBUSB_ERROR_TIMEOUT if the transfer timed out * @returns LIBUSB_ERROR_PIPE if the endpoint halted * @returns LIBUSB_ERROR_OVERFLOW if the device offered more data, see * @returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected * @returns another LIBUSB_ERROR code on other error */ virtual int InterruptTransfer(libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *data, int length, int *actual_length, unsigned int timeout) = 0; /** * @brief Get the USBDeviceID for a device. * @param device The libusb device to get the ID of. * @returns The USBDeviceID for this device. */ virtual USBDeviceID GetDeviceId(libusb_device *device) const = 0; // Static helper methods. /** * @brief Initialize a new libusb context. * @param context A pointer to a libusb context. * @returns true if the context is initialized, false otherwise. */ static bool Initialize(struct libusb_context **context); /** * @brief Fetch the manufacturer, product and serial strings from a device. * @param usb_device The USB device to get information for. * @param device_descriptor The descriptor to use * @param[out] device_info The DeviceInformation struct to populate. * @returns true if we fetched the information, false otherwise. */ static bool GetDeviceInfo( struct libusb_device *usb_device, const struct libusb_device_descriptor &device_descriptor, DeviceInformation *device_info); /** * @brief Check if the manufacturer string matches the expected value. * @param expected The expected manufacturer string. * @param device_info The DeviceInformation struct to check against. * @returns true if the strings matched, false otherwise. */ static bool CheckManufacturer(const std::string &expected, const DeviceInformation &device_info); /** * @brief Check if the product string matches the expected value. * @param expected The expected product string. * @param device_info The DeviceInformation struct to check against. * @returns true if the strings matched, false otherwise. */ static bool CheckProduct(const std::string &expected, const DeviceInformation &device_info); /** * @brief Check if this platform supports hotplug. * @returns true if hotplug is supported and enabled on this platform, false * otherwise. */ static bool HotplugSupported(); /** * @brief Try and convert an error code to a string * @param error_code The error code. * @returns A string representing the error code. */ static std::string ErrorCodeToString(const int error_code); }; /** * @brief The base LibUsbAdaptor that passes most calls through to libusb. */ class BaseLibUsbAdaptor : public LibUsbAdaptor { public: // Device handling and enumeration libusb_device* RefDevice(libusb_device *dev); void UnrefDevice(libusb_device *dev); int SetConfiguration(libusb_device_handle *dev, int configuration); int ClaimInterface(libusb_device_handle *dev, int interface_number); int DetachKernelDriver(libusb_device_handle *dev, int interface_number); // USB descriptors int GetDeviceDescriptor(libusb_device *dev, struct libusb_device_descriptor *descriptor); int GetActiveConfigDescriptor( libusb_device *dev, struct libusb_config_descriptor **config); int GetConfigDescriptor(libusb_device *dev, uint8_t config_index, struct libusb_config_descriptor **config); void FreeConfigDescriptor(struct libusb_config_descriptor *config); bool GetStringDescriptor(libusb_device_handle *usb_handle, uint8_t descriptor_index, std::string *data); // Asynchronous device I/O struct libusb_transfer* AllocTransfer(int iso_packets); void FreeTransfer(struct libusb_transfer *transfer); int SubmitTransfer(struct libusb_transfer *transfer); int CancelTransfer(struct libusb_transfer *transfer); void FillControlSetup(unsigned char *buffer, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint16_t wLength); void FillControlTransfer(struct libusb_transfer *transfer, libusb_device_handle *dev_handle, unsigned char *buffer, libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout); void FillBulkTransfer(struct libusb_transfer *transfer, libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *buffer, int length, libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout); void FillInterruptTransfer(struct libusb_transfer *transfer, libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *buffer, int length, libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout); // Synchronous device I/O int ControlTransfer(libusb_device_handle *dev_handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned char *data, uint16_t wLength, unsigned int timeout); int BulkTransfer(struct libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *data, int length, int *transferred, unsigned int timeout); int InterruptTransfer(libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *data, int length, int *actual_length, unsigned int timeout); USBDeviceID GetDeviceId(libusb_device *device) const; }; /** * @brief A LibUsbAdaptor for use with Syncronous widgets. * * When using syncronous mode, we don't have the requirement of interacting * with a LibUsbThread. */ class SyncronousLibUsbAdaptor : public BaseLibUsbAdaptor { public: SyncronousLibUsbAdaptor() {} bool OpenDevice(libusb_device *usb_device, libusb_device_handle **usb_handle); bool OpenDeviceAndClaimInterface(libusb_device *usb_device, int interface, libusb_device_handle **usb_handle); void Close(libusb_device_handle *usb_handle); private: DISALLOW_COPY_AND_ASSIGN(SyncronousLibUsbAdaptor); }; /** * @brief A LibUsbAdaptor for use with Asyncronous widgets. * * Asyncronous mode requires notifying the LibUsbThread when handles are opened * and closed. */ class AsyncronousLibUsbAdaptor : public BaseLibUsbAdaptor { public: explicit AsyncronousLibUsbAdaptor(class LibUsbThread *thread) : m_thread(thread) { } bool OpenDevice(libusb_device *usb_device, libusb_device_handle **usb_handle); bool OpenDeviceAndClaimInterface(libusb_device *usb_device, int interface, libusb_device_handle **usb_handle); void Close(libusb_device_handle *usb_handle); int ControlTransfer(libusb_device_handle *dev_handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned char *data, uint16_t wLength, unsigned int timeout); int BulkTransfer(struct libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *data, int length, int *transferred, unsigned int timeout); int InterruptTransfer(libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *data, int length, int *actual_length, unsigned int timeout); private: class LibUsbThread *m_thread; DISALLOW_COPY_AND_ASSIGN(AsyncronousLibUsbAdaptor); }; } // namespace usb } // namespace ola #endif // LIBS_USB_LIBUSBADAPTOR_H_ ola-0.10.5.nojsmin/libs/usb/JaRuleConstants.h0000644000175000017500000001167313023355232020440 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * JaRuleConstants.h * Constants used with Ja Rule devices. * Copyright (C) 2015 Simon Newton */ #ifndef LIBS_USB_JARULECONSTANTS_H_ #define LIBS_USB_JARULECONSTANTS_H_ #include #include #include namespace ola { namespace usb { /** * @brief Ja Rule status flags. */ typedef enum { FLAGS_CHANGED_FLAG = 0x02, //!< Flags have changed MSG_TRUNCATED_FLAG = 0x04 //!< The message has been truncated. } JaRuleStatusFlags; /** * @brief Ja Rule Port modes. */ typedef enum { CONTROLLER_MODE, //!< DMX/RDM Controller mode RESPONDER_MODE, //!< DMX/RDM Responder mode SELF_TEST_MODE, //!< Self test mode } JaRulePortMode; /** * @brief Indicates the eventual state of a Ja Rule command. * * Various failures can occur at the libusb layer. */ typedef enum { /** * @brief The command was sent and a response was received. */ COMMAND_RESULT_OK, /** * @brief The command is malformed. * * This could mean the payload is too big or a NULL pointer with a non-0 * size was provided. */ COMMAND_RESULT_MALFORMED, /** * @brief An error occured when trying to send the command. */ COMMAND_RESULT_SEND_ERROR, /** * @brief The command was not sent as the TX queue was full. */ COMMAND_RESULT_QUEUE_FULL, /** * @brief The command was sent but no response was received. */ COMMAND_RESULT_TIMEOUT, /** * @brief The command class returned did not match the request. */ COMMAND_RESULT_CLASS_MISMATCH, /** * @brief The command was cancelled. */ COMMAND_RESULT_CANCELLED, /** * @brief Invalid port */ COMMAND_RESULT_INVALID_PORT } USBCommandResult; /** * @brief The Ja Rule command set. */ typedef enum { JARULE_CMD_RESET_DEVICE = 0x00, JARULE_CMD_SET_MODE = 0x01, JARULE_CMD_GET_HARDWARE_INFO = 0x02, JARULE_CMD_RUN_SELF_TEST = 0x03, JARULE_CMD_SET_BREAK_TIME = 0x10, JARULE_CMD_GET_BREAK_TIME = 0x11, JARULE_CMD_SET_MARK_TIME = 0x12, JARULE_CMD_GET_MARK_TIME = 0x13, JARULE_CMD_SET_RDM_BROADCAST_TIMEOUT = 0x20, JARULE_CMD_GET_RDM_BROADCAST_TIMEOUT = 0x21, JARULE_CMD_SET_RDM_RESPONSE_TIMEOUT = 0x22, JARULE_CMD_GET_RDM_RESPONSE_TIMEOUT = 0x23, JARULE_CMD_SET_RDM_DUB_RESPONSE_LIMIT = 0x24, JARULE_CMD_GET_RDM_DUB_RESPONSE_LIMIT = 0x25, JARULE_CMD_SET_RDM_RESPONDER_DELAY = 0x26, JARULE_CMD_GET_RDM_RESPONDER_DELAY = 0x27, JARULE_CMD_SET_RDM_RESPONDER_JITTER = 0x28, JARULE_CMD_GET_RDM_RESPONDER_JITTER = 0x29, JARULE_CMD_TX_DMX = 0x30, JARULE_CMD_RDM_DUB_REQUEST = 0x40, JARULE_CMD_RDM_REQUEST = 0x41, JARULE_CMD_RDM_BROADCAST_REQUEST = 0x42, // Experimental / testing JARULE_CMD_ECHO = 0xf0, JARULE_CMD_GET_FLAGS = 0xf2, } CommandClass; /** * @brief JaRule command return codes. */ typedef enum { RC_OK, //!< The command completed successfully. RC_UNKNOWN, //!< Unknown command /** * @brief The command could not be completed due to a full memory buffer */ RC_BUFFER_FULL, RC_BAD_PARAM, //!< The command was malformed. RC_TX_ERROR, //!< There was an error during transceiver transmit. RC_RDM_TIMEOUT, //!< No RDM response was received. /** * @brief Data was received in response to a broadcast RDM command. * * This usually indicates a broken responder. */ RC_RDM_BCAST_RESPONSE, RC_RDM_INVALID_RESPONSE, //!< An invalid RDM response was received. RC_INVALID_MODE, //!< The command is invalid in the current mode. RC_LAST //!< One past the last valid return code. } JaRuleReturnCode; /** * @brief A command completion callback. * @tparam The result of the command operation * @tparam The return code from the Ja Rule device. * @tparam The status flags. * @tparam The response payload. * * If the USBCommandResult is not COMMAND_COMPLETED_OK, the remaining values * are undefined. */ typedef ola::BaseCallback4 CommandCompleteCallback; std::ostream& operator<<(std::ostream& os, const USBCommandResult &result); std::ostream& operator<<(std::ostream& os, const CommandClass &command_class); std::ostream& operator<<(std::ostream& os, const JaRuleReturnCode &rc); } // namespace usb } // namespace ola #endif // LIBS_USB_JARULECONSTANTS_H_ ola-0.10.5.nojsmin/libs/usb/JaRuleWidget.h0000644000175000017500000001245413023355232017705 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * JaRuleWidget.h * A Ja Rule widget. * Copyright (C) 2015 Simon Newton */ #ifndef LIBS_USB_JARULEWIDGET_H_ #define LIBS_USB_JARULEWIDGET_H_ #include #include #include #include #include #include #include #include "libs/usb/LibUsbAdaptor.h" #include "libs/usb/JaRuleConstants.h" #include "libs/usb/Types.h" namespace ola { namespace usb { /** * @brief A Ja Rule hardware device (widget). * * Ja Rule devices may have more than one DMX/RDM port. * * This class provides two ways to control the ports on the device: * - The low level SendCommand() method, which sends a single request and * invokes a callback when the response is received. * - The high level API where the port is accessed via a JaRulePortHandle. * Since the JaRulePortHandle implements the * ola::rdm::DiscoverableRDMControllerInterface, the usual RDM methods can * be used. * * To obtain a JaRulePortHandle, call ClaimPort(), when you're finished with * the JaRulePortHandle you must call ReleasePort(). */ class JaRuleWidget { public: /** * @brief Create a new Ja Rule widget. * @param executor The Executor to run the callbacks on. * @param adaptor The LibUsbAdaptor to use. * @param usb_device the libusb_device for the Ja Rule widget. */ JaRuleWidget(ola::thread::ExecutorInterface *executor, AsyncronousLibUsbAdaptor *adaptor, libusb_device *usb_device); /** * @brief Destructor */ ~JaRuleWidget(); /** * @brief Initialize the Ja Rule widget. * @returns true if the USB device was opened and claimed correctly, false * otherwise. */ bool Init(); /** * @brief The device ID of this widget. * @returns The USBDeviceID. */ USBDeviceID GetDeviceId() const; /** * @brief Cancel all queued and inflight commands. * @param port_id The port id of the commands to cancel * * This will immediately run all CommandCompleteCallbacks with the * COMMAND_CANCELLED code. */ void CancelAll(uint8_t port_id); /** * @brief The number of ports on the widget. * @pre Init() has been called and returned true; * @returns The number of ports. * * Ports are numbered consecutively from 0. */ uint8_t PortCount() const; /** * @brief The UID of the widget. * @pre Init() has been called and returned true; * @returns The UID for the device. */ ola::rdm::UID GetUID() const; /** * @brief Get the manufacturer string. * @pre Init() has been called and returned true; * @returns The manufacturer string. */ std::string ManufacturerString() const; /** * @brief Get the product string. * @pre Init() has been called and returned true; * @returns The product string. */ std::string ProductString() const; /** * @brief Claim a handle to a port. * @param port_index The port to claim. * @returns a port handle, ownership is not transferred. Will return NULL if * the port id is invalid, or already claimed. */ class JaRulePortHandle* ClaimPort(uint8_t port_index); /** * @brief Release a handle to a port. * @param port_index The port to claim * @returns a port handle, ownership is not transferred. */ void ReleasePort(uint8_t port_index); /** * @brief The low level API to send a command to the widget. * @param port_index The port on which to send the command. * @param command the Command type. * @param data the payload data. The data is copied and can be freed once the * method returns. * @param size the payload size. * @param callback The callback to run when the command completes. * This may be run immediately in some conditions. * * SendCommand() can be called from any thread, and messages will be queued. */ void SendCommand(uint8_t port_index, CommandClass command, const uint8_t *data, unsigned int size, CommandCompleteCallback *callback); private: typedef std::vector PortHandles; ola::thread::ExecutorInterface *m_executor; LibUsbAdaptor *m_adaptor; libusb_device *m_device; libusb_device_handle *m_usb_handle; ola::rdm::UID m_uid; // The UID of the device, or 0000:00000000 if unset std::string m_manufacturer; std::string m_product; PortHandles m_ports; // The list of port handles. bool InternalInit(); static const uint8_t SUBCLASS_VALUE = 0xff; static const uint8_t PROTOCOL_VALUE = 0xff; DISALLOW_COPY_AND_ASSIGN(JaRuleWidget); }; } // namespace usb } // namespace ola #endif // LIBS_USB_JARULEWIDGET_H_ ola-0.10.5.nojsmin/libs/usb/JaRuleConstants.cpp0000644000175000017500000001126313023355232020766 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * JaRuleConstants.cpp * Constants used with Ja Rule devices. * Copyright (C) 2015 Simon Newton */ #include "libs/usb/JaRuleConstants.h" #include namespace ola { namespace usb { using std::ostream; ostream& operator<<(ostream& os, const USBCommandResult &result) { switch (result) { case COMMAND_RESULT_OK: os << "OK"; break; case COMMAND_RESULT_MALFORMED: os << "MALFORMED"; break; case COMMAND_RESULT_SEND_ERROR: os << "SEND_ERROR"; break; case COMMAND_RESULT_QUEUE_FULL: os << "QUEUE_FULL"; break; case COMMAND_RESULT_TIMEOUT: os << "TIMEOUT"; break; case COMMAND_RESULT_CLASS_MISMATCH: os << "CLASS_MISMATCH"; break; case COMMAND_RESULT_CANCELLED: os << "CANCELLED"; break; case COMMAND_RESULT_INVALID_PORT: os << "INVALID_PORT"; break; default: os << "Unknown"; } os << " (" << static_cast(result) << ")"; return os; } ostream& operator<<(ostream& os, const CommandClass &command_class) { switch (command_class) { case JARULE_CMD_RESET_DEVICE: os << "RESET_DEVICE"; break; case JARULE_CMD_SET_MODE: os << "SET_MODE"; break; case JARULE_CMD_GET_HARDWARE_INFO: os << "GET_HARDWARE_INFO"; break; case JARULE_CMD_RUN_SELF_TEST: os << "RUN_SELF_TEST"; break; case JARULE_CMD_SET_BREAK_TIME: os << "SET_BREAK_TIME"; break; case JARULE_CMD_GET_BREAK_TIME: os << "GET_BREAK_TIME"; break; case JARULE_CMD_SET_MARK_TIME: os << "SET_MARK_TIME"; break; case JARULE_CMD_GET_MARK_TIME: os << "GET_MARK_TIME"; break; case JARULE_CMD_SET_RDM_BROADCAST_TIMEOUT: os << "SET_RDM_BROADCAST_TIMEOUT"; break; case JARULE_CMD_GET_RDM_BROADCAST_TIMEOUT: os << "GET_RDM_BROADCAST_TIMEOUT"; break; case JARULE_CMD_SET_RDM_RESPONSE_TIMEOUT: os << "SET_RDM_RESPONSE_TIMEOUT"; break; case JARULE_CMD_GET_RDM_RESPONSE_TIMEOUT: os << "GET_RDM_RESPONSE_TIMEOUT"; break; case JARULE_CMD_SET_RDM_DUB_RESPONSE_LIMIT: os << "SET_RDM_DUB_RESPONSE_LIMIT"; break; case JARULE_CMD_GET_RDM_DUB_RESPONSE_LIMIT: os << "GET_RDM_DUB_RESPONSE_LIMIT"; break; case JARULE_CMD_SET_RDM_RESPONDER_DELAY: os << "SET_RDM_RESPONDER_DELAY"; break; case JARULE_CMD_GET_RDM_RESPONDER_DELAY: os << "GET_RDM_RESPONDER_DELAY"; break; case JARULE_CMD_SET_RDM_RESPONDER_JITTER: os << "SET_RDM_RESPONDER_JITTER"; break; case JARULE_CMD_GET_RDM_RESPONDER_JITTER: os << "GET_RDM_RESPONDER_JITTER"; break; case JARULE_CMD_TX_DMX: os << "TX_DMX"; break; case JARULE_CMD_RDM_DUB_REQUEST: os << "RDM_DUB_REQUEST"; break; case JARULE_CMD_RDM_REQUEST: os << "RDM_REQUEST"; break; case JARULE_CMD_RDM_BROADCAST_REQUEST: os << "RDM_BROADCAST_REQUEST"; break; case JARULE_CMD_ECHO: os << "ECHO"; break; case JARULE_CMD_GET_FLAGS: os << "GET_FLAGS"; break; default: os << "Unknown"; } os << " (" << static_cast(command_class) << ")"; return os; } ostream& operator<<(ostream& os, const JaRuleReturnCode &rc) { switch (rc) { case RC_OK: os << "OK"; break; case RC_UNKNOWN: os << "UNKNOWN"; break; case RC_BUFFER_FULL: os << "BUFFER_FULL"; break; case RC_BAD_PARAM: os << "BAD_PARAM"; break; case RC_TX_ERROR: os << "TX_ERROR"; break; case RC_RDM_TIMEOUT: os << "RDM_TIMEOUT"; break; case RC_RDM_BCAST_RESPONSE: os << "RDM_BCAST_RESPONSE"; break; case RC_RDM_INVALID_RESPONSE: os << "RDM_INVALID_RESPONSE"; break; case RC_INVALID_MODE: os << "INVALID_MODE"; break; default: os << "Unknown"; } os << " (" << static_cast(rc) << ")"; return os; } } // namespace usb } // namespace ola ola-0.10.5.nojsmin/libs/usb/Types.h0000644000175000017500000000241513023355232016457 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Types.h * Types used with the USB subsystem. * Copyright (C) 2015 Simon Newton */ #ifndef LIBS_USB_TYPES_H_ #define LIBS_USB_TYPES_H_ #include #include namespace ola { namespace usb { class USBDeviceID { public: USBDeviceID(uint8_t bus_number, uint8_t device_address); const uint8_t bus_number; const uint8_t device_address; bool operator<(const USBDeviceID &id) const; friend std::ostream& operator<<(std::ostream& os, const USBDeviceID &id); }; } // namespace usb } // namespace ola #endif // LIBS_USB_TYPES_H_ ola-0.10.5.nojsmin/libs/usb/HotplugAgent.h0000644000175000017500000001174613023355232017763 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * HotplugAgent.h * Handles auto-detection of USB devices. * Copyright (C) 2015 Simon Newton */ #ifndef LIBS_USB_HOTPLUGAGENT_H_ #define LIBS_USB_HOTPLUGAGENT_H_ #include #include #include #include #include #include "libs/usb/LibUsbAdaptor.h" #include "libs/usb/LibUsbThread.h" #include "libs/usb/Types.h" namespace ola { namespace usb { /** * @brief Detects when USB devices are added or removed. * * The HotplugAgent will run a callback when a USB device is added or removed. * On systems with libusb >= 1.0.16 which also support hotplug we'll use the * Hotplug API, otherwise we'll periodically check for devices. */ class HotplugAgent { public: enum EventType { DEVICE_ADDED, //!< The device was added. DEVICE_REMOVED, //!< The device ws removed. }; /** * @brief Called when a USB device has been added or removed * @tparam EventType The type of the event. * @tparam The libusb device for this event. * * The callback can be run in either the thread calling Start() or from * an internal hotplug thread. However it won't be called from both at once. */ typedef ola::Callback2 NotificationCallback; /** * @brief Create a new HotplugAgent. * @param notification_cb The callback to run when the device is added or * removed. Ownership is transferred. * @param debug_level The libusb debug level. */ HotplugAgent(NotificationCallback* notification_cb, int debug_level); /** * @brief Destructor. * * This will stop the HotplugAgent if it's still running. */ ~HotplugAgent(); /** * @brief Get the AsyncronousLibUsbAdaptor to use. * @returns An AsyncronousLibUsbAdaptor, ownership is not transferred. * @pre Must be called after Init() * * The adaptor is valid until the call to Stop(). */ AsyncronousLibUsbAdaptor *GetUSBAdaptor() const; /** * @brief Initialize the hotplug agent. * @returns true if the agent started correctly, false otherwise. */ bool Init(); /** * @brief Start the hotplug agent. * @returns true if the agent started correctly, false otherwise. * @pre Init() has been called and returned true. */ bool Start(); /** * @brief Prevent any further notifications from occuring. * * Once this returns, the NotificationCallback will not be called. */ void HaltNotifications(); /** * @brief Stop the HotplugAgent. * @returns true if stopped correctly, false otherwise. * * Stop() may result in notifications being run, however once Stop() returns, * no further calls to the notification callback will be made. */ bool Stop(); #ifdef HAVE_LIBUSB_HOTPLUG_API /** * @brief Called when a USB hotplug event occurs. * @param dev the libusb_device the event occurred for. * @param event indicates if the device was added or removed. * * This can be called from either the thread that called * Start(), or from the libusb thread. It can't be called from both threads at * once though, since the libusb thread is only started once the initial call * to libusb_hotplug_register_callback returns. */ void HotPlugEvent(struct libusb_device *dev, libusb_hotplug_event event); #endif // HAVE_LIBUSB_HOTPLUG_API private: typedef std::map DeviceMap; std::auto_ptr const m_notification_cb; const int m_debug_level; bool m_use_hotplug; libusb_context *m_context; std::auto_ptr m_usb_thread; std::auto_ptr m_usb_adaptor; std::auto_ptr m_scanner_thread; ola::thread::Mutex m_mutex; bool m_suppress_hotplug_events; // GUARDED_BY(m_mutex); // In hotplug mode, this is guarded by m_mutex while // m_suppress_hotplug_events is false. // In non-hotplug mode, this is only accessed from the scanner thread, unless // the thread is no longer running in which case it's accessed from the main // thread during cleanup DeviceMap m_devices; bool HotplugSupported(); bool ScanUSBDevices(); DISALLOW_COPY_AND_ASSIGN(HotplugAgent); }; } // namespace usb } // namespace ola #endif // LIBS_USB_HOTPLUGAGENT_H_ ola-0.10.5.nojsmin/libs/usb/LibUsbThreadTest.cpp0000644000175000017500000000705013134123277021063 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * LibUsbThreadTest.cpp * Test fixture for the LibUsbThread class * Copyright (C) 2014 Simon Newton */ #include #include #include "libs/usb/LibUsbAdaptor.h" #include "libs/usb/LibUsbThread.h" #include "ola/Logging.h" #include "ola/testing/TestUtils.h" namespace { #if HAVE_LIBUSB_HOTPLUG_API int LIBUSB_CALL hotplug_callback(OLA_UNUSED struct libusb_context *ctx, OLA_UNUSED struct libusb_device *dev, OLA_UNUSED libusb_hotplug_event event, OLA_UNUSED void *user_data) { return 0; } #endif // HAVE_LIBUSB_HOTPLUG_API } // namespace class LibUsbThreadTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(LibUsbThreadTest); CPPUNIT_TEST(testNonHotplug); #if HAVE_LIBUSB_HOTPLUG_API CPPUNIT_TEST(testHotplug); #endif // HAVE_LIBUSB_HOTPLUG_API CPPUNIT_TEST_SUITE_END(); public: LibUsbThreadTest() : m_context(NULL) {} void setUp(); void tearDown(); void testNonHotplug(); #if HAVE_LIBUSB_HOTPLUG_API void testHotplug(); #endif // HAVE_LIBUSB_HOTPLUG_API private: libusb_context *m_context; void AttemptDeviceOpen(ola::usb::LibUsbThread *thread); }; CPPUNIT_TEST_SUITE_REGISTRATION(LibUsbThreadTest); void LibUsbThreadTest::setUp() { if (libusb_init(&m_context)) { OLA_INFO << "Failed to init libusb"; } } void LibUsbThreadTest::tearDown() { if (m_context) { libusb_exit(m_context); } } void LibUsbThreadTest::testNonHotplug() { if (!m_context) { return; } ola::usb::LibUsbSimpleThread thread(m_context); OLA_ASSERT_TRUE(thread.Init()); AttemptDeviceOpen(&thread); } #if HAVE_LIBUSB_HOTPLUG_API void LibUsbThreadTest::testHotplug() { if (!m_context) { return; } bool hotplug_support = ola::usb::LibUsbAdaptor::HotplugSupported(); OLA_DEBUG << "HotplugSupported(): " << hotplug_support; ola::usb::LibUsbHotplugThread thread(m_context, hotplug_callback, NULL); if (hotplug_support) { OLA_ASSERT_TRUE(thread.Init()); AttemptDeviceOpen(&thread); thread.Shutdown(); } else { OLA_WARN << "No hotplug support, check that starting the thread fails"; OLA_ASSERT_FALSE(thread.Init()); } } #endif // HAVE_LIBUSB_HOTPLUG_API /* * Try to open any USB device so we can test interaction with the thread. */ void LibUsbThreadTest::AttemptDeviceOpen(ola::usb::LibUsbThread *thread) { libusb_device_handle *usb_handle = NULL; libusb_device **device_list; size_t device_count = libusb_get_device_list(m_context, &device_list); for (unsigned int i = 0; i < device_count; i++) { libusb_device *usb_device = device_list[i]; if (libusb_open(usb_device, &usb_handle) == 0) { thread->OpenHandle(); break; } } if (usb_handle) { thread->CloseHandle(usb_handle); } libusb_free_device_list(device_list, 1); } ola-0.10.5.nojsmin/libs/usb/HotplugAgent.cpp0000644000175000017500000001617713134123277020326 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * HotplugAgent.cpp * Handles auto-detection of USB devices. * Copyright (C) 2015 Simon Newton */ #include "libs/usb/HotplugAgent.h" #include #include #include #include #include #include #include #include #include #include #include "libs/usb/LibUsbAdaptor.h" #include "libs/usb/LibUsbThread.h" namespace ola { namespace usb { using ola::usb::AsyncronousLibUsbAdaptor; using ola::usb::LibUsbAdaptor; using std::auto_ptr; using std::pair; namespace { #ifdef HAVE_LIBUSB_HOTPLUG_API int LIBUSB_CALL hotplug_callback(OLA_UNUSED struct libusb_context *ctx, struct libusb_device *dev, libusb_hotplug_event event, void *user_data) { HotplugAgent *agent = reinterpret_cast(user_data); agent->HotPlugEvent(dev, event); return 0; } #endif // HAVE_LIBUSB_HOTPLUG_API } // namespace HotplugAgent::HotplugAgent(NotificationCallback* notification_cb, int debug_level) : m_notification_cb(notification_cb), m_debug_level(debug_level), m_use_hotplug(false), m_context(NULL), m_suppress_hotplug_events(false) { } HotplugAgent::~HotplugAgent() { if (m_context) { Stop(); } } AsyncronousLibUsbAdaptor *HotplugAgent::GetUSBAdaptor() const { return m_usb_adaptor.get(); } bool HotplugAgent::Init() { if (!LibUsbAdaptor::Initialize(&m_context)) { return false; } OLA_DEBUG << "libusb_set_debug(" << m_debug_level << ")"; libusb_set_debug(m_context, m_debug_level); m_use_hotplug = ola::usb::LibUsbAdaptor::HotplugSupported(); OLA_DEBUG << "HotplugSupported(): " << m_use_hotplug; #ifdef HAVE_LIBUSB_HOTPLUG_API if (m_use_hotplug) { m_usb_thread.reset(new ola::usb::LibUsbHotplugThread( m_context, hotplug_callback, this)); } #endif // HAVE_LIBUSB_HOTPLUG_API if (!m_usb_thread.get()) { m_usb_thread.reset(new ola::usb::LibUsbSimpleThread(m_context)); } m_usb_adaptor.reset( new ola::usb::AsyncronousLibUsbAdaptor(m_usb_thread.get())); return true; } bool HotplugAgent::Start() { // If we're using hotplug, this starts the hotplug thread. if (!m_usb_thread->Init()) { m_usb_adaptor.reset(); m_usb_thread.reset(); return false; } if (!m_use_hotplug) { // Either we don't support hotplug or the setup failed. // As poor man's hotplug, we call libusb_get_device_list periodically to // check for new devices. m_scanner_thread.reset(new ola::thread::PeriodicThread( TimeInterval(5, 0), NewCallback(this, &HotplugAgent::ScanUSBDevices))); } return true; } void HotplugAgent::HaltNotifications() { // To prevent any further notifications, we need to either: // - suppress hotplug events so we don't add any new devices. // OR // - Stop the scanner thread, same idea above applies. if (m_scanner_thread.get()) { m_scanner_thread->Stop(); } { ola::thread::MutexLocker locker(&m_mutex); m_suppress_hotplug_events = true; } } bool HotplugAgent::Stop() { // Prevent any further notifications if we haven't already. // Once this completes, we're free to access m_devices without a lock. HaltNotifications(); m_devices.clear(); // Stop the usb_thread (if using hotplug, otherwise this is a noop). m_usb_thread->Shutdown(); m_usb_thread.reset(); m_usb_adaptor.reset(); libusb_exit(m_context); m_context = NULL; return true; } #ifdef HAVE_LIBUSB_HOTPLUG_API void HotplugAgent::HotPlugEvent(struct libusb_device *usb_device, libusb_hotplug_event event) { ola::thread::MutexLocker locker(&m_mutex); if (m_suppress_hotplug_events) { return; } USBDeviceID device_id = m_usb_adaptor->GetDeviceId(usb_device); OLA_INFO << "USB hotplug event: " << device_id << " @" << usb_device << " [" << (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED ? "add" : "del") << "]"; if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED) { pair p = m_devices.insert( DeviceMap::value_type(device_id, usb_device)); if (!p.second) { // already an entry in the map if (p.first->second != usb_device) { OLA_WARN << "Received double hotplug notification for " << device_id; } return; } m_notification_cb->Run(DEVICE_ADDED, usb_device); } else if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT) { DeviceMap::iterator iter = m_devices.find(device_id); if (iter == m_devices.end()) { OLA_WARN << "Failed to find " << device_id; return; } if (iter->second != usb_device) { OLA_WARN << "Device mismatch for " << device_id; return; } m_devices.erase(iter); m_notification_cb->Run(DEVICE_REMOVED, usb_device); } } #endif // HAVE_LIBUSB_HOTPLUG_API /** * @brief Check if this platform supports hotplug. * @returns true if hotplug is supported and enabled on this platform, false * otherwise. * @deprecated This is only here for backwards compatibility. New code should * use ola::usb::LibUsbAdaptor::HotplugSupported(). */ bool HotplugAgent::HotplugSupported() { return ola::usb::LibUsbAdaptor::HotplugSupported(); } /* * If hotplug isn't supported, this is called periodically to check for * USB devices that have been added or removed. */ bool HotplugAgent::ScanUSBDevices() { std::set current_device_ids; libusb_device **device_list; size_t device_count = libusb_get_device_list(m_context, &device_list); for (unsigned int i = 0; i < device_count; i++) { libusb_device *usb_device = device_list[i]; USBDeviceID device_id = m_usb_adaptor->GetDeviceId(usb_device); current_device_ids.insert(device_id); pair p = m_devices.insert( DeviceMap::value_type(device_id, usb_device)); if (p.second) { m_notification_cb->Run(DEVICE_ADDED, usb_device); } } libusb_free_device_list(device_list, 1); // unref devices // Remove any old ones. DeviceMap::iterator iter = m_devices.begin(); while (iter != m_devices.end()) { if (!STLContains(current_device_ids, iter->first)) { m_notification_cb->Run(DEVICE_REMOVED, iter->second); m_devices.erase(iter++); } else { iter++; } } return true; } } // namespace usb } // namespace ola ola-0.10.5.nojsmin/libs/usb/LibUsbThread.h0000644000175000017500000001265613023355232017673 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * LibUsbThread.h * The thread for asynchronous libusb communication. * Copyright (C) 2014 Simon Newton */ #ifndef LIBS_USB_LIBUSBTHREAD_H_ #define LIBS_USB_LIBUSBTHREAD_H_ #include #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include "ola/base/Macro.h" #include "ola/thread/Thread.h" namespace ola { namespace usb { /** * @brief The base class for the dedicated libusb thread. * * Asynchronous I/O for libusb requires either i) a dedicated thread ii) * integration with the i/o event loop. From the libusb documentation, i) has * the advantage that it works on Windows, so we do that. * * However, there is no easy way to interrupt libusb_handle_events(). Instead * we use either libusb_close (for the non-hotplug case) or * libusb_hotplug_deregister_callback() (for the hotplug case) to wake * libusb_handle_events(). * * Both these techniques have require care to avoid deadlocks / race * conditions. For the non-hotplug case, it's imperative that libusb_open() and * libusb_close() are paired with calls to OpenHandle() and CloseHandle(). * * http://libusb.sourceforge.net/api-1.0/group__asyncio.html covers both * approaches. */ class LibUsbThread : private ola::thread::Thread { public: /** * @brief Base constructor * @param context the libusb context to use. */ explicit LibUsbThread(libusb_context *context) : m_context(context), m_term(false) { } /** * @brief Destructor. */ virtual ~LibUsbThread() {} /** * @brief Initialize the thread. */ virtual bool Init() { return true; } /** * @brief Shutdown the thread. */ virtual void Shutdown() {} /** * @brief The entry point to the libusb thread. * * Don't call this directly. It's executed when the thread starts. */ void *Run(); /** * @brief This must be called whenever libusb_open() is called. */ virtual void OpenHandle() = 0; /** * @brief This must be called whenever libusb_close() is called. */ virtual void CloseHandle(libusb_device_handle *handle) = 0; protected: /** * @brief Indicate that the libusb thread should terminate. * * This doesn't wake up libusb_handle_events(), it simply sets m_term to * true. */ void SetTerminate() { ola::thread::MutexLocker locker(&m_term_mutex); m_term = true; } /** * @brief Start the libusb thread. */ void LaunchThread(); /** * @brief Join the libusb thread. */ void JoinThread(); /** * @brief Return the libusb_context this thread uses. * @returns A libusb_context. */ libusb_context* Context() const { return m_context; } private: libusb_context *m_context; bool m_term; // GUARDED_BY(m_term_mutex) ola::thread::Mutex m_term_mutex; }; #if HAVE_LIBUSB_HOTPLUG_API /** * @brief The hotplug version of the LibUsbThread. */ class LibUsbHotplugThread : public LibUsbThread { public: /** * @brief Create a new LibUsbHotplugThread * @param context the libusb context to use. * @param callback_fn The callback function to run when hotplug events occur. * @param user_data User data to pass to the callback function. * * The thread is started in Init(). When the object is * destroyed, the handle is de-registered as part of the thread shutdown * sequence. */ LibUsbHotplugThread(libusb_context *context, libusb_hotplug_callback_fn callback_fn, void *user_data); bool Init(); void Shutdown(); void OpenHandle() {} void CloseHandle(libusb_device_handle *handle); private: libusb_hotplug_callback_handle m_hotplug_handle; libusb_hotplug_callback_fn m_callback_fn; void *m_user_data; DISALLOW_COPY_AND_ASSIGN(LibUsbHotplugThread); }; #endif // HAVE_LIBUSB_HOTPLUG_API /** * @brief The non-hotplug version of LibUsbThread. * * The libusb thread is only run when one of more handles are open. Otherwise * there is no way to interrupt libusb_handle_events(). See the libusb Async * documentation at http://libusb.sourceforge.net/api-1.0/group__asyncio.html * for more information. */ class LibUsbSimpleThread : public LibUsbThread { public: /** * @brief Create a new LibUsbHotplugThread * @param context the libusb context to use. * * The thread is starts as soon as this object is created. When the object is * destroyed, the handle is de-registered as part of the thread shutdown * sequence. */ explicit LibUsbSimpleThread(libusb_context *context) : LibUsbThread(context), m_device_count(0) { } void OpenHandle(); void CloseHandle(libusb_device_handle *handle); private: unsigned int m_device_count; DISALLOW_COPY_AND_ASSIGN(LibUsbSimpleThread); }; } // namespace usb } // namespace ola #endif // LIBS_USB_LIBUSBTHREAD_H_ ola-0.10.5.nojsmin/libs/usb/JaRulePortHandle.cpp0000644000175000017500000000457713023355232021064 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * JaRulePortHandle.cpp * A Ja Rule Port Handle. * Copyright (C) 2015 Simon Newton */ #include "libs/usb/JaRulePortHandle.h" #include #include #include #include #include #include "libs/usb/JaRulePortHandleImpl.h" namespace ola { namespace usb { JaRulePortHandle::JaRulePortHandle(class JaRuleWidgetPort *parent_port, const ola::rdm::UID &uid, uint8_t physical_port) : m_impl(new JaRulePortHandleImpl(parent_port, uid, physical_port)), m_queueing_controller(m_impl.get(), RDM_QUEUE_SIZE) { } JaRulePortHandle::~JaRulePortHandle() { // Pause the queuing controller so it stops sending anything more to the // impl. m_queueing_controller.Pause(); // This will run any remaining callbacks. m_impl.reset(); // m_queueing_controller will be destroyed next. } void JaRulePortHandle::SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *on_complete) { m_queueing_controller.SendRDMRequest(request, on_complete); } void JaRulePortHandle::RunFullDiscovery( ola::rdm::RDMDiscoveryCallback *callback) { m_queueing_controller.RunFullDiscovery(callback); } void JaRulePortHandle::RunIncrementalDiscovery( ola::rdm::RDMDiscoveryCallback *callback) { m_queueing_controller.RunIncrementalDiscovery(callback); } bool JaRulePortHandle::SendDMX(const DmxBuffer &buffer) { return m_impl->SendDMX(buffer); } bool JaRulePortHandle::SetPortMode(JaRulePortMode new_mode) { return m_impl->SetPortMode(new_mode); } } // namespace usb } // namespace ola ola-0.10.5.nojsmin/libs/usb/LibUsbAdaptor.cpp0000644000175000017500000003505013134123277020407 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * LibUsbAdaptor.cpp * The wrapper around libusb calls. * Copyright (C) 2014 Simon Newton */ #include "libs/usb/LibUsbAdaptor.h" #include #include #include #include #include "libs/usb/LibUsbThread.h" namespace ola { namespace usb { using std::ostringstream; using std::string; namespace { /** * @brief A wrapper around libusb_get_string_descriptor_ascii. */ bool GetStringDescriptorAscii(libusb_device_handle *usb_handle, uint8_t desc_index, string *data) { enum { buffer_size = 32 }; // static arrays FTW! unsigned char buffer[buffer_size]; int r = libusb_get_string_descriptor_ascii( usb_handle, desc_index, buffer, buffer_size); if (r <= 0) { OLA_INFO << "libusb_get_string_descriptor_ascii failed: " << LibUsbAdaptor::ErrorCodeToString(r); return false; } data->assign(reinterpret_cast(buffer)); return true; } /** * @brief A wrapper around libusb_open. */ bool Open(libusb_device *usb_device, libusb_device_handle **usb_handle) { int r = libusb_open(usb_device, usb_handle); if (r) { OLA_WARN << "Failed to open libusb device: " << usb_device << ": " << LibUsbAdaptor::ErrorCodeToString(r); return false; } return true; } bool OpenHandleAndClaimInterface(libusb_device *usb_device, int interface, libusb_device_handle **usb_handle) { if (!Open(usb_device, usb_handle)) { return false; } int r = libusb_claim_interface(*usb_handle, interface); if (r) { OLA_WARN << "Failed to claim interface " << interface << " on device: " << usb_device << ": " << LibUsbAdaptor::ErrorCodeToString(r); libusb_close(*usb_handle); *usb_handle = NULL; return false; } return true; } } // namespace // LibUsbAdaptor // ---------------------------------------------------------------------------- bool LibUsbAdaptor::Initialize(struct libusb_context **context) { int r = libusb_init(context); if (r) { OLA_WARN << "libusb_init() failed: " << ErrorCodeToString(r); return false; } return true; } bool LibUsbAdaptor::GetDeviceInfo( struct libusb_device *usb_device, const struct libusb_device_descriptor &device_descriptor, DeviceInformation *device_info) { // Since the calls on the handle are syncronous, we don't bother adding the // handle to the thread. libusb_device_handle *usb_handle; if (!Open(usb_device, &usb_handle)) { return false; } if (!GetStringDescriptorAscii(usb_handle, device_descriptor.iManufacturer, &device_info->manufacturer)) { OLA_INFO << "Failed to get manufacturer name"; } if (!GetStringDescriptorAscii(usb_handle, device_descriptor.iProduct, &device_info->product)) { OLA_INFO << "Failed to get product name"; } if (!GetStringDescriptorAscii(usb_handle, device_descriptor.iSerialNumber, &device_info->serial)) { OLA_WARN << "Failed to read serial number, the device probably doesn't " << "have one"; } libusb_close(usb_handle); return true; } bool LibUsbAdaptor::CheckManufacturer(const string &expected, const DeviceInformation &device_info) { if (expected != device_info.manufacturer) { OLA_WARN << "Manufacturer mismatch: " << expected << " != " << device_info.manufacturer; return false; } return true; } bool LibUsbAdaptor::CheckProduct(const string &expected, const DeviceInformation &device_info) { if (expected != device_info.product) { OLA_WARN << "Product mismatch: " << expected << " != " << device_info.product; return false; } return true; } bool LibUsbAdaptor::HotplugSupported() { #ifdef HAVE_LIBUSB_HOTPLUG_API return libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG) != 0; #else return false; #endif // HAVE_LIBUSB_HOTPLUG_API } string LibUsbAdaptor::ErrorCodeToString(const int error_code) { #ifdef HAVE_LIBUSB_ERROR_NAME return libusb_error_name(error_code); #else ostringstream str; str << "Error code " << error_code; return str.str(); #endif // HAVE_LIBUSB_ERROR_NAME } // BaseLibUsbAdaptor // ---------------------------------------------------------------------------- libusb_device* BaseLibUsbAdaptor::RefDevice(libusb_device *dev) { return libusb_ref_device(dev); } void BaseLibUsbAdaptor::UnrefDevice(libusb_device *dev) { libusb_unref_device(dev); } int BaseLibUsbAdaptor::SetConfiguration(libusb_device_handle *dev, int configuration) { return libusb_set_configuration(dev, configuration); } int BaseLibUsbAdaptor::ClaimInterface(libusb_device_handle *dev, int interface_number) { return libusb_claim_interface(dev, interface_number); } int BaseLibUsbAdaptor::DetachKernelDriver(libusb_device_handle *dev, int interface_number) { if (libusb_kernel_driver_active(dev, interface_number)) { int r = libusb_detach_kernel_driver(dev, interface_number); if (r) { OLA_WARN << "libusb_detach_kernel_driver failed for: " << dev << ": " << LibUsbAdaptor::ErrorCodeToString(r); } return r; } else { return 0; } } int BaseLibUsbAdaptor::GetActiveConfigDescriptor( libusb_device *dev, struct libusb_config_descriptor **config) { int r = libusb_get_active_config_descriptor(dev, config); if (r) { OLA_WARN << "libusb_get_active_config_descriptor failed for: " << dev << ": " << LibUsbAdaptor::ErrorCodeToString(r); } return r; } int BaseLibUsbAdaptor::GetDeviceDescriptor( libusb_device *dev, struct libusb_device_descriptor *desc) { int r = libusb_get_device_descriptor(dev, desc); if (r) { OLA_WARN << "libusb_get_device_descriptor failed for: " << dev << ": " << LibUsbAdaptor::ErrorCodeToString(r); } return r; } int BaseLibUsbAdaptor::GetConfigDescriptor( libusb_device *dev, uint8_t config_index, struct libusb_config_descriptor **config) { int r = libusb_get_config_descriptor(dev, config_index, config); if (r) { OLA_WARN << "libusb_get_config_descriptor failed for: " << dev << ": " << LibUsbAdaptor::ErrorCodeToString(r); } return r; } void BaseLibUsbAdaptor::FreeConfigDescriptor( struct libusb_config_descriptor *config) { libusb_free_config_descriptor(config); } bool BaseLibUsbAdaptor::GetStringDescriptor( libusb_device_handle *usb_handle, uint8_t descriptor_index, string *data) { return GetStringDescriptorAscii(usb_handle, descriptor_index, data); } struct libusb_transfer* BaseLibUsbAdaptor::AllocTransfer(int iso_packets) { return libusb_alloc_transfer(iso_packets); } void BaseLibUsbAdaptor::FreeTransfer(struct libusb_transfer *transfer) { return libusb_free_transfer(transfer); } int BaseLibUsbAdaptor::SubmitTransfer(struct libusb_transfer *transfer) { return libusb_submit_transfer(transfer); } int BaseLibUsbAdaptor::CancelTransfer(struct libusb_transfer *transfer) { return libusb_cancel_transfer(transfer); } void BaseLibUsbAdaptor::FillControlSetup(unsigned char *buffer, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint16_t wLength) { return libusb_fill_control_setup(buffer, bmRequestType, bRequest, wValue, wIndex, wLength); } void BaseLibUsbAdaptor::FillControlTransfer( struct libusb_transfer *transfer, libusb_device_handle *dev_handle, unsigned char *buffer, libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout) { return libusb_fill_control_transfer(transfer, dev_handle, buffer, callback, user_data, timeout); } void BaseLibUsbAdaptor::FillBulkTransfer(struct libusb_transfer *transfer, libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *buffer, int length, libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout) { libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer, length, callback, user_data, timeout); } void BaseLibUsbAdaptor::FillInterruptTransfer(struct libusb_transfer *transfer, libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *buffer, int length, libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout) { libusb_fill_interrupt_transfer(transfer, dev_handle, endpoint, buffer, length, callback, user_data, timeout); } int BaseLibUsbAdaptor::ControlTransfer( libusb_device_handle *dev_handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned char *data, uint16_t wLength, unsigned int timeout) { return libusb_control_transfer(dev_handle, bmRequestType, bRequest, wValue, wIndex, data, wLength, timeout); } int BaseLibUsbAdaptor::BulkTransfer(struct libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *data, int length, int *transferred, unsigned int timeout) { return libusb_bulk_transfer(dev_handle, endpoint, data, length, transferred, timeout); } int BaseLibUsbAdaptor::InterruptTransfer(libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *data, int length, int *actual_length, unsigned int timeout) { return libusb_interrupt_transfer(dev_handle, endpoint, data, length, actual_length, timeout); } USBDeviceID BaseLibUsbAdaptor::GetDeviceId(libusb_device *device) const { return USBDeviceID(libusb_get_bus_number(device), libusb_get_device_address(device)); } // SyncronousLibUsbAdaptor // ----------------------------------------------------------------------------- bool SyncronousLibUsbAdaptor::OpenDevice(libusb_device *usb_device, libusb_device_handle **usb_handle) { return Open(usb_device, usb_handle); } bool SyncronousLibUsbAdaptor::OpenDeviceAndClaimInterface( libusb_device *usb_device, int interface, libusb_device_handle **usb_handle) { return OpenHandleAndClaimInterface(usb_device, interface, usb_handle); } void SyncronousLibUsbAdaptor::Close(libusb_device_handle *usb_handle) { libusb_close(usb_handle); } // AsyncronousLibUsbAdaptor // ----------------------------------------------------------------------------- bool AsyncronousLibUsbAdaptor::OpenDevice(libusb_device *usb_device, libusb_device_handle **usb_handle) { bool ok = Open(usb_device, usb_handle); if (ok) { m_thread->OpenHandle(); } return ok; } bool AsyncronousLibUsbAdaptor::OpenDeviceAndClaimInterface( libusb_device *usb_device, int interface, libusb_device_handle **usb_handle) { bool ok = OpenHandleAndClaimInterface(usb_device, interface, usb_handle); if (ok) { m_thread->OpenHandle(); } return ok; } void AsyncronousLibUsbAdaptor::Close(libusb_device_handle *handle) { m_thread->CloseHandle(handle); } int AsyncronousLibUsbAdaptor::ControlTransfer( OLA_UNUSED libusb_device_handle *dev_handle, OLA_UNUSED uint8_t bmRequestType, OLA_UNUSED uint8_t bRequest, OLA_UNUSED uint16_t wValue, OLA_UNUSED uint16_t wIndex, OLA_UNUSED unsigned char *data, OLA_UNUSED uint16_t wLength, OLA_UNUSED unsigned int timeout) { OLA_DEBUG << "libusb_control_transfer in an AsyncronousLibUsbAdaptor"; return BaseLibUsbAdaptor::ControlTransfer(dev_handle, bmRequestType, bRequest, wValue, wIndex, data, wLength, timeout); } int AsyncronousLibUsbAdaptor::BulkTransfer( struct libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *data, int length, int *transferred, unsigned int timeout) { OLA_DEBUG << "libusb_bulk_transfer in an AsyncronousLibUsbAdaptor"; return BaseLibUsbAdaptor::BulkTransfer(dev_handle, endpoint, data, length, transferred, timeout); } int AsyncronousLibUsbAdaptor::InterruptTransfer( OLA_UNUSED libusb_device_handle *dev_handle, OLA_UNUSED unsigned char endpoint, OLA_UNUSED unsigned char *data, OLA_UNUSED int length, OLA_UNUSED int *actual_length, OLA_UNUSED unsigned int timeout) { OLA_DEBUG << "libusb_interrupt_transfer in an AsyncronousLibUsbAdaptor"; return BaseLibUsbAdaptor::InterruptTransfer(dev_handle, endpoint, data, length, actual_length, timeout); } } // namespace usb } // namespace ola ola-0.10.5.nojsmin/libs/acn/0000755000175000017500000000000013155164170015155 5ustar wouterwouterola-0.10.5.nojsmin/libs/acn/E133Inflator.cpp0000644000175000017500000000455613023355232020000 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E133Inflator.cpp * The Inflator for the E1.33 PDUs * Copyright (C) 2011 Simon Newton */ #include #include "ola/Logging.h" #include "ola/network/NetworkUtils.h" #include "libs/acn/E133Inflator.h" namespace ola { namespace acn { using ola::network::NetworkToHost; /* * Decode the E1.33 headers. If data is null we're expected to use the last * header we got. * @param headers the HeaderSet to add to * @param data a pointer to the data * @param length length of the data * @returns true if successful, false otherwise */ bool E133Inflator::DecodeHeader(HeaderSet *headers, const uint8_t *data, unsigned int length, unsigned int *bytes_used) { if (data) { // the header bit was set, decode it if (length >= sizeof(E133Header::e133_pdu_header)) { E133Header::e133_pdu_header raw_header; memcpy(&raw_header, data, sizeof(E133Header::e133_pdu_header)); raw_header.source[E133Header::SOURCE_NAME_LEN - 1] = 0x00; E133Header header( raw_header.source, NetworkToHost(raw_header.sequence), NetworkToHost(raw_header.endpoint)); m_last_header = header; m_last_header_valid = true; headers->SetE133Header(header); *bytes_used = sizeof(E133Header::e133_pdu_header); return true; } *bytes_used = 0; return false; } // use the last header if it exists *bytes_used = 0; if (!m_last_header_valid) { OLA_WARN << "Missing E1.33 Header data"; return false; } headers->SetE133Header(m_last_header); return true; } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/BaseInflator.h0000644000175000017500000001052713023355232017677 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * BaseInflator.h * Provides the base class for inflating PDU blocks. * Copyright (C) 2007 Simon Newton * * The BaseInflator takes care of most of the heavy lifting when inflating PDU * blocks. To create a specific Inflator, subclass BaseInflator and implement * the Id() and DecodeHeader() methods. */ #ifndef LIBS_ACN_BASEINFLATOR_H_ #define LIBS_ACN_BASEINFLATOR_H_ #include #include #include "libs/acn/HeaderSet.h" #include "libs/acn/PDU.h" namespace ola { namespace acn { class BaseInflatorTest; /** * The inflator interface. */ class InflatorInterface { public: virtual ~InflatorInterface() {} /* * Return the id for this inflator */ virtual uint32_t Id() const = 0; /* * Parse a block of PDU data */ virtual unsigned int InflatePDUBlock(HeaderSet *headers, const uint8_t *data, unsigned int len) = 0; }; /* * An abstract PDU inflator */ class BaseInflator : public InflatorInterface { friend class BaseInflatorTest; public: explicit BaseInflator(PDU::vector_size v_size = PDU::FOUR_BYTES); virtual ~BaseInflator() {} /* * Add another inflator as a handler. Ownership is not transferred. */ bool AddInflator(InflatorInterface *inflator); /* * Return the inflator used for a particular vector. */ class InflatorInterface *GetInflator(uint32_t vector) const; /* * Parse a block of PDU data */ virtual unsigned int InflatePDUBlock(HeaderSet *headers, const uint8_t *data, unsigned int len); // masks for the flag fields // This indicates a 20 bit length field (default is 12 bits) static const uint8_t LFLAG_MASK = 0x80; // This masks the first 4 bits of the length field static const uint8_t LENGTH_MASK = 0x0F; protected: uint32_t m_last_vector; bool m_vector_set; PDU::vector_size m_vector_size; // size of the vector field // map protos to inflators std::map m_proto_map; // Reset repeated pdu fields virtual void ResetPDUFields(); virtual void ResetHeaderField() = 0; // determine the length of a pdu bool DecodeLength(const uint8_t *data, unsigned int data_length, unsigned int *pdu_length, unsigned int *bytes_used) const; // determine the vector of a pdu bool DecodeVector(uint8_t flags, const uint8_t *data, unsigned int length, uint32_t *vector, unsigned int *bytes_used); // Decode a header block and adds any PduHeaders to the HeaderSet object virtual bool DecodeHeader(HeaderSet *headers, const uint8_t *data, unsigned int len, unsigned int *bytes_used) = 0; // parse the body of a pdu bool InflatePDU(HeaderSet *headers, uint8_t flags, const uint8_t *data, unsigned int pdu_len); // called after the header is parsed virtual bool PostHeader(uint32_t vector, const HeaderSet &headers); // called in the absence of an inflator to handle the pdu data virtual bool HandlePDUData(uint32_t vector, const HeaderSet &headers, const uint8_t *data, unsigned int pdu_len); }; } // namespace acn } // namespace ola #endif // LIBS_ACN_BASEINFLATOR_H_ ola-0.10.5.nojsmin/libs/acn/Makefile.mk0000644000175000017500000001107413023355232017221 0ustar wouterwouterCOMMON_E131_CXXFLAGS = $(COMMON_CXXFLAGS) -Wconversion # pkg-config ################################################## if INSTALL_E133 pkgconfig_DATA += libs/acn/libolaacn.pc endif # LIBRARIES ################################################## if INSTALL_ACN lib_LTLIBRARIES += libs/acn/libolaacn.la else noinst_LTLIBRARIES += libs/acn/libolaacn.la endif # libolaacn.la libs_acn_libolaacn_la_SOURCES = \ libs/acn/CID.cpp \ libs/acn/CIDImpl.cpp \ libs/acn/CIDImpl.h libs_acn_libolaacn_la_CXXFLAGS = $(COMMON_E131_CXXFLAGS) $(uuid_CFLAGS) libs_acn_libolaacn_la_LIBADD = $(uuid_LIBS) \ common/libolacommon.la # libolae131core.la # This needs to be after libolaacn.la since it depends on it. Otherwise it # breaks the freeBSD build noinst_LTLIBRARIES += libs/acn/libolae131core.la libs_acn_libolae131core_la_SOURCES = \ libs/acn/BaseInflator.cpp \ libs/acn/BaseInflator.h \ libs/acn/DMPAddress.cpp \ libs/acn/DMPAddress.h \ libs/acn/DMPE131Inflator.cpp \ libs/acn/DMPE131Inflator.h \ libs/acn/DMPHeader.h \ libs/acn/DMPInflator.cpp \ libs/acn/DMPInflator.h \ libs/acn/DMPPDU.cpp \ libs/acn/DMPPDU.h \ libs/acn/E131DiscoveryInflator.cpp \ libs/acn/E131DiscoveryInflator.h \ libs/acn/E131Header.h \ libs/acn/E131Inflator.cpp \ libs/acn/E131Inflator.h \ libs/acn/E131Node.cpp \ libs/acn/E131Node.h \ libs/acn/E131PDU.cpp \ libs/acn/E131PDU.h \ libs/acn/E131Sender.cpp \ libs/acn/E131Sender.h \ libs/acn/E133Header.h \ libs/acn/E133Inflator.cpp \ libs/acn/E133Inflator.h \ libs/acn/E133PDU.cpp \ libs/acn/E133PDU.h \ libs/acn/E133StatusInflator.cpp \ libs/acn/E133StatusInflator.h \ libs/acn/E133StatusPDU.cpp \ libs/acn/E133StatusPDU.h \ libs/acn/HeaderSet.h \ libs/acn/PDU.cpp \ libs/acn/PDU.h \ libs/acn/PDUTestCommon.h \ libs/acn/PreamblePacker.cpp \ libs/acn/PreamblePacker.h \ libs/acn/RDMInflator.cpp \ libs/acn/RDMInflator.h \ libs/acn/RDMPDU.cpp \ libs/acn/RDMPDU.h \ libs/acn/RootHeader.h \ libs/acn/RootInflator.cpp \ libs/acn/RootInflator.h \ libs/acn/RootPDU.cpp \ libs/acn/RootPDU.h \ libs/acn/RootSender.cpp \ libs/acn/RootSender.h \ libs/acn/TCPTransport.cpp \ libs/acn/TCPTransport.h \ libs/acn/Transport.h \ libs/acn/TransportHeader.h \ libs/acn/UDPTransport.cpp \ libs/acn/UDPTransport.h libs_acn_libolae131core_la_CXXFLAGS = \ $(COMMON_E131_CXXFLAGS) $(uuid_CFLAGS) libs_acn_libolae131core_la_LIBADD = $(uuid_LIBS) \ common/libolacommon.la \ libs/acn/libolaacn.la # PROGRAMS ################################################## noinst_PROGRAMS += libs/acn/e131_transmit_test \ libs/acn/e131_loadtest libs_acn_e131_transmit_test_SOURCES = \ libs/acn/e131_transmit_test.cpp \ libs/acn/E131TestFramework.cpp \ libs/acn/E131TestFramework.h libs_acn_e131_transmit_test_LDADD = libs/acn/libolae131core.la libs_acn_e131_loadtest_SOURCES = libs/acn/e131_loadtest.cpp libs_acn_e131_loadtest_LDADD = libs/acn/libolae131core.la # TESTS ################################################## test_programs += \ libs/acn/E131Tester \ libs/acn/E133Tester \ libs/acn/TransportTester libs_acn_E131Tester_SOURCES = \ libs/acn/BaseInflatorTest.cpp \ libs/acn/CIDTest.cpp \ libs/acn/DMPAddressTest.cpp \ libs/acn/DMPInflatorTest.cpp \ libs/acn/DMPPDUTest.cpp \ libs/acn/E131InflatorTest.cpp \ libs/acn/E131PDUTest.cpp \ libs/acn/HeaderSetTest.cpp \ libs/acn/PDUTest.cpp \ libs/acn/RootInflatorTest.cpp \ libs/acn/RootPDUTest.cpp \ libs/acn/RootSenderTest.cpp libs_acn_E131Tester_CPPFLAGS = $(COMMON_TESTING_FLAGS) # For some completely messed up reason on mac CPPUNIT_LIBS has to come after # the ossp uuid library. # CPPUNIT_LIBS contains -ldl which causes the tests to fail in strange ways libs_acn_E131Tester_LDADD = \ libs/acn/libolae131core.la \ $(COMMON_TESTING_LIBS) libs_acn_E133Tester_SOURCES = \ libs/acn/E133InflatorTest.cpp \ libs/acn/E133PDUTest.cpp \ libs/acn/RDMPDUTest.cpp libs_acn_E133Tester_CPPFLAGS = $(COMMON_TESTING_FLAGS) libs_acn_E133Tester_LDADD = \ libs/acn/libolae131core.la \ $(COMMON_TESTING_LIBS) libs_acn_TransportTester_SOURCES = \ libs/acn/TCPTransportTest.cpp \ libs/acn/UDPTransportTest.cpp libs_acn_TransportTester_CPPFLAGS = $(COMMON_TESTING_FLAGS) libs_acn_TransportTester_LDADD = libs/acn/libolae131core.la \ $(COMMON_TESTING_LIBS) ola-0.10.5.nojsmin/libs/acn/E133StatusPDU.cpp0000644000175000017500000000335513023355232020052 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E133StatusPDU.cpp * The E133StatusPDU * Copyright (C) 2013 Simon Newton */ #include #include #include #include "libs/acn/E133StatusPDU.h" namespace ola { namespace acn { using ola::network::HostToNetwork; using std::string; void E133StatusPDU::PrependPDU(ola::io::IOStack *stack, ola::e133::E133StatusCode status_code_enum, const string &status) { const string truncated_status_code = status.substr( 0, std::min(status.size(), static_cast(ola::e133::MAX_E133_STATUS_STRING_SIZE))); stack->Write(reinterpret_cast(truncated_status_code.data()), static_cast(truncated_status_code.size())); uint16_t status_code = HostToNetwork(static_cast(status_code_enum)); stack->Write(reinterpret_cast(&status_code), sizeof(status_code)); PrependFlagsAndLength(stack); } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/e131_loadtest.cpp0000644000175000017500000000431013023355232020222 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * e131_loadtest.cpp * A simple E1.31 load tester * Copyright (C) 2013 Simon Newton */ #include #include #include #include "ola/Callback.h" #include "ola/DmxBuffer.h" #include "ola/Logging.h" #include "ola/base/Flags.h" #include "ola/base/Init.h" #include "ola/io/SelectServer.h" #include "libs/acn/E131Node.h" using ola::DmxBuffer; using ola::io::SelectServer; using ola::acn::E131Node; using ola::NewCallback; using std::min; DEFINE_s_uint32(fps, s, 10, "Frames per second per universe [1 - 40]"); DEFINE_s_uint16(universes, u, 1, "Number of universes to send"); /** * Send N DMX frames using E1.31, where N is given by number_of_universes. */ bool SendFrames(E131Node *node, DmxBuffer *buffer, uint16_t number_of_universes) { for (uint16_t i = 1; i < number_of_universes + 1; i++) { node->SendDMX(i, *buffer); } return true; } int main(int argc, char* argv[]) { ola::AppInit(&argc, argv, "", "Run the E1.31 load test."); if (FLAGS_universes == 0 || FLAGS_fps == 0) return -1; unsigned int fps = min(40u, static_cast(FLAGS_fps)); uint16_t universes = FLAGS_universes; DmxBuffer output; output.Blackout(); SelectServer ss; E131Node node(&ss, "", E131Node::Options()); if (!node.Start()) return -1; ss.AddReadDescriptor(node.GetSocket()); ss.RegisterRepeatingTimeout( 1000 / fps, NewCallback(&SendFrames, &node, &output, universes)); OLA_INFO << "Starting loadtester..."; ss.Run(); } ola-0.10.5.nojsmin/libs/acn/RootInflator.h0000644000175000017500000000452613023355232017752 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RootInflator.h * Interface for the RootInflator class. * Copyright (C) 2009 Simon Newton */ #ifndef LIBS_ACN_ROOTINFLATOR_H_ #define LIBS_ACN_ROOTINFLATOR_H_ #include #include #include #include "ola/acn/ACNVectors.h" #include "libs/acn/BaseInflator.h" namespace ola { namespace acn { class NullInflator : public InflatorInterface { public: uint32_t Id() const { return ola::acn::VECTOR_ROOT_NULL; } unsigned int InflatePDUBlock(OLA_UNUSED HeaderSet *headers, OLA_UNUSED const uint8_t *data, unsigned int len) { if (len) { OLA_WARN << "VECTOR_ROOT_NULL contained data of size " << len; } return 0; } }; class RootInflator: public BaseInflator { public: typedef ola::Callback1 OnDataCallback; /** * The OnDataCallback is a hook for the health checking mechanism */ explicit RootInflator(OnDataCallback *on_data = NULL) : BaseInflator(), m_on_data(on_data) { AddInflator(&m_null_inflator); } uint32_t Id() const { return 0; } // no effect for the root inflator protected: // Decode a header block and adds any PduHeaders to the HeaderSet object bool DecodeHeader(HeaderSet *headers, const uint8_t *data, unsigned int len, unsigned int *bytes_used); void ResetHeaderField(); bool PostHeader(uint32_t vector, const HeaderSet &headers); private : NullInflator m_null_inflator; RootHeader m_last_hdr; std::auto_ptr m_on_data; }; } // namespace acn } // namespace ola #endif // LIBS_ACN_ROOTINFLATOR_H_ ola-0.10.5.nojsmin/libs/acn/RootPDU.cpp0000644000175000017500000000437313023355232017157 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RootPDU.cpp * The RootPDU class * Copyright (C) 2007 Simon Newton */ #include "ola/Logging.h" #include "ola/io/IOStack.h" #include "libs/acn/BaseInflator.h" #include "libs/acn/RootPDU.h" namespace ola { namespace acn { using ola::acn::CID; using ola::io::IOStack; using ola::io::OutputStream; using ola::network::HostToNetwork; /* * Pack the header into a buffer. */ bool RootPDU::PackHeader(uint8_t *data, unsigned int *length) const { if (*length < HeaderSize()) { *length = 0; return false; } m_cid.Pack(data); *length = HeaderSize(); return true; } /* * Pack the data into a buffer */ bool RootPDU::PackData(uint8_t *data, unsigned int *length) const { if (m_block) return m_block->Pack(data, length); *length = 0; return true; } /* * Pack the header into a buffer. */ void RootPDU::PackHeader(OutputStream *stream) const { uint8_t cid[CID::CID_LENGTH]; m_cid.Pack(cid); stream->Write(cid, CID::CID_LENGTH); } /* * Pack the data into a buffer */ void RootPDU::PackData(OutputStream *stream) const { if (m_block) m_block->Write(stream); } void RootPDU::SetBlock(const PDUBlock *block) { m_block = block; m_block_size = m_block ? block->Size() : 0; } /* * Prepend a Root Layer flags, length, vector & header */ void RootPDU::PrependPDU(IOStack *stack, uint32_t vector, const CID &cid) { cid.Write(stack); vector = HostToNetwork(vector); stack->Write(reinterpret_cast(&vector), sizeof(vector)); PrependFlagsAndLength(stack); } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/TCPTransportTest.cpp0000644000175000017500000001660113023355232021063 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * TCPTransportTest.cpp * Test fixture for the TCPTransport class * Copyright (C) 2012 Simon Newton */ #include #include #include #include "ola/Clock.h" #include "ola/Logging.h" #include "ola/io/IOQueue.h" #include "ola/io/IOStack.h" #include "ola/io/SelectServer.h" #include "libs/acn/PDUTestCommon.h" #include "libs/acn/PreamblePacker.h" #include "libs/acn/TCPTransport.h" #include "ola/testing/TestUtils.h" namespace ola { namespace acn { using ola::TimeInterval; using ola::acn::CID; using ola::io::IOQueue; using ola::io::IOStack; using ola::network::IPV4SocketAddress; using std::auto_ptr; using std::string; class TCPTransportTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(TCPTransportTest); CPPUNIT_TEST(testSinglePDU); CPPUNIT_TEST(testShortPreamble); CPPUNIT_TEST(testBadPreamble); CPPUNIT_TEST(testZeroLengthPDUBlock); CPPUNIT_TEST(testMultiplePDUs); CPPUNIT_TEST(testSinglePDUBlock); CPPUNIT_TEST_SUITE_END(); public: TCPTransportTest(): TestFixture(), m_ss(NULL) {} void testSinglePDU(); void testShortPreamble(); void testBadPreamble(); void testZeroLengthPDUBlock(); void testMultiplePDUs(); void testMultiplePDUsWithExtraData(); void testSinglePDUBlock(); void setUp(); void tearDown(); void Stop(); void FatalStop() { OLA_ASSERT(false); } void PDUReceived() { m_pdus_received++; } void Receive(); private: unsigned int m_pdus_received; bool m_stream_ok; ola::network::IPV4SocketAddress m_localhost; auto_ptr m_ss; ola::io::LoopbackDescriptor m_loopback; CID m_cid; auto_ptr > m_rx_callback; auto_ptr m_inflator; auto_ptr m_transport; void SendEmptyPDUBLock(const ola::testing::SourceLine &source_line); void SendPDU(const ola::testing::SourceLine &source_line); void SendPDUBlock(const ola::testing::SourceLine &source_line); void SendPacket(const ola::testing::SourceLine &source_line, IOStack *packet); static const int ABORT_TIMEOUT_IN_MS = 1000; }; CPPUNIT_TEST_SUITE_REGISTRATION(TCPTransportTest); void TCPTransportTest::setUp() { ola::InitLogging(ola::OLA_LOG_DEBUG, ola::OLA_LOG_STDERR); m_stream_ok = true; m_pdus_received = 0; m_localhost = IPV4SocketAddress::FromStringOrDie("127.0.0.1:9999"); // mock inflator CID cid; m_rx_callback.reset(NewCallback(this, &TCPTransportTest::PDUReceived)); m_inflator.reset(new MockInflator(m_cid, m_rx_callback.get())); // transport to test m_transport.reset( new IncomingStreamTransport(m_inflator.get(), &m_loopback, m_localhost)); // SelectServer m_ss.reset(new ola::io::SelectServer()); m_ss->RegisterSingleTimeout( ABORT_TIMEOUT_IN_MS, NewSingleCallback(this, &TCPTransportTest::FatalStop)); // loopback descriptor OLA_ASSERT(m_loopback.Init()); m_loopback.SetOnClose(NewSingleCallback(this, &TCPTransportTest::Stop)); m_loopback.SetOnData( NewCallback(this, &TCPTransportTest::Receive)); OLA_ASSERT(m_ss->AddReadDescriptor(&m_loopback)); } void TCPTransportTest::tearDown() { // Close the loopback descriptor and drain the ss m_loopback.Close(); m_ss->RunOnce(); } /** * Called when the descriptor is closed. */ void TCPTransportTest::Stop() { if (m_ss.get()) m_ss->Terminate(); } /** * Receive data and terminate if the stream is bad. */ void TCPTransportTest::Receive() { m_stream_ok = m_transport->Receive(); if (!m_stream_ok) m_ss->Terminate(); } /* * Send a single PDU. */ void TCPTransportTest::testSinglePDU() { OLA_ASSERT_EQ(0u, m_pdus_received); SendPDU(OLA_SOURCELINE()); m_ss->RunOnce(TimeInterval(1, 0)); m_loopback.CloseClient(); m_ss->RunOnce(TimeInterval(1, 0)); OLA_ASSERT(m_stream_ok); OLA_ASSERT_EQ(1u, m_pdus_received); } /** * Test a short preamble. */ void TCPTransportTest::testShortPreamble() { uint8_t bogus_data[] = { 1, 2, 3, 4, 1, 2, 3, 4}; m_loopback.Send(bogus_data, sizeof(bogus_data)); m_ss->RunOnce(TimeInterval(1, 0)); m_loopback.CloseClient(); m_ss->RunOnce(TimeInterval(1, 0)); OLA_ASSERT(m_stream_ok); OLA_ASSERT_EQ(0u, m_pdus_received); } /** * Test bogus data, this should show up as an invalid stream */ void TCPTransportTest::testBadPreamble() { uint8_t bogus_data[] = { 1, 2, 3, 4, 5, 0, 1, 0, 0, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4}; m_loopback.Send(bogus_data, sizeof(bogus_data)); m_ss->RunOnce(TimeInterval(1, 0)); m_loopback.CloseClient(); m_ss->RunOnce(TimeInterval(1, 0)); OLA_ASSERT_FALSE(m_stream_ok); OLA_ASSERT_EQ(0u, m_pdus_received); } /** * Test a 0-length PDU block */ void TCPTransportTest::testZeroLengthPDUBlock() { SendEmptyPDUBLock(OLA_SOURCELINE()); SendPDU(OLA_SOURCELINE()); m_ss->RunOnce(TimeInterval(1, 0)); m_loopback.CloseClient(); m_ss->RunOnce(TimeInterval(1, 0)); OLA_ASSERT(m_stream_ok); OLA_ASSERT_EQ(1u, m_pdus_received); } /** * Send multiple PDUs. */ void TCPTransportTest::testMultiplePDUs() { SendPDU(OLA_SOURCELINE()); SendPDU(OLA_SOURCELINE()); SendPDU(OLA_SOURCELINE()); m_ss->RunOnce(TimeInterval(1, 0)); m_loopback.CloseClient(); m_ss->RunOnce(TimeInterval(1, 0)); OLA_ASSERT(m_stream_ok); OLA_ASSERT_EQ(3u, m_pdus_received); } /** * Send a block of PDUs */ void TCPTransportTest::testSinglePDUBlock() { SendPDUBlock(OLA_SOURCELINE()); m_ss->RunOnce(TimeInterval(1, 0)); m_loopback.CloseClient(); m_ss->RunOnce(TimeInterval(1, 0)); OLA_ASSERT(m_stream_ok); OLA_ASSERT_EQ(3u, m_pdus_received); } /** * Send empty PDU block. */ void TCPTransportTest::SendEmptyPDUBLock( const ola::testing::SourceLine &source_line) { IOStack packet; PreamblePacker::AddTCPPreamble(&packet); SendPacket(source_line, &packet); } /** * Send a PDU */ void TCPTransportTest::SendPDU(const ola::testing::SourceLine &source_line) { IOStack packet; MockPDU::PrependPDU(&packet, 4, 8); PreamblePacker::AddTCPPreamble(&packet); SendPacket(source_line, &packet); } /** * Send a block of PDUs */ void TCPTransportTest::SendPDUBlock( const ola::testing::SourceLine &source_line) { IOStack packet; MockPDU::PrependPDU(&packet, 1, 2); MockPDU::PrependPDU(&packet, 2, 4); MockPDU::PrependPDU(&packet, 3, 6); PreamblePacker::AddTCPPreamble(&packet); SendPacket(source_line, &packet); } void TCPTransportTest::SendPacket(const ola::testing::SourceLine &source_line, IOStack *packet) { IOQueue output; packet->MoveToIOQueue(&output); ola::testing::_FailIf( source_line, !m_loopback.Send(&output), "Loopback send failed"); } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/E133PDU.cpp0000644000175000017500000000715713023355232016652 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E133PDU.cpp * The E133PDU * Copyright (C) 2011 Simon Newton */ #include #include #include "ola/Logging.h" #include "ola/base/Array.h" #include "ola/network/NetworkUtils.h" #include "ola/strings/Utils.h" #include "libs/acn/E133PDU.h" namespace ola { namespace acn { using ola::io::OutputStream; using ola::network::HostToNetwork; using std::string; /* * Size of the header portion. */ unsigned int E133PDU::HeaderSize() const { return sizeof(E133Header::e133_pdu_header); } /* * Size of the data portion */ unsigned int E133PDU::DataSize() const { return m_pdu ? m_pdu->Size() : 0; } /* * Pack the header portion. */ bool E133PDU::PackHeader(uint8_t *data, unsigned int *length) const { unsigned int header_size = HeaderSize(); if (*length < header_size) { OLA_WARN << "E133PDU::PackHeader: buffer too small, got " << *length << " required " << header_size; *length = 0; return false; } E133Header::e133_pdu_header header; strings::CopyToFixedLengthBuffer(m_header.Source(), header.source, arraysize(header.source)); header.sequence = HostToNetwork(m_header.Sequence()); header.endpoint = HostToNetwork(m_header.Endpoint()); header.reserved = 0; *length = sizeof(E133Header::e133_pdu_header); memcpy(data, &header, *length); return true; } /* * Pack the data portion. */ bool E133PDU::PackData(uint8_t *data, unsigned int *length) const { if (m_pdu) return m_pdu->Pack(data, length); *length = 0; return true; } /* * Pack the header into a buffer. */ void E133PDU::PackHeader(OutputStream *stream) const { E133Header::e133_pdu_header header; strings::CopyToFixedLengthBuffer(m_header.Source(), header.source, arraysize(header.source)); header.sequence = HostToNetwork(m_header.Sequence()); header.endpoint = HostToNetwork(m_header.Endpoint()); header.reserved = 0; stream->Write(reinterpret_cast(&header), sizeof(E133Header::e133_pdu_header)); } /* * Pack the data into a buffer */ void E133PDU::PackData(OutputStream *stream) const { if (m_pdu) m_pdu->Write(stream); } void E133PDU::PrependPDU(ola::io::IOStack *stack, uint32_t vector, const string &source_name, uint32_t sequence_number, uint16_t endpoint_id) { E133Header::e133_pdu_header header; strings::CopyToFixedLengthBuffer(source_name, header.source, arraysize(header.source)); header.sequence = HostToNetwork(sequence_number); header.endpoint = HostToNetwork(endpoint_id); header.reserved = 0; stack->Write(reinterpret_cast(&header), sizeof(E133Header::e133_pdu_header)); vector = HostToNetwork(vector); stack->Write(reinterpret_cast(&vector), sizeof(vector)); PrependFlagsAndLength(stack); } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/RootPDUTest.cpp0000644000175000017500000001453613023355232020021 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RootPDUTest.cpp * Test fixture for the RootPDU class * Copyright (C) 2005 Simon Newton */ #include #include #include "ola/Logging.h" #include "ola/acn/CID.h" #include "ola/io/IOQueue.h" #include "ola/io/OutputStream.h" #include "ola/network/NetworkUtils.h" #include "ola/testing/TestUtils.h" #include "libs/acn/PDUTestCommon.h" #include "libs/acn/RootPDU.h" namespace ola { namespace acn { using ola::acn::CID; using ola::io::IOQueue; using ola::io::OutputStream; using ola::network::NetworkToHost; using ola::network::HostToNetwork; class RootPDUTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(RootPDUTest); CPPUNIT_TEST(testSimpleRootPDU); CPPUNIT_TEST(testSimpleRootPDUToOutputStream); CPPUNIT_TEST(testNestedRootPDU); CPPUNIT_TEST(testNestedRootPDUToOutputStream); CPPUNIT_TEST_SUITE_END(); public: void testSimpleRootPDU(); void testSimpleRootPDUToOutputStream(); void testNestedRootPDU(); void testNestedRootPDUToOutputStream(); void setUp() { ola::InitLogging(ola::OLA_LOG_DEBUG, ola::OLA_LOG_STDERR); } private: static const unsigned int TEST_VECTOR = 4; static const unsigned int TEST_VECTOR2 = 99; }; CPPUNIT_TEST_SUITE_REGISTRATION(RootPDUTest); /* * Test that packing a RootPDU without data works. */ void RootPDUTest::testSimpleRootPDU() { CID cid = CID::Generate(); RootPDU pdu1(TEST_VECTOR, cid, NULL); OLA_ASSERT(cid == pdu1.Cid()); OLA_ASSERT_EQ(22u, pdu1.Size()); unsigned int size = pdu1.Size(); uint8_t *data = new uint8_t[size]; unsigned int bytes_used = size; OLA_ASSERT(pdu1.Pack(data, &bytes_used)); OLA_ASSERT_EQ(size, bytes_used); // spot check the data OLA_ASSERT_EQ((uint8_t) 0x70, data[0]); OLA_ASSERT_EQ((uint8_t) bytes_used, data[1]); unsigned int actual_value; memcpy(&actual_value, data + 2, sizeof(actual_value)); OLA_ASSERT_EQ(HostToNetwork(TEST_VECTOR), actual_value); CID cid2 = CID::FromData(&data[6]); OLA_ASSERT(cid2 == cid); // test undersized buffer bytes_used = size - 1; OLA_ASSERT_FALSE(pdu1.Pack(data, &bytes_used)); OLA_ASSERT_EQ(0u, bytes_used); // test oversized buffer bytes_used = size + 1; OLA_ASSERT(pdu1.Pack(data, &bytes_used)); OLA_ASSERT_EQ(size, bytes_used); // change the vector pdu1.SetVector(TEST_VECTOR2); OLA_ASSERT(pdu1.Pack(data, &bytes_used)); OLA_ASSERT_EQ(size, bytes_used); OLA_ASSERT_EQ((uint8_t) 0x70, data[0]); OLA_ASSERT_EQ((uint8_t) bytes_used, data[1]); memcpy(&actual_value, data + 2, sizeof(actual_value)); OLA_ASSERT_EQ(HostToNetwork(TEST_VECTOR2), actual_value); cid2 = CID::FromData(&data[6]); OLA_ASSERT(cid2 == cid); // use the other constructor RootPDU pdu2(TEST_VECTOR); pdu2.Cid(cid); OLA_ASSERT(cid == pdu1.Cid()); OLA_ASSERT_EQ(22u, pdu1.Size()); bytes_used = size; uint8_t *data2 = new uint8_t[size]; OLA_ASSERT(pdu1.Pack(data2, &bytes_used)); OLA_ASSERT_EQ(size, bytes_used); OLA_ASSERT_FALSE(memcmp(data, data2, bytes_used)); delete[] data; delete[] data2; } /** * Check that writing an Root PDU to an output stream works */ void RootPDUTest::testSimpleRootPDUToOutputStream() { CID cid = CID::Generate(); RootPDU pdu1(TEST_VECTOR, cid, NULL); OLA_ASSERT(cid == pdu1.Cid()); OLA_ASSERT_EQ(16u, pdu1.HeaderSize()); OLA_ASSERT_EQ(4u, pdu1.VectorSize()); OLA_ASSERT_EQ(0u, pdu1.DataSize()); OLA_ASSERT_EQ(22u, pdu1.Size()); IOQueue output; OutputStream stream(&output); pdu1.Write(&stream); OLA_ASSERT_EQ(22u, output.Size()); uint8_t *raw_pdu = new uint8_t[output.Size()]; unsigned int raw_pdu_size = output.Peek(raw_pdu, output.Size()); OLA_ASSERT_EQ(output.Size(), raw_pdu_size); uint8_t EXPECTED[] = { 0x70, 22, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; cid.Pack(EXPECTED + 6); OLA_ASSERT_DATA_EQUALS(EXPECTED, sizeof(EXPECTED), raw_pdu, raw_pdu_size); output.Pop(output.Size()); delete[] raw_pdu; } /* * Test that packing a RootPDU with nested data works */ void RootPDUTest::testNestedRootPDU() { FakePDU pdu1(1); FakePDU pdu2(42); PDUBlock block; block.AddPDU(&pdu1); block.AddPDU(&pdu2); CID cid = CID::Generate(); RootPDU pdu(TEST_VECTOR, cid, &block); OLA_ASSERT(cid == pdu.Cid()); OLA_ASSERT_EQ(30u, pdu.Size()); unsigned int size = pdu.Size(); uint8_t *data = new uint8_t[size]; unsigned int bytes_used = size; OLA_ASSERT(pdu.Pack(data, &bytes_used)); OLA_ASSERT_EQ(size, bytes_used); // spot check unsigned int actual_value; memcpy(&actual_value, data + 22, sizeof(actual_value)); OLA_ASSERT_EQ(1u, actual_value); memcpy(&actual_value, data + 26, sizeof(actual_value)); OLA_ASSERT_EQ(42u, actual_value); delete[] data; } /* * Test that packing a RootPDU with nested data works */ void RootPDUTest::testNestedRootPDUToOutputStream() { FakePDU pdu1(1); FakePDU pdu2(42); PDUBlock block; block.AddPDU(&pdu1); block.AddPDU(&pdu2); CID cid = CID::Generate(); RootPDU pdu(TEST_VECTOR, cid, &block); OLA_ASSERT(cid == pdu.Cid()); OLA_ASSERT_EQ(30u, pdu.Size()); IOQueue output; OutputStream stream(&output); pdu.Write(&stream); OLA_ASSERT_EQ(30u, output.Size()); uint8_t *raw_pdu = new uint8_t[output.Size()]; unsigned int raw_pdu_size = output.Peek(raw_pdu, output.Size()); OLA_ASSERT_EQ(output.Size(), raw_pdu_size); uint8_t EXPECTED[] = { 0x70, 30, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 42 }; cid.Pack(EXPECTED + 6); OLA_ASSERT_DATA_EQUALS(EXPECTED, sizeof(EXPECTED), raw_pdu, raw_pdu_size); output.Pop(output.Size()); delete[] raw_pdu; } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/E133Inflator.h0000644000175000017500000000324513023355232017437 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E133Inflator.h * Interface for the E133Inflator class. * Copyright (C) 2011 Simon Newton */ #ifndef LIBS_ACN_E133INFLATOR_H_ #define LIBS_ACN_E133INFLATOR_H_ #include "ola/acn/ACNVectors.h" #include "libs/acn/BaseInflator.h" #include "libs/acn/E133Header.h" namespace ola { namespace acn { class E133Inflator: public BaseInflator { friend class E133InflatorTest; public: E133Inflator() : BaseInflator(), m_last_header_valid(false) { } ~E133Inflator() {} uint32_t Id() const { return ola::acn::VECTOR_ROOT_E133; } protected: bool DecodeHeader(HeaderSet *headers, const uint8_t *data, unsigned int len, unsigned int *bytes_used); void ResetHeaderField() { m_last_header_valid = false; } private: E133Header m_last_header; bool m_last_header_valid; }; } // namespace acn } // namespace ola #endif // LIBS_ACN_E133INFLATOR_H_ ola-0.10.5.nojsmin/libs/acn/BaseInflator.cpp0000644000175000017500000001736513023355232020241 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * BaseInflator.cpp * The BaseInflator, other Inflators inherit from this one. * Copyright (C) 2007 Simon Newton */ #include "libs/acn/BaseInflator.h" #include #include #include "ola/Logging.h" #include "ola/stl/STLUtils.h" #include "ola/network/NetworkUtils.h" #include "ola/util/Utils.h" namespace ola { namespace acn { using ola::network::NetworkToHost; using ola::utils::JoinUInt8; /* * Setup the base inflator */ BaseInflator::BaseInflator(PDU::vector_size v_size) : m_last_vector(0), m_vector_set(false), m_vector_size(v_size) { } /* * Set the inflator for a particular protocol * @param inflator a inflator * @return true if added, false if an inflator with this id already exists. */ bool BaseInflator::AddInflator(InflatorInterface *inflator) { return STLInsertIfNotPresent(&m_proto_map, inflator->Id(), inflator); } /* * Get the current inflator for a protocol * @param proto the vector ID * @return the inflator for this vector, or NULL if there isn't one set. */ InflatorInterface *BaseInflator::GetInflator(uint32_t vector) const { return STLFindOrNull(m_proto_map, vector); } /* * Parse a block of PDUs * @param headers the HeaderSet for this PDU * @param data pointer to the data * @param length length of the data * @returns the amount of data used */ unsigned int BaseInflator::InflatePDUBlock(HeaderSet *headers, const uint8_t *data, unsigned int length) { unsigned int offset = 0; ResetPDUFields(); if (length == 0) { return 0; } do { unsigned int bytes_used = 0; unsigned int pdu_length = 0; if (!DecodeLength(data + offset, length - offset, &pdu_length, &bytes_used)) { return offset; } if (offset + pdu_length <= length) { InflatePDU(headers, data[offset], data + offset + bytes_used, pdu_length - bytes_used); } offset += pdu_length; } while (offset < length); return std::min(offset, length); } /* * Reset the pdu fields */ void BaseInflator::ResetPDUFields() { m_vector_set = false; ResetHeaderField(); } /* * Fetch the length from a pdu header * @param data pointer to the head of the PDU * @param length length of the PDU data * @param pdu_length set to the length of the PDU * @param bytes_used set to the number of bytes used for the length field * @return true if everything worked, false if invalid data was found */ bool BaseInflator::DecodeLength(const uint8_t *data, unsigned int length, unsigned int *pdu_length, unsigned int *bytes_used) const { uint8_t flags = data[0]; if (!length) { *bytes_used = 0; *pdu_length = 0; return false; } if (flags & LFLAG_MASK) { if (length < 3) { OLA_WARN << "PDU length " << length << " < 3 and the LENGTH bit is set"; return false; } *bytes_used = 3; *pdu_length = JoinUInt8(0, (data[0] & LENGTH_MASK), data[1], data[2]); } else { if (length < 2) { OLA_WARN << "PDU length " << length << " < 2"; return false; } *bytes_used = 2; *pdu_length = JoinUInt8((data[0] & LENGTH_MASK), data[1]); } if (*pdu_length < *bytes_used) { OLA_WARN << "PDU length was set to " << *pdu_length << " but " << *bytes_used << " bytes were used in the header"; *bytes_used = 0; return false; } return true; } /* * @brief Decode the vector field * @param flags the PDU flags * @param data pointer to the pdu data * @param length length of the data * @param vector the result of the vector * @param bytes_used the number of bytes consumed */ bool BaseInflator::DecodeVector(uint8_t flags, const uint8_t *data, unsigned int length, uint32_t *vector, unsigned int *bytes_used) { if (flags & PDU::VFLAG_MASK) { if ((unsigned int) m_vector_size > length) { *vector = 0; *bytes_used = 0; return false; } switch (m_vector_size) { case PDU::ONE_BYTE: *vector = *data; break; case PDU::TWO_BYTES: *vector = JoinUInt8(data[0], data[1]); break; case PDU::FOUR_BYTES: // careful: we can't cast to a uint32 because this isn't word aligned *vector = JoinUInt8(data[0], data[1], data[2], data[3]); break; default: OLA_WARN << "Unknown vector size " << m_vector_size; return false; } m_vector_set = true; *bytes_used = m_vector_size; m_last_vector = *vector; } else { *bytes_used = 0; if (m_vector_set) { *vector = m_last_vector; } else { *vector = 0; *bytes_used = 0; OLA_WARN << "Vector not set and no field to inherit from"; return false; } } return true; } /* * @brief Parse a generic PDU structure * @param headers a reference to the header set * @param flags the flag field * @param data pointer to the vector field * @param pdu_len length of the PDU * @return true if we inflated without errors */ bool BaseInflator::InflatePDU(HeaderSet *headers, uint8_t flags, const uint8_t *data, unsigned int pdu_len) { uint32_t vector; unsigned int data_offset, header_bytes_used; bool result; if (!DecodeVector(flags, data, pdu_len, &vector, &data_offset)) { return false; } if (flags & PDU::HFLAG_MASK) { result = DecodeHeader(headers, data + data_offset, pdu_len - data_offset, &header_bytes_used); } else { result = DecodeHeader(headers, NULL, 0, &header_bytes_used); header_bytes_used = 0; } if (!result) { return false; } if (!PostHeader(vector, *headers)) { return true; } // TODO(simon): handle the crazy DFLAG here data_offset += header_bytes_used; InflatorInterface *inflator = STLFindOrNull(m_proto_map, vector); if (inflator) { return inflator->InflatePDUBlock(headers, data + data_offset, pdu_len - data_offset); } else { return HandlePDUData(vector, *headers, data + data_offset, pdu_len - data_offset); } } /* * @brief The Post header hook. * * This is called once the header has been decoded but before either the next * inflator or handle_data is called. * @return false will cease processing this PDU */ bool BaseInflator::PostHeader(OLA_UNUSED uint32_t, OLA_UNUSED const HeaderSet &headers) { return true; } /* * @brief The base handle data method - does nothing */ bool BaseInflator::HandlePDUData(uint32_t vector, OLA_UNUSED const HeaderSet &headers, const uint8_t *, unsigned int) { OLA_WARN << "In BaseInflator::HandlePDUData, someone forgot to add" << " a handler, vector id " << vector; return false; } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/RootInflatorTest.cpp0000644000175000017500000000416013023355232021137 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RootInflatorTest.cpp * Test fixture for the RootInflator class * Copyright (C) 2005 Simon Newton */ #include #include "libs/acn/HeaderSet.h" #include "libs/acn/PDUTestCommon.h" #include "libs/acn/RootInflator.h" #include "libs/acn/RootPDU.h" #include "ola/testing/TestUtils.h" namespace ola { namespace acn { using ola::acn::CID; class RootInflatorTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(RootInflatorTest); CPPUNIT_TEST(testInflatePDU); CPPUNIT_TEST_SUITE_END(); public: void testInflatePDU(); }; CPPUNIT_TEST_SUITE_REGISTRATION(RootInflatorTest); /* * Check that we can inflate a Root PDU that contains other PDUs */ void RootInflatorTest::testInflatePDU() { MockPDU pdu1(1, 2); MockPDU pdu2(4, 8); PDUBlock block; block.AddPDU(&pdu1); block.AddPDU(&pdu2); CID cid = CID::Generate(); RootPDU pdu(MockPDU::TEST_VECTOR, cid, &block); OLA_ASSERT_EQ((unsigned int) 50, pdu.Size()); unsigned int size = pdu.Size(); uint8_t *data = new uint8_t[size]; unsigned int bytes_used = size; OLA_ASSERT(pdu.Pack(data, &bytes_used)); OLA_ASSERT_EQ((unsigned int) size, bytes_used); MockInflator mock_inflator(cid); RootInflator inflator; inflator.AddInflator(&mock_inflator); HeaderSet header_set; OLA_ASSERT(inflator.InflatePDUBlock(&header_set, data, size)); delete[] data; } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/TransportHeader.h0000644000175000017500000000415513023355232020433 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * TransportHeader.h * Interface for the TransportHeader class. * This holds the source IP of the packet which is used to address replies * correctly. At some point in the future we should try to abtract the * transport protocol (IP/UDP in this case). * Copyright (C) 2011 Simon Newton */ #ifndef LIBS_ACN_TRANSPORTHEADER_H_ #define LIBS_ACN_TRANSPORTHEADER_H_ #include "ola/network/SocketAddress.h" namespace ola { namespace acn { /* * The header for the transport layer */ class TransportHeader { public: enum TransportType { TCP, UDP, UNDEFINED, }; TransportHeader() : m_transport_type(UNDEFINED) {} TransportHeader(const ola::network::IPV4SocketAddress &source, TransportType type) : m_source(source), m_transport_type(type) {} ~TransportHeader() {} const ola::network::IPV4SocketAddress& Source() const { return m_source; } TransportType Transport() const { return m_transport_type; } bool operator==(const TransportHeader &other) const { return (m_source == other.m_source && m_transport_type == other.m_transport_type); } void operator=(const TransportHeader &other) { m_source = other.m_source; m_transport_type = other.m_transport_type; } private: ola::network::IPV4SocketAddress m_source; TransportType m_transport_type; }; } // namespace acn } // namespace ola #endif // LIBS_ACN_TRANSPORTHEADER_H_ ola-0.10.5.nojsmin/libs/acn/DMPPDUTest.cpp0000644000175000017500000001651613023355232017516 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DMPPDUTest.cpp * Test fixture for the DMPPDU class * Copyright (C) 2005 Simon Newton */ #include #include #include #include "ola/Logging.h" #include "ola/acn/ACNVectors.h" #include "libs/acn/DMPAddress.h" #include "libs/acn/DMPInflator.h" #include "libs/acn/DMPPDU.h" #include "libs/acn/HeaderSet.h" #include "libs/acn/PDUTestCommon.h" #include "ola/testing/TestUtils.h" namespace ola { namespace acn { using ola::acn::DMP_GET_PROPERTY_VECTOR; using ola::acn::DMP_SET_PROPERTY_VECTOR; using std::vector; class MockDMPInflator: public DMPInflator { public: MockDMPInflator(): DMPInflator(), expected_vector(0), expected_virtual(false), expected_relative(false), expected_type(NON_RANGE), expected_size(RES_BYTES) , expected_start(0), expected_increment(0), expected_number(0) {} ~MockDMPInflator() {} unsigned int expected_length; unsigned int expected_data_length; unsigned int expected_vector; bool expected_virtual; bool expected_relative; dmp_address_type expected_type; dmp_address_size expected_size; unsigned int expected_start; unsigned int expected_increment; unsigned int expected_number; protected: bool HandlePDUData(uint32_t vector, const HeaderSet &headers, const uint8_t *data, unsigned int pdu_len); }; class DMPPDUTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(DMPPDUTest); CPPUNIT_TEST(testGetProperty); CPPUNIT_TEST(testSetProperty); CPPUNIT_TEST_SUITE_END(); public: void testGetProperty(); void testSetProperty(); private: void PackPduAndInflate(const DMPPDU *pdu); MockDMPInflator m_inflator; }; CPPUNIT_TEST_SUITE_REGISTRATION(DMPPDUTest); /* * Verify a PDU is what we expected */ bool MockDMPInflator::HandlePDUData(uint32_t vector, const HeaderSet &headers, const uint8_t *data, unsigned int pdu_len) { DMPHeader header = headers.GetDMPHeader(); OLA_ASSERT_EQ(expected_vector, vector); OLA_ASSERT_EQ(expected_virtual, header.IsVirtual()); OLA_ASSERT_EQ(expected_relative, header.IsRelative()); OLA_ASSERT(expected_type == header.Type()); OLA_ASSERT(expected_size == header.Size()); if (vector == DMP_GET_PROPERTY_VECTOR || vector == DMP_SET_PROPERTY_VECTOR) { unsigned int length = pdu_len; const BaseDMPAddress *addr = DecodeAddress(header.Size(), header.Type(), data, &length); OLA_ASSERT(addr); OLA_ASSERT_EQ(expected_start, addr->Start()); OLA_ASSERT_EQ(expected_increment, addr->Increment()); OLA_ASSERT_EQ(expected_number, addr->Number()); delete addr; } return true; } /* * Pack a PDU and check it inflates correctly. */ void DMPPDUTest::PackPduAndInflate(const DMPPDU *pdu) { unsigned int size = pdu->Size() + 10; // overallocate to catch overflows uint8_t *data = new uint8_t[size]; OLA_ASSERT(pdu->Pack(data, &size)); OLA_ASSERT_EQ(pdu->Size(), size); HeaderSet headers; m_inflator.InflatePDUBlock(&headers, data, size); delete[] data; } /* * Test that GetProperty PDUs can be constructed */ void DMPPDUTest::testGetProperty() { m_inflator.expected_vector = DMP_GET_PROPERTY_VECTOR; m_inflator.expected_type = NON_RANGE; m_inflator.expected_size = ONE_BYTES; m_inflator.expected_virtual = false; m_inflator.expected_relative = true; m_inflator.expected_start = 10; m_inflator.expected_increment = 0; m_inflator.expected_number = 1; // Non-ranged GetProperty PDUs const DMPPDU *pdu = NewDMPGetProperty(false, true, 10); OLA_ASSERT(pdu); OLA_ASSERT_EQ((unsigned int) 5, pdu->Size()); PackPduAndInflate(pdu); delete pdu; m_inflator.expected_start = 1024; pdu = NewDMPGetProperty(true, true, 1024); OLA_ASSERT(pdu); OLA_ASSERT_EQ((unsigned int) 6, pdu->Size()); m_inflator.expected_size = TWO_BYTES; m_inflator.expected_virtual = true; PackPduAndInflate(pdu); delete pdu; // Ranged GetProperty PDUs m_inflator.expected_start = 10; m_inflator.expected_increment = 1; m_inflator.expected_number = 20; m_inflator.expected_type = RANGE_SINGLE; pdu = NewRangeDMPGetProperty(true, false, 10, 1, 20); OLA_ASSERT(pdu); OLA_ASSERT_EQ((unsigned int) 7, pdu->Size()); m_inflator.expected_size = ONE_BYTES; m_inflator.expected_relative = false; PackPduAndInflate(pdu); delete pdu; m_inflator.expected_start = 10; m_inflator.expected_increment = 1; m_inflator.expected_number = 1024; pdu = NewRangeDMPGetProperty(false, false, 10, 1, 1024); OLA_ASSERT(pdu); OLA_ASSERT_EQ((unsigned int) 10, pdu->Size()); m_inflator.expected_size = TWO_BYTES; m_inflator.expected_virtual = false; PackPduAndInflate(pdu); delete pdu; } /* * Test that packing a DMPPDU without data works. */ void DMPPDUTest::testSetProperty() { m_inflator.expected_vector = DMP_SET_PROPERTY_VECTOR; m_inflator.expected_type = NON_RANGE; m_inflator.expected_size = ONE_BYTES; m_inflator.expected_virtual = false; m_inflator.expected_relative = false; m_inflator.expected_start = 10; m_inflator.expected_increment = 0; m_inflator.expected_number = 1; // non-range first uint8_t data = 0xab; OneByteDMPAddress addr(10); DMPAddressData chunk(&addr, &data, sizeof(data)); vector > chunks; chunks.push_back(chunk); const DMPPDU *pdu = NewDMPSetProperty(false, false, chunks); OLA_ASSERT(pdu); OLA_ASSERT_EQ((unsigned int) 6, pdu->Size()); PackPduAndInflate(pdu); delete pdu; // ranged address m_inflator.expected_type = RANGE_SINGLE; m_inflator.expected_increment = 1; m_inflator.expected_number = 20; OneByteRangeDMPAddress range_addr(10, 1, 20); DMPAddressData range_chunk(&range_addr, &data, sizeof(data)); vector > ranged_chunks; ranged_chunks.push_back(range_chunk); // range single first pdu = NewRangeDMPSetProperty(false, false, ranged_chunks, false); OLA_ASSERT(pdu); OLA_ASSERT_EQ((unsigned int) 8, pdu->Size()); PackPduAndInflate(pdu); delete pdu; // range equal m_inflator.expected_type = RANGE_EQUAL; pdu = NewRangeDMPSetProperty(false, false, ranged_chunks); OLA_ASSERT(pdu); OLA_ASSERT_EQ((unsigned int) 8, pdu->Size()); PackPduAndInflate(pdu); delete pdu; } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/E131Node.h0000644000175000017500000002056113023355232016544 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E131Node.h * Header file for the E131Node class, this is the interface between OLA and * the E1.31 library. * Copyright (C) 2007 Simon Newton */ #ifndef LIBS_ACN_E131NODE_H_ #define LIBS_ACN_E131NODE_H_ #include #include #include #include #include "ola/Callback.h" #include "ola/Constants.h" #include "ola/DmxBuffer.h" #include "ola/acn/ACNPort.h" #include "ola/acn/CID.h" #include "ola/base/Macro.h" #include "ola/io/SelectServerInterface.h" #include "ola/thread/SchedulerInterface.h" #include "ola/network/Interface.h" #include "ola/network/Socket.h" #include "libs/acn/DMPE131Inflator.h" #include "libs/acn/E131DiscoveryInflator.h" #include "libs/acn/E131Inflator.h" #include "libs/acn/E131Sender.h" #include "libs/acn/RootInflator.h" #include "libs/acn/RootSender.h" #include "libs/acn/UDPTransport.h" namespace ola { namespace acn { class E131Node { public: /** * @brief Options for the E131Node. */ struct Options { public: Options() : use_rev2(false), ignore_preview(true), enable_draft_discovery(false), dscp(0), port(ola::acn::ACN_PORT), source_name(ola::OLA_DEFAULT_INSTANCE_NAME) { } bool use_rev2; /**< Use Revision 0.2 of the 2009 draft */ bool ignore_preview; /**< Ignore preview data */ bool enable_draft_discovery; /**< Enable 2014 draft discovery */ uint8_t dscp; /**< The DSCP value to tag packets with */ uint16_t port; /**< The UDP port to use, defaults to ACN_PORT */ std::string source_name; /**< The source name to use */ }; struct KnownController { acn::CID cid; ola::network::IPV4Address ip_address; std::string source_name; std::set universes; }; /** * @brief Create a new E1.31 node. * @param ss the SchedulerInterface to use. * @param ip_address the IP address to prefer to listen on * @param options the Options to use for the node. * @param cid the CID to use, if not provided we generate one. */ E131Node(ola::thread::SchedulerInterface *ss, const std::string &ip_address, const Options &options, const ola::acn::CID &cid = ola::acn::CID::Generate()); ~E131Node(); /** * @brief Start this node */ bool Start(); /** * @brief Stop this node */ bool Stop(); /** * @brief Set the name for a universe. * @param universe the id of the universe to send * @param source the new source name. */ bool SetSourceName(uint16_t universe, const std::string &source); /** * @brief Signal that we will start sending on this particular universe. * Without sending any DMX data. * @param universe to start sending on. */ bool StartStream(uint16_t universe); /** * @brief Signal that we will no longer send on this particular universe. * @param universe to terminate sending on. * @param priority the priority to use in the stream terminated message. */ bool TerminateStream(uint16_t universe, uint8_t priority = DEFAULT_PRIORITY); /** * @brief Send some DMX data. * @param universe the id of the universe to send * @param buffer the DMX data. * @param priority the priority to use * @param preview set to true to turn on the preview bit * @return true if it was sent successfully, false otherwise */ bool SendDMX(uint16_t universe, const ola::DmxBuffer &buffer, uint8_t priority = DEFAULT_PRIORITY, bool preview = false); /** * @brief Send some DMX data, allowing finer grained control of parameters. * * The method is provided for the testing framework. Don't use it in * production code! * * @param universe the id of the universe to send * @param buffer the DMX data * @param sequence_offset used to twiddle the sequence numbers, this doesn't * increment the sequence counter. * @param priority the priority to use * @param preview set to true to turn on the preview bit * @return true if it was sent successfully, false otherwise */ bool SendDMXWithSequenceOffset(uint16_t universe, const ola::DmxBuffer &buffer, int8_t sequence_offset, uint8_t priority = DEFAULT_PRIORITY, bool preview = false); /** * @brief Signal termination of the stream for a universe. * @param universe the id of the universe to send * @param buffer the last DmxBuffer to send. * @param priority the priority to use, this doesn't actually make a * difference. * * This does not remove the universe from the list of active TX universes, so * it should only be used for testing purposes. */ bool SendStreamTerminated(uint16_t universe, const ola::DmxBuffer &buffer = DmxBuffer(), uint8_t priority = DEFAULT_PRIORITY); /** * @brief Set the Callback to be run when we receive data for this universe. * @param universe the universe to register the handler for * @param buffer the DmxBuffer to copy the data to. * @param priority the priority to set. * @param handler the Callback to call when there is data for this universe. * Ownership is transferred. */ bool SetHandler(uint16_t universe, ola::DmxBuffer *buffer, uint8_t *priority, ola::Callback0 *handler); /** * @brief Remove the handler for a particular universe. * @param universe the universe handler to remove * @return true if removed, false if it didn't exist */ bool RemoveHandler(uint16_t universe); /** * @brief Return the Interface this node is using. */ const ola::network::Interface &GetInterface() const { return m_interface; } /** * @brief Return the UDP socket this node is using. */ ola::network::UDPSocket* GetSocket() { return &m_socket; } /** * @brief Return a list of known controllers. * * This will return an empty list unless enable_draft_discovery was set in * the node Options. */ void GetKnownControllers(std::vector *controllers); private: struct tx_universe { std::string source; uint8_t sequence; }; typedef std::map ActiveTxUniverses; typedef std::map TrackedSources; ola::thread::SchedulerInterface *m_ss; const Options m_options; const std::string m_preferred_ip; const ola::acn::CID m_cid; ola::network::Interface m_interface; ola::network::UDPSocket m_socket; // senders RootSender m_root_sender; E131Sender m_e131_sender; // inflators RootInflator m_root_inflator; E131Inflator m_e131_inflator; E131InflatorRev2 m_e131_rev2_inflator; DMPE131Inflator m_dmp_inflator; E131DiscoveryInflator m_discovery_inflator; IncomingUDPTransport m_incoming_udp_transport; ActiveTxUniverses m_tx_universes; uint8_t *m_send_buffer; // Discovery members ola::thread::timeout_id m_discovery_timeout; TrackedSources m_discovered_sources; tx_universe *SetupOutgoingSettings(uint16_t universe); bool PerformDiscoveryHousekeeping(); void NewDiscoveryPage(const HeaderSet &headers, const E131DiscoveryInflator::DiscoveryPage &page); void SendDiscoveryPage(const std::vector &universes, uint8_t page, uint8_t last_page, uint32_t sequence_number); static const uint16_t DEFAULT_PRIORITY = 100; static const uint16_t UNIVERSE_DISCOVERY_INTERVAL = 10000; // milliseconds static const uint16_t DISCOVERY_UNIVERSE_ID = 64214; static const uint16_t DISCOVERY_PAGE_SIZE = 512; DISALLOW_COPY_AND_ASSIGN(E131Node); }; } // namespace acn } // namespace ola #endif // LIBS_ACN_E131NODE_H_ ola-0.10.5.nojsmin/libs/acn/RootSenderTest.cpp0000644000175000017500000001051113023355232020576 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RootSenderTest.cpp * Test fixture for the RootSender class * Copyright (C) 2005 Simon Newton */ #include #include #include "ola/io/SelectServer.h" #include "ola/network/InterfacePicker.h" #include "ola/network/NetworkUtils.h" #include "ola/network/Socket.h" #include "libs/acn/PDUTestCommon.h" #include "libs/acn/RootInflator.h" #include "libs/acn/RootSender.h" #include "libs/acn/UDPTransport.h" #include "ola/testing/TestUtils.h" namespace ola { namespace acn { using ola::acn::CID; using ola::network::IPV4Address; using ola::network::IPV4SocketAddress; class RootSenderTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(RootSenderTest); CPPUNIT_TEST(testRootSender); CPPUNIT_TEST(testRootSenderWithCustomCID); CPPUNIT_TEST_SUITE_END(); public: RootSenderTest(): TestFixture(), m_ss(NULL) {} void testRootSender(); void testRootSenderWithCustomCID(); void setUp(); void tearDown(); void Stop(); void FatalStop() { OLA_ASSERT(false); } private: void testRootSenderWithCIDs(const CID &root_cid, const CID &send_cid); ola::io::SelectServer *m_ss; static const int ABORT_TIMEOUT_IN_MS = 1000; }; CPPUNIT_TEST_SUITE_REGISTRATION(RootSenderTest); void RootSenderTest::setUp() { m_ss = new ola::io::SelectServer(); } void RootSenderTest::tearDown() { delete m_ss; } void RootSenderTest::Stop() { if (m_ss) m_ss->Terminate(); } /* * Test the RootSender */ void RootSenderTest::testRootSender() { CID cid = CID::Generate(); testRootSenderWithCIDs(cid, cid); } /* * Test the method to send using a custom cid works */ void RootSenderTest::testRootSenderWithCustomCID() { CID cid = CID::Generate(); CID send_cid = CID::Generate(); testRootSenderWithCIDs(cid, send_cid); } void RootSenderTest::testRootSenderWithCIDs(const CID &root_cid, const CID &send_cid) { std::auto_ptr > stop_closure( NewCallback(this, &RootSenderTest::Stop)); // inflators MockInflator inflator(send_cid, stop_closure.get()); RootInflator root_inflator; OLA_ASSERT(root_inflator.AddInflator(&inflator)); // sender RootSender root_sender(root_cid); // setup the socket ola::network::UDPSocket socket; OLA_ASSERT(socket.Init()); OLA_ASSERT( socket.Bind(IPV4SocketAddress(IPV4Address::Loopback(), 0))); OLA_ASSERT(socket.EnableBroadcast()); IncomingUDPTransport incoming_udp_transport(&socket, &root_inflator); socket.SetOnData(NewCallback(&incoming_udp_transport, &IncomingUDPTransport::Receive)); OLA_ASSERT(m_ss->AddReadDescriptor(&socket)); // Get the port we bound to. IPV4SocketAddress local_address; OLA_ASSERT(socket.GetSocketAddress(&local_address)); OutgoingUDPTransportImpl udp_transport_impl(&socket); OutgoingUDPTransport outgoing_udp_transport(&udp_transport_impl, IPV4Address::Loopback(), local_address.Port()); // now actually send some data MockPDU mock_pdu(4, 8); if (root_cid == send_cid) OLA_ASSERT(root_sender.SendPDU(MockPDU::TEST_VECTOR, mock_pdu, &outgoing_udp_transport)); else OLA_ASSERT(root_sender.SendPDU(MockPDU::TEST_VECTOR, mock_pdu, send_cid, &outgoing_udp_transport)); SingleUseCallback0 *closure = NewSingleCallback(this, &RootSenderTest::FatalStop); m_ss->RegisterSingleTimeout(ABORT_TIMEOUT_IN_MS, closure); m_ss->Run(); } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/E133StatusInflator.h0000644000175000017500000000472413023355232020646 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E133StatusInflator.h * Copyright (C) 2013 Simon Newton */ #ifndef LIBS_ACN_E133STATUSINFLATOR_H_ #define LIBS_ACN_E133STATUSINFLATOR_H_ #include #include #include "ola/Callback.h" #include "ola/acn/ACNVectors.h" #include "ola/e133/E133Enums.h" #include "libs/acn/BaseInflator.h" #include "libs/acn/TransportHeader.h" #include "libs/acn/E133Header.h" namespace ola { namespace acn { class E133StatusInflator: public BaseInflator { public: // These are pointers so the callers don't have to pull in all the headers. typedef ola::Callback4 StatusMessageHandler; E133StatusInflator(); uint32_t Id() const { return ola::acn::VECTOR_FRAMING_STATUS; } // Ownership is transferred. void SetStatusHandler(StatusMessageHandler *handler) { m_handler.reset(handler); } protected: // The 'header' is 0 bytes in length. bool DecodeHeader(HeaderSet*, const uint8_t*, unsigned int, unsigned int *bytes_used) { *bytes_used = 0; return true; } void ResetHeaderField() {} // namespace noop virtual bool HandlePDUData(uint32_t vector, const HeaderSet &headers, const uint8_t *data, unsigned int pdu_len); private: std::auto_ptr m_handler; }; } // namespace acn } // namespace ola #endif // LIBS_ACN_E133STATUSINFLATOR_H_ ola-0.10.5.nojsmin/libs/acn/Transport.h0000644000175000017500000000263513023355232017323 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Transport.h * Interface for the Transport class * Copyright (C) 2012 Simon Newton */ #ifndef LIBS_ACN_TRANSPORT_H_ #define LIBS_ACN_TRANSPORT_H_ #include #include "ola/acn/ACNPort.h" #include "ola/network/Interface.h" #include "ola/network/Socket.h" #include "libs/acn/PDU.h" namespace ola { namespace acn { /* * The interface that all Outgoing (sending) Transports inherit from. This * allows us to support several different protocol transports. */ class OutgoingTransport { public: OutgoingTransport() {} virtual ~OutgoingTransport() {} virtual bool Send(const PDUBlock &pdu_block) = 0; }; } // namespace acn } // namespace ola #endif // LIBS_ACN_TRANSPORT_H_ ola-0.10.5.nojsmin/libs/acn/E133PDUTest.cpp0000644000175000017500000001103713023355232017502 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E133PDUTest.cpp * Test fixture for the E133PDU class * Copyright (C) 2011 Simon Newton */ #include #include #include #include "ola/Logging.h" #include "ola/io/IOQueue.h" #include "ola/io/OutputStream.h" #include "ola/network/NetworkUtils.h" #include "ola/testing/TestUtils.h" #include "libs/acn/E133PDU.h" #include "libs/acn/PDUTestCommon.h" namespace ola { namespace acn { using ola::io::IOQueue; using ola::io::OutputStream; using ola::network::HostToNetwork; using std::string; class E133PDUTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(E133PDUTest); CPPUNIT_TEST(testSimpleE133PDU); CPPUNIT_TEST(testSimpleE133PDUToOutputStream); CPPUNIT_TEST_SUITE_END(); public: void testSimpleE133PDU(); void testSimpleE133PDUToOutputStream(); void setUp() { ola::InitLogging(ola::OLA_LOG_DEBUG, ola::OLA_LOG_STDERR); } private: static const unsigned int TEST_VECTOR; }; CPPUNIT_TEST_SUITE_REGISTRATION(E133PDUTest); const unsigned int E133PDUTest::TEST_VECTOR = 39; /* * Test that packing a E133PDU without data works. */ void E133PDUTest::testSimpleE133PDU() { const string source = "foo source"; E133Header header(source, 101, 2); E133PDU pdu(TEST_VECTOR, header, NULL); OLA_ASSERT_EQ(71u, pdu.HeaderSize()); OLA_ASSERT_EQ(0u, pdu.DataSize()); OLA_ASSERT_EQ(77u, pdu.Size()); unsigned int size = pdu.Size(); uint8_t *data = new uint8_t[size]; unsigned int bytes_used = size; OLA_ASSERT(pdu.Pack(data, &bytes_used)); OLA_ASSERT_EQ(size, bytes_used); // spot check the data OLA_ASSERT_EQ((uint8_t) 0x70, data[0]); OLA_ASSERT_EQ((uint8_t) bytes_used, data[1]); unsigned int actual_value; memcpy(&actual_value, data + 2, sizeof(actual_value)); OLA_ASSERT_EQ(HostToNetwork(TEST_VECTOR), actual_value); OLA_ASSERT_FALSE(memcmp(&data[6], source.data(), source.length())); // universe OLA_ASSERT_EQ((uint8_t) 0, data[6 + E133Header::SOURCE_NAME_LEN]); OLA_ASSERT_EQ((uint8_t) 0, data[6 + E133Header::SOURCE_NAME_LEN + 1]); OLA_ASSERT_EQ((uint8_t) 0, data[6 + E133Header::SOURCE_NAME_LEN + 2]); OLA_ASSERT_EQ((uint8_t) 101, data[6 + E133Header::SOURCE_NAME_LEN + 3]); // endpoint OLA_ASSERT_EQ((uint8_t) 0, data[6 + E133Header::SOURCE_NAME_LEN + 4]); OLA_ASSERT_EQ((uint8_t) 2, data[6 + E133Header::SOURCE_NAME_LEN + 5]); // options OLA_ASSERT_EQ((uint8_t) 0, data[6 + E133Header::SOURCE_NAME_LEN + 6]); // test undersized buffer bytes_used = size - 1; OLA_ASSERT_FALSE(pdu.Pack(data, &bytes_used)); OLA_ASSERT_EQ(0u, bytes_used); // test oversized buffer bytes_used = size + 1; OLA_ASSERT(pdu.Pack(data, &bytes_used)); OLA_ASSERT_EQ(size, bytes_used); delete[] data; } /* * Test that writing to an output stream works. */ void E133PDUTest::testSimpleE133PDUToOutputStream() { const string source = "foo source"; E133Header header(source, 101, 2); E133PDU pdu(TEST_VECTOR, header, NULL); OLA_ASSERT_EQ(71u, pdu.HeaderSize()); OLA_ASSERT_EQ(0u, pdu.DataSize()); OLA_ASSERT_EQ(77u, pdu.Size()); IOQueue output; OutputStream stream(&output); pdu.Write(&stream); OLA_ASSERT_EQ(77u, output.Size()); uint8_t *pdu_data = new uint8_t[output.Size()]; unsigned int pdu_size = output.Peek(pdu_data, output.Size()); OLA_ASSERT_EQ(output.Size(), pdu_size); uint8_t EXPECTED[] = { 0x70, 77, 0, 0, 0, 39, 'f', 'o', 'o', ' ', 's', 'o', 'u', 'r', 'c', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, // seq # 0, 2, // endpoint 0, }; OLA_ASSERT_DATA_EQUALS(EXPECTED, sizeof(EXPECTED), pdu_data, pdu_size); output.Pop(output.Size()); delete[] pdu_data; } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/UDPTransport.cpp0000644000175000017500000000611413023355232020223 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * UDPTransport.cpp * The OutgoingUDPTransport and IncomingUDPTransport classes * Copyright (C) 2007 Simon Newton */ #include #include "ola/Callback.h" #include "ola/Logging.h" #include "ola/network/NetworkUtils.h" #include "ola/network/SocketAddress.h" #include "libs/acn/BaseInflator.h" #include "libs/acn/HeaderSet.h" #include "libs/acn/UDPTransport.h" namespace ola { namespace acn { using ola::network::HostToNetwork; using ola::network::IPV4SocketAddress; /* * Send a block of PDU messages. * @param pdu_block the block of pdus to send */ bool OutgoingUDPTransport::Send(const PDUBlock &pdu_block) { return m_impl->Send(pdu_block, m_destination); } /* * Send a block of PDU messages using UDP. * @param pdu_block the block of pdus to send * @param destination the ipv4 address to send to * @param port the destination port to send to */ bool OutgoingUDPTransportImpl::Send(const PDUBlock &pdu_block, const IPV4SocketAddress &destination) { unsigned int data_size; const uint8_t *data = m_packer->Pack(pdu_block, &data_size); if (!data) return false; return m_socket->SendTo(data, data_size, destination); } IncomingUDPTransport::IncomingUDPTransport(ola::network::UDPSocket *socket, BaseInflator *inflator) : m_socket(socket), m_inflator(inflator), m_recv_buffer(NULL) { } /* * Called when new data arrives. */ void IncomingUDPTransport::Receive() { if (!m_recv_buffer) m_recv_buffer = new uint8_t[PreamblePacker::MAX_DATAGRAM_SIZE]; ssize_t size = PreamblePacker::MAX_DATAGRAM_SIZE; ola::network::IPV4SocketAddress source; if (!m_socket->RecvFrom(m_recv_buffer, &size, &source)) return; unsigned int header_size = PreamblePacker::ACN_HEADER_SIZE; if (size < static_cast(header_size)) { OLA_WARN << "short ACN frame, discarding"; return; } if (memcmp(m_recv_buffer, PreamblePacker::ACN_HEADER, header_size)) { OLA_WARN << "ACN header is bad, discarding"; return; } HeaderSet header_set; TransportHeader transport_header(source, TransportHeader::UDP); header_set.SetTransportHeader(transport_header); m_inflator->InflatePDUBlock( &header_set, m_recv_buffer + header_size, static_cast(size) - header_size); return; } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/E131TestFramework.cpp0000644000175000017500000001334213023355232021006 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E131TestFramework.cpp * Allows testing of a remote E1.31 implementation. * Copyright (C) 2010 Simon Newton * * The remote node needs to be listening for Universe 1. */ #include #include #include #include #include #include "ola/acn/CID.h" #include "ola/Callback.h" #include "ola/Constants.h" #include "ola/DmxBuffer.h" #include "ola/Logging.h" #include "ola/io/SelectServer.h" #include "ola/io/StdinHandler.h" #include "ola/network/Socket.h" #include "libs/acn/E131Node.h" #include "libs/acn/E131TestFramework.h" using ola::DmxBuffer; using ola::acn::CID; using ola::io::SelectServer; using ola::io::StdinHandler; using ola::acn::E131Node; using std::cout; using std::endl; using std::string; using std::vector; StateManager::StateManager(const std::vector &states, bool interactive_mode) : m_interactive(interactive_mode), m_count(0), m_ticker(0), m_local_node(NULL), m_node1(NULL), m_node2(NULL), m_ss(NULL), m_stdin_handler(NULL), m_states(states) { } bool StateManager::Init() { m_cid1 = CID::Generate(); m_cid2 = CID::Generate(); m_ss = new SelectServer(); // setup notifications for stdin m_stdin_handler.reset(new StdinHandler( m_ss, ola::NewCallback(this, &StateManager::Input))); if (!m_interactive) { // local node test CID local_cid = CID::Generate(); m_local_node = new E131Node(m_ss, "", E131Node::Options(), local_cid); assert(m_local_node->Start()); assert(m_ss->AddReadDescriptor(m_local_node->GetSocket())); assert(m_local_node->SetHandler( UNIVERSE_ID, &m_recv_buffer, NULL, // don't track the priority ola::NewCallback(this, &StateManager::NewDMX))); } E131Node::Options options1; options1.port = 5567; E131Node::Options options2(options1); options1.port = 5569; m_node1 = new E131Node(m_ss, "", options1, m_cid1); m_node2 = new E131Node(m_ss, "", options2, m_cid2); assert(m_node1->Start()); assert(m_node2->Start()); assert(m_ss->AddReadDescriptor(m_node1->GetSocket())); assert(m_ss->AddReadDescriptor(m_node2->GetSocket())); m_node1->SetSourceName(UNIVERSE_ID, "E1.31 Merge Test Node 1"); m_node2->SetSourceName(UNIVERSE_ID, "E1.31 Merge Test Node 2"); // tick every 200ms m_ss->RegisterRepeatingTimeout( TICK_INTERVAL_MS, ola::NewCallback(this, &StateManager::Tick)); cout << endl; cout << "========= E1.31 Tester ==========" << endl; if (m_interactive) { cout << "Space for the next state, 'e' for expected results, 'q' to quit" << endl; } EnterState(m_states[0]); return true; } StateManager::~StateManager() { if (m_node1) { m_ss->RemoveReadDescriptor(m_node1->GetSocket()); delete m_node1; } if (m_node2) { m_ss->RemoveReadDescriptor(m_node2->GetSocket()); delete m_node2; } if (m_local_node) { m_ss->RemoveReadDescriptor(m_local_node->GetSocket()); delete m_local_node; } m_stdin_handler.reset(); delete m_ss; } bool StateManager::Tick() { if (m_ticker > (TIME_PER_STATE_MS / TICK_INTERVAL_MS) && !m_interactive) { NextState(); if (m_count == m_states.size()) { return false; } } else { m_ticker++; } m_states[m_count]->Tick(); switch (m_ticker % 4) { case 0: cout << "|"; break; case 1: cout << "/"; break; case 2: cout << "-"; break; case 3: cout << "\\"; break; } cout << '\b' << std::flush; return true; } void StateManager::Input(int c) { switch (c) { case 'e': cout << m_states[m_count]->ExpectedResults() << endl; break; case 'q': m_ss->Terminate(); ShowStatus(); break; case ' ': NextState(); break; default: break; } } /* * Called when new DMX is received by the local node */ void StateManager::NewDMX() { if (!m_states[m_count]->Verify(m_recv_buffer)) { cout << "FAILED TEST" << endl; } } /* * Switch states */ void StateManager::EnterState(TestState *state) { cout << "------------------------------------" << endl; cout << "Test Case: " << static_cast(m_count + 1) << "/" << m_states.size() << endl; cout << "Test Name: " << state->StateName() << endl; state->SetNodes(m_node1, m_node2); m_ticker = 0; } void StateManager::NextState() { if (!m_states[m_count]->Passed()) { m_failed_tests.push_back(m_states[m_count]); } m_count++; if (m_count == m_states.size()) { cout << "------------------------------------" << endl; cout << "Tests complete!" << endl; ShowStatus(); m_ss->Terminate(); } else { EnterState(m_states[m_count]); } } void StateManager::ShowStatus() { if (!m_failed_tests.empty()) { cout << "Some tests failed:" << endl; vector::iterator iter; for (iter = m_failed_tests.begin(); iter != m_failed_tests.end(); ++iter) { cout << " " << (*iter)->StateName() << endl; } } else { cout << "All tests passed." << endl; } } ola-0.10.5.nojsmin/libs/acn/RootInflator.cpp0000644000175000017500000000426013023355232020300 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RootInflator.cpp * The Inflator for the root level packets over UDP * Copyright (C) 2007 Simon Newton */ #include "ola/Logging.h" #include "libs/acn/RootInflator.h" namespace ola { namespace acn { using ola::acn::CID; /* * Decode the root headers. If data is null we're expected to use the last * header we got. * @param headers the HeaderSet to add to * @param data a pointer to the data * @param length length of the data * @returns true if successful, false otherwise */ bool RootInflator::DecodeHeader(HeaderSet *headers, const uint8_t *data, unsigned int length, unsigned int *bytes_used) { if (data) { if (length >= CID::CID_LENGTH) { CID cid = CID::FromData(data); m_last_hdr.SetCid(cid); headers->SetRootHeader(m_last_hdr); *bytes_used = CID::CID_LENGTH; return true; } return false; } *bytes_used = 0; if (m_last_hdr.GetCid().IsNil()) { OLA_WARN << "Missing CID data"; return false; } headers->SetRootHeader(m_last_hdr); return true; } /* * Reset the header field */ void RootInflator::ResetHeaderField() { CID cid; m_last_hdr.SetCid(cid); } /** * This runs the on_data callback if we have one */ bool RootInflator::PostHeader(uint32_t, const HeaderSet &headers) { if (m_on_data.get()) m_on_data->Run(headers.GetTransportHeader()); return true; } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/E131InflatorTest.cpp0000644000175000017500000001547413023355232020637 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E131InflatorTest.cpp * Test fixture for the E131Inflator class * Copyright (C) 2005 Simon Newton */ #include #include #include #include "ola/Logging.h" #include "ola/network/NetworkUtils.h" #include "libs/acn/HeaderSet.h" #include "libs/acn/PDUTestCommon.h" #include "libs/acn/E131Inflator.h" #include "libs/acn/E131PDU.h" #include "ola/testing/TestUtils.h" namespace ola { namespace acn { using ola::network::HostToNetwork; using std::string; class E131InflatorTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(E131InflatorTest); CPPUNIT_TEST(testDecodeRev2Header); CPPUNIT_TEST(testDecodeHeader); CPPUNIT_TEST(testInflateRev2PDU); CPPUNIT_TEST(testInflatePDU); CPPUNIT_TEST_SUITE_END(); public: void testDecodeRev2Header(); void testDecodeHeader(); void testInflatePDU(); void testInflateRev2PDU(); }; CPPUNIT_TEST_SUITE_REGISTRATION(E131InflatorTest); /* * Check that we can decode headers properly */ void E131InflatorTest::testDecodeRev2Header() { E131Rev2Header::e131_rev2_pdu_header header; E131InflatorRev2 inflator; HeaderSet header_set, header_set2; unsigned int bytes_used; const string source_name = "foobar"; strncpy(header.source, source_name.data(), source_name.size() + 1); header.priority = 99; header.sequence = 10; header.universe = HostToNetwork(static_cast(42)); OLA_ASSERT(inflator.DecodeHeader(&header_set, reinterpret_cast(&header), sizeof(header), &bytes_used)); OLA_ASSERT_EQ((unsigned int) sizeof(header), bytes_used); E131Header decoded_header = header_set.GetE131Header(); OLA_ASSERT(source_name == decoded_header.Source()); OLA_ASSERT_EQ((uint8_t) 99, decoded_header.Priority()); OLA_ASSERT_EQ((uint8_t) 10, decoded_header.Sequence()); OLA_ASSERT_EQ((uint16_t) 42, decoded_header.Universe()); // try an undersized header OLA_ASSERT_FALSE(inflator.DecodeHeader( &header_set, reinterpret_cast(&header), static_cast(sizeof(header) - 1), &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); // test inherting the header from the prev call OLA_ASSERT(inflator.DecodeHeader(&header_set2, NULL, 0, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); decoded_header = header_set2.GetE131Header(); OLA_ASSERT(source_name == decoded_header.Source()); OLA_ASSERT_EQ((uint8_t) 99, decoded_header.Priority()); OLA_ASSERT_EQ((uint8_t) 10, decoded_header.Sequence()); OLA_ASSERT_EQ((uint16_t) 42, decoded_header.Universe()); inflator.ResetHeaderField(); OLA_ASSERT_FALSE(inflator.DecodeHeader(&header_set2, NULL, 0, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); } /* * Check that we can decode headers properly */ void E131InflatorTest::testDecodeHeader() { E131Header::e131_pdu_header header; E131Inflator inflator; HeaderSet header_set, header_set2; unsigned int bytes_used; const string source_name = "foobar"; strncpy(header.source, source_name.data(), source_name.size() + 1); header.priority = 99; header.sequence = 10; header.universe = HostToNetwork(static_cast(42)); OLA_ASSERT(inflator.DecodeHeader(&header_set, reinterpret_cast(&header), sizeof(header), &bytes_used)); OLA_ASSERT_EQ((unsigned int) sizeof(header), bytes_used); E131Header decoded_header = header_set.GetE131Header(); OLA_ASSERT(source_name == decoded_header.Source()); OLA_ASSERT_EQ((uint8_t) 99, decoded_header.Priority()); OLA_ASSERT_EQ((uint8_t) 10, decoded_header.Sequence()); OLA_ASSERT_EQ((uint16_t) 42, decoded_header.Universe()); // try an undersized header OLA_ASSERT_FALSE(inflator.DecodeHeader( &header_set, reinterpret_cast(&header), static_cast(sizeof(header) - 1), &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); // test inherting the header from the prev call OLA_ASSERT(inflator.DecodeHeader(&header_set2, NULL, 0, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); decoded_header = header_set2.GetE131Header(); OLA_ASSERT(source_name == decoded_header.Source()); OLA_ASSERT_EQ((uint8_t) 99, decoded_header.Priority()); OLA_ASSERT_EQ((uint8_t) 10, decoded_header.Sequence()); OLA_ASSERT_EQ((uint16_t) 42, decoded_header.Universe()); inflator.ResetHeaderField(); OLA_ASSERT_FALSE(inflator.DecodeHeader(&header_set2, NULL, 0, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); } /* * Check that we can inflate a E131 PDU that contains other PDUs */ void E131InflatorTest::testInflateRev2PDU() { const string source = "foo source"; E131Rev2Header header(source, 1, 2, 6000); // TODO(simon): pass a DMP msg here as well E131PDU pdu(3, header, NULL); OLA_ASSERT_EQ((unsigned int) 42, pdu.Size()); unsigned int size = pdu.Size(); uint8_t *data = new uint8_t[size]; unsigned int bytes_used = size; OLA_ASSERT(pdu.Pack(data, &bytes_used)); OLA_ASSERT_EQ((unsigned int) size, bytes_used); E131InflatorRev2 inflator; HeaderSet header_set; OLA_ASSERT_EQ( size, (unsigned int) inflator.InflatePDUBlock(&header_set, data, size)); OLA_ASSERT(header == header_set.GetE131Header()); delete[] data; } /* * Check that we can inflate a E131 PDU that contains other PDUs */ void E131InflatorTest::testInflatePDU() { const string source = "foobar source"; E131Header header(source, 1, 2, 6000); // TODO(simon): pass a DMP msg here as well E131PDU pdu(3, header, NULL); OLA_ASSERT_EQ((unsigned int) 77, pdu.Size()); unsigned int size = pdu.Size(); uint8_t *data = new uint8_t[size]; unsigned int bytes_used = size; OLA_ASSERT(pdu.Pack(data, &bytes_used)); OLA_ASSERT_EQ((unsigned int) size, bytes_used); E131Inflator inflator; HeaderSet header_set; OLA_ASSERT(inflator.InflatePDUBlock(&header_set, data, size)); OLA_ASSERT(header == header_set.GetE131Header()); delete[] data; } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/DMPPDU.h0000644000175000017500000002173313023355232016320 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DMPPDU.h * Interface for the DMP PDU * Copyright (C) 2007 Simon Newton */ #ifndef LIBS_ACN_DMPPDU_H_ #define LIBS_ACN_DMPPDU_H_ #include #include #include "ola/acn/ACNVectors.h" #include "libs/acn/DMPAddress.h" #include "libs/acn/DMPHeader.h" #include "libs/acn/PDU.h" namespace ola { namespace acn { /* * The base DMPPDU class. * More specific dmp pdus like the SetPropery inherit from this. */ class DMPPDU: public PDU { public: DMPPDU(unsigned int vector, const DMPHeader &dmp_header): PDU(vector, ONE_BYTE), m_header(dmp_header) { } ~DMPPDU() {} unsigned int HeaderSize() const { return DMPHeader::DMP_HEADER_SIZE; } bool PackHeader(uint8_t *data, unsigned int *length) const; void PackHeader(ola::io::OutputStream *stream) const; protected: DMPHeader m_header; }; /* * A DMPGetPropertyPDU, templatized by the address type. * Don't create these directly, instead use the helper function below which * enforces compile time consistency. */ template class DMPGetProperty: public DMPPDU { public: DMPGetProperty(const DMPHeader &header, const std::vector
&addresses): DMPPDU(ola::acn::DMP_GET_PROPERTY_VECTOR, header), m_addresses(addresses) {} unsigned int DataSize() const { return static_cast(m_addresses.size() * m_header.Bytes() * (m_header.Type() == NON_RANGE ? 1 : 3)); } bool PackData(uint8_t *data, unsigned int *length) const { typename std::vector
::const_iterator iter; unsigned int offset = 0; for (iter = m_addresses.begin(); iter != m_addresses.end(); ++iter) { unsigned int remaining = *length - offset; if (!iter->Pack(data + offset, &remaining)) return false; offset += remaining; } *length = offset; return true; } void PackData(ola::io::OutputStream *stream) const { typename std::vector
::const_iterator iter; for (iter = m_addresses.begin(); iter != m_addresses.end(); ++iter) iter->Write(stream); } private: std::vector
m_addresses; }; /* * Create a non-ranged GetProperty PDU * @param type uint8_t, uint16_t or uint32_t * @param is_virtual set to true if this is a virtual address * @param is_relative set to true if this is a relative address * @param addresses a vector of DMPAddress objects */ template const DMPPDU *NewDMPGetProperty( bool is_virtual, bool is_relative, const std::vector > &addresses) { DMPHeader header(is_virtual, is_relative, NON_RANGE, TypeToDMPSize()); return new DMPGetProperty >(header, addresses); } /* * Create a non-ranged DMP GetProperty PDU * @param type uint8_t, uint16_t, uint32_t */ template const DMPPDU *_CreateDMPGetProperty(bool is_virtual, bool is_relative, unsigned int start) { DMPAddress address((type) start); std::vector > addresses; addresses.push_back(address); return NewDMPGetProperty(is_virtual, is_relative, addresses); } /* * A helper to create a new single, non-ranged GetProperty PDU. * @param is_virtual set to true if this is a virtual address * @param is_relative set to true if this is a relative address * @param start the start offset * @return A pointer to a DMPPDU. */ const DMPPDU *NewDMPGetProperty(bool is_virtual, bool is_relative, unsigned int start); /* * Create a Ranged DMP GetProperty Message. * @param type uint8_t, uint16_t or uint32_t * @param is_virtual set to true if this is a virtual address * @param is_relative set to true if this is a relative address * @param addresses a vector of addresses that match the type * @return A pointer to a DMPPDU. */ template const DMPPDU *NewRangeDMPGetProperty( bool is_virtual, bool is_relative, const std::vector > &addresses) { DMPHeader header(is_virtual, is_relative, RANGE_SINGLE, TypeToDMPSize()); return new DMPGetProperty >(header, addresses); } template const DMPPDU *_CreateRangeDMPGetProperty(bool is_virtual, bool is_relative, unsigned int start, unsigned int increment, unsigned int number) { std::vector > addresses; RangeDMPAddress address((type) start, (type) increment, (type) number); addresses.push_back(address); return NewRangeDMPGetProperty(is_virtual, is_relative, addresses); } /* * A helper to create a new ranged address GetProperty PDU. * @param is_virtual set to true if this is a virtual address * @param is_relative set to true if this is a relative address * @param start the start offset * @param increment the increments between addresses * @param number the number of addresses defined * @return A pointer to a DMPGetProperty. */ const DMPPDU *NewRangeDMPGetProperty( bool is_virtual, bool is_relative, unsigned int start, unsigned int increment, unsigned int number); /* * A DMPSetPropertyPDU, templatized by the address type. * Don't create these directly, instead use the helper functions below which * enforce compile time consistency. * @param type either DMPAddress<> or RangeDMPAddress<> */ template class DMPSetProperty: public DMPPDU { public: typedef std::vector > AddressDataChunks; DMPSetProperty(const DMPHeader &header, const AddressDataChunks &chunks): DMPPDU(ola::acn::DMP_SET_PROPERTY_VECTOR, header), m_chunks(chunks) {} unsigned int DataSize() const { typename AddressDataChunks::const_iterator iter; unsigned int length = 0; for (iter = m_chunks.begin(); iter != m_chunks.end(); ++iter) length += iter->Size(); return length; } bool PackData(uint8_t *data, unsigned int *length) const { typename AddressDataChunks::const_iterator iter; unsigned int offset = 0; for (iter = m_chunks.begin(); iter != m_chunks.end(); ++iter) { unsigned int remaining = *length - offset; if (!iter->Pack(data + offset, &remaining)) return false; offset += remaining; } *length = offset; return true; } void PackData(ola::io::OutputStream *stream) const { typename AddressDataChunks::const_iterator iter; for (iter = m_chunks.begin(); iter != m_chunks.end(); ++iter) iter->Write(stream); } private: AddressDataChunks m_chunks; }; /* * Create a new DMP SetProperty Message */ template const DMPPDU *NewDMPSetProperty( bool is_virtual, bool is_relative, const std::vector > > &chunks) { DMPHeader header(is_virtual, is_relative, NON_RANGE, TypeToDMPSize()); return new DMPSetProperty >(header, chunks); } /* * Create a new DMP SetProperty PDU * @param type either DMPAddress or RangeDMPAddress * @param is_virtual set to true if this is a virtual address * @param is_relative set to true if this is a relative address * @param chunks a vector of DMPAddressData objects */ template const DMPPDU *NewRangeDMPSetProperty( bool is_virtual, bool is_relative, const std::vector > > &chunks, bool multiple_elements = true, bool equal_size_elements = true) { dmp_address_type address_type; if (multiple_elements) { if (equal_size_elements) address_type = RANGE_EQUAL; else address_type = RANGE_MIXED; } else { address_type = RANGE_SINGLE; } DMPHeader header(is_virtual, is_relative, address_type, TypeToDMPSize()); return new DMPSetProperty >(header, chunks); } } // namespace acn } // namespace ola #endif // LIBS_ACN_DMPPDU_H_ ola-0.10.5.nojsmin/libs/acn/TCPTransport.cpp0000644000175000017500000002217313023355232020224 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * TCPTransport.cpp * The classes for transporting ACN over TCP. * Copyright (C) 2012 Simon Newton */ #include #include #include #include #include #include "libs/acn/BaseInflator.h" #include "libs/acn/HeaderSet.h" #include "libs/acn/TCPTransport.h" namespace ola { namespace acn { const uint8_t ACN_HEADER[] = { 0x00, 0x14, // preamble size 0x00, 0x00, // post amble size 0x41, 0x53, 0x43, 0x2d, 0x45, 0x31, 0x2e, 0x31, 0x37, 0x00, 0x00, 0x00 // For TCP, the next 4 bytes are the block size }; const unsigned int ACN_HEADER_SIZE = sizeof(ACN_HEADER); // TODO(simon): tune this once we have an idea of what the sizes will be const unsigned int IncomingStreamTransport::INITIAL_SIZE = 500; /** * Create a new IncomingStreamTransport. * @param inflator the inflator to call for each PDU * @param descriptor the descriptor to read from * @param source the IP and port to use in the transport header */ IncomingStreamTransport::IncomingStreamTransport( BaseInflator *inflator, ola::io::ConnectedDescriptor *descriptor, const ola::network::IPV4SocketAddress &source) : m_transport_header(source, TransportHeader::TCP), m_inflator(inflator), m_descriptor(descriptor), m_buffer_start(NULL), m_buffer_end(NULL), m_data_end(NULL), m_block_size(0), m_consumed_block_size(0), m_stream_valid(true), m_pdu_length_size(TWO_BYTES), m_pdu_size(0) { EnterWaitingForPreamble(); } /** * Clean up */ IncomingStreamTransport::~IncomingStreamTransport() { if (m_buffer_start) delete[] m_buffer_start; } /** * Read from this stream, looking for ACN messages. * @returns false if the stream is no longer consistent. At this point the * caller should close the descriptor since the data is no longer valid. */ bool IncomingStreamTransport::Receive() { while (true) { OLA_DEBUG << "start read, outstanding bytes is " << m_outstanding_data; // Read as much as we need ReadRequiredData(); OLA_DEBUG << "done read, bytes outstanding is " << m_outstanding_data; // if we still don't have enough, return if (m_stream_valid == false || m_outstanding_data) return m_stream_valid; OLA_DEBUG << "state is " << m_state; switch (m_state) { case WAITING_FOR_PREAMBLE: HandlePreamble(); break; case WAITING_FOR_PDU_FLAGS: HandlePDUFlags(); break; case WAITING_FOR_PDU_LENGTH: HandlePDULength(); break; case WAITING_FOR_PDU: HandlePDU(); break; } if (!m_stream_valid) return false; } } /** * Handle the Preamble data. * @pre 20 bytes in the buffer */ void IncomingStreamTransport::HandlePreamble() { OLA_DEBUG << "in handle preamble, data len is " << DataLength(); if (memcmp(m_buffer_start, ACN_HEADER, ACN_HEADER_SIZE) != 0) { ola::FormatData(&std::cout, m_buffer_start, ACN_HEADER_SIZE); ola::FormatData(&std::cout, ACN_HEADER, ACN_HEADER_SIZE); OLA_WARN << "bad ACN header"; m_stream_valid = false; return; } // read the PDU block length memcpy(reinterpret_cast(&m_block_size), m_buffer_start + ACN_HEADER_SIZE, sizeof(m_block_size)); m_block_size = ola::network::NetworkToHost(m_block_size); OLA_DEBUG << "pdu block size is " << m_block_size; if (m_block_size) { m_consumed_block_size = 0; EnterWaitingForPDU(); } else { EnterWaitingForPreamble(); } } /** * Handle the PDU Flag data, this allows us to figure out how many bytes we * need to read the length. * @pre 1 byte in the buffer */ void IncomingStreamTransport::HandlePDUFlags() { OLA_DEBUG << "Reading PDU flags, data size is " << DataLength(); m_pdu_length_size = (*m_buffer_start & BaseInflator::LFLAG_MASK) ? THREE_BYTES : TWO_BYTES; m_outstanding_data += static_cast(m_pdu_length_size) - 1; OLA_DEBUG << "PDU length size is " << static_cast(m_pdu_length_size) << " bytes"; m_state = WAITING_FOR_PDU_LENGTH; } /** * Handle the PDU Length data. * @pre 2 or 3 bytes of data in the buffer, depending on m_pdu_length_size */ void IncomingStreamTransport::HandlePDULength() { if (m_pdu_length_size == THREE_BYTES) { m_pdu_size = ( m_buffer_start[2] + static_cast(m_buffer_start[1] << 8) + static_cast((m_buffer_start[0] & BaseInflator::LENGTH_MASK) << 16)); } else { m_pdu_size = m_buffer_start[1] + static_cast( (m_buffer_start[0] & BaseInflator::LENGTH_MASK) << 8); } OLA_DEBUG << "PDU size is " << m_pdu_size; if (m_pdu_size < static_cast(m_pdu_length_size)) { OLA_WARN << "PDU length was set to " << m_pdu_size << " but " << static_cast(m_pdu_length_size) << " bytes were used in the header"; m_stream_valid = false; return; } m_outstanding_data += ( m_pdu_size - static_cast(m_pdu_length_size)); OLA_DEBUG << "Processed length, now waiting on another " << m_outstanding_data << " bytes"; m_state = WAITING_FOR_PDU; } /** * Handle a PDU * @pre m_pdu_size bytes in the buffer */ void IncomingStreamTransport::HandlePDU() { OLA_DEBUG << "Got PDU, data length is " << DataLength() << ", expected " << m_pdu_size; if (DataLength() != m_pdu_size) { OLA_WARN << "PDU size doesn't match the available data"; m_stream_valid = false; return; } HeaderSet header_set; header_set.SetTransportHeader(m_transport_header); unsigned int data_consumed = m_inflator->InflatePDUBlock( &header_set, m_buffer_start, m_pdu_size); OLA_DEBUG << "inflator consumed " << data_consumed << " bytes"; if (m_pdu_size != data_consumed) { OLA_WARN << "PDU inflation size mismatch, " << m_pdu_size << " != " << data_consumed; m_stream_valid = false; return; } m_consumed_block_size += data_consumed; if (m_consumed_block_size == m_block_size) { // all PDUs in this block have been processed EnterWaitingForPreamble(); } else { EnterWaitingForPDU(); } } /** * Grow the rx buffer to the new size. */ void IncomingStreamTransport::IncreaseBufferSize(unsigned int new_size) { if (new_size <= BufferSize()) return; new_size = std::max(new_size, INITIAL_SIZE); unsigned int data_length = DataLength(); if (!m_buffer_start) data_length = 0; // allocate new buffer and copy the data over uint8_t *buffer = new uint8_t[new_size]; if (m_buffer_start) { if (data_length > 0) // this moves the data to the start of the buffer if it wasn't already memcpy(buffer, m_buffer_start, data_length); delete[] m_buffer_start; } m_buffer_start = buffer; m_buffer_end = buffer + new_size; m_data_end = buffer + data_length; } /** * Read data until we reach the number of bytes we required or there is no more * data to be read */ void IncomingStreamTransport::ReadRequiredData() { if (m_outstanding_data == 0) return; if (m_outstanding_data > FreeSpace()) IncreaseBufferSize(DataLength() + m_outstanding_data); unsigned int data_read; int ok = m_descriptor->Receive(m_data_end, m_outstanding_data, data_read); if (ok != 0) OLA_WARN << "tcp rx failed"; OLA_DEBUG << "read " << data_read; m_data_end += data_read; m_outstanding_data -= data_read; } /** * Enter the wait-for-preamble state */ void IncomingStreamTransport::EnterWaitingForPreamble() { m_data_end = m_buffer_start; m_state = WAITING_FOR_PREAMBLE; m_outstanding_data = ACN_HEADER_SIZE + PDU_BLOCK_SIZE; } /** * Enter the wait-for-pdu state */ void IncomingStreamTransport::EnterWaitingForPDU() { m_state = WAITING_FOR_PDU_FLAGS; m_data_end = m_buffer_start; // we need 1 byte to read the flags m_outstanding_data = 1; } /** * Create a new IncomingTCPTransport */ IncomingTCPTransport::IncomingTCPTransport(BaseInflator *inflator, ola::network::TCPSocket *socket) : m_transport(NULL) { ola::network::GenericSocketAddress address = socket->GetPeerAddress(); if (address.Family() == AF_INET) { ola::network::IPV4SocketAddress v4_addr = address.V4Addr(); m_transport.reset( new IncomingStreamTransport(inflator, socket, v4_addr)); } else { OLA_WARN << "Invalid address for fd " << socket->ReadDescriptor(); } } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/E131Sender.h0000644000175000017500000000361413023355232017077 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E131Sender.h * Interface for the E131Sender class, this abstracts the encapsulation and * sending of DMP PDUs contained within E131PDUs. * Copyright (C) 2007 Simon Newton */ #ifndef LIBS_ACN_E131SENDER_H_ #define LIBS_ACN_E131SENDER_H_ #include "ola/network/Socket.h" #include "libs/acn/DMPPDU.h" #include "libs/acn/E131Header.h" #include "libs/acn/PreamblePacker.h" #include "libs/acn/Transport.h" #include "libs/acn/UDPTransport.h" namespace ola { namespace acn { class DMPInflator; class E131Sender { public: E131Sender(ola::network::UDPSocket *socket, class RootSender *root_sender); ~E131Sender() {} bool SendDMP(const E131Header &header, const DMPPDU *pdu); bool SendDiscoveryData(const E131Header &header, const uint8_t *data, unsigned int data_size); static bool UniverseIP(uint16_t universe, class ola::network::IPV4Address *addr); private: ola::network::UDPSocket *m_socket; PreamblePacker m_packer; OutgoingUDPTransportImpl m_transport_impl; class RootSender *m_root_sender; DISALLOW_COPY_AND_ASSIGN(E131Sender); }; } // namespace acn } // namespace ola #endif // LIBS_ACN_E131SENDER_H_ ola-0.10.5.nojsmin/libs/acn/PreamblePacker.h0000644000175000017500000000354413023355232020204 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * PreamblePacker.h * This class takes a block of Root Layer PDUs, prepends the ACN preamble and * writes the data to a buffer. * Copyright (C) 2012 Simon Newton */ #ifndef LIBS_ACN_PREAMBLEPACKER_H_ #define LIBS_ACN_PREAMBLEPACKER_H_ #include "ola/io/IOStack.h" #include "libs/acn/PDU.h" namespace ola { namespace acn { /* * Pack a Root PDU block and the ACN Preamble into a memory block. This class * isn't reentrant so be careful where you use it. */ class PreamblePacker { public: PreamblePacker() : m_send_buffer(NULL) {} ~PreamblePacker(); const uint8_t *Pack(const PDUBlock &pdu_block, unsigned int *length); static void AddUDPPreamble(ola::io::IOStack *stack); static void AddTCPPreamble(ola::io::IOStack *stack); static const uint8_t ACN_HEADER[]; static const unsigned int ACN_HEADER_SIZE; static const unsigned int MAX_DATAGRAM_SIZE = 1472; private: uint8_t *m_send_buffer; void Init(); static const uint8_t TCP_ACN_HEADER[]; static const unsigned int TCP_ACN_HEADER_SIZE; }; } // namespace acn } // namespace ola #endif // LIBS_ACN_PREAMBLEPACKER_H_ ola-0.10.5.nojsmin/libs/acn/libolaacn.pc.in0000644000175000017500000000033713023355232020030 0ustar wouterwouterprefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libolaacn Version: @VERSION@ Description: Open Lighting Architecture ACN Requires: Libs: -L${libdir} -lolaacn Cflags: -I${includedir} ola-0.10.5.nojsmin/libs/acn/E131Sender.cpp0000644000175000017500000000736613023355232017442 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E131Sender.cpp * The E131Sender * Copyright (C) 2007 Simon Newton */ #include "ola/Logging.h" #include "ola/acn/ACNVectors.h" #include "ola/network/IPV4Address.h" #include "ola/network/NetworkUtils.h" #include "ola/util/Utils.h" #include "libs/acn/DMPE131Inflator.h" #include "libs/acn/E131Inflator.h" #include "libs/acn/E131Sender.h" #include "libs/acn/E131PDU.h" #include "libs/acn/RootSender.h" #include "libs/acn/UDPTransport.h" namespace ola { namespace acn { using ola::network::IPV4Address; using ola::network::HostToNetwork; /* * Create a new E131Sender * @param root_sender the root layer to use */ E131Sender::E131Sender(ola::network::UDPSocket *socket, RootSender *root_sender) : m_socket(socket), m_transport_impl(socket, &m_packer), m_root_sender(root_sender) { if (!m_root_sender) { OLA_WARN << "root_sender is null, this won't work"; } } /* * Send a DMPPDU * @param header the E131Header * @param dmp_pdu the DMPPDU to send */ bool E131Sender::SendDMP(const E131Header &header, const DMPPDU *dmp_pdu) { if (!m_root_sender) { return false; } IPV4Address addr; if (!UniverseIP(header.Universe(), &addr)) { OLA_INFO << "Could not convert universe " << header.Universe() << " to IP."; return false; } OutgoingUDPTransport transport(&m_transport_impl, addr); E131PDU pdu(ola::acn::VECTOR_E131_DATA, header, dmp_pdu); unsigned int vector = ola::acn::VECTOR_ROOT_E131; if (header.UsingRev2()) { vector = ola::acn::VECTOR_ROOT_E131_REV2; } return m_root_sender->SendPDU(vector, pdu, &transport); } bool E131Sender::SendDiscoveryData(const E131Header &header, const uint8_t *data, unsigned int data_size) { if (!m_root_sender) { return false; } IPV4Address addr; if (!UniverseIP(header.Universe(), &addr)) { OLA_INFO << "Could not convert universe " << header.Universe() << " to IP."; return false; } OutgoingUDPTransport transport(&m_transport_impl, addr); E131PDU pdu(ola::acn::VECTOR_E131_DISCOVERY, header, data, data_size); unsigned int vector = ola::acn::VECTOR_ROOT_E131; return m_root_sender->SendPDU(vector, pdu, &transport); } /* * Calculate the IP that corresponds to a universe. * @param universe the universe id * @param addr where to store the address * @return true if this is a valid E1.31 universe, false otherwise */ bool E131Sender::UniverseIP(uint16_t universe, IPV4Address *addr) { uint8_t universe_high; uint8_t universe_low; ola::utils::SplitUInt16(universe, &universe_high, &universe_low); *addr = IPV4Address( HostToNetwork(ola::utils::JoinUInt8(239, 255, universe_high, universe_low))); if (universe && (universe != 0xFFFF)) { return true; } OLA_WARN << "Universe " << universe << " isn't a valid E1.31 universe"; return false; } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/RootHeader.h0000644000175000017500000000252613023355232017362 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RootHeader.h * Interface for the RootHeader class * Copyright (C) 2007 Simon Newton */ #ifndef LIBS_ACN_ROOTHEADER_H_ #define LIBS_ACN_ROOTHEADER_H_ #include "ola/acn/CID.h" namespace ola { namespace acn { /* * The header for the root layer */ class RootHeader { public: RootHeader() {} ~RootHeader() {} void SetCid(ola::acn::CID cid) { m_cid = cid; } ola::acn::CID GetCid() const { return m_cid; } bool operator==(const RootHeader &other) const { return m_cid == other.m_cid; } private: ola::acn::CID m_cid; }; } // namespace acn } // namespace ola #endif // LIBS_ACN_ROOTHEADER_H_ ola-0.10.5.nojsmin/libs/acn/PDUTest.cpp0000644000175000017500000000565613023355232017160 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * PDUTest.cpp * Test fixture for the PDU class * Copyright (C) 2005 Simon Newton */ #include #include "ola/Logging.h" #include "ola/io/IOQueue.h" #include "ola/io/OutputStream.h" #include "ola/testing/TestUtils.h" #include "libs/acn/PDU.h" #include "libs/acn/PDUTestCommon.h" namespace ola { namespace acn { using ola::io::IOQueue; using ola::io::OutputStream; class PDUTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(PDUTest); CPPUNIT_TEST(testPDUBlock); CPPUNIT_TEST(testBlockToOutputStream); CPPUNIT_TEST_SUITE_END(); public: void testPDUBlock(); void testBlockToOutputStream(); void setUp() { ola::InitLogging(ola::OLA_LOG_DEBUG, ola::OLA_LOG_STDERR); } }; CPPUNIT_TEST_SUITE_REGISTRATION(PDUTest); /* * Test that packing a PDUBlock works. */ void PDUTest::testPDUBlock() { FakePDU pdu1(1); FakePDU pdu2(2); FakePDU pdu42(42); PDUBlock block; block.AddPDU(&pdu1); block.AddPDU(&pdu2); block.AddPDU(&pdu42); unsigned int block_size = block.Size(); OLA_ASSERT_EQ(12u, block_size); uint8_t *data = new uint8_t[block_size]; unsigned int bytes_used = block_size; OLA_ASSERT(block.Pack(data, &bytes_used)); OLA_ASSERT_EQ(block_size, bytes_used); unsigned int *test = (unsigned int*) data; OLA_ASSERT_EQ(1u, *test++); OLA_ASSERT_EQ(2u, *test++); OLA_ASSERT_EQ(42u, *test); delete[] data; block.Clear(); OLA_ASSERT_EQ(0u, block.Size()); } /* * Test that writing to an OutputStream works. */ void PDUTest::testBlockToOutputStream() { FakePDU pdu1(1); FakePDU pdu2(2); FakePDU pdu42(42); PDUBlock block; block.AddPDU(&pdu1); block.AddPDU(&pdu2); block.AddPDU(&pdu42); IOQueue output; OutputStream stream(&output); block.Write(&stream); OLA_ASSERT_EQ(12u, output.Size()); uint8_t *block_data = new uint8_t[output.Size()]; unsigned int block_size = output.Peek(block_data, output.Size()); OLA_ASSERT_EQ(output.Size(), block_size); uint8_t EXPECTED[] = { 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 42 }; OLA_ASSERT_DATA_EQUALS(EXPECTED, sizeof(EXPECTED), block_data, block_size); output.Pop(output.Size()); delete[] block_data; } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/DMPHeader.h0000644000175000017500000000454613023355232017063 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DMPHeader.h * The DMP Header * Copyright (C) 2007 Simon Newton */ #ifndef LIBS_ACN_DMPHEADER_H_ #define LIBS_ACN_DMPHEADER_H_ #include #include "libs/acn/DMPAddress.h" namespace ola { namespace acn { /* * Header for the DMP layer */ class DMPHeader { public: static const unsigned int DMP_HEADER_SIZE = 1; explicit DMPHeader(uint8_t header = 0): m_header(header) {} DMPHeader(bool is_virtual, bool is_relative, dmp_address_type type, dmp_address_size size) { m_header = (uint8_t) (is_virtual << 7 | is_relative << 6 | type << 4 | size); } ~DMPHeader() {} bool IsVirtual() const { return m_header & VIRTUAL_MASK; } bool IsRelative() const { return m_header & RELATIVE_MASK; } dmp_address_type Type() const { return (dmp_address_type) ((m_header & TYPE_MASK) >> 4); } dmp_address_size Size() const { return (dmp_address_size) (m_header & SIZE_MASK); } unsigned int Bytes() const { return DMPSizeToByteSize(Size()); } bool operator==(const DMPHeader &other) const { return m_header == other.m_header; } bool operator!=(const DMPHeader &other) const { return m_header != other.m_header; } uint8_t Header() const { return m_header; } private: static const uint8_t VIRTUAL_MASK = 0x80; static const uint8_t RELATIVE_MASK = 0x40; static const uint8_t TYPE_MASK = 0x30; static const uint8_t SIZE_MASK = 0x03; uint8_t m_header; }; } // namespace acn } // namespace ola #endif // LIBS_ACN_DMPHEADER_H_ ola-0.10.5.nojsmin/libs/acn/DMPE131Inflator.h0000644000175000017500000000567113023355232020003 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DMPE131Inflator.h * This is a subclass of the DMPInflator which knows how to handle DMP over * E1.31 messages. * Copyright (C) 2009 Simon Newton */ #ifndef LIBS_ACN_DMPE131INFLATOR_H_ #define LIBS_ACN_DMPE131INFLATOR_H_ #include #include #include "ola/Clock.h" #include "ola/Callback.h" #include "ola/DmxBuffer.h" #include "libs/acn/DMPInflator.h" namespace ola { namespace acn { class DMPE131Inflator: public DMPInflator { friend class DMPE131InflatorTest; public: explicit DMPE131Inflator(bool ignore_preview): DMPInflator(), m_ignore_preview(ignore_preview) { } ~DMPE131Inflator(); bool SetHandler(uint16_t universe, ola::DmxBuffer *buffer, uint8_t *priority, ola::Callback0 *handler); bool RemoveHandler(uint16_t universe); void RegisteredUniverses(std::vector *universes); protected: virtual bool HandlePDUData(uint32_t vector, const HeaderSet &headers, const uint8_t *data, unsigned int pdu_len); private: typedef struct { ola::acn::CID cid; uint8_t sequence; TimeStamp last_heard_from; DmxBuffer buffer; } dmx_source; typedef struct { DmxBuffer *buffer; Callback0 *closure; uint8_t active_priority; uint8_t *priority; std::vector sources; } universe_handler; typedef std::map UniverseHandlers; UniverseHandlers m_handlers; bool m_ignore_preview; ola::Clock m_clock; bool TrackSourceIfRequired(universe_handler *universe_data, const HeaderSet &headers, DmxBuffer **buffer); // The max number of sources we'll track per universe. static const uint8_t MAX_MERGE_SOURCES = 6; // The max merge priority. static const uint8_t MAX_E131_PRIORITY = 200; // ignore packets that differ by less than this amount from the last one static const int8_t SEQUENCE_DIFF_THRESHOLD = -20; // expire sources after 2.5s static const TimeInterval EXPIRY_INTERVAL; }; } // namespace acn } // namespace ola #endif // LIBS_ACN_DMPE131INFLATOR_H_ ola-0.10.5.nojsmin/libs/acn/DMPE131Inflator.cpp0000644000175000017500000002636413023355232020340 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DMPE131Inflator.cpp * The Inflator for the DMP PDUs * Copyright (C) 2007 Simon Newton */ #include #include #include #include #include #include "ola/Logging.h" #include "libs/acn/DMPE131Inflator.h" #include "libs/acn/DMPHeader.h" #include "libs/acn/DMPPDU.h" namespace ola { namespace acn { using ola::Callback0; using ola::acn::CID; using ola::io::OutputStream; using std::map; using std::pair; using std::vector; const TimeInterval DMPE131Inflator::EXPIRY_INTERVAL(2500000); DMPE131Inflator::~DMPE131Inflator() { UniverseHandlers::iterator iter; for (iter = m_handlers.begin(); iter != m_handlers.end(); ++iter) { delete iter->second.closure; } m_handlers.clear(); } /* * Handle a DMP PDU for E1.31. */ bool DMPE131Inflator::HandlePDUData(uint32_t vector, const HeaderSet &headers, const uint8_t *data, unsigned int pdu_len) { if (vector != ola::acn::DMP_SET_PROPERTY_VECTOR) { OLA_INFO << "not a set property msg: " << vector; return true; } E131Header e131_header = headers.GetE131Header(); UniverseHandlers::iterator universe_iter = m_handlers.find(e131_header.Universe()); if (e131_header.PreviewData() && m_ignore_preview) { OLA_DEBUG << "Ignoring preview data"; return true; } if (universe_iter == m_handlers.end()) return true; DMPHeader dmp_header = headers.GetDMPHeader(); if (!dmp_header.IsVirtual() || dmp_header.IsRelative() || dmp_header.Size() != TWO_BYTES || dmp_header.Type() != RANGE_EQUAL) { OLA_INFO << "malformed E1.31 dmp header " << dmp_header.Header(); return true; } if (e131_header.Priority() > MAX_E131_PRIORITY) { OLA_INFO << "Priority " << static_cast(e131_header.Priority()) << " is greater than the max priority (" << static_cast(MAX_E131_PRIORITY) << "), ignoring data"; return true; } unsigned int available_length = pdu_len; std::auto_ptr address( DecodeAddress(dmp_header.Size(), dmp_header.Type(), data, &available_length)); if (!address.get()) { OLA_INFO << "DMP address parsing failed, the length is probably too small"; return true; } if (address->Increment() != 1) { OLA_INFO << "E1.31 DMP packet with increment " << address->Increment() << ", disarding"; return true; } unsigned int length_remaining = pdu_len - available_length; int start_code = -1; if (e131_header.UsingRev2()) start_code = static_cast(address->Start()); else if (length_remaining && address->Number()) start_code = *(data + available_length); // The only time we want to continue processing a non-0 start code is if it // contains a Terminate message. if (start_code && !e131_header.StreamTerminated()) { OLA_INFO << "Skipping packet with non-0 start code: " << start_code; return true; } DmxBuffer *target_buffer; if (!TrackSourceIfRequired(&universe_iter->second, headers, &target_buffer)) { // no need to continue processing return true; } // Reaching here means that we actually have new data and we should merge. if (target_buffer && start_code == 0) { unsigned int channels = std::min(length_remaining, address->Number()); if (e131_header.UsingRev2()) target_buffer->Set(data + available_length, channels); else target_buffer->Set(data + available_length + 1, channels - 1); } if (universe_iter->second.priority) *universe_iter->second.priority = universe_iter->second.active_priority; // merge the sources switch (universe_iter->second.sources.size()) { case 0: universe_iter->second.buffer->Reset(); break; case 1: universe_iter->second.buffer->Set( universe_iter->second.sources[0].buffer); universe_iter->second.closure->Run(); break; default: // HTP Merge universe_iter->second.buffer->Reset(); std::vector::const_iterator source_iter = universe_iter->second.sources.begin(); for (; source_iter != universe_iter->second.sources.end(); ++source_iter) universe_iter->second.buffer->HTPMerge(source_iter->buffer); universe_iter->second.closure->Run(); } return true; } /* * Set the closure to be called when we receive data for this universe. * @param universe the universe to register the handler for * @param buffer the DmxBuffer to update with the data * @param handler the Callback0 to call when there is data for this universe. * Ownership of the closure is transferred to the node. */ bool DMPE131Inflator::SetHandler(uint16_t universe, ola::DmxBuffer *buffer, uint8_t *priority, ola::Callback0 *closure) { if (!closure || !buffer) return false; UniverseHandlers::iterator iter = m_handlers.find(universe); if (iter == m_handlers.end()) { universe_handler handler; handler.buffer = buffer; handler.closure = closure; handler.active_priority = 0; handler.priority = priority; m_handlers[universe] = handler; } else { Callback0 *old_closure = iter->second.closure; iter->second.closure = closure; iter->second.buffer = buffer; iter->second.priority = priority; delete old_closure; } return true; } /* * Remove the handler for this universe * @param universe the universe handler to remove * @param true if removed, false if it didn't exist */ bool DMPE131Inflator::RemoveHandler(uint16_t universe) { UniverseHandlers::iterator iter = m_handlers.find(universe); if (iter != m_handlers.end()) { Callback0 *old_closure = iter->second.closure; m_handlers.erase(iter); delete old_closure; return true; } return false; } /** * Get the list of registered universes * @param universes a pointer to a vector which is populated with the list of * universes that have handlers installed. */ void DMPE131Inflator::RegisteredUniverses(vector *universes) { universes->clear(); UniverseHandlers::iterator iter; for (iter = m_handlers.begin(); iter != m_handlers.end(); ++iter) { universes->push_back(iter->first); } } /* * Check if this source is operating at the highest priority for this universe. * This takes care of tracking all sources for a universe at the active * priority. * @param universe_data the universe_handler struct for this universe, * @param HeaderSet the set of headers in this packet * @param buffer, if set to a non-NULL pointer, the caller should copy the data * in the buffer. * @returns true if we should remerge the data, false otherwise. */ bool DMPE131Inflator::TrackSourceIfRequired( universe_handler *universe_data, const HeaderSet &headers, DmxBuffer **buffer) { *buffer = NULL; // default the buffer to NULL ola::TimeStamp now; m_clock.CurrentTime(&now); const E131Header &e131_header = headers.GetE131Header(); uint8_t priority = e131_header.Priority(); vector &sources = universe_data->sources; vector::iterator iter = sources.begin(); while (iter != sources.end()) { if (iter->cid != headers.GetRootHeader().GetCid()) { TimeStamp expiry_time = iter->last_heard_from + EXPIRY_INTERVAL; if (now > expiry_time) { OLA_INFO << "source " << iter->cid.ToString() << " has expired"; iter = sources.erase(iter); continue; } } iter++; } if (sources.empty()) universe_data->active_priority = 0; for (iter = sources.begin(); iter != sources.end(); ++iter) { if (iter->cid == headers.GetRootHeader().GetCid()) break; } if (iter == sources.end()) { // This is an untracked source if (e131_header.StreamTerminated() || priority < universe_data->active_priority) return false; if (priority > universe_data->active_priority) { OLA_INFO << "Raising priority for universe " << e131_header.Universe() << " from " << static_cast(universe_data->active_priority) << " to " << static_cast(priority); sources.clear(); universe_data->active_priority = priority; } if (sources.size() == MAX_MERGE_SOURCES) { // TODO(simon): flag this in the export map OLA_WARN << "Max merge sources reached for universe " << e131_header.Universe() << ", " << headers.GetRootHeader().GetCid().ToString() << " won't be tracked"; return false; } else { OLA_INFO << "Added new E1.31 source: " << headers.GetRootHeader().GetCid().ToString(); dmx_source new_source; new_source.cid = headers.GetRootHeader().GetCid(); new_source.sequence = e131_header.Sequence(); new_source.last_heard_from = now; iter = sources.insert(sources.end(), new_source); *buffer = &iter->buffer; return true; } } else { // We already know about this one, check the seq # int8_t seq_diff = static_cast(e131_header.Sequence() - iter->sequence); if (seq_diff <= 0 && seq_diff > SEQUENCE_DIFF_THRESHOLD) { OLA_INFO << "Old packet received, ignoring, this # " << static_cast(e131_header.Sequence()) << ", last " << static_cast(iter->sequence); return false; } iter->sequence = e131_header.Sequence(); if (e131_header.StreamTerminated()) { OLA_INFO << "CID " << headers.GetRootHeader().GetCid().ToString() << " sent a termination for universe " << e131_header.Universe(); sources.erase(iter); if (sources.empty()) universe_data->active_priority = 0; // We need to trigger a merge here else the buffer will be stale, we keep // the buffer as NULL though so we don't use the data. return true; } iter->last_heard_from = now; if (priority < universe_data->active_priority) { if (sources.size() == 1) { universe_data->active_priority = priority; } else { sources.erase(iter); return true; } } else if (priority > universe_data->active_priority) { // new active priority universe_data->active_priority = priority; if (sources.size() != 1) { // clear all sources other than this one dmx_source this_source = *iter; sources.clear(); iter = sources.insert(sources.end(), this_source); } } *buffer = &iter->buffer; return true; } } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/UDPTransport.h0000644000175000017500000000630313023355232017670 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * UDPTransport.h * Interface for the UDPTransport class * Copyright (C) 2007 Simon Newton */ #ifndef LIBS_ACN_UDPTRANSPORT_H_ #define LIBS_ACN_UDPTRANSPORT_H_ #include "ola/acn/ACNPort.h" #include "ola/network/IPV4Address.h" #include "ola/network/Socket.h" #include "libs/acn/PDU.h" #include "libs/acn/PreamblePacker.h" #include "libs/acn/Transport.h" namespace ola { namespace acn { /* * The OutgoingUDPTransport is a small shim that provides the options to * UDPTransportImpl. */ class OutgoingUDPTransport: public OutgoingTransport { public: OutgoingUDPTransport(class OutgoingUDPTransportImpl *impl, const ola::network::IPV4Address &destination, uint16_t port = ola::acn::ACN_PORT) : m_impl(impl), m_destination(destination, port) { } ~OutgoingUDPTransport() {} bool Send(const PDUBlock &pdu_block); private: class OutgoingUDPTransportImpl *m_impl; ola::network::IPV4SocketAddress m_destination; OutgoingUDPTransport(const OutgoingUDPTransport&); OutgoingUDPTransport& operator=(const OutgoingUDPTransport&); }; /** * OutgoingUDPTransportImpl is the class that actually does the sending. */ class OutgoingUDPTransportImpl { public: OutgoingUDPTransportImpl(ola::network::UDPSocket *socket, PreamblePacker *packer = NULL) : m_socket(socket), m_packer(packer), m_free_packer(false) { if (!m_packer) { m_packer = new PreamblePacker(); m_free_packer = true; } } ~OutgoingUDPTransportImpl() { if (m_free_packer) delete m_packer; } bool Send(const PDUBlock &pdu_block, const ola::network::IPV4SocketAddress &destination); private: ola::network::UDPSocket *m_socket; PreamblePacker *m_packer; bool m_free_packer; }; /** * IncomingUDPTransport is responsible for receiving over UDP * TODO(simon): pass the socket as an argument to receive so we can reuse the * transport for multiple sockets. */ class IncomingUDPTransport { public: IncomingUDPTransport(ola::network::UDPSocket *socket, class BaseInflator *inflator); ~IncomingUDPTransport() { if (m_recv_buffer) delete[] m_recv_buffer; } void Receive(); private: ola::network::UDPSocket *m_socket; class BaseInflator *m_inflator; uint8_t *m_recv_buffer; }; } // namespace acn } // namespace ola #endif // LIBS_ACN_UDPTRANSPORT_H_ ola-0.10.5.nojsmin/libs/acn/RootPDU.h0000644000175000017500000000423213023355232016616 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RootPDU.h * Interface for the RootPDU class * Copyright (C) 2007 Simon Newton */ #ifndef LIBS_ACN_ROOTPDU_H_ #define LIBS_ACN_ROOTPDU_H_ #include #include "ola/acn/CID.h" #include "ola/io/IOStack.h" #include "libs/acn/PDU.h" namespace ola { namespace acn { class RootPDU: public PDU { public: explicit RootPDU(unsigned int vector): PDU(vector), m_block(NULL), m_block_size(0) {} RootPDU(unsigned int vector, const ola::acn::CID &cid, const PDUBlock *block): PDU(vector), m_cid(cid), m_block(block) { m_block_size = block ? block->Size() : 0; } ~RootPDU() {} unsigned int HeaderSize() const { return ola::acn::CID::CID_LENGTH; } unsigned int DataSize() const { return m_block_size; } bool PackHeader(uint8_t *data, unsigned int *length) const; bool PackData(uint8_t *data, unsigned int *length) const; void PackHeader(ola::io::OutputStream *stream) const; void PackData(ola::io::OutputStream *stream) const; const ola::acn::CID &Cid() const { return m_cid; } const ola::acn::CID &Cid(const ola::acn::CID &cid) { return m_cid = cid; } void SetBlock(const PDUBlock *block); static void PrependPDU(ola::io::IOStack *stack, uint32_t vector, const ola::acn::CID &cid); private: ola::acn::CID m_cid; const PDUBlock *m_block; unsigned int m_block_size; }; } // namespace acn } // namespace ola #endif // LIBS_ACN_ROOTPDU_H_ ola-0.10.5.nojsmin/libs/acn/E131DiscoveryInflator.cpp0000644000175000017500000000376613023355232021670 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E131DiscoveryInflator.cpp * An inflator for E1.31 discovery messages. * Copyright (C) 2014 Simon Newton */ #include #include "ola/Logging.h" #include "ola/base/Macro.h" #include "libs/acn/E131DiscoveryInflator.h" namespace ola { namespace acn { using std::vector; unsigned int E131DiscoveryInflator::InflatePDUBlock(HeaderSet *headers, const uint8_t *data, unsigned int len) { if (!m_page_callback.get()) { return len; } PACK( struct page_header { uint8_t page_number; uint8_t last_page; }); STATIC_ASSERT(sizeof(page_header) == 2); page_header header; if (len < sizeof(header)) { OLA_WARN << "Universe Discovery packet is too small: " << len; return len; } memcpy(reinterpret_cast(&header), data, sizeof(header)); DiscoveryPage page(header.page_number, header.last_page); for (const uint8_t *ptr = data + sizeof(header); ptr != data + len; ptr += 2) { uint16_t universe; memcpy(reinterpret_cast(&universe), ptr, sizeof(universe)); page.universes.push_back(ola::network::NetworkToHost(universe)); } m_page_callback->Run(*headers, page); return len; } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/DMPInflator.h0000644000175000017500000000320513023355232017440 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DMPInflator.h * Interface for the DMPInflator class. * Copyright (C) 2009 Simon Newton */ #ifndef LIBS_ACN_DMPINFLATOR_H_ #define LIBS_ACN_DMPINFLATOR_H_ #include "ola/acn/ACNVectors.h" #include "libs/acn/BaseInflator.h" #include "libs/acn/DMPHeader.h" namespace ola { namespace acn { class DMPInflator: public BaseInflator { friend class DMPInflatorTest; public: DMPInflator(): BaseInflator(PDU::ONE_BYTE), m_last_header_valid(false) { } virtual ~DMPInflator() {} uint32_t Id() const { return ola::acn::VECTOR_E131_DATA; } protected: bool DecodeHeader(HeaderSet *headers, const uint8_t *data, unsigned int len, unsigned int *bytes_used); void ResetHeaderField(); private: DMPHeader m_last_header; bool m_last_header_valid; }; } // namespace acn } // namespace ola #endif // LIBS_ACN_DMPINFLATOR_H_ ola-0.10.5.nojsmin/libs/acn/DMPAddressTest.cpp0000644000175000017500000001640013023355232020443 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DMPAddressTest.cpp * Test fixture for the DMPAddress class * Copyright (C) 2005 Simon Newton */ #include #include #include "ola/network/NetworkUtils.h" #include "libs/acn/PDUTestCommon.h" #include "libs/acn/DMPAddress.h" #include "ola/testing/TestUtils.h" namespace ola { namespace acn { using ola::network::NetworkToHost; class DMPAddressTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(DMPAddressTest); CPPUNIT_TEST(testAddress); CPPUNIT_TEST(testRangeAddress); CPPUNIT_TEST(testAddressData); CPPUNIT_TEST_SUITE_END(); public: void testAddress(); void testRangeAddress(); void testAddressData(); private: void checkAddress( const BaseDMPAddress *address, unsigned int start, unsigned int increment, unsigned int number, unsigned int size, dmp_address_size address_size, bool is_range); }; CPPUNIT_TEST_SUITE_REGISTRATION(DMPAddressTest); /* * Check the properties match, pack the address, decode it, and check the * decoded address matches the first one. */ void DMPAddressTest::checkAddress( const BaseDMPAddress *address, unsigned int start, unsigned int increment, unsigned int number, unsigned int size, dmp_address_size address_size, bool is_range) { OLA_ASSERT_EQ(size, address->Size()); OLA_ASSERT_EQ(address_size, address->AddressSize()); OLA_ASSERT_EQ(is_range, address->IsRange()); OLA_ASSERT_EQ(start, address->Start()); OLA_ASSERT_EQ(increment, address->Increment()); OLA_ASSERT_EQ(number, address->Number()); unsigned int length = address->Size(); uint8_t *buffer = new uint8_t[length]; OLA_ASSERT(address->Pack(buffer, &length)); OLA_ASSERT_EQ(size, length); const BaseDMPAddress *addr = DecodeAddress( address_size, is_range ? RANGE_SINGLE: NON_RANGE, buffer, &length); OLA_ASSERT_EQ(size, length); OLA_ASSERT_EQ(start, address->Start()); OLA_ASSERT_EQ(increment, address->Increment()); OLA_ASSERT_EQ(number, address->Number()); length--; OLA_ASSERT_FALSE(DecodeAddress(address_size, is_range ? RANGE_SINGLE: NON_RANGE, buffer, &length)); length = 0; OLA_ASSERT_FALSE(DecodeAddress(address_size, is_range ? RANGE_SINGLE: NON_RANGE, buffer, &length)); delete[] buffer; delete addr; } /* * Test that addresses work. */ void DMPAddressTest::testAddress() { OneByteDMPAddress addr1(10); checkAddress(&addr1, 10, 0, 1, 1, ONE_BYTES, false); TwoByteDMPAddress addr2(1024); checkAddress(&addr2, 1024, 0, 1, 2, TWO_BYTES, false); FourByteDMPAddress addr3(66000); checkAddress(&addr3, 66000, 0, 1, 4, FOUR_BYTES, false); const BaseDMPAddress *addr4 = NewSingleAddress(10); checkAddress(addr4, 10, 0, 1, 1, ONE_BYTES, false); delete addr4; const BaseDMPAddress *addr5 = NewSingleAddress(1024); checkAddress(addr5, 1024, 0, 1, 2, TWO_BYTES, false); delete addr5; const BaseDMPAddress *addr6 = NewSingleAddress(66000); checkAddress(addr6, 66000, 0, 1, 4, FOUR_BYTES, false); delete addr6; } /* * Test that Ranged Addresses work */ void DMPAddressTest::testRangeAddress() { uint8_t buffer[12]; uint16_t *p = reinterpret_cast(buffer); uint32_t *pp = reinterpret_cast(buffer); unsigned int length = sizeof(buffer); OneByteRangeDMPAddress addr1(10, 2, 4); checkAddress(&addr1, 10, 2, 4, 3, ONE_BYTES, true); OLA_ASSERT(addr1.Pack(buffer, &length)); OLA_ASSERT_EQ(addr1.Size(), length); OLA_ASSERT_EQ((uint8_t) 10, buffer[0]); OLA_ASSERT_EQ((uint8_t) 2, buffer[1]); OLA_ASSERT_EQ((uint8_t) 4, buffer[2]); length = sizeof(buffer); TwoByteRangeDMPAddress addr2(1024, 2, 99); checkAddress(&addr2, 1024, 2, 99, 6, TWO_BYTES, true); OLA_ASSERT(addr2.Pack(buffer, &length)); OLA_ASSERT_EQ(addr2.Size(), length); OLA_ASSERT_EQ((uint16_t) 1024, NetworkToHost(*p++)); OLA_ASSERT_EQ((uint16_t) 2, NetworkToHost(*p++)); OLA_ASSERT_EQ((uint16_t) 99, NetworkToHost(*p)); length = sizeof(buffer); FourByteRangeDMPAddress addr3(66000, 2, 100); checkAddress(&addr3, 66000, 2, 100, 12, FOUR_BYTES, true); OLA_ASSERT(addr3.Pack(buffer, &length)); OLA_ASSERT_EQ(addr3.Size(), length); OLA_ASSERT_EQ((uint32_t) 66000, NetworkToHost(*pp++)); OLA_ASSERT_EQ((uint32_t) 2, NetworkToHost(*pp++)); OLA_ASSERT_EQ((uint32_t) 100, NetworkToHost(*pp)); const BaseDMPAddress *addr4 = NewRangeAddress(10, 1, 10); length = sizeof(buffer); checkAddress(addr4, 10, 1, 10, 3, ONE_BYTES, true); OLA_ASSERT(addr4->Pack(buffer, &length)); OLA_ASSERT_EQ(addr4->Size(), length); OLA_ASSERT_EQ((uint8_t) 10, buffer[0]); OLA_ASSERT_EQ((uint8_t) 1, buffer[1]); OLA_ASSERT_EQ((uint8_t) 10, buffer[2]); delete addr4; p = reinterpret_cast(buffer); const BaseDMPAddress *addr5 = NewRangeAddress(10, 1, 1024); length = sizeof(buffer); checkAddress(addr5, 10, 1, 1024, 6, TWO_BYTES, true); OLA_ASSERT(addr5->Pack(buffer, &length)); OLA_ASSERT_EQ(addr5->Size(), length); OLA_ASSERT_EQ((uint16_t) 10, NetworkToHost(*p++)); OLA_ASSERT_EQ((uint16_t) 1, NetworkToHost(*p++)); OLA_ASSERT_EQ((uint16_t) 1024, NetworkToHost(*p)); delete addr5; pp = reinterpret_cast(buffer); const BaseDMPAddress *addr6 = NewRangeAddress(66000, 1, 1024); length = sizeof(buffer); checkAddress(addr6, 66000, 1, 1024, 12, FOUR_BYTES, true); OLA_ASSERT(addr6->Pack(buffer, &length)); OLA_ASSERT_EQ(addr6->Size(), length); OLA_ASSERT_EQ((uint32_t) 66000, NetworkToHost(*pp++)); OLA_ASSERT_EQ((uint32_t) 1, NetworkToHost(*pp++)); OLA_ASSERT_EQ((uint32_t) 1024, NetworkToHost(*pp)); delete addr6; } /* * test that AddressData objects work */ void DMPAddressTest::testAddressData() { uint8_t buffer[12]; unsigned int length = sizeof(buffer); OneByteDMPAddress addr1(10); DMPAddressData chunk(&addr1, NULL, 0); OLA_ASSERT_EQ((const OneByteDMPAddress*) &addr1, chunk.Address()); OLA_ASSERT_EQ((const uint8_t*) NULL, chunk.Data()); OLA_ASSERT_EQ((unsigned int) 1, chunk.Size()); OLA_ASSERT_FALSE(chunk.Pack(buffer, &length)); length = sizeof(buffer); TwoByteRangeDMPAddress addr2(10, 2, 10); DMPAddressData chunk2(&addr2, NULL, 0); OLA_ASSERT_EQ((const TwoByteRangeDMPAddress*) &addr2, chunk2.Address()); OLA_ASSERT_EQ((const uint8_t*) NULL, chunk2.Data()); OLA_ASSERT_EQ((unsigned int) 6, chunk2.Size()); OLA_ASSERT_FALSE(chunk2.Pack(buffer, &length)); } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/E131Inflator.cpp0000644000175000017500000000771513023355232017776 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E131Inflator.cpp * The Inflator for the E1.31 PDUs * Copyright (C) 2007 Simon Newton */ #include #include "ola/Logging.h" #include "ola/network/NetworkUtils.h" #include "libs/acn/E131Inflator.h" namespace ola { namespace acn { using ola::network::NetworkToHost; /* * Decode the E1.31 headers. If data is null we're expected to use the last * header we got. * @param headers the HeaderSet to add to * @param data a pointer to the data * @param length length of the data * @returns true if successful, false otherwise */ bool E131Inflator::DecodeHeader(HeaderSet *headers, const uint8_t *data, unsigned int length, unsigned int *bytes_used) { if (data) { // the header bit was set, decode it if (length >= sizeof(E131Header::e131_pdu_header)) { E131Header::e131_pdu_header raw_header; memcpy(&raw_header, data, sizeof(E131Header::e131_pdu_header)); raw_header.source[E131Header::SOURCE_NAME_LEN - 1] = 0x00; E131Header header( raw_header.source, raw_header.priority, raw_header.sequence, NetworkToHost(raw_header.universe), raw_header.options & E131Header::PREVIEW_DATA_MASK, raw_header.options & E131Header::STREAM_TERMINATED_MASK); m_last_header = header; m_last_header_valid = true; headers->SetE131Header(header); *bytes_used = sizeof(E131Header::e131_pdu_header); return true; } *bytes_used = 0; return false; } // use the last header if it exists *bytes_used = 0; if (!m_last_header_valid) { OLA_WARN << "Missing E131 Header data"; return false; } headers->SetE131Header(m_last_header); return true; } /* * Decode the E1.31 headers. If data is null we're expected to use the last * header we got. * @param headers the HeaderSet to add to * @param data a pointer to the data * @param length length of the data * @returns true if successful, false otherwise */ bool E131InflatorRev2::DecodeHeader(HeaderSet *headers, const uint8_t *data, unsigned int length, unsigned int *bytes_used) { if (data) { // the header bit was set, decode it if (length >= sizeof(E131Rev2Header::e131_rev2_pdu_header)) { E131Rev2Header::e131_rev2_pdu_header raw_header; memcpy(&raw_header, data, sizeof(E131Rev2Header::e131_rev2_pdu_header)); raw_header.source[E131Rev2Header::REV2_SOURCE_NAME_LEN - 1] = 0x00; E131Rev2Header header(raw_header.source, raw_header.priority, raw_header.sequence, NetworkToHost(raw_header.universe)); m_last_header = header; m_last_header_valid = true; headers->SetE131Header(header); *bytes_used = sizeof(E131Rev2Header::e131_rev2_pdu_header); return true; } *bytes_used = 0; return false; } // use the last header if it exists *bytes_used = 0; if (!m_last_header_valid) { OLA_WARN << "Missing E131 Header data"; return false; } headers->SetE131Header(m_last_header); return true; } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/E131PDUTest.cpp0000644000175000017500000001164313023355232017503 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E131PDUTest.cpp * Test fixture for the E131PDU class * Copyright (C) 2005 Simon Newton */ #include #include #include #include "ola/network/NetworkUtils.h" #include "libs/acn/PDUTestCommon.h" #include "libs/acn/E131PDU.h" #include "ola/testing/TestUtils.h" namespace ola { namespace acn { using ola::network::HostToNetwork; using std::string; class E131PDUTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(E131PDUTest); CPPUNIT_TEST(testSimpleRev2E131PDU); CPPUNIT_TEST(testSimpleE131PDU); CPPUNIT_TEST(testNestedE131PDU); CPPUNIT_TEST_SUITE_END(); public: void testSimpleRev2E131PDU(); void testSimpleE131PDU(); void testNestedE131PDU(); private: static const unsigned int TEST_VECTOR; }; CPPUNIT_TEST_SUITE_REGISTRATION(E131PDUTest); const unsigned int E131PDUTest::TEST_VECTOR = 39; /* * Test that packing a E131PDU without data works. */ void E131PDUTest::testSimpleRev2E131PDU() { const string source = "foo source"; E131Rev2Header header(source, 1, 2, 6000); E131PDU pdu(TEST_VECTOR, header, NULL); OLA_ASSERT_EQ((unsigned int) 36, pdu.HeaderSize()); OLA_ASSERT_EQ((unsigned int) 0, pdu.DataSize()); OLA_ASSERT_EQ((unsigned int) 42, pdu.Size()); unsigned int size = pdu.Size(); uint8_t *data = new uint8_t[size]; unsigned int bytes_used = size; OLA_ASSERT(pdu.Pack(data, &bytes_used)); OLA_ASSERT_EQ((unsigned int) size, bytes_used); // spot check the data OLA_ASSERT_EQ((uint8_t) 0x70, data[0]); OLA_ASSERT_EQ((uint8_t) bytes_used, data[1]); unsigned int actual_value; memcpy(&actual_value, data + 2, sizeof(actual_value)); OLA_ASSERT_EQ((unsigned int) HostToNetwork(TEST_VECTOR), actual_value); OLA_ASSERT_FALSE(memcmp(&data[6], source.data(), source.length())); OLA_ASSERT_EQ((uint8_t) 1, data[6 + E131Rev2Header::REV2_SOURCE_NAME_LEN]); OLA_ASSERT_EQ((uint8_t) 2, data[7 + E131Rev2Header::REV2_SOURCE_NAME_LEN]); OLA_ASSERT_EQ( HostToNetwork((uint16_t) 6000), *(reinterpret_cast( data + 8 + E131Rev2Header::REV2_SOURCE_NAME_LEN))); // test undersized buffer bytes_used = size - 1; OLA_ASSERT_FALSE(pdu.Pack(data, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); // test oversized buffer bytes_used = size + 1; OLA_ASSERT(pdu.Pack(data, &bytes_used)); OLA_ASSERT_EQ((unsigned int) size, bytes_used); delete[] data; } /* * Test that packing a E131PDU without data works. */ void E131PDUTest::testSimpleE131PDU() { const string source = "foo source"; E131Header header(source, 1, 2, 6000, true, true); E131PDU pdu(TEST_VECTOR, header, NULL); OLA_ASSERT_EQ((unsigned int) 71, pdu.HeaderSize()); OLA_ASSERT_EQ((unsigned int) 0, pdu.DataSize()); OLA_ASSERT_EQ((unsigned int) 77, pdu.Size()); unsigned int size = pdu.Size(); uint8_t *data = new uint8_t[size]; unsigned int bytes_used = size; OLA_ASSERT(pdu.Pack(data, &bytes_used)); OLA_ASSERT_EQ((unsigned int) size, bytes_used); // spot check the data OLA_ASSERT_EQ((uint8_t) 0x70, data[0]); OLA_ASSERT_EQ((uint8_t) bytes_used, data[1]); unsigned int actual_value; memcpy(&actual_value, data + 2, sizeof(actual_value)); OLA_ASSERT_EQ((unsigned int) HostToNetwork(TEST_VECTOR), actual_value); OLA_ASSERT_FALSE(memcmp(&data[6], source.data(), source.length())); OLA_ASSERT_EQ((uint8_t) 1, data[6 + E131Header::SOURCE_NAME_LEN]); OLA_ASSERT_EQ((uint8_t) 2, data[9 + E131Header::SOURCE_NAME_LEN]); uint16_t actual_universe; memcpy(&actual_universe, data + 11 + E131Header::SOURCE_NAME_LEN, sizeof(actual_universe)); OLA_ASSERT_EQ(HostToNetwork((uint16_t) 6000), actual_universe); // test undersized buffer bytes_used = size - 1; OLA_ASSERT_FALSE(pdu.Pack(data, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); // test oversized buffer bytes_used = size + 1; OLA_ASSERT(pdu.Pack(data, &bytes_used)); OLA_ASSERT_EQ((unsigned int) size, bytes_used); delete[] data; } /* * Test that packing a E131PDU with nested data works */ void E131PDUTest::testNestedE131PDU() { // TODO(simon): add this test } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/PreamblePacker.cpp0000644000175000017500000000647113023355232020541 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * PreamblePacker.cpp * The PreamblePacker class * Copyright (C) 2007 Simon Newton */ #include #include #include "ola/Callback.h" #include "ola/Logging.h" #include "ola/io/BigEndianStream.h" #include "ola/network/IPV4Address.h" #include "ola/network/NetworkUtils.h" #include "libs/acn/BaseInflator.h" #include "libs/acn/HeaderSet.h" #include "libs/acn/PreamblePacker.h" namespace ola { namespace acn { using ola::network::HostToNetwork; using ola::network::IPV4Address; using ola::io::IOStack; const uint8_t PreamblePacker::ACN_HEADER[] = { 0x00, 0x10, 0x00, 0x00, 0x41, 0x53, 0x43, 0x2d, 0x45, 0x31, 0x2e, 0x31, 0x37, 0x00, 0x00, 0x00 }; const unsigned int PreamblePacker::ACN_HEADER_SIZE = sizeof(ACN_HEADER); const uint8_t PreamblePacker::TCP_ACN_HEADER[] = { 0x00, 0x14, // preamble size 0x00, 0x00, // post amble size 0x41, 0x53, 0x43, 0x2d, 0x45, 0x31, 0x2e, 0x31, 0x37, 0x00, 0x00, 0x00 // For TCP, the next 4 bytes are the block size }; const unsigned int PreamblePacker::TCP_ACN_HEADER_SIZE = sizeof(TCP_ACN_HEADER); /* * Clean up */ PreamblePacker::~PreamblePacker() { if (m_send_buffer) delete[] m_send_buffer; } /* * Pack the PDU block along with the preamble into a memory location. * @param pdu_block the block of pdus to send * @param length the size of the data buffer to send. * @return */ const uint8_t *PreamblePacker::Pack(const PDUBlock &pdu_block, unsigned int *length) { if (!m_send_buffer) Init(); unsigned int size = MAX_DATAGRAM_SIZE - static_cast(sizeof(ACN_HEADER)); if (!pdu_block.Pack(m_send_buffer + sizeof(ACN_HEADER), &size)) { OLA_WARN << "Failed to pack E1.31 PDU"; return NULL; } *length = static_cast(sizeof(ACN_HEADER) + size); return m_send_buffer; } /** * Add the UDP Preamble to an IOStack */ void PreamblePacker::AddUDPPreamble(IOStack *stack) { ola::io::BigEndianOutputStream output(stack); stack->Write(ACN_HEADER, ACN_HEADER_SIZE); } /** * Add the TCP Preamble to an IOStack */ void PreamblePacker::AddTCPPreamble(IOStack *stack) { ola::io::BigEndianOutputStream output(stack); output << stack->Size(); stack->Write(TCP_ACN_HEADER, TCP_ACN_HEADER_SIZE); } /* * Allocate memory for the data. */ void PreamblePacker::Init() { if (!m_send_buffer) { m_send_buffer = new uint8_t[MAX_DATAGRAM_SIZE]; memset(m_send_buffer + sizeof(ACN_HEADER), 0, MAX_DATAGRAM_SIZE - sizeof(ACN_HEADER)); memcpy(m_send_buffer, ACN_HEADER, sizeof(ACN_HEADER)); } } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/RDMInflator.cpp0000644000175000017500000000500413023355232017774 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RDMInflator.cpp * The Inflator for the RDM PDUs * Copyright (C) 2011 Simon Newton */ #include #include #include "ola/Logging.h" #include "ola/rdm/RDMCommand.h" #include "libs/acn/RDMInflator.h" namespace ola { namespace acn { using std::string; /** * Create a new RDM inflator */ RDMInflator::RDMInflator() : BaseInflator(PDU::ONE_BYTE) { } /** * Set a RDMHandler to run when receiving a RDM message. * @param handler the callback to invoke when there is rdm data for this * universe. */ void RDMInflator::SetRDMHandler(RDMMessageHandler *handler) { m_rdm_handler.reset(handler); } /* * Decode the RDM 'header', which is 0 bytes in length. * @param headers the HeaderSet to add to * @param data a pointer to the data * @param length length of the data * @returns true if successful, false otherwise */ bool RDMInflator::DecodeHeader(HeaderSet *, const uint8_t*, unsigned int, unsigned int *bytes_used) { *bytes_used = 0; return true; } /* * Handle a DMP PDU for E1.33. */ bool RDMInflator::HandlePDUData(uint32_t vector, const HeaderSet &headers, const uint8_t *data, unsigned int pdu_len) { if (vector != VECTOR_RDMNET_DATA) { OLA_INFO << "Not a RDM message, vector was " << vector; return true; } string rdm_message(reinterpret_cast(&data[0]), pdu_len); E133Header e133_header = headers.GetE133Header(); if (m_rdm_handler.get()) { m_rdm_handler->Run(&headers.GetTransportHeader(), &e133_header, rdm_message); } else { OLA_WARN << "No RDM handler defined!"; } return true; } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/E131PDU.cpp0000644000175000017500000001121013023355232016631 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E131PDU.cpp * The E131PDU * Copyright (C) 2007 Simon Newton */ #include #include "ola/Logging.h" #include "ola/base/Array.h" #include "ola/network/NetworkUtils.h" #include "ola/strings/Utils.h" #include "libs/acn/DMPPDU.h" #include "libs/acn/E131PDU.h" namespace ola { namespace acn { using ola::io::OutputStream; using ola::network::HostToNetwork; /* * Size of the header portion. */ unsigned int E131PDU::HeaderSize() const { if (m_header.UsingRev2()) return sizeof(E131Rev2Header::e131_rev2_pdu_header); else return sizeof(E131Header::e131_pdu_header); } /* * Size of the data portion */ unsigned int E131PDU::DataSize() const { if (m_dmp_pdu) return m_dmp_pdu->Size(); if (m_data) return m_data_size; return 0; } /* * Pack the header portion. */ bool E131PDU::PackHeader(uint8_t *data, unsigned int *length) const { unsigned int header_size = HeaderSize(); if (*length < header_size) { OLA_WARN << "E131PDU::PackHeader: buffer too small, got " << *length << " required " << header_size; *length = 0; return false; } if (m_header.UsingRev2()) { E131Rev2Header::e131_rev2_pdu_header header; strings::CopyToFixedLengthBuffer(m_header.Source(), header.source, arraysize(header.source)); header.priority = m_header.Priority(); header.sequence = m_header.Sequence(); header.universe = HostToNetwork(m_header.Universe()); *length = sizeof(E131Rev2Header::e131_rev2_pdu_header); memcpy(data, &header, *length); } else { E131Header::e131_pdu_header header; strings::CopyToFixedLengthBuffer(m_header.Source(), header.source, arraysize(header.source)); header.priority = m_header.Priority(); header.reserved = 0; header.sequence = m_header.Sequence(); header.options = static_cast( (m_header.PreviewData() ? E131Header::PREVIEW_DATA_MASK : 0) | (m_header.StreamTerminated() ? E131Header::STREAM_TERMINATED_MASK : 0)); header.universe = HostToNetwork(m_header.Universe()); *length = sizeof(E131Header::e131_pdu_header); memcpy(data, &header, *length); } return true; } /* * Pack the data portion. */ bool E131PDU::PackData(uint8_t *data, unsigned int *length) const { if (m_dmp_pdu) return m_dmp_pdu->Pack(data, length); if (m_data) { memcpy(data, m_data, m_data_size); *length = m_data_size; return true; } *length = 0; return true; } /* * Pack the header into a buffer. */ void E131PDU::PackHeader(OutputStream *stream) const { if (m_header.UsingRev2()) { E131Rev2Header::e131_rev2_pdu_header header; strings::CopyToFixedLengthBuffer(m_header.Source(), header.source, arraysize(header.source)); header.priority = m_header.Priority(); header.sequence = m_header.Sequence(); header.universe = HostToNetwork(m_header.Universe()); stream->Write(reinterpret_cast(&header), sizeof(E131Rev2Header::e131_rev2_pdu_header)); } else { E131Header::e131_pdu_header header; strings::CopyToFixedLengthBuffer(m_header.Source(), header.source, arraysize(header.source)); header.priority = m_header.Priority(); header.reserved = 0; header.sequence = m_header.Sequence(); header.options = static_cast( (m_header.PreviewData() ? E131Header::PREVIEW_DATA_MASK : 0) | (m_header.StreamTerminated() ? E131Header::STREAM_TERMINATED_MASK : 0)); header.universe = HostToNetwork(m_header.Universe()); stream->Write(reinterpret_cast(&header), sizeof(E131Header::e131_pdu_header)); } } /* * Pack the data into a buffer */ void E131PDU::PackData(OutputStream *stream) const { if (m_dmp_pdu) { m_dmp_pdu->Write(stream); } else if (m_data) { stream->Write(m_data, m_data_size); } } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/PDUTestCommon.h0000644000175000017500000001356313023355232017772 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * PDUTestCommon.h * Provides a simple PDU class for testing * Copyright (C) 2005 Simon Newton */ #ifndef LIBS_ACN_PDUTESTCOMMON_H_ #define LIBS_ACN_PDUTESTCOMMON_H_ #include "ola/Callback.h" #include "ola/acn/CID.h" #include "ola/io/OutputStream.h" #include "ola/io/IOStack.h" #include "libs/acn/BaseInflator.h" #include "libs/acn/PDU.h" namespace ola { namespace acn { /* * This isn't a PDU at all, it just packs a uint32 for testing. */ class FakePDU: public PDU { public: explicit FakePDU(unsigned int value): PDU(0), m_value(value) {} unsigned int Size() const { return sizeof(m_value); } unsigned int HeaderSize() const { return 0; } unsigned int DataSize() const { return 0; } bool Pack(uint8_t *data, unsigned int *length) const { if (*length < sizeof(m_value)) return false; memcpy(data, &m_value, sizeof(m_value)); *length = sizeof(m_value); return true; } bool PackHeader(OLA_UNUSED uint8_t *data, OLA_UNUSED unsigned int *length) const { return true; } bool PackData(OLA_UNUSED uint8_t *data, OLA_UNUSED unsigned int *length) const { return true; } void Write(ola::io::OutputStream *stream) const { *stream << ola::network::HostToNetwork(m_value); } void PackHeader(ola::io::OutputStream*) const {} void PackData(ola::io::OutputStream*) const {} private: unsigned int m_value; }; /* * A Mock PDU class that can be used for testing. * Mock PDUs have a 4 byte header, and a 4 byte data payload which the inflator * will check is 2x the header value. */ class MockPDU: public PDU { public: MockPDU(unsigned int header, unsigned int value): PDU(TEST_DATA_VECTOR), m_header(header), m_value(value) {} unsigned int HeaderSize() const { return sizeof(m_header); } unsigned int DataSize() const { return sizeof(m_value); } bool PackHeader(uint8_t *data, unsigned int *length) const { if (*length < HeaderSize()) { *length = 0; return false; } memcpy(data, &m_header, sizeof(m_header)); *length = HeaderSize(); return true; } void PackHeader(ola::io::OutputStream *stream) const { stream->Write(reinterpret_cast(&m_header), sizeof(m_header)); } bool PackData(uint8_t *data, unsigned int *length) const { if (*length < DataSize()) { *length = 0; return false; } memcpy(data, &m_value, sizeof(m_value)); *length = DataSize(); return true; } void PackData(ola::io::OutputStream *stream) const { stream->Write(reinterpret_cast(&m_value), sizeof(m_value)); } static void PrependPDU(ola::io::IOStack *stack, unsigned int header, unsigned int data) { stack->Write(reinterpret_cast(&data), sizeof(data)); stack->Write(reinterpret_cast(&header), sizeof(header)); unsigned int vector = ola::network::HostToNetwork(TEST_DATA_VECTOR); stack->Write(reinterpret_cast(&vector), sizeof(vector)); PrependFlagsAndLength( stack, static_cast( sizeof(data) + sizeof(header) + sizeof(vector)), VFLAG_MASK | HFLAG_MASK | DFLAG_MASK); } // This is used to id 'Mock' PDUs in the higher level protocol static const unsigned int TEST_VECTOR = 42; // This is is the vector used by MockPDUs static const unsigned int TEST_DATA_VECTOR = 43; private: unsigned int m_header; unsigned int m_value; }; /* * The inflator the works with MockPDUs. We check that the data = 2 * header */ class MockInflator: public BaseInflator { public: explicit MockInflator(const ola::acn::CID &cid, Callback0 *on_recv = NULL): BaseInflator(), m_cid(cid), m_on_recv(on_recv) {} uint32_t Id() const { return MockPDU::TEST_VECTOR; } protected: void ResetHeaderField() {} bool DecodeHeader(HeaderSet*, const uint8_t *data, unsigned int, unsigned int *bytes_used) { if (data) { *bytes_used = 4; memcpy(&m_last_header, data, sizeof(m_last_header)); } return true; } bool HandlePDUData(uint32_t vector, const HeaderSet &headers, const uint8_t *data, unsigned int pdu_length) { CPPUNIT_ASSERT_EQUAL((uint32_t) MockPDU::TEST_DATA_VECTOR, vector); CPPUNIT_ASSERT_EQUAL((unsigned int) 4, pdu_length); unsigned int *value = (unsigned int*) data; CPPUNIT_ASSERT_EQUAL(m_last_header * 2, *value); if (!m_cid.IsNil()) { // check the CID as well RootHeader root_header = headers.GetRootHeader(); CPPUNIT_ASSERT(m_cid == root_header.GetCid()); } if (m_on_recv) m_on_recv->Run(); return true; } private: ola::acn::CID m_cid; Callback0 *m_on_recv; unsigned int m_last_header; }; } // namespace acn } // namespace ola #endif // LIBS_ACN_PDUTESTCOMMON_H_ ola-0.10.5.nojsmin/libs/acn/E131Inflator.h0000644000175000017500000000464513023355232017442 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E131Inflator.h * Interface for the E131Inflator class. * Copyright (C) 2009 Simon Newton * * This contains two inflators a E131Inflator as per the standard and an * E131InflatorRev2 which implements the revision 2 draft specification. */ #ifndef LIBS_ACN_E131INFLATOR_H_ #define LIBS_ACN_E131INFLATOR_H_ #include "ola/acn/ACNVectors.h" #include "libs/acn/BaseInflator.h" #include "libs/acn/E131Header.h" namespace ola { namespace acn { class E131Inflator: public BaseInflator { friend class E131InflatorTest; public: E131Inflator(): BaseInflator(), m_last_header_valid(false) { } ~E131Inflator() {} uint32_t Id() const { return ola::acn::VECTOR_ROOT_E131; } protected: bool DecodeHeader(HeaderSet *headers, const uint8_t *data, unsigned int len, unsigned int *bytes_used); void ResetHeaderField() { m_last_header_valid = false; } private: E131Header m_last_header; bool m_last_header_valid; }; /* * A Revision 2 version of the inflator. */ class E131InflatorRev2: public BaseInflator { friend class E131InflatorTest; public: E131InflatorRev2(): BaseInflator(), m_last_header_valid(false) { } ~E131InflatorRev2() {} uint32_t Id() const { return ola::acn::VECTOR_ROOT_E131_REV2; } protected: bool DecodeHeader(HeaderSet *headers, const uint8_t *data, unsigned int len, unsigned int *bytes_used); void ResetHeaderField() { m_last_header_valid = false; } private: E131Header m_last_header; bool m_last_header_valid; }; } // namespace acn } // namespace ola #endif // LIBS_ACN_E131INFLATOR_H_ ola-0.10.5.nojsmin/libs/acn/E133Header.h0000644000175000017500000000407013023355232017046 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E133Header.h * The E1.33 Header * Copyright (C) 2011 Simon Newton */ #ifndef LIBS_ACN_E133HEADER_H_ #define LIBS_ACN_E133HEADER_H_ #include #include #include namespace ola { namespace acn { /* * Header for the E133 layer */ class E133Header { public: E133Header() : m_sequence(0), m_endpoint(0) { } E133Header(const std::string &source, uint32_t sequence, uint16_t endpoint) : m_source(source), m_sequence(sequence), m_endpoint(endpoint) { } ~E133Header() {} const std::string Source() const { return m_source; } uint32_t Sequence() const { return m_sequence; } uint16_t Endpoint() const { return m_endpoint; } bool operator==(const E133Header &other) const { return m_source == other.m_source && m_sequence == other.m_sequence && m_endpoint == other.m_endpoint; } enum { SOURCE_NAME_LEN = 64 }; PACK( struct e133_pdu_header_s { char source[SOURCE_NAME_LEN]; uint32_t sequence; uint16_t endpoint; uint8_t reserved; }); typedef struct e133_pdu_header_s e133_pdu_header; private: std::string m_source; uint32_t m_sequence; uint16_t m_endpoint; }; } // namespace acn } // namespace ola #endif // LIBS_ACN_E133HEADER_H_ ola-0.10.5.nojsmin/libs/acn/RootSender.cpp0000644000175000017500000000651613023355232017750 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RootSender.cpp * The RootSender class manages the sending of Root Layer PDUs. * Copyright (C) 2007 Simon Newton */ #include "ola/Logging.h" #include "libs/acn/RootSender.h" #include "libs/acn/Transport.h" namespace ola { namespace acn { using ola::acn::CID; /* * Create a new RootSender * @param cid The CID to send in the Root PDU. */ RootSender::RootSender(const CID &cid) : m_root_pdu(0) { m_root_pdu.Cid(cid); } /* * Encapsulate this PDU in a RootPDU and send it to the destination. * @param vector the vector to use at the root level * @param pdu the pdu to send. * @param transport the OutgoingTransport to use when sending the message. */ bool RootSender::SendPDU(unsigned int vector, const PDU &pdu, OutgoingTransport *transport) { m_working_block.Clear(); m_working_block.AddPDU(&pdu); return SendPDUBlock(vector, m_working_block, transport); } /* * Send a RootPDU with no data. * @param vector the vector to use at the root level * @param transport the OutgoingTransport to use when sending the message. */ bool RootSender::SendEmpty(unsigned int vector, OutgoingTransport *transport) { m_working_block.Clear(); return SendPDUBlock(vector, m_working_block, transport); } /* * This is used to inject a packet from a different CID. * @param vector the vector to use at the root level * @param pdu the pdu to send. * @param cid the cid to send from * @param transport the OutgoingTransport to use when sending the message. */ bool RootSender::SendPDU(unsigned int vector, const PDU &pdu, const CID &cid, OutgoingTransport *transport) { if (!transport) return false; PDUBlock root_block, working_block; working_block.AddPDU(&pdu); RootPDU root_pdu(vector); root_pdu.Cid(cid); root_pdu.SetBlock(&working_block); root_block.AddPDU(&root_pdu); return transport->Send(root_block); } /* * Encapsulate this PDUBlock in a RootPDU and send it to the destination. * @param vector the vector to use at the root level * @param block the PDUBlock to send. * @param transport the OutgoingTransport to use when sending the message. */ bool RootSender::SendPDUBlock(unsigned int vector, const PDUBlock &block, OutgoingTransport *transport) { if (!transport) return false; m_root_pdu.SetVector(vector); m_root_pdu.SetBlock(&block); m_root_block.Clear(); m_root_block.AddPDU(&m_root_pdu); return transport->Send(m_root_block); } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/DMPAddress.h0000644000175000017500000001661313023355232017256 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DMPAddress.h * Defines the DMP property address types * Copyright (C) 2007 Simon Newton */ #ifndef LIBS_ACN_DMPADDRESS_H_ #define LIBS_ACN_DMPADDRESS_H_ #include #include #include "ola/io/OutputStream.h" #include "ola/network/NetworkUtils.h" namespace ola { namespace acn { typedef enum { ONE_BYTES = 0x00, TWO_BYTES = 0x01, FOUR_BYTES = 0x02, RES_BYTES = 0x03 } dmp_address_size; typedef enum { NON_RANGE = 0x00, RANGE_SINGLE = 0x01, RANGE_EQUAL = 0x02, RANGE_MIXED = 0x03, } dmp_address_type; static const unsigned int MAX_TWO_BYTE = 0xffff; static const unsigned int MAX_ONE_BYTE = 0xff; /* * Return the dmp_address_size that corresponds to a type */ template dmp_address_size TypeToDMPSize() { switch (sizeof(type)) { case 1: return ONE_BYTES; case 2: return TWO_BYTES; case 4: return FOUR_BYTES; default: return RES_BYTES; } } /* * Return the number of bytes that correspond to a DMPType */ unsigned int DMPSizeToByteSize(dmp_address_size size); /* * The Base DMPAddress class. * The addresses represented by this class may be actual or virtual & relative * or absolute, ranged or non-ranged. */ class BaseDMPAddress { public: BaseDMPAddress() {} virtual ~BaseDMPAddress() {} // The start address virtual unsigned int Start() const = 0; // The increment virtual unsigned int Increment() const = 0; // The number of properties referenced virtual unsigned int Number() const = 0; // Size of this address structure virtual unsigned int Size() const { return (IsRange() ? 3 : 1) * BaseSize(); } virtual dmp_address_size AddressSize() const = 0; // Pack this address into memory virtual bool Pack(uint8_t *data, unsigned int *length) const = 0; // Write this address to an OutputStream virtual void Write(ola::io::OutputStream *stream) const = 0; // True if this is a range address. virtual bool IsRange() const = 0; protected: virtual unsigned int BaseSize() const = 0; }; /* * These type of addresses only reference one property. */ template class DMPAddress: public BaseDMPAddress { public: explicit DMPAddress(type start): BaseDMPAddress(), m_start(start) {} unsigned int Start() const { return m_start; } unsigned int Increment() const { return 0; } unsigned int Number() const { return 1; } dmp_address_size AddressSize() const { return TypeToDMPSize(); } bool Pack(uint8_t *data, unsigned int *length) const { if (*length < Size()) { *length = 0; return false; } type field = ola::network::HostToNetwork(m_start); memcpy(data, &field, BaseSize()); *length = Size(); return true; } void Write(ola::io::OutputStream *stream) const { *stream << ola::network::HostToNetwork(m_start); } bool IsRange() const { return false; } protected: unsigned int BaseSize() const { return sizeof(type); } private: type m_start; }; typedef DMPAddress OneByteDMPAddress; typedef DMPAddress TwoByteDMPAddress; typedef DMPAddress FourByteDMPAddress; /* * Create a new single address */ const BaseDMPAddress *NewSingleAddress(unsigned int value); /* * These type of addresses reference multiple properties. */ template class RangeDMPAddress: public BaseDMPAddress { public: RangeDMPAddress(type start, type increment, type number): BaseDMPAddress(), m_start(start), m_increment(increment), m_number(number) {} unsigned int Start() const { return m_start; } unsigned int Increment() const { return m_increment; } unsigned int Number() const { return m_number; } dmp_address_size AddressSize() const { return TypeToDMPSize(); } bool Pack(uint8_t *data, unsigned int *length) const { if (*length < Size()) { *length = 0; return false; } type field[3]; field[0] = ola::network::HostToNetwork(m_start); field[1] = ola::network::HostToNetwork(m_increment); field[2] = ola::network::HostToNetwork(m_number); memcpy(data, &field, Size()); *length = Size(); return true; } void Write(ola::io::OutputStream *stream) const { type field[3]; field[0] = ola::network::HostToNetwork(m_start); field[1] = ola::network::HostToNetwork(m_increment); field[2] = ola::network::HostToNetwork(m_number); stream->Write(reinterpret_cast(&field), Size()); } bool IsRange() const { return true; } protected: unsigned int BaseSize() const { return sizeof(type); } private: type m_start, m_increment, m_number; }; typedef RangeDMPAddress OneByteRangeDMPAddress; typedef RangeDMPAddress TwoByteRangeDMPAddress; typedef RangeDMPAddress FourByteRangeDMPAddress; /* * Create a new range address. */ const BaseDMPAddress *NewRangeAddress(unsigned int value, unsigned int increment, unsigned int number); /* * Decode an Address */ const BaseDMPAddress *DecodeAddress(dmp_address_size size, dmp_address_type type, const uint8_t *data, unsigned int *length); /* * A DMPAddressData object, this hold an address/data pair * @param type either DMPAddress<> or RangeDMPAddress<> */ template class DMPAddressData { public: DMPAddressData(const type *address, const uint8_t *data, unsigned int length): m_address(address), m_data(data), m_length(length) {} const type *Address() const { return m_address; } const uint8_t *Data() const { return m_data; } unsigned int Size() const { return m_address->Size() + m_length; } // Pack the data into a buffer bool Pack(uint8_t *data, unsigned int *length) const { if (!m_data) return false; unsigned int total = *length; if (!m_address->Pack(data, length)) { length = 0; return false; } if (total - *length < m_length) { length = 0; return false; } memcpy(data + *length, m_data, m_length); *length += m_length; return true; } void Write(ola::io::OutputStream *stream) const { if (!m_data) return; m_address->Write(stream); stream->Write(m_data, m_length); } private: const type *m_address; const uint8_t *m_data; unsigned int m_length; }; } // namespace acn } // namespace ola #endif // LIBS_ACN_DMPADDRESS_H_ ola-0.10.5.nojsmin/libs/acn/e131_transmit_test.cpp0000644000175000017500000002332513023355232021312 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * e131_transmit_test.cpp * The sends custom E1.31 packets in order to test the implementation of a * remote node. * Copyright (C) 2010 Simon Newton * * The remote node needs to be listening for Universe 1. */ #include #include #include #include "ola/DmxBuffer.h" #include "ola/Logging.h" #include "libs/acn/E131TestFramework.h" using ola::DmxBuffer; using std::string; using std::vector; DmxBuffer BufferFromString(const string &data) { DmxBuffer buffer; buffer.SetFromString(data); return buffer; } DmxBuffer BufferFromValue(uint8_t value) { DmxBuffer buffer; buffer.SetRangeToValue(0, value, ola::DMX_UNIVERSE_SIZE); return buffer; } TestState s1("Single Source Send", new NodeSimpleSend(20), new NodeInactive(), "512 x 20", BufferFromValue(20)); TestState s2("Single Source Timeout", new NodeInactive(), new NodeInactive(), "Loss of data after 2.5s", DmxBuffer()); TestState s3("Single Source Send", new NodeSimpleSend(10), new NodeInactive(), "512 x 10", BufferFromValue(10)); TestState s4("Single Source Terminate", new NodeTerminate(), new NodeInactive(), "Immediate loss of data", DmxBuffer()); TestState s5("Single Source Send", new NodeSimpleSend(30), new NodeInactive(), "512 x 30", BufferFromValue(30)); TestState s6("Single Source Terminate with data", new NodeTerminateWithData(10), new NodeInactive(), "Immediate loss of data, no values of 10", DmxBuffer()); TestState s7("Single Source priority = 201", new NodeSimpleSend(201), new NodeInactive(), "No data, priority > 200 should be ignored", DmxBuffer()); TestState s8("Single Source priority = 100", new NodeSimpleSend(100), new NodeInactive(), "512 x 100", BufferFromValue(100)); TestState s9("Single Source priority = 99", new NodeSimpleSend(99), new NodeInactive(), "512 x 99, missing data indicates a problem when a source reduces" " it's priority", BufferFromValue(99)); // stay in this state for 3s TestState s10("Single Source Timeout", new NodeInactive(), new NodeInactive(), "Loss of data after 2.5s", DmxBuffer()); TestState s11("Single Source Terminate with data", new NodeTerminateWithData(10), new NodeInactive(), "No effect, source should have already timed out", DmxBuffer()); // now test sequence handling TestState s12("Single Source Sequence Test", // 1 in 4 change of sending a packet with 0s rather than 255s new NodeVarySequenceNumber(255, 0, 4), new NodeInactive(), "512x255, any 0s indicate a problem ith seq #", BufferFromValue(255)); TestState s13("Single Source Terminate", new NodeTerminate(), new NodeInactive(), "Immediate loss of data", DmxBuffer()); // now we do the merge tests, this tests a second source appearing with a // priority less than the active one TestState s14("Single Source Send", new NodeSimpleSend(20), new NodeInactive(), "512 x 20", BufferFromValue(20)); TestState s15("Dual Sources with pri 20 & 10", new NodeSimpleSend(20), new NodeSimpleSend(10), "512 x 20, no values of 10 otherwise this indicates a priority " "problem", BufferFromValue(20)); RelaxedTestState s16("Dual Sources with pri 20 & 30", new NodeSimpleSend(20), new NodeSimpleSend(30), "One packet of 512x20, the 512 x 30", BufferFromValue(20), BufferFromValue(30)); RelaxedTestState s17("Dual Sources with pri 20 & 10", new NodeSimpleSend(20), new NodeSimpleSend(10, "100,100,100,100"), "512 x 20, may see single packet with 4 x 100", BufferFromString("100,100,100,100"), BufferFromValue(20)); RelaxedTestState s18("Dual Sources with pri 20 & 20, HTP merge", new NodeSimpleSend(20, "1,1,100,100"), new NodeSimpleSend(20, "100,100,1,1"), "4 x 100 if we HTP merge for arbitration", BufferFromString("1,1,100,100"), BufferFromString("100,100,100,100")); RelaxedTestState s19("Dual Sources with pri 20 & 20, HTP merge", new NodeSimpleSend(20, "1,1,100,0"), new NodeSimpleSend(20, "100,0,1,1"), "[100,1,100,1] if we HTP merge for arbitration", BufferFromString("100,100,100,1"), BufferFromString("100,1,100,1")); // timing is important here OrderedTestState s20("Dual Sources with one timing out", new NodeInactive(), new NodeSimpleSend(20, "100,0,1,1"), "[100,0,1,1] after 2.5s", BufferFromString("100,1,100,1"), BufferFromString("100,0,1,1")); TestState s21("Timeout", new NodeInactive(), new NodeInactive(), "Loss of all data after 2.5s", BufferFromString("100,0,1,1")); // now we test the case where a data arrives from a new source more than the // active priority TestState s22("Single Source Send", new NodeSimpleSend(20), new NodeInactive(), "512 x 20", BufferFromValue(20)); RelaxedTestState s23("Dual Sources with pri 20 & 30", new NodeSimpleSend(20), new NodeSimpleSend(30), "512 x 20, followed by 512 x 30", BufferFromValue(20), BufferFromValue(30)); TestState s24("Both Sources Terminate", new NodeTerminate(), new NodeTerminate(), "Loss of data, may see 512 x 20", DmxBuffer()); // now we test the case where a data arrives from a new source equal to the // active priority TestState s25("Single Source Send", new NodeSimpleSend(20, "20,20,20,20"), new NodeInactive(), "20,20,20,20", BufferFromString("20,20,20,20")); RelaxedTestState s26("Dual Sources with pri 20 & 20", new NodeSimpleSend(20, "20,20,20,20"), new NodeSimpleSend(20, "100,100,100,100"), "[20,20,20,20], then [100,100,100,100]", BufferFromString("20,20,20,20"), BufferFromString("100,100,100,100")); RelaxedTestState s27("Terminate second source", new NodeSimpleSend(20, "20,20,20,20"), new NodeTerminate(), "512 x 20", BufferFromString("100,100,100,100"), BufferFromString("20,20,20,20")); TestState *states[] = {&s1, &s2, &s3, &s4, &s5, &s6, &s7, &s8, &s9, &s10, &s11, &s11, &s12, &s13, &s14, &s15, &s16, &s17, &s18, &s19, &s20, &s21, &s22, &s23, &s24, &s25, &s26, &s27, NULL}; /* * Display the help message */ void DisplayHelp(const char *binary_name) { std::cout << "Usage: " << binary_name << " [--interactive]\n" "\n" "Run the E1.31 Transmit test. This test can run in one of two modes:\n" " * interactive mode. This sends data to the multicast addresses\n" " and a human gets to verify it.\n" " * local mode (default). This starts a local E131Node and sends it data,\n" " verifying against the expected output.\n" "\n" " -h, --help Display this help message and exit.\n" " -i, --interactive Run in interactive mode.\n" << std::endl; } int main(int argc, char* argv[]) { bool interactive_mode = false; ola::InitLogging(ola::OLA_LOG_INFO, ola::OLA_LOG_STDERR); vector test_states; TestState **ptr = states; while (*ptr) test_states.push_back(*ptr++); static struct option long_options[] = { {"interactive", no_argument, 0, 'i'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} }; int option_index = 0; while (1) { int c = getopt_long(argc, argv, "ih", long_options, &option_index); if (c == -1) break; switch (c) { case 0: break; case 'h': DisplayHelp(argv[0]); return 0; case 'i': interactive_mode = true; break; case '?': break; default: break; } } StateManager manager(test_states, interactive_mode); manager.Init(); manager.Run(); return manager.Passed() ? 0 : 1; } ola-0.10.5.nojsmin/libs/acn/DMPPDU.cpp0000644000175000017500000000725413023355232016655 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DMPPDU.cpp * The DMPPDU * Copyright (C) 2007 Simon Newton */ #include "ola/Logging.h" #include "libs/acn/DMPPDU.h" namespace ola { namespace acn { using ola::io::OutputStream; /* * Pack the header portion. */ bool DMPPDU::PackHeader(uint8_t *data, unsigned int *length) const { if (*length < DMPHeader::DMP_HEADER_SIZE) { OLA_WARN << "DMPPDU::PackHeader: buffer too small, got " << *length << " required " << DMPHeader::DMP_HEADER_SIZE; *length = 0; return false; } *data = m_header.Header(); *length = DMPHeader::DMP_HEADER_SIZE; return true; } /* * Pack the header into a buffer. */ void DMPPDU::PackHeader(OutputStream *stream) const { *stream << m_header.Header(); } /* * Create a new Single Address GetProperty PDU. * @param is_virtual set to true if this is a virtual address * @param is_relative set to true if this is a relative address * @param start the start offset * @return A pointer to a DMPGetProperty. */ const DMPPDU *NewDMPGetProperty(bool is_virtual, bool is_relative, unsigned int start) { if (start > MAX_TWO_BYTE) return _CreateDMPGetProperty(is_virtual, is_relative, start); else if (start > MAX_ONE_BYTE) return _CreateDMPGetProperty(is_virtual, is_relative, start); return _CreateDMPGetProperty(is_virtual, is_relative, start); } /* * Create a new range address GetProperty PDU. * @param is_virtual set to true if this is a virtual address * @param is_relative set to true if this is a relative address * @param start the start offset * @param increment the increments between addresses * @param number the number of addresses defined * @return A pointer to a DMPGetProperty. */ const DMPPDU *NewRangeDMPGetProperty( bool is_virtual, bool is_relative, unsigned int start, unsigned int increment, unsigned int number) { if (start > MAX_TWO_BYTE || increment > MAX_TWO_BYTE || number > MAX_TWO_BYTE) return _CreateRangeDMPGetProperty(is_virtual, is_relative, start, increment, number); else if (start > MAX_ONE_BYTE || increment > MAX_ONE_BYTE || number > MAX_ONE_BYTE) return _CreateRangeDMPGetProperty(is_virtual, is_relative, start, increment, number); return _CreateRangeDMPGetProperty(is_virtual, is_relative, start, increment, number); } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/BaseInflatorTest.cpp0000644000175000017500000003101213023355232021062 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * BaseInflatorTest.cpp * Test fixture for the BaseInflator class * Copyright (C) 2005 Simon Newton */ #include #include #include "libs/acn/BaseInflator.h" #include "libs/acn/HeaderSet.h" #include "ola/testing/TestUtils.h" namespace ola { namespace acn { uint8_t PDU_DATA[] = "this is some test data"; class BaseInflatorTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(BaseInflatorTest); CPPUNIT_TEST(testChildInflators); CPPUNIT_TEST(testDecodeLength); CPPUNIT_TEST(testDecodeVector); CPPUNIT_TEST(testInflatePDU); CPPUNIT_TEST(testInflatePDUBlock); CPPUNIT_TEST_SUITE_END(); public: void testChildInflators(); void testDecodeLength(); void testDecodeVector(); void testInflatePDU(); void testInflatePDUBlock(); private: }; class TestInflator: public ola::acn::BaseInflator { public: explicit TestInflator(unsigned int id = 0, PDU::vector_size v_size = PDU::TWO_BYTES) : BaseInflator(v_size), m_id(id), m_blocks_handled(0) {} uint32_t Id() const { return m_id; } unsigned int BlocksHandled() const { return m_blocks_handled; } protected: void ResetHeaderField() {} bool DecodeHeader(HeaderSet*, const uint8_t*, unsigned int, unsigned int *bytes_used) { *bytes_used = 0; return true; } bool HandlePDUData(uint32_t vector, OLA_UNUSED const HeaderSet &headers, const uint8_t *data, unsigned int pdu_length) { OLA_ASSERT_EQ((uint32_t) 289, vector); OLA_ASSERT_EQ((unsigned int) sizeof(PDU_DATA), pdu_length); OLA_ASSERT_FALSE(memcmp(data, PDU_DATA, pdu_length)); m_blocks_handled++; return true; } private: unsigned int m_id; unsigned int m_blocks_handled; }; CPPUNIT_TEST_SUITE_REGISTRATION(BaseInflatorTest); /* * Test that we can setup the child inflators correctly */ void BaseInflatorTest::testChildInflators() { TestInflator inflator; TestInflator inflator1(1); TestInflator inflator2(2); OLA_ASSERT_EQ((uint32_t) 1, inflator1.Id()); OLA_ASSERT_EQ((uint32_t) 2, inflator2.Id()); OLA_ASSERT(inflator.AddInflator(&inflator1)); OLA_ASSERT(inflator.AddInflator(&inflator2)); OLA_ASSERT(&inflator1 == inflator.GetInflator(inflator1.Id())); OLA_ASSERT(&inflator2 == inflator.GetInflator(inflator2.Id())); OLA_ASSERT(NULL == inflator.GetInflator(3)); // Once an inflator is set it can't be changed. OLA_ASSERT_FALSE(inflator.AddInflator(&inflator1)); OLA_ASSERT_FALSE(inflator.AddInflator(&inflator2)); } /* * Test that DecodeLength works */ void BaseInflatorTest::testDecodeLength() { TestInflator inflator; uint8_t data[] = {0, 0, 0, 0}; // the test data unsigned int pdu_length; unsigned int bytes_used = 0; // with the length data set to 0, any length should fail. for (unsigned int i = 0; i <= sizeof(data); i++) { OLA_ASSERT_FALSE(inflator.DecodeLength(data, i, &pdu_length, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); } // Set the length of the pdu to 1, note that as the length includes the // size of the length, vector & header fields, this is less than the number // of bytes required to determine the length and so it fails data[1] = 1; for (unsigned int i = 0; i <= sizeof(data); i++) { OLA_ASSERT_FALSE(inflator.DecodeLength(data, i, &pdu_length, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); } // now set the length to 2, a data length of 0 or 1 should fail, but anything // more than that should return correctly. data[1] = 2; for (unsigned int i = 0; i <= 1; i++) { OLA_ASSERT_FALSE(inflator.DecodeLength(data, i, &pdu_length, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); } for (unsigned int i = 2; i <= sizeof(data) ; i++) { OLA_ASSERT(inflator.DecodeLength(data, i, &pdu_length, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 2, pdu_length); OLA_ASSERT_EQ((unsigned int) 2, bytes_used); } // now check that both bytes are used data[0] = 1; // total length of 258 OLA_ASSERT(inflator.DecodeLength(data, sizeof(data), &pdu_length, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 258, pdu_length); OLA_ASSERT_EQ((unsigned int) 2, bytes_used); // now check that the extend length format works data[0] = BaseInflator::LFLAG_MASK; // with the length data set to 0, any length should fail. data[1] = 0; for (unsigned int i = 0; i <= sizeof(data); i++) { OLA_ASSERT_FALSE(inflator.DecodeLength(data, i, &pdu_length, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); } // Set the length of the pdu to 1, note that as the length includes the // size of the length, vector & header fields, this is less than the number // of bytes required to determine the length and so it fails data[2] = 1; for (unsigned int i = 0; i <= sizeof(data); i++) { OLA_ASSERT_FALSE(inflator.DecodeLength(data, i, &pdu_length, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); } // now set the length to 3, a data length of 0, 1 or 2 should fail, but // anything more than that should return correctly. data[2] = 3; for (unsigned int i = 0; i <= 2; i++) { OLA_ASSERT_FALSE(inflator.DecodeLength(data, i, &pdu_length, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); } for (unsigned int i = 3; i <= sizeof(data) ; i++) { OLA_ASSERT(inflator.DecodeLength(data, i, &pdu_length, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 3, pdu_length); OLA_ASSERT_EQ((unsigned int) 3, bytes_used); } // now check that all 3 bytes are used data[0] = BaseInflator::LFLAG_MASK + 1; data[1] = 0x01; OLA_ASSERT(inflator.DecodeLength(data, sizeof(data), &pdu_length, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 65795, pdu_length); OLA_ASSERT_EQ((unsigned int) 3, bytes_used); } /* * test that DecodeVector works */ void BaseInflatorTest::testDecodeVector() { TestInflator inflator(0, PDU::ONE_BYTE); uint8_t data[] = {1, 2, 3, 4, 5, 6}; // the test data unsigned int vector = 1; unsigned int bytes_used = 0; uint8_t flags = PDU::VFLAG_MASK; OLA_ASSERT_FALSE(inflator.DecodeVector(flags, data, 0, &vector, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, vector); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); data[0] = 42; for (unsigned int i = 1; i < sizeof(data); i++) { OLA_ASSERT(inflator.DecodeVector(flags, data, i, &vector, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 42, vector); OLA_ASSERT_EQ((unsigned int) 1, bytes_used); } // now make sure we can reuse the vector flags = 0; for (unsigned int i = 0; i < sizeof(data); i++) { OLA_ASSERT(inflator.DecodeVector(flags, data, i, &vector, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 42, vector); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); } // resetting doesn't allow us to reuse the vector inflator.ResetPDUFields(); for (unsigned int i = 0; i < sizeof(data); i++) { OLA_ASSERT_FALSE(inflator.DecodeVector(flags, data, i, &vector, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, vector); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); } // now try with a vector size of 2 flags = PDU::VFLAG_MASK; TestInflator inflator2(0, PDU::TWO_BYTES); for (unsigned int i = 0; i < 2; i++) { OLA_ASSERT_FALSE( inflator2.DecodeVector(flags, data, i, &vector, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, vector); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); } data[0] = 0x80; data[1] = 0x21; for (unsigned int i = 2; i < sizeof(data); i++) { OLA_ASSERT(inflator2.DecodeVector(flags, data, i, &vector, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 32801, vector); OLA_ASSERT_EQ((unsigned int) 2, bytes_used); } // now make sure we can reuse the vector flags = 0; for (unsigned int i = 0; i < sizeof(data); i++) { OLA_ASSERT(inflator2.DecodeVector(flags, data, i, &vector, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 32801, vector); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); } // resetting doesn't allow us to reuse the vector inflator2.ResetPDUFields(); for (unsigned int i = 0; i < sizeof(data); i++) { OLA_ASSERT_FALSE( inflator2.DecodeVector(flags, data, i, &vector, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, vector); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); } // now try with a vector size of 4 flags = PDU::VFLAG_MASK; TestInflator inflator4(0, PDU::FOUR_BYTES); for (unsigned int i = 0; i < 4; i++) { OLA_ASSERT_FALSE( inflator4.DecodeVector(flags, data, i, &vector, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, vector); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); } data[0] = 0x01; data[1] = 0x21; data[2] = 0x32; data[3] = 0x45; for (unsigned int i = 4; i < 8; i++) { OLA_ASSERT(inflator4.DecodeVector(flags, data, i, &vector, &bytes_used)); OLA_ASSERT_EQ((uint32_t) 18952773, vector); OLA_ASSERT_EQ((unsigned int) 4, bytes_used); } } /* * Check that we can inflate a PDU */ void BaseInflatorTest::testInflatePDU() { TestInflator inflator; // test with a vector size of 2 HeaderSet header_set; uint8_t flags = PDU::VFLAG_MASK; unsigned int data_size = static_cast(PDU::TWO_BYTES + sizeof(PDU_DATA)); uint8_t *data = new uint8_t[data_size]; // setup the vector data[0] = 0x01; data[1] = 0x21; memcpy(data + PDU::TWO_BYTES, PDU_DATA, sizeof(PDU_DATA)); OLA_ASSERT(inflator.InflatePDU(&header_set, flags, data, data_size)); delete[] data; } /* * Check that we can inflate a PDU block correctly. */ void BaseInflatorTest::testInflatePDUBlock() { TestInflator inflator; // test with a vector size of 2 HeaderSet header_set; const unsigned int length_size = 2; // inflate a single pdu block unsigned int data_size = static_cast( length_size + PDU::TWO_BYTES + sizeof(PDU_DATA)); uint8_t *data = new uint8_t[data_size]; // setup the vector data[0] = PDU::VFLAG_MASK; data[1] = static_cast(data_size); data[2] = 0x01; data[3] = 0x21; memcpy(data + length_size + PDU::TWO_BYTES, PDU_DATA, sizeof(PDU_DATA)); OLA_ASSERT_EQ(data_size, inflator.InflatePDUBlock(&header_set, data, data_size)); OLA_ASSERT_EQ(1u, inflator.BlocksHandled()); delete[] data; // inflate a multi-pdu block data = new uint8_t[2 * data_size]; data[0] = PDU::VFLAG_MASK; data[1] = static_cast(data_size); data[2] = 0x01; data[3] = 0x21; memcpy(data + length_size + PDU::TWO_BYTES, PDU_DATA, sizeof(PDU_DATA)); data[data_size] = PDU::VFLAG_MASK; data[data_size + 1] = static_cast(data_size); data[data_size + 2] = 0x01; data[data_size + 3] = 0x21; memcpy(data + data_size + length_size + PDU::TWO_BYTES, PDU_DATA, sizeof(PDU_DATA)); OLA_ASSERT_EQ( 2 * data_size, inflator.InflatePDUBlock(&header_set, data, 2 * data_size)); delete[] data; OLA_ASSERT_EQ(3u, inflator.BlocksHandled()); // inflate with nested inflators TestInflator child_inflator(289); inflator.AddInflator(&child_inflator); unsigned int pdu_size = data_size + length_size + PDU::TWO_BYTES; data = new uint8_t[pdu_size]; data[0] = PDU::VFLAG_MASK; data[1] = static_cast(pdu_size); data[2] = 0x01; data[3] = 0x21; data[4] = PDU::VFLAG_MASK; data[5] = static_cast(data_size); data[6] = 0x01; data[7] = 0x21; memcpy(data + 2 * (length_size + PDU::TWO_BYTES), PDU_DATA, sizeof(PDU_DATA)); OLA_ASSERT_EQ(pdu_size, inflator.InflatePDUBlock(&header_set, data, pdu_size)); OLA_ASSERT_EQ((unsigned int) 3, inflator.BlocksHandled()); OLA_ASSERT_EQ((unsigned int) 1, child_inflator.BlocksHandled()); delete[] data; } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/CIDTest.cpp0000644000175000017500000000715613023355232017124 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * CIDTest.cpp * Test fixture for the CID class * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include #include #include "ola/acn/CID.h" #include "ola/io/IOQueue.h" #include "ola/io/OutputBuffer.h" #include "ola/testing/TestUtils.h" using ola::acn::CID; using std::string; class CIDTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(CIDTest); CPPUNIT_TEST(testCID); CPPUNIT_TEST(testSetPack); CPPUNIT_TEST(testGenerate); CPPUNIT_TEST(testToString); CPPUNIT_TEST(testFromString); CPPUNIT_TEST(testToOutputBuffer); CPPUNIT_TEST_SUITE_END(); public: void testCID(); void testSetPack(); void testGenerate(); void testToString(); void testFromString(); void testToOutputBuffer(); private: static const uint8_t TEST_DATA[]; }; const uint8_t CIDTest::TEST_DATA[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; CPPUNIT_TEST_SUITE_REGISTRATION(CIDTest); /* * Check that basic assignment & equality works */ void CIDTest::testCID() { CID cid; OLA_ASSERT(cid.IsNil()); CID cid1 = CID::Generate(); OLA_ASSERT_FALSE(cid1.IsNil()); CID cid2 = cid1; OLA_ASSERT(cid2 == cid1); OLA_ASSERT_FALSE(cid2.IsNil()); CID cid3; cid3 = cid1; OLA_ASSERT(cid3 == cid1); OLA_ASSERT_FALSE(cid3.IsNil()); } void CIDTest::testSetPack() { uint8_t buffer[CID::CID_LENGTH]; CID cid = CID::FromData(TEST_DATA); cid.Pack(buffer); OLA_ASSERT_FALSE(memcmp(TEST_DATA, buffer, CID::CID_LENGTH)); } /* * Check that generate works */ void CIDTest::testGenerate() { CID cid1 = CID::Generate(); CID cid2 = CID::Generate(); OLA_ASSERT_NE(cid1, cid2); } /* * Check that ToString works. */ void CIDTest::testToString() { CID cid = CID::FromData(TEST_DATA); string cid_str = cid.ToString(); transform(cid_str.begin(), cid_str.end(), cid_str.begin(), toupper); OLA_ASSERT_EQ(string("00010203-0405-0607-0809-0A0B0C0D0E0F"), cid_str); } /* * Check that from string works. */ void CIDTest::testFromString() { const string uuid = "00010203-0405-0607-0809-0A0B0C0D0E0F"; CID cid = CID::FromString(uuid); string cid_str = cid.ToString(); transform(cid_str.begin(), cid_str.end(), cid_str.begin(), toupper); OLA_ASSERT_EQ(uuid, cid_str); const string bad_uuid = "foo"; cid = CID::FromString(bad_uuid); OLA_ASSERT(cid.IsNil()); } /** * Check writing to an OutputBuffer works. */ void CIDTest::testToOutputBuffer() { ola::io::IOQueue output; const string uuid = "00010203-0405-0607-0809-0A0B0C0D0E0F"; CID cid = CID::FromString(uuid); cid.Write(&output); OLA_ASSERT_EQ(16u, output.Size()); unsigned int size = output.Size(); uint8_t cid_data[size]; OLA_ASSERT_EQ(size, output.Read(cid_data, size)); OLA_ASSERT_DATA_EQUALS(TEST_DATA, sizeof(TEST_DATA), cid_data, size); } ola-0.10.5.nojsmin/libs/acn/RDMPDU.h0000644000175000017500000000212513023355232016314 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RDMPDU.h * The RDMPDU class * Copyright (C) 2012 Simon Newton */ #ifndef LIBS_ACN_RDMPDU_H_ #define LIBS_ACN_RDMPDU_H_ #include #include "libs/acn/PDU.h" namespace ola { namespace acn { class RDMPDU : private PDU { public: static void PrependPDU(ola::io::IOStack *stack); }; } // namespace acn } // namespace ola #endif // LIBS_ACN_RDMPDU_H_ ola-0.10.5.nojsmin/libs/acn/CIDImpl.h0000644000175000017500000000413413023355232016544 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * CIDImpl.h * The actual implementation of a CID. The implementation changes based on * which uuid library is installed. * Copyright (C) 2007 Simon Newton */ #ifndef LIBS_ACN_CIDIMPL_H_ #define LIBS_ACN_CIDIMPL_H_ #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #ifdef HAVE_OSSP_UUID_H #include #else #ifdef HAVE_UUID_UUID_H #include #else #include #endif // HAVE_UUID_UUID_H #endif // HAVE_OSSP_UUID_H #include #include #include "ola/io/OutputBuffer.h" namespace ola { namespace acn { class CIDImpl { public : enum { CIDImpl_LENGTH = 16 }; CIDImpl(); CIDImpl(const CIDImpl& other); ~CIDImpl(); bool IsNil() const; void Pack(uint8_t *buf) const; std::string ToString() const; void Write(ola::io::OutputBufferInterface *output) const; CIDImpl& operator=(const CIDImpl& c1); bool operator==(const CIDImpl& c1) const; bool operator!=(const CIDImpl& c1) const; bool operator<(const CIDImpl& c1) const; static CIDImpl* Generate(); static CIDImpl* FromData(const uint8_t *data); static CIDImpl* FromString(const std::string &cid); private: #ifdef USE_OSSP_UUID uuid_t *m_uuid; explicit CIDImpl(uuid_t *uuid); #else uuid_t m_uuid; explicit CIDImpl(uuid_t uuid); #endif // HAVE_OSSP_UUID }; } // namespace acn } // namespace ola #endif // LIBS_ACN_CIDIMPL_H_ ola-0.10.5.nojsmin/libs/acn/DMPInflator.cpp0000644000175000017500000000406413023355232017777 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DMPInflator.cpp * The Inflator for the DMP PDUs * Copyright (C) 2007 Simon Newton */ #include "ola/Logging.h" #include "libs/acn/DMPInflator.h" namespace ola { namespace acn { /* * Decode the DMP header. If data is null we're expected to use the last * header we got. * @param headers the HeaderSet to add to * @param data a pointer to the data * @param length length of the data * @returns true if successful, false otherwise */ bool DMPInflator::DecodeHeader(HeaderSet *headers, const uint8_t *data, unsigned int length, unsigned int *bytes_used) { if (data) { // the header bit was set, decode it if (length >= DMPHeader::DMP_HEADER_SIZE) { DMPHeader header(*data); m_last_header = header; m_last_header_valid = true; headers->SetDMPHeader(header); *bytes_used = DMPHeader::DMP_HEADER_SIZE; return true; } *bytes_used = 0; return false; } // use the last header if it exists *bytes_used = 0; if (!m_last_header_valid) { OLA_WARN << "Missing DMP Header data"; return false; } headers->SetDMPHeader(m_last_header); return true; } /* * Reset the header field */ void DMPInflator::ResetHeaderField() { m_last_header_valid = false; } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/RootSender.h0000644000175000017500000000427513023355232017415 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RootSender.h * The RootSender class manages the sending of Root Layer PDUs. * Copyright (C) 2007 Simon Newton */ #ifndef LIBS_ACN_ROOTSENDER_H_ #define LIBS_ACN_ROOTSENDER_H_ #include "ola/acn/CID.h" #include "libs/acn/PDU.h" #include "libs/acn/RootPDU.h" #include "libs/acn/Transport.h" namespace ola { namespace acn { class RootSender { public: explicit RootSender(const ola::acn::CID &cid); ~RootSender() {} // Convenience method to encapsulate & send a single PDU bool SendPDU(unsigned int vector, const PDU &pdu, OutgoingTransport *transport); // Send a RootPDU with no data bool SendEmpty(unsigned int vector, OutgoingTransport *transport); // Use for testing to force a message from a particular cid bool SendPDU(unsigned int vector, const PDU &pdu, const ola::acn::CID &cid, OutgoingTransport *transport); // Encapsulation & send a block of PDUs bool SendPDUBlock(unsigned int vector, const PDUBlock &block, OutgoingTransport *transport); // TODO(simon): add methods to queue and send PDUs/blocks with different // vectors private: PDUBlock m_working_block; PDUBlock m_root_block; RootPDU m_root_pdu; RootSender(const RootSender&); RootSender& operator=(const RootSender&); }; } // namespace acn } // namespace ola #endif // LIBS_ACN_ROOTSENDER_H_ ola-0.10.5.nojsmin/libs/acn/E131PDU.h0000644000175000017500000000367413023355232016315 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E131PDU.h * Interface for the E131PDU class * Copyright (C) 2007 Simon Newton */ #ifndef LIBS_ACN_E131PDU_H_ #define LIBS_ACN_E131PDU_H_ #include "libs/acn/PDU.h" #include "libs/acn/E131Header.h" namespace ola { namespace acn { class DMPPDU; class E131PDU: public PDU { public: E131PDU(unsigned int vector, const E131Header &header, const DMPPDU *dmp_pdu): PDU(vector), m_header(header), m_dmp_pdu(dmp_pdu), m_data(NULL), m_data_size(0) {} E131PDU(unsigned int vector, const E131Header &header, const uint8_t *data, unsigned int data_size): PDU(vector), m_header(header), m_dmp_pdu(NULL), m_data(data), m_data_size(data_size) {} ~E131PDU() {} unsigned int HeaderSize() const; unsigned int DataSize() const; bool PackHeader(uint8_t *data, unsigned int *length) const; bool PackData(uint8_t *data, unsigned int *length) const; void PackHeader(ola::io::OutputStream *stream) const; void PackData(ola::io::OutputStream *stream) const; private: E131Header m_header; const DMPPDU *m_dmp_pdu; const uint8_t *m_data; const unsigned int m_data_size; }; } // namespace acn } // namespace ola #endif // LIBS_ACN_E131PDU_H_ ola-0.10.5.nojsmin/libs/acn/HeaderSet.h0000644000175000017500000000505413023355232017171 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * HeaderSet.h * Interface for the HeaderSet class * HeaderSet is passed down the parsing stack and contains a collection of PDU * headers * Copyright (C) 2007 Simon Newton */ #ifndef LIBS_ACN_HEADERSET_H_ #define LIBS_ACN_HEADERSET_H_ #include "libs/acn/DMPHeader.h" #include "libs/acn/E131Header.h" #include "libs/acn/E133Header.h" #include "libs/acn/RootHeader.h" #include "libs/acn/TransportHeader.h" namespace ola { namespace acn { class HeaderSet { public: HeaderSet() {} ~HeaderSet() {} const TransportHeader &GetTransportHeader() const { return m_transport_header; } void SetTransportHeader(const TransportHeader &header) { m_transport_header = header; } const RootHeader &GetRootHeader() const { return m_root_header; } void SetRootHeader(const RootHeader &header) { m_root_header = header; } const E131Header &GetE131Header() const { return m_e131_header; } void SetE131Header(const E131Header &header) { m_e131_header = header; } const E133Header &GetE133Header() const { return m_e133_header; } void SetE133Header(const E133Header &header) { m_e133_header = header; } const DMPHeader &GetDMPHeader() const { return m_dmp_header; } void SetDMPHeader(const DMPHeader &header) { m_dmp_header = header; } bool operator==(const HeaderSet &other) const { return ( m_transport_header == other.m_transport_header && m_root_header == other.m_root_header && m_e131_header == other.m_e131_header && m_e133_header == other.m_e133_header && m_dmp_header == other.m_dmp_header); } private: TransportHeader m_transport_header; RootHeader m_root_header; E131Header m_e131_header; E133Header m_e133_header; DMPHeader m_dmp_header; }; } // namespace acn } // namespace ola #endif // LIBS_ACN_HEADERSET_H_ ola-0.10.5.nojsmin/libs/acn/RDMPDU.cpp0000644000175000017500000000233713023355232016654 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RDMPDU.cpp * The RDMPDU * Copyright (C) 2012 Simon Newton */ #include "libs/acn/RDMPDU.h" #include #include namespace ola { namespace acn { using ola::io::OutputStream; using ola::network::HostToNetwork; void RDMPDU::PrependPDU(ola::io::IOStack *stack) { uint8_t vector = HostToNetwork(ola::rdm::START_CODE); stack->Write(reinterpret_cast(&vector), sizeof(vector)); PrependFlagsAndLength(stack); } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/E131DiscoveryInflator.h0000644000175000017500000000403013023355232021316 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E131DiscoveryInflator.h * An inflator for E1.31 discovery messages. * Copyright (C) 2014 Simon Newton */ #ifndef LIBS_ACN_E131DISCOVERYINFLATOR_H_ #define LIBS_ACN_E131DISCOVERYINFLATOR_H_ #include #include #include "ola/Callback.h" #include "ola/acn/ACNVectors.h" #include "libs/acn/BaseInflator.h" namespace ola { namespace acn { class E131DiscoveryInflator: public InflatorInterface { public: struct DiscoveryPage { public: const uint8_t page_number; const uint8_t last_page; const uint32_t page_sequence; std::vector universes; DiscoveryPage(uint8_t page_number, uint8_t last_page) : page_number(page_number), last_page(last_page), page_sequence(0) { // not yet part of the standard } }; typedef ola::Callback2 PageCallback; explicit E131DiscoveryInflator(PageCallback *callback) : m_page_callback(callback) {} uint32_t Id() const { return acn::VECTOR_E131_DISCOVERY; } unsigned int InflatePDUBlock(HeaderSet *headers, const uint8_t *data, unsigned int len); private: std::auto_ptr m_page_callback; }; } // namespace acn } // namespace ola #endif // LIBS_ACN_E131DISCOVERYINFLATOR_H_ ola-0.10.5.nojsmin/libs/acn/E131TestFramework.h0000644000175000017500000002153713023355232020460 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E131TestFramework.h * Allows testing of a remote E1.31 implementation. * Copyright (C) 2010 Simon Newton * * The remote node needs to be listening for Universe 1. */ #ifndef LIBS_ACN_E131TESTFRAMEWORK_H_ #define LIBS_ACN_E131TESTFRAMEWORK_H_ #include #include #include #include #include "ola/Constants.h" #include "ola/DmxBuffer.h" #include "ola/acn/CID.h" #include "ola/io/Descriptor.h" #include "ola/io/SelectServer.h" #include "ola/io/StdinHandler.h" #include "ola/math/Random.h" #include "libs/acn/E131Node.h" static const unsigned int UNIVERSE_ID = 1; /* * NodeAction, this reflects an action to be performed on a node. */ class NodeAction { public: virtual ~NodeAction() {} void SetNode(ola::acn::E131Node *node) { m_node = node; } virtual void Tick() {} protected: ola::acn::E131Node *m_node; }; /* * A TestState, this represents a particular state of the testing engine. This * one specifies the behaviour of two nodes. */ class TestState { public: TestState(const std::string &name, NodeAction *action1, NodeAction *action2, const std::string &expected, const ola::DmxBuffer &expected_result): m_passed(true), m_expected_result(expected_result), m_name(name), m_expected(expected), m_action1(action1), m_action2(action2) { } virtual ~TestState() { delete m_action1; delete m_action2; } void SetNodes(ola::acn::E131Node *node1, ola::acn::E131Node *node2) { m_action1->SetNode(node1); m_action2->SetNode(node2); } void Tick() { m_action1->Tick(); m_action2->Tick(); } virtual bool Verify(const ola::DmxBuffer &data) { if (!(data == m_expected_result)) return m_passed = false; return true; } std::string StateName() const { return m_name; } std::string ExpectedResults() const { return m_expected; } bool Passed() const { return m_passed; } protected: bool m_passed; ola::DmxBuffer m_expected_result; private: std::string m_name, m_expected; NodeAction *m_action1, *m_action2; }; /* * This is similar to a TestStart but it checks for a particular first packet. * It's useful for state transitions. */ class RelaxedTestState: public TestState { public: RelaxedTestState(const std::string &name, NodeAction *action1, NodeAction *action2, const std::string &expected, const ola::DmxBuffer &expected_first_result, const ola::DmxBuffer &expected_result): TestState(name, action1, action2, expected, expected_result), m_first(true), m_expected_first_result(expected_first_result) { } bool Verify(const ola::DmxBuffer &buffer) { if (m_first) { m_first = false; if (!(m_expected_first_result == buffer)) return m_passed = false; return true; } else { if (!(m_expected_result == buffer)) return m_passed = false; return true; } } private: bool m_first; ola::DmxBuffer m_expected_first_result; }; /* * This is similar to a TestStart but it checks for one style of packet, * followed by another. It's useful for state transitions. */ class OrderedTestState: public TestState { public: OrderedTestState(const std::string &name, NodeAction *action1, NodeAction *action2, const std::string &expected, const ola::DmxBuffer &expected_first_result, const ola::DmxBuffer &expected_result): TestState(name, action1, action2, expected, expected_result), m_found_second(false), m_expected_first_result(expected_first_result) { } bool Verify(const ola::DmxBuffer &buffer) { if (m_found_second) { if (!(m_expected_result == buffer)) return m_passed = false; return true; } else { if (m_expected_result == buffer) { m_found_second = true; return true; } if (!(m_expected_first_result == buffer)) return m_passed = false; return true; } } private: bool m_found_second; ola::DmxBuffer m_expected_first_result; }; /* * This action does nothing. */ class NodeInactive: public NodeAction { public: NodeInactive() {} void Tick() {} }; /* * This action just sends some data wil the selected priority. */ class NodeSimpleSend: public NodeAction { public: explicit NodeSimpleSend(uint8_t priority, const std::string &data = "") : m_priority(priority) { if (data.empty()) m_buffer.SetRangeToValue(0, m_priority, ola::DMX_UNIVERSE_SIZE); else m_buffer.SetFromString(data); } void Tick() { m_node->SendDMX(UNIVERSE_ID, m_buffer, m_priority); } private: ola::DmxBuffer m_buffer; uint8_t m_priority; }; /* * This action sends a terminated msg the does nothing. */ class NodeTerminate: public NodeAction { public: NodeTerminate(): m_sent(false) { } void Tick() { if (!m_sent) m_node->SendStreamTerminated(UNIVERSE_ID); m_sent = true; } private: bool m_sent; }; /* * This state sends a terminated msg with data then does nothing */ class NodeTerminateWithData: public NodeAction { public: explicit NodeTerminateWithData(uint8_t data): m_data(data), m_sent(false) { } void Tick() { if (!m_sent) { ola::DmxBuffer output; output.SetRangeToValue(0, m_data, ola::DMX_UNIVERSE_SIZE); m_node->SendStreamTerminated(UNIVERSE_ID, output); } m_sent = true; } private: uint8_t m_data; bool m_sent; }; /* * This state sends data and occasionally sends old packets to test sequence # * handling. */ class NodeVarySequenceNumber: public NodeAction { public: NodeVarySequenceNumber(uint8_t good_value, uint8_t bad_value, unsigned int chance): m_counter(0), m_chance(chance), m_good(good_value), m_bad(bad_value) { ola::math::InitRandom(); } void Tick() { int random = ola::math::Random(0, static_cast(m_chance) - 1); if (!m_counter || random) { // start off with good data ola::DmxBuffer output; output.SetRangeToValue(0, m_good, ola::DMX_UNIVERSE_SIZE); m_node->SendDMX(UNIVERSE_ID, output); } else { // fake an old packet, 1 to 18 packets behind. ola::DmxBuffer output; output.SetRangeToValue(0, m_bad, ola::DMX_UNIVERSE_SIZE); int offset = ola::math::Random(1, 18); m_node->SendDMXWithSequenceOffset(UNIVERSE_ID, output, static_cast(-offset)); } m_counter++; } private: unsigned int m_counter, m_chance; uint8_t m_good, m_bad; }; /* * The state manager can run in one of three modes: * - local, non-interactive. This starts a local E131Node and sends it data, * verifying against the expected output. * - interactive mode. This sends data to the multicast addresses and a human * gets to verify it. */ class StateManager { public: StateManager(const std::vector &states, bool interactive_mode = false); ~StateManager(); bool Init(); void Run() { m_ss->Run(); } bool Tick(); void Input(int c); void NewDMX(); bool Passed() const { return m_failed_tests.empty(); } private: bool m_interactive; unsigned int m_count, m_ticker; ola::acn::CID m_cid1, m_cid2; ola::acn::E131Node *m_local_node, *m_node1, *m_node2; ola::io::SelectServer *m_ss; std::auto_ptr m_stdin_handler; std::vector m_states; ola::DmxBuffer m_recv_buffer; std::vector m_failed_tests; void EnterState(TestState *state); void NextState(); void ShowStatus(); static const unsigned int TICK_INTERVAL_MS = 100; static const unsigned int TIME_PER_STATE_MS = 3000; }; #endif // LIBS_ACN_E131TESTFRAMEWORK_H_ ola-0.10.5.nojsmin/libs/acn/PDU.h0000644000175000017500000001210013023355232015743 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * PDU.h * Interface for the PDU and PDUBlock classes * Copyright (C) 2007 Simon Newton */ #ifndef LIBS_ACN_PDU_H_ #define LIBS_ACN_PDU_H_ #include #include #include #include namespace ola { namespace acn { /* * The Base PDU class * TODO(simon): make this into a template based on vector size. */ class PDU { public: typedef enum { ONE_BYTE = 1, TWO_BYTES = 2, FOUR_BYTES = 4, } vector_size; explicit PDU(unsigned int vector, vector_size size = FOUR_BYTES): m_vector(vector), m_vector_size(size) {} virtual ~PDU() {} // Returns the size of this PDU virtual unsigned int Size() const; virtual unsigned int VectorSize() const { return m_vector_size; } virtual unsigned int HeaderSize() const = 0; virtual unsigned int DataSize() const = 0; // Set the vector void SetVector(unsigned int vector) { m_vector = vector; } /* * Pack the PDU into the memory pointed to by data * @return true on success, false on failure */ virtual bool Pack(uint8_t *data, unsigned int *length) const; virtual bool PackHeader(uint8_t *data, unsigned int *length) const = 0; virtual bool PackData(uint8_t *data, unsigned int *length) const = 0; /** * Write the PDU to an OutputStream */ virtual void Write(ola::io::OutputStream *stream) const; virtual void PackHeader(ola::io::OutputStream *stream) const = 0; virtual void PackData(ola::io::OutputStream *stream) const = 0; static void PrependFlagsAndLength( ola::io::OutputBufferInterface *output, uint8_t flags = VFLAG_MASK | HFLAG_MASK | DFLAG_MASK); static void PrependFlagsAndLength( ola::io::OutputBufferInterface *output, unsigned int length, uint8_t flags); // This indicates a vector is present static const uint8_t VFLAG_MASK = 0x40; // This indicates a header field is present static const uint8_t HFLAG_MASK = 0x20; // This indicates a data field is present static const uint8_t DFLAG_MASK = 0x10; private: unsigned int m_vector; unsigned int m_vector_size; // The max PDU length that can be represented with the 2 byte format for // the length field. static const unsigned int TWOB_LENGTH_LIMIT = 0x0FFF; }; /* * Represents a block of pdus */ template class PDUBlock { public: PDUBlock(): m_size(0) {} ~PDUBlock() {} // Add a PDU to this block void AddPDU(const C *msg) { m_pdus.push_back(msg); m_size += msg->Size(); } // Remove all PDUs from the block void Clear() { m_pdus.clear(); m_size = 0; } // The number of bytes this block would consume, this ignores optimizations // like repeating headers/vectors. unsigned int Size() const { return m_size; } /* * Pack this PDUBlock into memory pointed to by data * @return true on success, false on failure */ bool Pack(uint8_t *data, unsigned int *length) const; /** * Write this PDU block to an OutputStream */ void Write(ola::io::OutputStream *stream) const; private: std::vector m_pdus; unsigned int m_size; }; /* * Pack this block of PDUs into a buffer * @param data a pointer to the buffer * @param length size of the buffer, updated with the number of bytes used * @return true on success, false on failure */ template bool PDUBlock::Pack(uint8_t *data, unsigned int *length) const { bool status = true; unsigned int i = 0; typename std::vector::const_iterator iter; for (iter = m_pdus.begin(); iter != m_pdus.end(); ++iter) { // TODO(simon): optimize repeated headers & vectors here unsigned int remaining = i < *length ? *length - i : 0; status &= (*iter)->Pack(data + i, &remaining); i+= remaining; } *length = i; return status; } /* * Write this block of PDUs to an OutputStream. * @param stream the OutputStream to write to * @return true on success, false on failure */ template void PDUBlock::Write(ola::io::OutputStream *stream) const { typename std::vector::const_iterator iter; for (iter = m_pdus.begin(); iter != m_pdus.end(); ++iter) { // TODO(simon): optimize repeated headers & vectors here (*iter)->Write(stream); } } } // namespace acn } // namespace ola #endif // LIBS_ACN_PDU_H_ ola-0.10.5.nojsmin/libs/acn/CID.cpp0000644000175000017500000000374413023355232016263 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * CID.cpp * CID class, passes everything through to CIDImpl. * Copyright (C) 2007 Simon Newton */ #include #include #include "libs/acn/CIDImpl.h" namespace ola { namespace acn { using std::string; CID::CID() : m_impl(new CIDImpl()) {} CID::CID(const CID& other) : m_impl(new CIDImpl(*other.m_impl)) {} CID::CID(CIDImpl *impl) : m_impl(impl) {} CID::~CID() { delete m_impl; } bool CID::IsNil() const { return m_impl->IsNil(); } void CID::Pack(uint8_t *buffer) const { return m_impl->Pack(buffer); } CID& CID::operator=(const CID& other) { *m_impl = *other.m_impl; return *this; } bool CID::operator==(const CID& other) const { return (*m_impl == *other.m_impl); } bool CID::operator!=(const CID& c1) const { return !(*this == c1); } bool CID::operator<(const CID& c1) const { return *m_impl < *c1.m_impl; } string CID::ToString() const { return m_impl->ToString(); } void CID::Write(ola::io::OutputBufferInterface *output) const { m_impl->Write(output); } CID CID::Generate() { return CID(CIDImpl::Generate()); } CID CID::FromData(const uint8_t *data) { return CID(CIDImpl::FromData(data)); } CID CID::FromString(const string &cid) { return CID(CIDImpl::FromString(cid)); } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/E133InflatorTest.cpp0000644000175000017500000001000513023355232020622 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E133InflatorTest.cpp * Test fixture for the E133Inflator class * Copyright (C) 2011 Simon Newton */ #include #include #include #include "ola/Logging.h" #include "ola/network/NetworkUtils.h" #include "libs/acn/HeaderSet.h" #include "libs/acn/PDUTestCommon.h" #include "libs/acn/E133Inflator.h" #include "libs/acn/E133PDU.h" #include "ola/testing/TestUtils.h" namespace ola { namespace acn { using ola::network::HostToNetwork; using std::string; class E133InflatorTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(E133InflatorTest); CPPUNIT_TEST(testDecodeHeader); CPPUNIT_TEST(testInflatePDU); CPPUNIT_TEST_SUITE_END(); public: void testDecodeHeader(); void testInflatePDU(); }; CPPUNIT_TEST_SUITE_REGISTRATION(E133InflatorTest); /* * Check that we can decode headers properly */ void E133InflatorTest::testDecodeHeader() { E133Header::e133_pdu_header header; memset(&header, 0, sizeof(header)); E133Inflator inflator; HeaderSet header_set, header_set2; unsigned int bytes_used; const string source_name = "foobar"; strncpy(header.source, source_name.data(), source_name.size() + 1); header.sequence = HostToNetwork(72650u); header.endpoint = HostToNetwork(static_cast(42)); OLA_ASSERT(inflator.DecodeHeader(&header_set, reinterpret_cast(&header), sizeof(header), &bytes_used)); OLA_ASSERT_EQ((unsigned int) sizeof(header), bytes_used); E133Header decoded_header = header_set.GetE133Header(); OLA_ASSERT(source_name == decoded_header.Source()); OLA_ASSERT_EQ((uint32_t) 72650, decoded_header.Sequence()); OLA_ASSERT_EQ((uint16_t) 42, decoded_header.Endpoint()); // try an undersized header OLA_ASSERT_FALSE(inflator.DecodeHeader( &header_set, reinterpret_cast(&header), static_cast(sizeof(header) - 1), &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); // test inherting the header from the prev call OLA_ASSERT(inflator.DecodeHeader(&header_set2, NULL, 0, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); decoded_header = header_set2.GetE133Header(); OLA_ASSERT(source_name == decoded_header.Source()); OLA_ASSERT_EQ((uint32_t) 72650, decoded_header.Sequence()); OLA_ASSERT_EQ((uint16_t) 42, decoded_header.Endpoint()); inflator.ResetHeaderField(); OLA_ASSERT_FALSE(inflator.DecodeHeader(&header_set2, NULL, 0, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); } /* * Check that we can inflate a E133 PDU that contains other PDUs */ void E133InflatorTest::testInflatePDU() { const string source = "foobar source"; E133Header header(source, 2370, 2); // TODO(simon): pass a DMP msg here as well E133PDU pdu(3, header, NULL); OLA_ASSERT_EQ((unsigned int) 77, pdu.Size()); unsigned int size = pdu.Size(); uint8_t *data = new uint8_t[size]; unsigned int bytes_used = size; OLA_ASSERT(pdu.Pack(data, &bytes_used)); OLA_ASSERT_EQ((unsigned int) size, bytes_used); E133Inflator inflator; HeaderSet header_set; OLA_ASSERT(inflator.InflatePDUBlock(&header_set, data, size)); OLA_ASSERT(header == header_set.GetE133Header()); delete[] data; } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/E133StatusInflator.cpp0000644000175000017500000000345513023355232021201 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E133StatusInflator.cpp * The Inflator for the E1.33 Status messages. * Copyright (C) 2013 Simon Newton */ #include #include #include "ola/e133/E133Enums.h" #include "libs/acn/E133StatusInflator.h" namespace ola { namespace acn { using std::string; /** * Create a new E1.33 status inflator */ E133StatusInflator::E133StatusInflator() : BaseInflator(PDU::TWO_BYTES) { } /* * Handle a E1.33 Status PDU. */ bool E133StatusInflator::HandlePDUData(uint32_t vector, const HeaderSet &headers, const uint8_t *data, unsigned int pdu_len) { unsigned int size = std::min( pdu_len, static_cast(ola::e133::MAX_E133_STATUS_STRING_SIZE)); string description(reinterpret_cast(&data[0]), size); m_handler->Run(&headers.GetTransportHeader(), &headers.GetE133Header(), static_cast(vector), description); return true; } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/CIDImpl.cpp0000644000175000017500000001177613023355232017111 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * CIDImpl.cpp * The actual implementation of a CID. The implementation changes based on * which uuid library is installed. * Copyright (C) 2007 Simon Newton */ #include #include #include "libs/acn/CIDImpl.h" namespace ola { namespace acn { using std::string; #ifdef USE_OSSP_UUID CIDImpl::CIDImpl() : m_uuid(NULL) { } CIDImpl::CIDImpl(uuid_t *uuid) : m_uuid(uuid) { } CIDImpl::CIDImpl(const CIDImpl& other) : m_uuid(NULL) { if (other.m_uuid) uuid_clone(other.m_uuid, &m_uuid); } CIDImpl::~CIDImpl() { if (m_uuid) uuid_destroy(m_uuid); } bool CIDImpl::IsNil() const { if (!m_uuid) return true; int result; uuid_isnil(m_uuid, &result); return result; } /** * Pack a CIDImpl into the binary representation */ void CIDImpl::Pack(uint8_t *buffer) const { size_t data_length = CIDImpl_LENGTH; // buffer may not be 4 byte aligned char uid_data[CIDImpl_LENGTH]; void *ptr = static_cast(uid_data); if (m_uuid) { uuid_export(m_uuid, UUID_FMT_BIN, &ptr, &data_length); memcpy(buffer, uid_data, CIDImpl_LENGTH); } else { memset(buffer, 0, CIDImpl_LENGTH); } } CIDImpl& CIDImpl::operator=(const CIDImpl& other) { if (this != &other) { if (m_uuid) uuid_destroy(m_uuid); if (other.m_uuid) uuid_clone(other.m_uuid, &m_uuid); else m_uuid = NULL; } return *this; } bool CIDImpl::operator==(const CIDImpl& c1) const { int result; uuid_compare(m_uuid, c1.m_uuid, &result); return 0 == result; } bool CIDImpl::operator!=(const CIDImpl& c1) const { return !(*this == c1); } bool CIDImpl::operator<(const CIDImpl& c1) const { int result; uuid_compare(m_uuid, c1.m_uuid, &result); return result < 0; } string CIDImpl::ToString() const { char cid[UUID_LEN_STR + 1]; void *str = static_cast(cid); size_t length = UUID_LEN_STR + 1; uuid_export(m_uuid, UUID_FMT_STR, &str, &length); return string(cid); } void CIDImpl::Write(ola::io::OutputBufferInterface *output) const { size_t data_length = CIDImpl_LENGTH; // buffer may not be 4 byte aligned uint8_t uid_data[CIDImpl_LENGTH]; void *ptr = static_cast(uid_data); if (m_uuid) { uuid_export(m_uuid, UUID_FMT_BIN, &ptr, &data_length); } else { memset(ptr, 0, CIDImpl_LENGTH); } output->Write(uid_data, CIDImpl_LENGTH); } CIDImpl* CIDImpl::Generate() { uuid_t *uuid; uuid_create(&uuid); uuid_make(uuid, UUID_MAKE_V4); return new CIDImpl(uuid); } CIDImpl* CIDImpl::FromData(const uint8_t *data) { uuid_t *uuid; uuid_create(&uuid); uuid_import(uuid, UUID_FMT_BIN, data, CIDImpl_LENGTH); return new CIDImpl(uuid); } CIDImpl* CIDImpl::FromString(const string &cid) { uuid_t *uuid; uuid_create(&uuid); uuid_import(uuid, UUID_FMT_STR, cid.data(), cid.length()); return new CIDImpl(uuid); } #else // We're using the e2fs utils uuid library CIDImpl::CIDImpl() { uuid_clear(m_uuid); } CIDImpl::CIDImpl(uuid_t uuid) { uuid_copy(m_uuid, uuid); } CIDImpl::CIDImpl(const CIDImpl& other) { uuid_copy(m_uuid, other.m_uuid); } CIDImpl::~CIDImpl() {} bool CIDImpl::IsNil() const { return uuid_is_null(m_uuid); } void CIDImpl::Pack(uint8_t *buf) const { memcpy(buf, m_uuid, CIDImpl_LENGTH); } void CIDImpl::Write(ola::io::OutputBufferInterface *output) const { output->Write(m_uuid, CIDImpl_LENGTH); } CIDImpl& CIDImpl::operator=(const CIDImpl& other) { if (this != &other) { uuid_copy(m_uuid, other.m_uuid); } return *this; } bool CIDImpl::operator==(const CIDImpl& c1) const { return !uuid_compare(m_uuid, c1.m_uuid); } bool CIDImpl::operator!=(const CIDImpl& c1) const { return uuid_compare(m_uuid, c1.m_uuid); } bool CIDImpl::operator<(const CIDImpl& c1) const { return uuid_compare(m_uuid, c1.m_uuid) < 0; } string CIDImpl::ToString() const { char str[37]; uuid_unparse(m_uuid, str); return string(str); } CIDImpl* CIDImpl::Generate() { uuid_t uuid; uuid_generate(uuid); return new CIDImpl(uuid); } CIDImpl* CIDImpl::FromData(const uint8_t *data) { uuid_t uuid; uuid_copy(uuid, data); return new CIDImpl(uuid); } CIDImpl* CIDImpl::FromString(const string &cid) { uuid_t uuid; int ret = uuid_parse(cid.data(), uuid); if (ret == -1) uuid_clear(uuid); return new CIDImpl(uuid); } #endif // end the e2fs progs uuid implementation } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/E131Header.h0000644000175000017500000000732613023355232017053 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E131Header.h * The E1.31 Header * Copyright (C) 2007 Simon Newton */ #ifndef LIBS_ACN_E131HEADER_H_ #define LIBS_ACN_E131HEADER_H_ #include #include #include namespace ola { namespace acn { /* * Header for the E131 layer */ class E131Header { public: E131Header() : m_priority(0), m_sequence(0), m_universe(0), m_is_preview(false), m_has_terminated(false), m_is_rev2(false) { } E131Header(const std::string &source, uint8_t priority, uint8_t sequence, uint16_t universe, bool is_preview = false, bool has_terminated = false, bool is_rev2 = false) : m_source(source), m_priority(priority), m_sequence(sequence), m_universe(universe), m_is_preview(is_preview), m_has_terminated(has_terminated), m_is_rev2(is_rev2) { } ~E131Header() {} const std::string Source() const { return m_source; } uint8_t Priority() const { return m_priority; } uint8_t Sequence() const { return m_sequence; } uint16_t Universe() const { return m_universe; } bool PreviewData() const { return m_is_preview; } bool StreamTerminated() const { return m_has_terminated; } bool UsingRev2() const { return m_is_rev2; } bool operator==(const E131Header &other) const { return m_source == other.m_source && m_priority == other.m_priority && m_sequence == other.m_sequence && m_universe == other.m_universe && m_is_preview == other.m_is_preview && m_has_terminated == other.m_has_terminated && m_is_rev2 == other.m_is_rev2; } enum { SOURCE_NAME_LEN = 64 }; PACK( struct e131_pdu_header_s { char source[SOURCE_NAME_LEN]; uint8_t priority; uint16_t reserved; uint8_t sequence; uint8_t options; uint16_t universe; }); typedef struct e131_pdu_header_s e131_pdu_header; static const uint8_t PREVIEW_DATA_MASK = 0x80; static const uint8_t STREAM_TERMINATED_MASK = 0x40; private: std::string m_source; uint8_t m_priority; uint8_t m_sequence; uint16_t m_universe; bool m_is_preview; bool m_has_terminated; bool m_is_rev2; }; class E131Rev2Header: public E131Header { public: E131Rev2Header(const std::string &source, uint8_t priority, uint8_t sequence, uint16_t universe, bool is_preview = false, bool has_terminated = false) : E131Header(source, priority, sequence, universe, is_preview, has_terminated, true) { } enum { REV2_SOURCE_NAME_LEN = 32 }; typedef struct { char source[REV2_SOURCE_NAME_LEN]; uint8_t priority; uint8_t sequence; uint16_t universe; } e131_rev2_pdu_header; }; } // namespace acn } // namespace ola #endif // LIBS_ACN_E131HEADER_H_ ola-0.10.5.nojsmin/libs/acn/RDMInflator.h0000644000175000017500000000442013023355232017442 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RDMInflator.h * Copyright (C) 2011 Simon Newton */ #ifndef LIBS_ACN_RDMINFLATOR_H_ #define LIBS_ACN_RDMINFLATOR_H_ #include #include "ola/Callback.h" #include "ola/acn/ACNVectors.h" #include "libs/acn/BaseInflator.h" #include "libs/acn/TransportHeader.h" #include "libs/acn/E133Header.h" namespace ola { namespace acn { class RDMInflator: public BaseInflator { friend class RDMInflatorTest; public: // These are pointers so the callers don't have to pull in all the headers. typedef ola::Callback3 RDMMessageHandler; RDMInflator(); ~RDMInflator() {} uint32_t Id() const { return ola::acn::VECTOR_FRAMING_RDMNET; } void SetRDMHandler(RDMMessageHandler *handler); static const unsigned int VECTOR_RDMNET_DATA = 0xcc; protected: bool DecodeHeader(HeaderSet *headers, const uint8_t *data, unsigned int len, unsigned int *bytes_used); void ResetHeaderField() {} // namespace noop virtual bool HandlePDUData(uint32_t vector, const HeaderSet &headers, const uint8_t *data, unsigned int pdu_len); private: std::auto_ptr m_rdm_handler; }; } // namespace acn } // namespace ola #endif // LIBS_ACN_RDMINFLATOR_H_ ola-0.10.5.nojsmin/libs/acn/E133PDU.h0000644000175000017500000000354713023355232016316 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E133PDU.h * Interface for the E133PDU class * Copyright (C) 2011 Simon Newton */ #ifndef LIBS_ACN_E133PDU_H_ #define LIBS_ACN_E133PDU_H_ #include #include #include "libs/acn/PDU.h" #include "libs/acn/E133Header.h" namespace ola { namespace acn { class RDMPDU; class E133PDU: public PDU { public: E133PDU(unsigned int vector, const E133Header &header, const PDU *pdu): PDU(vector), m_header(header), m_pdu(pdu) {} ~E133PDU() {} unsigned int HeaderSize() const; unsigned int DataSize() const; bool PackHeader(uint8_t *data, unsigned int *length) const; bool PackData(uint8_t *data, unsigned int *length) const; void PackHeader(ola::io::OutputStream *stream) const; void PackData(ola::io::OutputStream *stream) const; static void PrependPDU(ola::io::IOStack *stack, uint32_t vector, const std::string &source, uint32_t sequence_number, uint16_t endpoint_id); private: E133Header m_header; const PDU *m_pdu; }; } // namespace acn } // namespace ola #endif // LIBS_ACN_E133PDU_H_ ola-0.10.5.nojsmin/libs/acn/E133StatusPDU.h0000644000175000017500000000244413023355232017515 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E133StatusPDU.h * The E133StatusPDU * Copyright (C) 2013 Simon Newton */ #ifndef LIBS_ACN_E133STATUSPDU_H_ #define LIBS_ACN_E133STATUSPDU_H_ #include #include #include "ola/e133/E133Enums.h" #include "libs/acn/PDU.h" namespace ola { namespace acn { class E133StatusPDU : private PDU { public: static void PrependPDU(ola::io::IOStack *stack, ola::e133::E133StatusCode status_code, const std::string &status); }; } // namespace acn } // namespace ola #endif // LIBS_ACN_E133STATUSPDU_H_ ola-0.10.5.nojsmin/libs/acn/DMPInflatorTest.cpp0000644000175000017500000000704613023355232020642 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DMPInflatorTest.cpp * Test fixture for the DMPInflator class * Copyright (C) 2005 Simon Newton */ #include #include "libs/acn/DMPAddress.h" #include "libs/acn/DMPInflator.h" #include "libs/acn/DMPPDU.h" #include "libs/acn/HeaderSet.h" #include "libs/acn/PDUTestCommon.h" #include "ola/testing/TestUtils.h" namespace ola { namespace acn { class DMPInflatorTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(DMPInflatorTest); CPPUNIT_TEST(testDecodeHeader); CPPUNIT_TEST(testInflatePDU); CPPUNIT_TEST_SUITE_END(); public: void testDecodeHeader(); void testInflatePDU(); }; CPPUNIT_TEST_SUITE_REGISTRATION(DMPInflatorTest); /* * Check that we can decode headers properly */ void DMPInflatorTest::testDecodeHeader() { DMPHeader header(true, true, NON_RANGE, TWO_BYTES); DMPInflator inflator; HeaderSet header_set, header_set2; unsigned int bytes_used; uint8_t header_data = header.Header(); OLA_ASSERT(inflator.DecodeHeader(&header_set, &header_data, sizeof(header_data), &bytes_used)); OLA_ASSERT_EQ((unsigned int) sizeof(header_data), bytes_used); DMPHeader decoded_header = header_set.GetDMPHeader(); OLA_ASSERT(decoded_header.IsVirtual()); OLA_ASSERT(decoded_header.IsRelative()); OLA_ASSERT(NON_RANGE == decoded_header.Type()); OLA_ASSERT(TWO_BYTES == decoded_header.Size()); // try an undersized header OLA_ASSERT_FALSE(inflator.DecodeHeader(&header_set, &header_data, 0, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); // test inherting the header from the prev call OLA_ASSERT(inflator.DecodeHeader(&header_set2, NULL, 0, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); decoded_header = header_set2.GetDMPHeader(); OLA_ASSERT(decoded_header.IsVirtual()); OLA_ASSERT(decoded_header.IsRelative()); OLA_ASSERT(NON_RANGE == decoded_header.Type()); OLA_ASSERT(TWO_BYTES == decoded_header.Size()); inflator.ResetHeaderField(); OLA_ASSERT_FALSE(inflator.DecodeHeader(&header_set2, NULL, 0, &bytes_used)); OLA_ASSERT_EQ((unsigned int) 0, bytes_used); } /* * Check that we can inflate a DMP PDU that contains other PDUs */ void DMPInflatorTest::testInflatePDU() { DMPHeader header(true, true, NON_RANGE, ONE_BYTES); const DMPPDU *pdu = NewDMPGetProperty(true, true, 1); OLA_ASSERT_EQ((unsigned int) 5, pdu->Size()); unsigned int size = pdu->Size(); uint8_t *data = new uint8_t[size]; unsigned int bytes_used = size; OLA_ASSERT(pdu->Pack(data, &bytes_used)); OLA_ASSERT_EQ((unsigned int) size, bytes_used); DMPInflator inflator; HeaderSet header_set; OLA_ASSERT(inflator.InflatePDUBlock(&header_set, data, size)); OLA_ASSERT(header == header_set.GetDMPHeader()); delete[] data; delete pdu; } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/RDMPDUTest.cpp0000644000175000017500000000353713023355232017517 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RDMPDUTest.cpp * Test fixture for the RDMPDU class * Copyright (C) 2012 Simon Newton */ #include #include #include #include "ola/Logging.h" #include "ola/io/IOStack.h" #include "ola/network/NetworkUtils.h" #include "ola/testing/TestUtils.h" #include "libs/acn/PDUTestCommon.h" #include "libs/acn/RDMPDU.h" namespace ola { namespace acn { using ola::io::IOStack; class RDMPDUTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(RDMPDUTest); CPPUNIT_TEST(testPrepend); CPPUNIT_TEST_SUITE_END(); public: void testPrepend(); private: static const unsigned int TEST_VECTOR; }; CPPUNIT_TEST_SUITE_REGISTRATION(RDMPDUTest); const unsigned int RDMPDUTest::TEST_VECTOR = 0xcc; void RDMPDUTest::testPrepend() { IOStack stack; RDMPDU::PrependPDU(&stack); unsigned int length = stack.Size(); uint8_t *buffer = new uint8_t[length]; OLA_ASSERT(stack.Read(buffer, length)); const uint8_t expected_data[] = {0x70, 3, TEST_VECTOR}; OLA_ASSERT_DATA_EQUALS(expected_data, sizeof(expected_data), buffer, length); delete[] buffer; } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/UDPTransportTest.cpp0000644000175000017500000000653513023355232021072 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * UDPTransportTest.cpp * Test fixture for the UDPTransport class * Copyright (C) 2005 Simon Newton */ #include #include #include "ola/Logging.h" #include "ola/io/SelectServer.h" #include "ola/network/InterfacePicker.h" #include "ola/network/NetworkUtils.h" #include "ola/network/Socket.h" #include "ola/testing/TestUtils.h" #include "libs/acn/PDUTestCommon.h" #include "libs/acn/UDPTransport.h" namespace ola { namespace acn { using ola::acn::CID; using ola::network::HostToNetwork; using ola::network::IPV4Address; using ola::network::IPV4SocketAddress; class UDPTransportTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(UDPTransportTest); CPPUNIT_TEST(testUDPTransport); CPPUNIT_TEST_SUITE_END(); public: UDPTransportTest(): TestFixture(), m_ss(NULL) {} void testUDPTransport(); void setUp(); void tearDown(); void Stop(); void FatalStop() { OLA_ASSERT(false); } private: ola::io::SelectServer *m_ss; static const int ABORT_TIMEOUT_IN_MS = 1000; }; CPPUNIT_TEST_SUITE_REGISTRATION(UDPTransportTest); void UDPTransportTest::setUp() { m_ss = new ola::io::SelectServer(); } void UDPTransportTest::tearDown() { delete m_ss; } void UDPTransportTest::Stop() { if (m_ss) m_ss->Terminate(); } /* * Test the UDPTransport */ void UDPTransportTest::testUDPTransport() { CID cid; std::auto_ptr > stop_closure( NewCallback(this, &UDPTransportTest::Stop)); MockInflator inflator(cid, stop_closure.get()); // setup the socket ola::network::UDPSocket socket; OLA_ASSERT(socket.Init()); OLA_ASSERT(socket.Bind(IPV4SocketAddress(IPV4Address::Loopback(), 0))); OLA_ASSERT(socket.EnableBroadcast()); // Get the port we bound to. IPV4SocketAddress local_address; OLA_ASSERT(socket.GetSocketAddress(&local_address)); IncomingUDPTransport incoming_udp_transport(&socket, &inflator); socket.SetOnData(NewCallback(&incoming_udp_transport, &IncomingUDPTransport::Receive)); OLA_ASSERT(m_ss->AddReadDescriptor(&socket)); // outgoing transport OutgoingUDPTransportImpl udp_transport_impl(&socket); OutgoingUDPTransport outgoing_udp_transport(&udp_transport_impl, IPV4Address::Loopback(), local_address.Port()); // now actually send some data PDUBlock pdu_block; MockPDU mock_pdu(4, 8); pdu_block.AddPDU(&mock_pdu); OLA_ASSERT(outgoing_udp_transport.Send(pdu_block)); SingleUseCallback0 *closure = NewSingleCallback(this, &UDPTransportTest::FatalStop); m_ss->RegisterSingleTimeout(ABORT_TIMEOUT_IN_MS, closure); m_ss->Run(); } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/E131Node.cpp0000644000175000017500000003551313023355232017102 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E131Node.cpp * A E1.31 node * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include #include #include #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/network/InterfacePicker.h" #include "ola/stl/STLUtils.h" #include "libs/acn/E131Node.h" namespace ola { namespace acn { using ola::Callback0; using ola::DmxBuffer; using ola::network::IPV4Address; using ola::network::IPV4SocketAddress; using ola::network::HostToNetwork; using std::auto_ptr; using std::map; using std::string; using std::set; using std::vector; class TrackedSource { public: TrackedSource() : clean_counter(0), current_sequence_number(0), total_pages(0) { } IPV4Address ip_address; string source_name; set universes; uint8_t clean_counter; void NewPage(uint8_t page_number, uint8_t last_page, uint32_t sequence_number, const vector &universes); private: uint32_t current_sequence_number; uint16_t total_pages; set received_pages; set new_universes; }; void TrackedSource::NewPage(uint8_t page_number, uint8_t last_page, uint32_t sequence_number, const vector &rx_universes) { clean_counter = 0; // This is broken because we don't actually get a sequence number in the // packet yet. // TODO(simon): Get the draft updated and fix this. if (sequence_number != current_sequence_number || total_pages != last_page) { current_sequence_number = sequence_number; total_pages = last_page; received_pages.clear(); new_universes.clear(); } received_pages.insert(page_number); std::copy(rx_universes.begin(), rx_universes.end(), std::inserter(new_universes, new_universes.end())); uint8_t expected_page = 0; set::const_iterator iter = received_pages.begin(); for (; iter != received_pages.end(); ++iter) { if (*iter != expected_page) return; expected_page++; } if (expected_page == total_pages + 1) { universes = new_universes; received_pages.clear(); new_universes.clear(); total_pages = 0; } } E131Node::E131Node(ola::thread::SchedulerInterface *ss, const string &ip_address, const Options &options, const ola::acn::CID &cid) : m_ss(ss), m_options(options), m_preferred_ip(ip_address), m_cid(cid), m_root_sender(m_cid), m_e131_sender(&m_socket, &m_root_sender), m_dmp_inflator(options.ignore_preview), m_discovery_inflator(NewCallback(this, &E131Node::NewDiscoveryPage)), m_incoming_udp_transport(&m_socket, &m_root_inflator), m_send_buffer(NULL), m_discovery_timeout(ola::thread::INVALID_TIMEOUT) { if (!m_options.use_rev2) { // Allocate a buffer for the dmx data + start code m_send_buffer = new uint8_t[DMX_UNIVERSE_SIZE + 1]; m_send_buffer[0] = 0; // start code is 0 } // setup all the inflators m_root_inflator.AddInflator(&m_e131_inflator); m_root_inflator.AddInflator(&m_e131_rev2_inflator); m_e131_inflator.AddInflator(&m_dmp_inflator); m_e131_inflator.AddInflator(&m_discovery_inflator); m_e131_rev2_inflator.AddInflator(&m_dmp_inflator); } /* * Cleanup */ E131Node::~E131Node() { // remove handlers for all universes. This also leaves the multicast groups. vector universes; m_dmp_inflator.RegisteredUniverses(&universes); vector::const_iterator iter = universes.begin(); for (; iter != universes.end(); ++iter) { RemoveHandler(*iter); } Stop(); if (m_send_buffer) delete[] m_send_buffer; STLDeleteValues(&m_discovered_sources); } bool E131Node::Start() { auto_ptr picker( ola::network::InterfacePicker::NewPicker()); if (!picker->ChooseInterface(&m_interface, m_preferred_ip)) { OLA_INFO << "Failed to find an interface"; return false; } if (!m_socket.Init()) { return false; } if (!m_socket.Bind( IPV4SocketAddress(IPV4Address::WildCard(), m_options.port))) return false; if (!m_socket.EnableBroadcast()) return false; m_socket.SetTos(m_options.dscp); m_socket.SetMulticastInterface(m_interface.ip_address); m_socket.SetOnData(NewCallback(&m_incoming_udp_transport, &IncomingUDPTransport::Receive)); if (m_options.enable_draft_discovery) { IPV4Address addr; m_e131_sender.UniverseIP(DISCOVERY_UNIVERSE_ID, &addr); if (!m_socket.JoinMulticast(m_interface.ip_address, addr)) { OLA_WARN << "Failed to join multicast group " << addr; } m_discovery_timeout = m_ss->RegisterRepeatingTimeout( UNIVERSE_DISCOVERY_INTERVAL, ola::NewCallback(this, &E131Node::PerformDiscoveryHousekeeping)); } return true; } bool E131Node::Stop() { m_ss->RemoveTimeout(m_discovery_timeout); m_discovery_timeout = ola::thread::INVALID_TIMEOUT; return true; } bool E131Node::SetSourceName(uint16_t universe, const string &source) { ActiveTxUniverses::iterator iter = m_tx_universes.find(universe); if (iter == m_tx_universes.end()) { tx_universe *settings = SetupOutgoingSettings(universe); settings->source = source; } else { iter->second.source = source; } return true; } bool E131Node::StartStream(uint16_t universe) { ActiveTxUniverses::iterator iter = m_tx_universes.find(universe); if (iter == m_tx_universes.end()) { SetupOutgoingSettings(universe); } else { OLA_WARN << "Trying to StartStream on universe " << universe << " which " << "is already started"; return false; } return true; } bool E131Node::TerminateStream(uint16_t universe, uint8_t priority) { // The standard says to send this 3 times for (unsigned int i = 0; i < 3; i++) { SendStreamTerminated(universe, DmxBuffer(), priority); } STLRemove(&m_tx_universes, universe); return true; } bool E131Node::SendDMX(uint16_t universe, const ola::DmxBuffer &buffer, uint8_t priority, bool preview) { return SendDMXWithSequenceOffset(universe, buffer, 0, priority, preview); } bool E131Node::SendDMXWithSequenceOffset(uint16_t universe, const ola::DmxBuffer &buffer, int8_t sequence_offset, uint8_t priority, bool preview) { ActiveTxUniverses::iterator iter = m_tx_universes.find(universe); tx_universe *settings; if (iter == m_tx_universes.end()) { settings = SetupOutgoingSettings(universe); } else { settings = &iter->second; } const uint8_t *dmp_data; unsigned int dmp_data_length; if (m_options.use_rev2) { dmp_data = buffer.GetRaw(); dmp_data_length = buffer.Size(); } else { unsigned int data_size = DMX_UNIVERSE_SIZE; buffer.Get(m_send_buffer + 1, &data_size); dmp_data = m_send_buffer; dmp_data_length = data_size + 1; } TwoByteRangeDMPAddress range_addr(0, 1, (uint16_t) dmp_data_length); DMPAddressData range_chunk(&range_addr, dmp_data, dmp_data_length); vector > ranged_chunks; ranged_chunks.push_back(range_chunk); const DMPPDU *pdu = NewRangeDMPSetProperty(true, false, ranged_chunks); E131Header header(settings->source, priority, static_cast(settings->sequence + sequence_offset), universe, preview, // preview false, // terminated m_options.use_rev2); bool result = m_e131_sender.SendDMP(header, pdu); if (result && !sequence_offset) settings->sequence++; delete pdu; return result; } bool E131Node::SendStreamTerminated(uint16_t universe, const ola::DmxBuffer &buffer, uint8_t priority) { ActiveTxUniverses::iterator iter = m_tx_universes.find(universe); string source_name; uint8_t sequence_number; if (iter == m_tx_universes.end()) { source_name = m_options.source_name; sequence_number = 0; } else { source_name = iter->second.source; sequence_number = iter->second.sequence; } unsigned int data_size = DMX_UNIVERSE_SIZE; buffer.Get(m_send_buffer + 1, &data_size); data_size++; TwoByteRangeDMPAddress range_addr(0, 1, (uint16_t) data_size); DMPAddressData range_chunk( &range_addr, m_send_buffer, data_size); vector > ranged_chunks; ranged_chunks.push_back(range_chunk); const DMPPDU *pdu = NewRangeDMPSetProperty( true, false, ranged_chunks); E131Header header(source_name, priority, sequence_number, universe, false, // preview true, // terminated false); bool result = m_e131_sender.SendDMP(header, pdu); // only update if we were previously tracking this universe if (result && iter != m_tx_universes.end()) iter->second.sequence++; delete pdu; return result; } bool E131Node::SetHandler(uint16_t universe, DmxBuffer *buffer, uint8_t *priority, Callback0 *closure) { IPV4Address addr; if (!m_e131_sender.UniverseIP(universe, &addr)) { OLA_WARN << "Unable to determine multicast group for universe " << universe; return false; } if (!m_socket.JoinMulticast(m_interface.ip_address, addr)) { OLA_WARN << "Failed to join multicast group " << addr; return false; } return m_dmp_inflator.SetHandler(universe, buffer, priority, closure); } bool E131Node::RemoveHandler(uint16_t universe) { IPV4Address addr; if (!m_e131_sender.UniverseIP(universe, &addr)) { OLA_WARN << "Unable to determine multicast group for universe " << universe; return false; } if (!m_socket.LeaveMulticast(m_interface.ip_address, addr)) { OLA_WARN << "Failed to leave multicast group " << addr; return false; } return m_dmp_inflator.RemoveHandler(universe); } void E131Node::GetKnownControllers(std::vector *controllers) { TrackedSources::const_iterator iter = m_discovered_sources.begin(); for (; iter != m_discovered_sources.end(); ++iter) { controllers->push_back(KnownController()); KnownController &controller = controllers->back(); controller.cid = iter->first; controller.ip_address = iter->second->ip_address; controller.source_name = iter->second->source_name; controller.universes = iter->second->universes; } } /* * Create a settings entry for an outgoing universe */ E131Node::tx_universe *E131Node::SetupOutgoingSettings(uint16_t universe) { tx_universe settings; settings.source = m_options.source_name; settings.sequence = 0; ActiveTxUniverses::iterator iter = m_tx_universes.insert(std::make_pair(universe, settings)).first; return &iter->second; } bool E131Node::PerformDiscoveryHousekeeping() { // Send the Universe Discovery packets. vector universes; STLKeys(m_tx_universes, &universes); uint8_t last_page = static_cast( universes.size() / DISCOVERY_PAGE_SIZE); uint32_t sequence_number = 0; for (uint8_t i = 0; i <= last_page; i++) { SendDiscoveryPage(universes, i, last_page, sequence_number); } // Delete any sources that we haven't heard from in 2 x // UNIVERSE_DISCOVERY_INTERVAL. TrackedSources::iterator iter = m_discovered_sources.begin(); while (iter != m_discovered_sources.end()) { if (iter->second->clean_counter >= 2) { delete iter->second; OLA_INFO << "Removing " << iter->first.ToString() << " due to inactivity"; m_discovered_sources.erase(iter++); } else { iter->second->clean_counter++; iter++; } } return true; } void E131Node::NewDiscoveryPage( const HeaderSet &headers, const E131DiscoveryInflator::DiscoveryPage &page) { if (!m_options.enable_draft_discovery) { return; } TrackedSources::iterator iter = STLLookupOrInsertNull( &m_discovered_sources, headers.GetRootHeader().GetCid()); if (!iter->second) { iter->second = new TrackedSource(); iter->second->ip_address = headers.GetTransportHeader().Source().Host(); iter->second->source_name = headers.GetE131Header().Source(); } TrackedSource *source = iter->second; if (source->ip_address != headers.GetTransportHeader().Source().Host()) { OLA_INFO << "CID " << headers.GetRootHeader().GetCid().ToString() << " changed from " << source->ip_address << " to " << headers.GetTransportHeader().Source().Host(); source->ip_address = headers.GetTransportHeader().Source().Host(); } source->source_name = headers.GetE131Header().Source(); source->NewPage(page.page_number, page.last_page, page.page_sequence, page.universes); } void E131Node::SendDiscoveryPage(const std::vector &universes, uint8_t this_page, uint8_t last_page, OLA_UNUSED uint32_t sequence_number) { uint16_t in_this_page = static_cast(this_page == last_page ? universes.size() % DISCOVERY_PAGE_SIZE : DISCOVERY_PAGE_SIZE); uint16_t *page_data = new uint16_t[in_this_page + 1]; page_data[0] = HostToNetwork( static_cast(this_page << 8 | last_page)); for (unsigned int i = 0; i < in_this_page; i++) { page_data[i + 1] = HostToNetwork( universes[this_page * DISCOVERY_PAGE_SIZE + i]); } E131Header header(m_options.source_name, 0, 0, DISCOVERY_UNIVERSE_ID); m_e131_sender.SendDiscoveryData( header, reinterpret_cast(page_data), (in_this_page + 1) * 2); delete[] page_data; } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/TCPTransport.h0000644000175000017500000001046413023355232017671 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * TCPTransport.h * Copyright (C) 2012 Simon Newton * * This defines the OutgoingStreamTransport and IncomingStreamTransport for * sending and receiving PDUs over stream connections. * * When receiving, the BaseInflator is passed a header containing the source IP * & port (since many higher layer protocols require this). When using the * IncomingStreamTransport you need to provide a fake ip:port pair. * * It's unlikely you want to use IncomingTCPTransport directly, since all * real world connections are TCP (rather than pipes etc.). The * IncomingStreamTransport is separate because it assists in testing. */ #ifndef LIBS_ACN_TCPTRANSPORT_H_ #define LIBS_ACN_TCPTRANSPORT_H_ #include #include "ola/io/OutputBuffer.h" #include "ola/io/OutputStream.h" #include "ola/io/Descriptor.h" #include "ola/network/TCPSocket.h" #include "libs/acn/PDU.h" #include "libs/acn/Transport.h" #include "libs/acn/TransportHeader.h" namespace ola { namespace acn { /** * Read ACN messages from a stream. Generally you want to use the * IncomingTCPTransport directly. This class is used for testing. */ class IncomingStreamTransport { public: IncomingStreamTransport(class BaseInflator *inflator, ola::io::ConnectedDescriptor *descriptor, const ola::network::IPV4SocketAddress &source); ~IncomingStreamTransport(); bool Receive(); private: // The receiver is a state machine. typedef enum { WAITING_FOR_PREAMBLE, WAITING_FOR_PDU_FLAGS, WAITING_FOR_PDU_LENGTH, WAITING_FOR_PDU, } RXState; typedef enum { TWO_BYTES = 2, THREE_BYTES = 3, } PDULengthSize; TransportHeader m_transport_header; class BaseInflator *m_inflator; ola::io::ConnectedDescriptor *m_descriptor; // end points to the byte after the data uint8_t *m_buffer_start, *m_buffer_end, *m_data_end; // the amount of data we need before we can move to the next stage unsigned int m_outstanding_data; // the state we're currently in RXState m_state; unsigned int m_block_size; unsigned int m_consumed_block_size; bool m_stream_valid; PDULengthSize m_pdu_length_size; unsigned int m_pdu_size; void HandlePreamble(); void HandlePDUFlags(); void HandlePDULength(); void HandlePDU(); void IncreaseBufferSize(unsigned int new_size); void ReadRequiredData(); void EnterWaitingForPreamble(); void EnterWaitingForPDU(); /** * Returns the free space at the end of the buffer. */ inline unsigned int FreeSpace() const { return m_buffer_start ? static_cast(m_buffer_end - m_data_end) : 0u; } /** * Return the amount of data in the buffer */ inline unsigned int DataLength() const { return m_buffer_start ? static_cast(m_data_end - m_buffer_start) : 0u; } /** * Return the size of the buffer */ inline unsigned int BufferSize() const { return static_cast(m_buffer_end - m_buffer_start); } static const unsigned int INITIAL_SIZE; static const unsigned int PDU_BLOCK_SIZE = 4; }; /** * IncomingTCPTransport is responsible for receiving ACN over TCP. */ class IncomingTCPTransport { public: IncomingTCPTransport(class BaseInflator *inflator, ola::network::TCPSocket *socket); ~IncomingTCPTransport() {} bool Receive() { return m_transport->Receive(); } private: std::auto_ptr m_transport; }; } // namespace acn } // namespace ola #endif // LIBS_ACN_TCPTRANSPORT_H_ ola-0.10.5.nojsmin/libs/acn/DMPAddress.cpp0000644000175000017500000001025613023355232017606 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DMPAddress.cpp * Defines the DMP property address types * Copyright (C) 2007 Simon Newton */ #include "ola/network/NetworkUtils.h" #include "libs/acn/DMPAddress.h" namespace ola { namespace acn { using ola::network::NetworkToHost; /* * Return the number of bytes that correspond to a DMPType */ unsigned int DMPSizeToByteSize(dmp_address_size size) { switch (size) { case ONE_BYTES: return 1; case TWO_BYTES: return 2; case FOUR_BYTES: return 4; default: return 0; } } /* * Create a new single address */ const BaseDMPAddress *NewSingleAddress(unsigned int value) { if (value > MAX_TWO_BYTE) return new FourByteDMPAddress(value); else if (value > MAX_ONE_BYTE) return new TwoByteDMPAddress((uint16_t) value); return new OneByteDMPAddress((uint8_t) value); } /* * Create a new range address. */ const BaseDMPAddress *NewRangeAddress(unsigned int value, unsigned int increment, unsigned int number) { if (value > MAX_TWO_BYTE || increment > MAX_TWO_BYTE || number > MAX_TWO_BYTE) return new FourByteRangeDMPAddress(value, increment, number); else if (value > MAX_ONE_BYTE || increment > MAX_ONE_BYTE || number > MAX_ONE_BYTE) return new TwoByteRangeDMPAddress((uint16_t) value, (uint16_t) increment, (uint16_t) number); return new OneByteRangeDMPAddress((uint8_t) value, (uint8_t) increment, (uint8_t) number); } /* * Decode a block of data into a DMPAddress */ const BaseDMPAddress *DecodeAddress(dmp_address_size size, dmp_address_type type, const uint8_t *data, unsigned int *length) { unsigned int byte_count = (type == NON_RANGE ? 1 : 3) * DMPSizeToByteSize(size); if (size == RES_BYTES || *length < byte_count) { *length = 0; return NULL; } *length = byte_count; const uint8_t *addr1 = data; // We have to do a memcpy to avoid the word alignment issues on ARM uint16_t addr2[3]; uint32_t addr4[3]; if (type == NON_RANGE) { switch (size) { case ONE_BYTES: return new OneByteDMPAddress(*data); case TWO_BYTES: memcpy(addr2, data, sizeof(addr2)); return new TwoByteDMPAddress(NetworkToHost(addr2[0])); case FOUR_BYTES: memcpy(addr4, data, sizeof(addr4)); return new FourByteDMPAddress(NetworkToHost(addr4[0])); default: return NULL; // should never make it here because we checked above } } switch (size) { case ONE_BYTES: return new OneByteRangeDMPAddress(addr1[0], addr1[1], addr1[2]); case TWO_BYTES: memcpy(addr2, data, sizeof(addr2)); return new TwoByteRangeDMPAddress(NetworkToHost(addr2[0]), NetworkToHost(addr2[1]), NetworkToHost(addr2[2])); case FOUR_BYTES: memcpy(addr4, data, sizeof(addr4)); return new FourByteRangeDMPAddress(NetworkToHost(addr4[0]), NetworkToHost(addr4[1]), NetworkToHost(addr4[2])); default: return NULL; // should never make it here because we checked above } } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/libs/acn/HeaderSetTest.cpp0000644000175000017500000002004513023355232020361 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * HeaderSetTest.cpp * Test fixture for the HeaderSet class * Copyright (C) 2007 Simon Newton */ #include #include #include #include "ola/acn/CID.h" #include "ola/network/SocketAddress.h" #include "ola/network/NetworkUtils.h" #include "libs/acn/HeaderSet.h" #include "ola/testing/TestUtils.h" using ola::acn::CID; using ola::network::IPV4SocketAddress; using ola::acn::DMPHeader; using ola::acn::E131Header; using ola::acn::E131Rev2Header; using ola::acn::E133Header; using ola::acn::FOUR_BYTES; using ola::acn::HeaderSet; using ola::acn::NON_RANGE; using ola::acn::ONE_BYTES; using ola::acn::RANGE_EQUAL; using ola::acn::RootHeader; using ola::acn::TransportHeader; class HeaderSetTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(HeaderSetTest); CPPUNIT_TEST(testTransportHeader); CPPUNIT_TEST(testRootHeader); CPPUNIT_TEST(testE131Header); CPPUNIT_TEST(testE133Header); CPPUNIT_TEST(testDMPHeader); CPPUNIT_TEST(testHeaderSet); CPPUNIT_TEST_SUITE_END(); public: void testRootHeader(); void testTransportHeader(); void testE131Header(); void testE133Header(); void testDMPHeader(); void testHeaderSet(); }; CPPUNIT_TEST_SUITE_REGISTRATION(HeaderSetTest); /* * Check that the transport header works. */ void HeaderSetTest::testTransportHeader() { IPV4SocketAddress address = IPV4SocketAddress::FromStringOrDie( "192.168.1.1:42"); TransportHeader header(address, TransportHeader::UDP); OLA_ASSERT(address == header.Source()); OLA_ASSERT_EQ(TransportHeader::UDP, header.Transport()); // test copy and assign TransportHeader header2 = header; OLA_ASSERT(address == header2.Source()); OLA_ASSERT(header2 == header); TransportHeader header3(header); OLA_ASSERT(address == header3.Source()); OLA_ASSERT(header3 == header); } /* * Check that the root header works. */ void HeaderSetTest::testRootHeader() { CID cid = CID::Generate(); RootHeader header; header.SetCid(cid); OLA_ASSERT(cid == header.GetCid()); // test copy and assign RootHeader header2 = header; OLA_ASSERT(cid == header2.GetCid()); OLA_ASSERT(header2 == header); RootHeader header3(header); OLA_ASSERT(cid == header3.GetCid()); OLA_ASSERT(header3 == header); } /* * test the E1.31 Header */ void HeaderSetTest::testE131Header() { E131Header header("foo", 1, 2, 2050); OLA_ASSERT("foo" == header.Source()); OLA_ASSERT_EQ((uint8_t) 1, header.Priority()); OLA_ASSERT_EQ((uint8_t) 2, header.Sequence()); OLA_ASSERT_EQ((uint16_t) 2050, header.Universe()); OLA_ASSERT_EQ(false, header.PreviewData()); OLA_ASSERT_EQ(false, header.StreamTerminated()); OLA_ASSERT_FALSE(header.UsingRev2()); // test copy and assign E131Header header2 = header; OLA_ASSERT(header.Source() == header2.Source()); OLA_ASSERT_EQ(header.Priority(), header2.Priority()); OLA_ASSERT_EQ(header.Sequence(), header2.Sequence()); OLA_ASSERT_EQ(header.Universe(), header2.Universe()); OLA_ASSERT_EQ(false, header2.PreviewData()); OLA_ASSERT_EQ(false, header2.StreamTerminated()); OLA_ASSERT_FALSE(header2.UsingRev2()); E131Header header3(header); OLA_ASSERT(header.Source() == header3.Source()); OLA_ASSERT_EQ(header.Priority(), header3.Priority()); OLA_ASSERT_EQ(header.Sequence(), header3.Sequence()); OLA_ASSERT_EQ(header.Universe(), header3.Universe()); OLA_ASSERT(header == header3); // test a rev 2 header E131Rev2Header header_rev2("foo", 1, 2, 2050); OLA_ASSERT("foo" == header_rev2.Source()); OLA_ASSERT_EQ((uint8_t) 1, header_rev2.Priority()); OLA_ASSERT_EQ((uint8_t) 2, header_rev2.Sequence()); OLA_ASSERT_EQ((uint16_t) 2050, header_rev2.Universe()); OLA_ASSERT(header_rev2.UsingRev2()); OLA_ASSERT_FALSE((header == header_rev2)); E131Rev2Header header2_rev2 = header_rev2; OLA_ASSERT(header2_rev2 == header_rev2); // test a header with the special bits set E131Header header4("foo", 1, 2, 2050, true, true); OLA_ASSERT("foo" == header4.Source()); OLA_ASSERT_EQ((uint8_t) 1, header4.Priority()); OLA_ASSERT_EQ((uint8_t) 2, header4.Sequence()); OLA_ASSERT_EQ((uint16_t) 2050, header4.Universe()); OLA_ASSERT_EQ(true, header4.PreviewData()); OLA_ASSERT_EQ(true, header4.StreamTerminated()); OLA_ASSERT_FALSE(header4.UsingRev2()); } /* * test the E1.33 Header */ void HeaderSetTest::testE133Header() { E133Header header("foo", 9840, 2); OLA_ASSERT("foo" == header.Source()); OLA_ASSERT_EQ((uint32_t) 9840, header.Sequence()); OLA_ASSERT_EQ((uint16_t) 2, header.Endpoint()); // test copy and assign E133Header header2 = header; OLA_ASSERT(header.Source() == header2.Source()); OLA_ASSERT_EQ(header.Sequence(), header2.Sequence()); OLA_ASSERT_EQ(header.Endpoint(), header2.Endpoint()); E133Header header3(header); OLA_ASSERT(header.Source() == header3.Source()); OLA_ASSERT_EQ(header.Sequence(), header3.Sequence()); OLA_ASSERT_EQ(header.Endpoint(), header3.Endpoint()); OLA_ASSERT(header == header3); } /* * test the DMP Header */ void HeaderSetTest::testDMPHeader() { DMPHeader header(false, false, NON_RANGE, ONE_BYTES); OLA_ASSERT_EQ(false, header.IsVirtual()); OLA_ASSERT_EQ(false, header.IsRelative()); OLA_ASSERT_EQ(NON_RANGE, header.Type()); OLA_ASSERT_EQ(ONE_BYTES, header.Size()); OLA_ASSERT_EQ((uint8_t) 0, header.Header()); DMPHeader test_header(0); OLA_ASSERT(test_header == header); DMPHeader header2(false, true, RANGE_EQUAL, FOUR_BYTES); OLA_ASSERT_EQ(false, header2.IsVirtual()); OLA_ASSERT_EQ(true, header2.IsRelative()); OLA_ASSERT_EQ(RANGE_EQUAL, header2.Type()); OLA_ASSERT_EQ(FOUR_BYTES, header2.Size()); OLA_ASSERT_EQ((uint8_t) 0x62, header2.Header()); DMPHeader test_header2(0x62); OLA_ASSERT_TRUE(test_header2 == header2); // test copy and assign DMPHeader header3 = header; OLA_ASSERT_TRUE(header3 == header); OLA_ASSERT_NE(header3, header2); DMPHeader header4(header); OLA_ASSERT_TRUE(header4 == header); OLA_ASSERT_NE(header4, header2); } /* * Check that the header set works */ void HeaderSetTest::testHeaderSet() { HeaderSet headers; RootHeader root_header; E131Header e131_header("e131", 1, 2, 6001); E133Header e133_header("foo", 1, 2050); DMPHeader dmp_header(false, false, NON_RANGE, ONE_BYTES); // test the root header component CID cid = CID::Generate(); root_header.SetCid(cid); headers.SetRootHeader(root_header); OLA_ASSERT(root_header == headers.GetRootHeader()); // test the E1.31 header component headers.SetE131Header(e131_header); OLA_ASSERT(e131_header == headers.GetE131Header()); // test the E1.33 header component headers.SetE133Header(e133_header); OLA_ASSERT(e133_header == headers.GetE133Header()); // test the DMP headers component headers.SetDMPHeader(dmp_header); OLA_ASSERT(dmp_header == headers.GetDMPHeader()); // test assign HeaderSet headers2 = headers; OLA_ASSERT(root_header == headers2.GetRootHeader()); OLA_ASSERT(e131_header == headers2.GetE131Header()); OLA_ASSERT(e133_header == headers2.GetE133Header()); OLA_ASSERT(dmp_header == headers2.GetDMPHeader()); OLA_ASSERT(headers2 == headers); // test copy HeaderSet headers3(headers); OLA_ASSERT(root_header == headers3.GetRootHeader()); OLA_ASSERT(e131_header == headers3.GetE131Header()); OLA_ASSERT(e133_header == headers3.GetE133Header()); OLA_ASSERT(dmp_header == headers3.GetDMPHeader()); OLA_ASSERT(headers3 == headers); } ola-0.10.5.nojsmin/libs/acn/PDU.cpp0000644000175000017500000001227613023355232016314 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * PDU.cpp * The base PDU class * Copyright (C) 2007 Simon Newton */ #include "ola/Logging.h" #include "ola/network/NetworkUtils.h" #include "libs/acn/PDU.h" namespace ola { namespace acn { using ola::io::OutputStream; using ola::network::HostToNetwork; /* * Return the length of this PDU * @return length of the pdu */ unsigned int PDU::Size() const { unsigned int length = m_vector_size + HeaderSize() + DataSize(); if (length > TWOB_LENGTH_LIMIT - 2) length += 1; length += 2; return length; } /* * Pack this PDU into a buffer * @param buffer pointer to the buffer * @param length length of the buffer * @return false on error, true otherwise */ bool PDU::Pack(uint8_t *buffer, unsigned int *length) const { unsigned int size = Size(); unsigned int offset = 0; if (*length < size) { OLA_WARN << "PDU Pack: buffer too small, required " << size << ", got " << *length; *length = 0; return false; } if (size <= TWOB_LENGTH_LIMIT) { buffer[0] = (uint8_t) ((size & 0x0f00) >> 8); buffer[1] = (uint8_t) (size & 0xff); } else { buffer[0] = (uint8_t) ((size & 0x0f0000) >> 16); buffer[1] = (uint8_t) ((size & 0xff00) >> 8); buffer[2] = (uint8_t) (size & 0xff); offset += 1; } buffer[0] |= VFLAG_MASK; buffer[0] |= HFLAG_MASK; buffer[0] |= DFLAG_MASK; offset += 2; switch (m_vector_size) { case PDU::ONE_BYTE: buffer[offset++] = (uint8_t) m_vector; break; case PDU::TWO_BYTES: buffer[offset++] = static_cast(0xff & (m_vector >> 8)); buffer[offset++] = static_cast(0xff & m_vector); break; case PDU::FOUR_BYTES: buffer[offset++] = static_cast(0xff & (m_vector >> 24)); buffer[offset++] = static_cast(0xff & (m_vector >> 16)); buffer[offset++] = static_cast(0xff & (m_vector >> 8)); buffer[offset++] = static_cast(0xff & m_vector); break; default: OLA_WARN << "unknown vector size " << m_vector_size; return false; } unsigned int bytes_used = *length - offset; if (!PackHeader(buffer + offset, &bytes_used)) { *length = 0; return false; } offset += bytes_used; bytes_used = *length - offset; if (!PackData(buffer + offset, &bytes_used)) { *length = 0; return false; } offset += bytes_used; *length = offset; return true; } /** * Write this PDU to an OutputStream. */ void PDU::Write(OutputStream *stream) const { unsigned int size = Size(); if (size <= TWOB_LENGTH_LIMIT) { uint16_t flags_and_length = static_cast(size); flags_and_length |= (VFLAG_MASK | HFLAG_MASK | DFLAG_MASK) << 8u; *stream << HostToNetwork(flags_and_length); } else { uint8_t vhl_flags = static_cast((size & 0x0f0000) >> 16); vhl_flags |= VFLAG_MASK | HFLAG_MASK | DFLAG_MASK; *stream << vhl_flags; *stream << (uint8_t) ((size & 0xff00) >> 8); *stream << (uint8_t) (size & 0xff); } switch (m_vector_size) { case PDU::ONE_BYTE: *stream << static_cast(m_vector); break; case PDU::TWO_BYTES: *stream << HostToNetwork(static_cast(m_vector)); break; case PDU::FOUR_BYTES: *stream << HostToNetwork(m_vector); break; } PackHeader(stream); PackData(stream); } /** * Prepend the flags and length to an OutputBufferInterface. */ void PDU::PrependFlagsAndLength(ola::io::OutputBufferInterface *output, uint8_t flags) { PrependFlagsAndLength(output, output->Size(), flags); } /** * Prepend the flags and length to an OutputBufferInterface. */ void PDU::PrependFlagsAndLength(ola::io::OutputBufferInterface *output, unsigned int size, uint8_t flags) { if (size + 2 <= TWOB_LENGTH_LIMIT) { size += 2; uint16_t flags_and_length = static_cast(size); flags_and_length |= static_cast(flags << 8u); flags_and_length = HostToNetwork(flags_and_length); output->Write(reinterpret_cast(&flags_and_length), sizeof(flags_and_length)); } else { size += 3; uint8_t flags_and_length[3]; flags_and_length[0] = static_cast((size & 0x0f0000) >> 16); flags_and_length[0] |= flags; flags_and_length[1] = static_cast((size & 0xff00) >> 8); flags_and_length[2] = static_cast(size & 0xff); output->Write(flags_and_length, sizeof(flags_and_length)); } } } // namespace acn } // namespace ola ola-0.10.5.nojsmin/COPYING0000644000175000017500000006350413023355232014521 0ustar wouterwouter GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, 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 and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, 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 library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete 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 distribute a copy of this License along with the Library. 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 Library or any portion of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, 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 Library, 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 Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you 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. If distribution of 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 satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be 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. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library 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. 9. 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 Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library 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 with this License. 11. 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 Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library 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 Library. 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. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library 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. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser 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 Library 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 Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, 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 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. 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 library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ola-0.10.5.nojsmin/LICENCE0000644000175000017500000000103313023355232014440 0ustar wouterwouterLicencing Information for OLA ========================================= C++ ----------------------------------------- The files required for libola and libolacommon are licenced under the LGPLv2.1 (or later), this means you are free to link against the OLA client library in your own programs. The files required for libolaserver and olad are licenced under the GPL v2 (or later). Python ------------------------------------------ The Python client API is LGPL, the examples and RDM Responder Test Suite is GPL. Simon Newton 15/7/2005 ola-0.10.5.nojsmin/python/0000755000175000017500000000000013155164170015004 5ustar wouterwouterola-0.10.5.nojsmin/python/Makefile.mk0000644000175000017500000000010313023355232017037 0ustar wouterwouterinclude python/examples/Makefile.mk include python/ola/Makefile.mk ola-0.10.5.nojsmin/python/ola/0000755000175000017500000000000013134123605015552 5ustar wouterwouterola-0.10.5.nojsmin/python/ola/Makefile.mk0000644000175000017500000000427113023355232017624 0ustar wouterwouter# OLA Python client include python/ola/rpc/Makefile.mk # Python modules. ################################################## artnet_path = ${top_srcdir}/plugins/artnet/messages artnet_proto = $(artnet_path)/ArtNetConfigMessages.proto ola_path = ${top_srcdir}/common/protocol ola_proto = $(ola_path)/Ola.proto pids_path = ${top_srcdir}/common/rdm pids_proto = $(pids_path)/Pids.proto usbpro_path = ${top_srcdir}/plugins/usbpro/messages usbpro_proto = $(usbpro_path)/UsbProConfigMessages.proto if BUILD_PYTHON_LIBS output_files = \ python/ola/ArtNetConfigMessages_pb2.py \ python/ola/Ola_pb2.py \ python/ola/UsbProConfigMessages_pb2.py \ python/ola/Pids_pb2.py \ python/ola/PidStoreLocation.py \ python/ola/Version.py built_sources += $(output_files) nodist_pkgpython_PYTHON = $(output_files) pkgpython_PYTHON = \ python/ola/ClientWrapper.py \ python/ola/DMXConstants.py \ python/ola/DUBDecoder.py \ python/ola/MACAddress.py \ python/ola/OlaClient.py \ python/ola/RDMAPI.py \ python/ola/RDMConstants.py \ python/ola/PidStore.py \ python/ola/UID.py \ python/ola/__init__.py endif python/ola/ArtNetConfigMessages_pb2.py: $(artnet_proto) $(PROTOC) --python_out python/ola/ -I $(artnet_path) $(artnet_proto) python/ola/Ola_pb2.py: $(ola_proto) $(PROTOC) --python_out python/ola/ -I $(ola_path) $(ola_proto) python/ola/Pids_pb2.py: $(pids_proto) $(PROTOC) --python_out python/ola/ -I $(pids_path) $(pids_proto) python/ola/UsbProConfigMessages_pb2.py: $(usbpro_proto) $(PROTOC) --python_out python/ola/ -I $(usbpro_path) $(usbpro_proto) python/ola/PidStoreLocation.py: python/ola/Makefile.mk configure.ac echo "location = '${piddatadir}'" > python/ola/PidStoreLocation.py python/ola/Version.py: python/ola/Makefile.mk configure.ac config/ola_version.m4 echo "version = '${VERSION}'" > python/ola/Version.py # TESTS ################################################## dist_check_SCRIPTS += \ python/ola/DUBDecoderTest.py \ python/ola/MACAddressTest.py \ python/ola/UIDTest.py if BUILD_PYTHON_LIBS test_scripts += \ python/ola/DUBDecoderTest.py \ python/ola/MACAddressTest.py \ python/ola/UIDTest.py endif CLEANFILES += python/ola/*.pyc ola-0.10.5.nojsmin/python/ola/DMXConstants.py0000644000175000017500000000165213023355232020455 0ustar wouterwouter# This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library 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 # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # DMXConstants.py # Copyright (C) 2014 Sean Sill """Constants for E1.11 DMX512A (DMX). """ __author__ = 'sms3h2@gmail.com (Sean Sill)' DMX_UNIVERSE_SIZE = 512 DMX_MIN_SLOT_VALUE = 0 DMX_MAX_SLOT_VALUE = 255 ola-0.10.5.nojsmin/python/ola/RDMAPI.py0000644000175000017500000002301613023355232017102 0ustar wouterwouter# This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library 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 # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # RDMAPI.py # Copyright (C) 2010 Simon Newton from __future__ import print_function import sys from ola.OlaClient import OlaClient from ola import PidStore """The Python RDM API.""" __author__ = 'nomis52@gmail.com (Simon Newton)' class RDMAPI(object): """The RDM API. The RDM API provides parameter data serialization & parsing using a PidStore. """ # This maps ola.proto enums to PidStore enums COMMAND_CLASS_DICT = { OlaClient.RDM_DISCOVERY_RESPONSE: PidStore.RDM_DISCOVERY, OlaClient.RDM_GET_RESPONSE: PidStore.RDM_GET, OlaClient.RDM_SET_RESPONSE: PidStore.RDM_SET, } def __init__(self, client, pid_store, strict_checks=True): """Create a new RDM API. Args: client: A OlaClient object. pid_store: A PidStore instance strict_checks: Enable strict checking """ self._client = client self._pid_store = pid_store self._strict_checks = strict_checks def Discovery(self, universe, uid, sub_device, pid, callback, args, include_frames=False): """Send an RDM Discovery message with the raw data supplied. Args: universe: The universe to send the request on. uid: The UID to address the request to. sub_device: The Sub Device to send the request to. pid: A PID object that describes the format of the request. callback: The callback to run when the request completes. args: The args to pack into the param data section. include_frames: True if the response should include the raw frame data. Return: True if sent ok, False otherwise. """ return self._SendRequest(universe, uid, sub_device, pid, callback, args, PidStore.RDM_DISCOVERY, include_frames) def RawDiscovery(self, universe, uid, sub_device, pid, callback, data, include_frames=False): """Send an RDM Discovery message with the raw data supplied. Args: universe: The universe to send the request on. uid: The UID to address the request to. sub_device: The Sub Device to send the request to. pid: A PID object that describes the format of the request. callback: The callback to run when the request completes. data: The param data include_frames: True if the response should include the raw frame data. Return: True if sent ok, False otherwise. """ return self._SendRawRequest(universe, uid, sub_device, pid, callback, data, PidStore.RDM_DISCOVERY, include_frames) def Get(self, universe, uid, sub_device, pid, callback, args=[], include_frames=False): """Send a RDM Get message, packing the arguments into a message. Args: universe: The universe to send the request on. uid: The UID to address the request to. sub_device: The Sub Device to send the request to. pid: A PID object that describes the format of the request. callback: The callback to run when the request completes. args: The args to pack into the param data section. include_frames: True if the response should include the raw frame data. Return: True if sent ok, False otherwise. """ if self._strict_checks and uid.IsBroadcast(): print("Can't send GET to broadcast address %s" % uid, file=sys.stderr) return False return self._SendRequest(universe, uid, sub_device, pid, callback, args, PidStore.RDM_GET, include_frames) def RawGet(self, universe, uid, sub_device, pid, callback, data, include_frames=False): """Send a RDM Get message with the raw data supplied. Args: universe: The universe to send the request on. uid: The UID to address the request to. sub_device: The Sub Device to send the request to. pid: A PID object that describes the format of the request. callback: The callback to run when the request completes. data: The param data include_frames: True if the response should include the raw frame data. Return: True if sent ok, False otherwise. """ if self._strict_checks and uid.IsBroadcast(): print("Can't send GET to broadcast address %s" % uid, file=sys.stderr) return False return self._SendRawRequest(universe, uid, sub_device, pid, callback, data, PidStore.RDM_GET, include_frames) def Set(self, universe, uid, sub_device, pid, callback, args=[], include_frames=False): """Send a RDM Set message. Args: universe: The universe to send the request on. uid: The UID to address the request to. sub_device: The Sub Device to send the request to. pid: A PID object that describes the format of the request. callback: The callback to run when the request completes. args: The args to pack into the param data section. include_frames: True if the response should include the raw frame data. Return: True if sent ok, False otherwise. """ return self._SendRequest(universe, uid, sub_device, pid, callback, args, PidStore.RDM_SET, include_frames) def RawSet(self, universe, uid, sub_device, pid, callback, args=[], include_frames=False): """Send a RDM Set message with the raw data supplied. Args: universe: The universe to send the request on. uid: The UID to address the request to. sub_device: The Sub Device to send the request to. pid: A PID object that describes the format of the request. callback: The callback to run when the request completes. data: The param data include_frames: True if the response should include the raw frame data. Return: True if sent ok, False otherwise. """ return self._SendRawRequest(universe, uid, sub_device, pid, callback, args, PidStore.RDM_SET, include_frames) def _SendRequest(self, universe, uid, sub_device, pid, callback, args, request_type, include_frames): """Send a RDM Request. Args: universe: The universe to send the request on. uid: The UID to address the request to. sub_device: The Sub Device to send the request to. pid: A PID object that describes the format of the request. callback: The callback to run when the request completes. args: The args to pack into the param data section. request_type: PidStore.RDM_GET or PidStore.RDM_SET or PidStore.RDM_DISCOVERY include_frames: True if the response should include the raw frame data. Return: True if sent ok, False otherwise. """ data = pid.Pack(args, request_type) if data is None: print('Could not pack data', file=sys.stderr) return False return self._SendRawRequest(universe, uid, sub_device, pid, callback, data, request_type, include_frames) def _SendRawRequest(self, universe, uid, sub_device, pid, callback, data, request_type, include_frames): """Send a RDM Request. Args: universe: The universe to send the request on. uid: The UID to address the request to. sub_device: The Sub Device to send the request to. pid: A PID object that describes the format of the request. callback: The callback to run when the request completes. data: The param data. request_type: PidStore.RDM_GET or PidStore.RDM_SET include_frames: True if the response should include the raw frame data. Return: True if sent ok, False otherwise. """ if self._strict_checks: request_params = { 'uid': uid, 'sub_device': sub_device, } if not pid.ValidateAddressing(request_params, request_type): return False if request_type == PidStore.RDM_SET: method = self._client.RDMSet elif request_type == PidStore.RDM_DISCOVERY: method = self._client.SendRawRDMDiscovery else: method = self._client.RDMGet return method( universe, uid, sub_device, pid.value, lambda response: self._GenericHandler(callback, uid, response), data, include_frames) def _GenericHandler(self, callback, uid, response): """ Args: callback: the function to run uid: The uid the request was for response: A RDMResponse object """ obj = None unpack_exception = None if response.WasAcked(): request_type = self.COMMAND_CLASS_DICT[response.command_class] pid_descriptor = self._pid_store.GetPid(response.pid, uid.manufacturer_id) if pid_descriptor: try: obj = pid_descriptor.Unpack(response.data, request_type) except PidStore.UnpackException as e: obj = None unpack_exception = e else: obj = response.data callback(response, obj, unpack_exception) ola-0.10.5.nojsmin/python/ola/UIDTest.py0000755000175000017500000000605313023355232017414 0ustar wouterwouter#!/usr/bin/env python # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library 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 # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # UIDTest.py # Copyright (C) 2005 Simon Newton import sys import unittest from ola.UID import UID, UIDOutOfRangeException """Test cases for the UID class.""" __author__ = 'nomis52@gmail.com (Simon Newton)' class UIDTest(unittest.TestCase): def testBasic(self): uid = UID(0x707a, 0x12345678) self.assertEqual(0x707a, uid.manufacturer_id) self.assertEqual(0x12345678, uid.device_id) self.assertEqual('707a:12345678', str(uid)) # Python 3 does not allow sorting of incompatible types. # We don't use sys.version_info.major to support Python 2.6. if sys.version_info[0] == 2: self.assertTrue(uid > None) uid2 = UID(0x707a, 0x12345679) self.assertTrue(uid2 > uid) uid3 = UID(0x7079, 0x12345678) self.assertTrue(uid > uid3) uids = [uid, uid2, uid3] self.assertEqual([uid3, uid, uid2], sorted(uids)) vendorcast_uid = UID.VendorcastAddress(0x707a) self.assertTrue(vendorcast_uid.IsBroadcast()) broadcast_uid = UID.AllDevices() self.assertTrue(broadcast_uid.IsBroadcast()) def testFromString(self): self.assertEqual(None, UID.FromString('')) self.assertEqual(None, UID.FromString('abc')) self.assertEqual(None, UID.FromString(':')) self.assertEqual(None, UID.FromString('0:1:2')) self.assertEqual(None, UID.FromString('12345:1234')) uid = UID.FromString('00a0:12345678') self.assertTrue(uid) self.assertEqual(0x00a0, uid.manufacturer_id) self.assertEqual(0x12345678, uid.device_id) self.assertEqual('00a0:12345678', str(uid)) def testSorting(self): u1 = UID(0x4845, 0xfffffffe) u2 = UID(0x4845, 0x0000022e) u3 = UID(0x4844, 0x0000022e) u4 = UID(0x4846, 0x0000022e) uids = sorted([u1, u2, u3, u4]) self.assertEqual([u3, u2, u1, u4], uids) def testNextAndPrevious(self): u1 = UID(0x4845, 0xfffffffe) u2 = UID.NextUID(u1) self.assertEqual('4845:ffffffff', str(u2)) u3 = UID.NextUID(u2) self.assertEqual('4846:00000000', str(u3)) u4 = UID.PreviousUID(u3) self.assertEqual(u2, u4) u5 = UID.PreviousUID(u4) self.assertEqual(u1, u5) first_uid = UID(0, 0) self.assertRaises(UIDOutOfRangeException, UID.PreviousUID, first_uid) all_uids = UID.AllDevices() self.assertRaises(UIDOutOfRangeException, UID.NextUID, all_uids) if __name__ == '__main__': unittest.main() ola-0.10.5.nojsmin/python/ola/UID.py0000644000175000017500000000640513023355232016552 0ustar wouterwouter# This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library 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 # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # UID.py # Copyright (C) 2010 Simon Newton """The UID class.""" __author__ = 'nomis52@gmail.com (Simon Newton)' class Error(Exception): """Base Error Class.""" class UIDOutOfRangeException(Error): """Returned when a UID would be out of range.""" class UID(object): """Represents a UID.""" def __init__(self, manufacturer_id, device_id): self._manufacturer_id = manufacturer_id self._device_id = device_id @property def manufacturer_id(self): return self._manufacturer_id @property def device_id(self): return self._device_id def IsBroadcast(self): return self._device_id == 0xffffffff def __str__(self): return '%04x:%08x' % (self._manufacturer_id, self._device_id) def __hash__(self): return hash(str(self)) def __repr__(self): return self.__str__() def __cmp__(self, other): if other is None: return 1 if self._manufacturer_id == other._manufacturer_id: return cmp(self._device_id, other._device_id) return cmp(self.manufacturer_id, other.manufacturer_id) def __lt__(self, other): if self.manufacturer_id != other.manufacturer_id: return self.manufacturer_id < other.manufacturer_id else: return self.device_id < other.device_id def __eq__(self, other): if other is None: return False return self.manufacturer_id == other.manufacturer_id and \ self.device_id == other.device_id @staticmethod def AllDevices(): return UID(0xffff, 0xffffffff) @staticmethod def VendorcastAddress(manufacturer_id): return UID(manufacturer_id, 0xffffffff) @staticmethod def FromString(uid_str): """Create a new UID from a string. Args: uid_str: The string representation of the UID, e.g. 00f0:12345678. """ parts = uid_str.split(':') if len(parts) != 2: return None try: manufacturer_id = int(parts[0], 16) device_id = int(parts[1], 16) except ValueError: return None if manufacturer_id > 0xffff or device_id > 0xffffffff: return None return UID(manufacturer_id, device_id) @staticmethod def NextUID(uid): if uid == UID.AllDevices(): raise UIDOutOfRangeException(uid) if uid.IsBroadcast(): return UID(uid.manufacturer_id + 1, 0) else: return UID(uid.manufacturer_id, uid.device_id + 1) @staticmethod def PreviousUID(uid): if uid == UID(0, 0): raise UIDOutOfRangeException(uid) if uid.device_id == 0: return UID(uid.manufacturer_id - 1, 0xffffffff) else: return UID(uid.manufacturer_id, uid.device_id - 1) ola-0.10.5.nojsmin/python/ola/PidStore.py0000644000175000017500000011050513023355232017657 0ustar wouterwouter# This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library 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 # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # PidStore.py # Copyright (C) 2010 Simon Newton # Holds all the information about RDM PIDs from __future__ import print_function import binascii import math import ola.RDMConstants import os import socket import struct import sys from google.protobuf import text_format from ola import PidStoreLocation from ola import Pids_pb2 from ola.MACAddress import MACAddress from ola.UID import UID """The PID Store.""" __author__ = 'nomis52@gmail.com (Simon Newton)' # Various sub device enums ROOT_DEVICE = 0 MAX_VALID_SUB_DEVICE = 0x0200 ALL_SUB_DEVICES = 0xffff # The two types of commands classes RDM_GET, RDM_SET, RDM_DISCOVERY = range(3) class Error(Exception): """Base error class.""" class InvalidPidFormat(Error): "Indicates the PID data file was invalid.""" class PidStructureException(Error): """Raised if the PID structure isn't vaild.""" class ArgsValidationError(Error): """Raised if the arguments don't match the expected frame format.""" class UnpackException(Error): """Raised if we can't unpack the data corectly.""" class MissingPLASAPIDs(Error): """Raises if the files did not contain the PLASA PIDs.""" class Pid(object): """A class that describes everything about a PID.""" def __init__(self, name, value, discovery_request=None, discovery_response=None, get_request=None, get_response=None, set_request=None, set_response=None, discovery_validators=[], get_validators=[], set_validators=[]): """Create a new PID. Args: name: the human readable name value: the 2 byte PID value discovery_request: A Group object, or None if DISCOVERY isn't supported discovery_response: A Group object, or None if DISCOVERY isn't supported get_request: A Group object, or None if GET isn't supported get_response: set_request: A Group object, or None if SET isn't supported set_response: discovery_validators: get_validators: set_validators: """ self._name = name self._value = value self._requests = { RDM_GET: get_request, RDM_SET: set_request, RDM_DISCOVERY: discovery_request, } self._responses = { RDM_GET: get_response, RDM_SET: set_response, RDM_DISCOVERY: discovery_response, } self._validators = { RDM_GET: get_validators, RDM_SET: set_validators, RDM_DISCOVERY: discovery_validators, } @property def name(self): return self._name @property def value(self): return self._value def RequestSupported(self, command_class): """Check if this PID allows a command class.""" return self._requests.get(command_class) is not None def GetRequest(self, command_class): return self._requests.get(command_class) def GetRequestField(self, command_class, field_name): fields = self.GetRequest(command_class).GetAtoms() fields = [f for f in fields if f.name == field_name] return fields[0] if fields else None def ResponseSupported(self, command_class): """Check if this PID responds to a command class.""" return self._requests.get(command_class) is not None def GetResponse(self, command_class): return self._responses.get(command_class) def GetResponseField(self, command_class, field_name): fields = self.GetResponse(command_class).GetAtoms() fields = [f for f in fields if f.name == field_name] return fields[0] if fields else None def ValidateAddressing(self, args, command_class): """Run the validators.""" validators = self._validators.get(command_class) if validators is None: return False args['pid'] = self for validator in validators: if not validator(args): return False return True def __cmp__(self, other): return cmp(self._value, other._value) def __str__(self): return '%s (0x%04hx)' % (self.name, self.value) def __hash__(self): return self._value def Pack(self, args, command_class): """Pack args Args: args: A list of arguments of the right types. command_class: RDM_GET or RDM_SET or RDM_DISCOVERY Returns: Binary data which can be used as the Param Data. """ group = self._requests.get(command_class) blob, args_used = group.Pack(args) return blob def Unpack(self, data, command_class): """Unpack a message. Args: data: The raw data command_class: RDM_GET or RDM_SET or RDM_DISCOVERY """ group = self._responses.get(command_class) if group is None: raise UnpackException('Response contained data (hex): %s' % binascii.b2a_hex(data)) output = group.Unpack(data)[0] return output def GetRequestDescription(self, command_class): """Get a help string that describes the format of the request. Args: command_class: RDM_GET or RDM_SET or RDM_DISCOVERY Returns: A help string. """ group = self._requests.get(command_class) return group.GetDescription() # The following classes are used to describe RDM messages class Atom(object): """The basic field in an RDM message.""" def __init__(self, name): self._name = name @property def name(self): return self._name def CheckForSingleArg(self, args): if len(args) < 1: raise ArgsValidationError('Missing argument for %s' % self.name) def __str__(self): return '%s, %s' % (self.__class__, self._name) def __repr__(self): return '%s, %s' % (self.__class__, self._name) def GetDescription(self, indent=0): return str(self) class FixedSizeAtom(Atom): def __init__(self, name, format_char): super(FixedSizeAtom, self).__init__(name) self._char = format_char @property def size(self): return struct.calcsize(self._FormatString()) def FixedSize(self): """Returns true if the size of this atom doesn't vary.""" return True def Unpack(self, data): format_string = self._FormatString() try: values = struct.unpack(format_string, data) except struct.error as e: raise UnpackException(e) return values[0] def Pack(self, args): format_string = self._FormatString() try: data = struct.pack(format_string, args[0]) except struct.error as e: raise ArgsValidationError("Can't pack data: %s" % e) return data, 1 def _FormatString(self): return '!%s' % self._char class Bool(FixedSizeAtom): BOOL_MAP = { 'true': 1, 'false': 0, } def __init__(self, name): # once we have 2.6 use ? here super(Bool, self).__init__(name, 'B') def Pack(self, args): self.CheckForSingleArg(args) arg = args[0] if isinstance(arg, str): arg = args[0].lower() if arg not in self.BOOL_MAP: raise ArgsValidationError('Argument should be true or false') arg = self.BOOL_MAP[arg] return super(Bool, self).Pack([arg]) def Unpack(self, value): return bool(super(Bool, self).Unpack(value)) def GetDescription(self, indent=0): indent = ' ' * indent return '%s%s: ' % (indent, self.name) class Range(object): """A range of allowed int values.""" def __init__(self, min, max): self.min = min self.max = max def Matches(self, value): return value >= self.min and value <= self.max def __str__(self): if self.min == self.max: return '%d' % self.min else: return '[%d, %d]' % (self.min, self.max) class IntAtom(FixedSizeAtom): def __init__(self, name, char, max_value, **kwargs): super(IntAtom, self).__init__(name, char) # About Labels & Ranges: # If neither labels nor ranges are specified, the valid values is the range # of the data type. # If labels are specified, and ranges aren't, the valid values are the # labels # If ranges are specified, the valid values are those which fall into the # range (inclusive). # If both are specified, the enum values must fall into the specified # ranges. # ranges limit the allowed values for a field self._ranges = kwargs.get('ranges', [])[:] self._multiplier = kwargs.get('multiplier', 0) # labels provide a user friendly way of referring to data values self._labels = {} for value, label in kwargs.get('labels', []): self._labels[label.lower()] = value if not kwargs.get('ranges', []): # Add the labels to the list of allowed values self._ranges.append(Range(value, value)) if not self._ranges: self._ranges.append(Range(0, max_value)) def Pack(self, args): self.CheckForSingleArg(args) arg = args[0] if isinstance(arg, str): arg = arg.lower() value = self._labels.get(arg) # not a labeled value if value is None: value = self._AccountForMultiplierPack(args[0]) for range in self._ranges: if range.Matches(value): break else: raise ArgsValidationError('Param %d out of range, must be one of %s' % (value, self._GetAllowedRanges())) return super(IntAtom, self).Pack([value]) def Unpack(self, data): return self._AccountForMultiplierUnpack(super(IntAtom, self).Unpack(data)) def GetDescription(self, indent=0): indent = ' ' * indent increment = '' if self._multiplier: increment = ', increment %s' % (10 ** self._multiplier) return ('%s%s: <%s> %s' % (indent, self.name, self._GetAllowedRanges(), increment)) def DisplayValue(self, value): """Converts a raw value, e.g. UInt16 (as opposed to an array of bytes) into the value it would be displayed as, e.g. float to 1 D.P. This takes into account any multipliers set for the field. """ return self._AccountForMultiplierUnpack(value) def RawValue(self, value): """Converts a display value, e.g. float to 1 D.P. into a raw value UInt16 (as opposed to an array of bytes) it would be transmitted as. This takes into account any multipliers set for the field. """ return self._AccountForMultiplierPack(value) def _GetAllowedRanges(self): values = list(self._labels.keys()) for range in self._ranges: if range.min == range.max: values.append(str(self._AccountForMultiplierUnpack(range.min))) else: values.append('[%s, %s]' % (self._AccountForMultiplierUnpack(range.min), self._AccountForMultiplierUnpack(range.max))) return ('%s' % ', '.join(values)) def _AccountForMultiplierUnpack(self, value): new_value = value * (10 ** self._multiplier) if self._multiplier < 0: new_value = round(new_value, abs(self._multiplier)) return new_value def _AccountForMultiplierPack(self, value): if self._multiplier >= 0: try: new_value = int(value) except ValueError as e: raise ArgsValidationError(e) multiplier = 10 ** self._multiplier if new_value % multiplier: raise ArgsValidationError( 'Conversion will lose data: %d -> %d' % (new_value, (new_value / multiplier * multiplier))) new_value = new_value / multiplier else: try: new_value = float(value) except ValueError as e: raise ArgsValidationError(e) scaled_value = new_value * 10 ** abs(self._multiplier) fraction, int_value = math.modf(scaled_value) if fraction: raise ArgsValidationError( 'Conversion will lose data: %s -> %s' % (new_value, int_value * (10.0 ** self._multiplier))) new_value = int(int_value) return new_value class Int8(IntAtom): """A single signed byte field.""" def __init__(self, name, **kwargs): super(Int8, self).__init__(name, 'b', 0xff, **kwargs) class UInt8(IntAtom): """A single unsigned byte field.""" def __init__(self, name, **kwargs): super(UInt8, self).__init__(name, 'B', 0xff, **kwargs) class Int16(IntAtom): """A two-byte signed field.""" def __init__(self, name, **kwargs): super(Int16, self).__init__(name, 'h', 0xffff, **kwargs) class UInt16(IntAtom): """A two-byte unsigned field.""" def __init__(self, name, **kwargs): super(UInt16, self).__init__(name, 'H', 0xffff, **kwargs) class Int32(IntAtom): """A four-byte signed field.""" def __init__(self, name, **kwargs): super(Int32, self).__init__(name, 'i', 0xffffffff, **kwargs) class UInt32(IntAtom): """A four-byte unsigned field.""" def __init__(self, name, **kwargs): super(UInt32, self).__init__(name, 'I', 0xffffffff, **kwargs) class IPV4(IntAtom): """A four-byte IPV4 address.""" def __init__(self, name, **kwargs): super(IPV4, self).__init__(name, 'I', 0xffffffff, **kwargs) def Unpack(self, data): try: return socket.inet_ntoa(data) except socket.error as e: raise ArgsValidationError("Can't unpack data: %s" % e) def Pack(self, args): # TODO(Peter): This currently allows some rather quirky values as per # inet_aton, we may want to restrict that in future try: value = struct.unpack("!I", socket.inet_aton(args[0])) except socket.error as e: raise ArgsValidationError("Can't pack data: %s" % e) return super(IntAtom, self).Pack(value) class MACAtom(FixedSizeAtom): """A MAC address.""" def __init__(self, name, **kwargs): super(MACAtom, self).__init__(name, 'BBBBBB') def Unpack(self, data): format_string = self._FormatString() try: values = struct.unpack(format_string, data) except struct.error as e: raise UnpackException(e) return MACAddress(bytearray([values[0], values[1], values[2], values[3], values[4], values[5]])) def Pack(self, args): mac = None if isinstance(args[0], MACAddress): mac = args[0] else: mac = MACAddress.FromString(args[0]) if mac is None: raise ArgsValidationError("Invalid MAC Address: %s" % args) format_string = self._FormatString() try: data = struct.pack(format_string, mac.mac_address[0], mac.mac_address[1], mac.mac_address[2], mac.mac_address[3], mac.mac_address[4], mac.mac_address[5]) except struct.error as e: raise ArgsValidationError("Can't pack data: %s" % e) return data, 1 class UIDAtom(FixedSizeAtom): """A UID.""" def __init__(self, name, **kwargs): super(UIDAtom, self).__init__(name, 'HI') def Unpack(self, data): format_string = self._FormatString() try: values = struct.unpack(format_string, data) except struct.error as e: raise UnpackException(e) return UID(values[0], values[1]) def Pack(self, args): uid = None if isinstance(args[0], UID): uid = args[0] else: uid = UID.FromString(args[0]) if uid is None: raise ArgsValidationError("Invalid UID: %s" % args) format_string = self._FormatString() try: data = struct.pack(format_string, uid.manufacturer_id, uid.device_id) except struct.error as e: raise ArgsValidationError("Can't pack data: %s" % e) return data, 1 class String(Atom): """A string field.""" def __init__(self, name, **kwargs): super(String, self).__init__(name) self._min = kwargs.get('min_size', 0) self._max = kwargs.get('max_size', 32) @property def min(self): return self._min @property def max(self): return self._max @property def size(self): # only valid if FixedSize() == True return self.min def FixedSize(self): return self.min == self.max def Pack(self, args): self.CheckForSingleArg(args) arg = args[0] arg_size = len(arg) if self.max is not None and arg_size > self.max: raise ArgsValidationError('%s can be at most %d,' % (self.name, self.max)) if self.min is not None and arg_size < self.min: raise ArgsValidationError('%s must be more than %d,' % (self.name, self.min)) try: data = struct.unpack('%ds' % arg_size, arg) except struct.error as e: raise ArgsValidationError("Can't pack data: %s" % e) return data[0], 1 def Unpack(self, data): data_size = len(data) if self.min and data_size < self.min: raise UnpackException('%s too short, required %d, got %d' % (self.name, self.min, data_size)) if self.max and data_size > self.max: raise UnpackException('%s too long, required %d, got %d' % (self.name, self.max, data_size)) try: value = struct.unpack('%ds' % data_size, data) except struct.error as e: raise UnpackException(e) return value[0].rstrip('\x00') def GetDescription(self, indent=0): indent = ' ' * indent return ('%s%s: ' % ( indent, self.name, self.min, self.max)) def __str__(self): return 'String(%s, min=%s, max=%s)' % (self.name, self.min, self.max) class Group(Atom): """A repeated group of atoms.""" def __init__(self, name, atoms, **kwargs): """Create a group of atoms. Args: name: The name of the group atoms: The list of atoms the group contains Raises: PidStructureException: if the structure of this group is invalid. """ super(Group, self).__init__(name) self._atoms = atoms self._min = kwargs.get('min_size') self._max = kwargs.get('max_size') # None for variable sized groups self._group_size = self._VerifyStructure() def HasAtoms(self): return (len(self._atoms) > 0) def GetAtoms(self): return self._atoms @property def min(self): return self._min @property def max(self): return self._max def _VerifyStructure(self): """Verify that we can pack & unpack this group. We need to make sure we have enough known information to pack & unpack a group. We don't support repeated groups of variable length data, nor nested, repeated groups. For now we support the following cases: - Fixed size group. This is easy to unpack - Groups of variable size. We enforce two conditions for these, i) the variable sized field MUST be the last one ii) Only a single occurance is allowed. This means you can't do things like: [(string, int)] # variable sized types must be last [(int, string)] # assuming string is variable sized [(int, [(bool,)]] # no way to tell where the group barriers are Returns: The number of bytes this group uses, or None if it's variable sized """ variable_sized_atoms = [] group_size = 0 for atom in self._atoms: if atom.FixedSize(): group_size += atom.size else: variable_sized_atoms.append(atom) if len(variable_sized_atoms) > 1: raise PidStore('More than one variable size field in %s: %s' % ( self.name, variable_sized_atoms)) if not variable_sized_atoms: # The group is of a fixed size, this means we don't care how many times # it's repeated. return group_size # for now we only support the case where the variable sized field is the # last one if variable_sized_atoms[0] != self._atoms[-1]: raise PidStructureException( 'The variable sized field %s must be the last one' % variable_sized_atoms[0].name) # It's impossible to unpack groups of variable length data without more # information. if self.min != 1 and self.max != 1: raise PidStructureException( "Repeated groups can't contain variable length data") return None def FixedSize(self): """This is true if we know the exact size of the group and min == max. Obviously this is unlikely. """ can_determine_size = True for atom in self._atoms: if not atom.FixedSize(): can_determine_size = False break return (can_determine_size and self._min is not None and self._min == self._max) @property def size(self): # only valid if FixedSize() == True return self.min def Pack(self, args): """Pack the args into binary data. Args: args: A list of string. Returns: binary data """ if self._group_size is None: # variable length data, work out the fixed length portion first data = [] arg_offset = 0 for atom in self._atoms[0:-1]: chunk, args_consumed = atom.Pack(args[arg_offset:]) data.append(chunk) arg_offset += args_consumed # what remains is for the variable length section chunk, args_used = self._atoms[-1].Pack(args[arg_offset:]) arg_offset += args_used data.append(chunk) if arg_offset < len(args): raise ArgsValidationError('Too many arguments, expected %d, got %d' % (arg_offset, len(args))) return ''.join(data), arg_offset elif self._group_size == 0: return '', 0 else: # this could be groups of fields, but we don't support that yet data = [] arg_offset = 0 for atom in self._atoms: chunk, args_consumed = atom.Pack(args[arg_offset:]) data.append(chunk) arg_offset += args_consumed if arg_offset < len(args): raise ArgsValidationError('Too many arguments, expected %d, got %d' % (arg_offset, len(args))) return ''.join(data), arg_offset def Unpack(self, data): """Unpack binary data. Args: data: The binary data Returns: A list of dicts. """ # we've already performed checks in _VerifyStructure so we can rely on # self._group_size data_size = len(data) if self._group_size is None: total_size = 0 for atom in self._atoms[0:-1]: total_size += atom.size if data_size < total_size: raise UnpackException( 'Response too small, required %d, only got %d' % ( total_size, data_size)) output, used = self._UnpackFixedLength(self._atoms[0:-1], data) # what remains is for the variable length section variable_sized_atom = self._atoms[-1] data = data[used:] output[variable_sized_atom.name] = variable_sized_atom.Unpack(data) return [output] elif self._group_size == 0: if data_size > 0: raise UnpackException('Expected 0 bytes but got %d' % data_size) return [{}] else: # groups of fixed length data if data_size % self._group_size: raise UnpackException( 'Data size issue for %s, data size %d, group size %d' % (self.name, data_size, self._group_size)) group_count = data_size / self._group_size if self.max is not None and group_count > self.max: raise UnpackException( 'Too many repeated group_count for %s, limit is %d, found %d' % (self.name, self.max, group_count)) if self.max is not None and group_count < self.min: raise UnpackException( 'Too few repeated group_count for %s, limit is %d, found %d' % (self.name, self.min, group_count)) offset = 0 groups = [] while offset + self._group_size <= data_size: group = self._UnpackFixedLength( self._atoms, data[offset:offset + self._group_size])[0] groups.append(group) offset += self._group_size return groups def GetDescription(self, indent=0): names = [] output = [] for atom in self._atoms: names.append('<%s>' % atom.name) output.append(atom.GetDescription(indent=2)) return ' '.join(names), '\n'.join(output) def _UnpackFixedLength(self, atoms, data): """Unpack a list of atoms of a known, fixed size. Args: atoms: A list of atoms, must all have FixedSize() == True. data: The binary data. Returns: A tuple in the form (output_dict, data_consumed) """ output = {} offset = 0 for atom in atoms: size = atom.size output[atom.name] = atom.Unpack(data[offset:offset + size]) offset += size return output, offset def __str__(self): return ('Group: atoms: %s, [%s, %s]' % (str(self._atoms), self.min, self.max)) # These are validators which can be applied before a request is sent def RootDeviceValidator(args): """Ensure the sub device is the root device.""" if args.get('sub_device') != ROOT_DEVICE: print("Can't send GET %s to non root sub devices" % args['pid'].name, file=sys.stderr) return False return True def SubDeviceValidator(args): """Ensure the sub device is in the range 0 - 512 or 0xffff.""" sub_device = args.get('sub_device') if (sub_device is None or (sub_device > MAX_VALID_SUB_DEVICE and sub_device != ALL_SUB_DEVICES)): print("%s isn't a valid sub device" % sub_device, file=sys.stderr) return False return True def NonBroadcastSubDeviceValidator(args): """Ensure the sub device is in the range 0 - 512.""" sub_device = args.get('sub_device') if (sub_device is None or sub_device > MAX_VALID_SUB_DEVICE): print("Sub device %s needs to be between 0 and 512" % sub_device, file=sys.stderr) return False return True def SpecificSubDeviceValidator(args): """Ensure the sub device is in the range 1 - 512.""" sub_device = args.get('sub_device') if (sub_device is None or sub_device == ROOT_DEVICE or sub_device > MAX_VALID_SUB_DEVICE): print("Sub device %s needs to be between 1 and 512" % sub_device, file=sys.stderr) return False return True class PidStore(object): """The class which holds information about all the PIDs.""" def __init__(self): self._pid_store = Pids_pb2.PidStore() self._pids = {} self._name_to_pid = {} self._manufacturer_pids = {} self._manufacturer_names_to_pids = {} self._manufacturer_id_to_name = {} def Load(self, pid_files, validate=True): """Load a PidStore from a file. Args: pid_files: A list of PID files on disk to load validate: When True, enable strict checking. """ self._pid_store.Clear() for pid_file in pid_files: self.LoadFile(pid_file, validate) def LoadFile(self, pid_file_name, validate): """Load a pid file.""" pid_file = open(pid_file_name, 'r') lines = pid_file.readlines() pid_file.close() try: text_format.Merge('\n'.join(lines), self._pid_store) except text_format.ParseError as e: raise InvalidPidFormat(str(e)) for pid_pb in self._pid_store.pid: if validate: if ((pid_pb.value >= ola.RDMConstants.RDM_MANUFACTURER_PID_MIN) and (pid_pb.value <= ola.RDMConstants.RDM_MANUFACTURER_PID_MAX)): raise InvalidPidFormat('%0x04hx between %0x04hx and %0x04hx in %s' % (pid_pb.value, ola.RDMConstants.RDM_MANUFACTURER_PID_MIN, ola.RDMConstants.RDM_MANUFACTURER_PID_MAX, pid_file_name)) if pid_pb.value in self._pids: raise InvalidPidFormat('0x%04hx listed more than once in %s' % (pid_pb.value, pid_file_name)) if pid_pb.name in self._name_to_pid: raise InvalidPidFormat('%s listed more than once in %s' % (pid_pb.name, pid_file_name)) pid = self._PidProtoToObject(pid_pb) self._pids[pid.value] = pid self._name_to_pid[pid.name] = pid for manufacturer in self._pid_store.manufacturer: pid_dict = self._manufacturer_pids.setdefault( manufacturer.manufacturer_id, {}) name_dict = self._manufacturer_names_to_pids.setdefault( manufacturer.manufacturer_id, {}) self._manufacturer_id_to_name[manufacturer.manufacturer_id] = ( manufacturer.manufacturer_name) for pid_pb in manufacturer.pid: if validate: if ((pid_pb.value < ola.RDMConstants.RDM_MANUFACTURER_PID_MIN) or (pid_pb.value > ola.RDMConstants.RDM_MANUFACTURER_PID_MAX)): raise InvalidPidFormat( 'Manufacturer pid 0x%04hx not between %0x04hx and %0x04hx' % (pid_pb.value, ola.RDMConstants.RDM_MANUFACTURER_PID_MIN, ola.RDMConstants.RDM_MANUFACTURER_PID_MAX)) if pid_pb.value in pid_dict: raise InvalidPidFormat( '0x%04hx listed more than once for 0x%04hx in %s' % ( pid_pb.value, manufacturer.manufacturer_id, pid_file_name)) if pid_pb.name in name_dict: raise InvalidPidFormat( '%s listed more than once for %s in %s' % ( pid_pb.name, manufacturer, pid_file_name)) pid = self._PidProtoToObject(pid_pb) pid_dict[pid.value] = pid name_dict[pid.name] = pid # we no longer need the protobuf representation self._pid_store.Clear() def Pids(self): """Returns a list of all PIDs. Manufacturer PIDs aren't included. Returns: A list of Pid objects. """ return list(self._pids.values()) def ManufacturerPids(self, esta_id): """Return a list of all Manufacturer PIDs for a given esta_id. Args: esta_id: The 2-byte esta / manufacturer ID. Returns: A list of Pid objects. """ return list(self._manufacturer_pids.get(esta_id, {}).values()) def GetPid(self, pid_value, esta_id=None): """Look up a PIDs by the 2-byte PID value. Args: pid_value: The 2-byte PID value, e.g. 0x8000 esta_id: The 2-byte esta / manufacturer ID. Returns: A Pid object, or None if no PID was found. """ pid = self._pids.get(pid_value, None) if not pid: pid = self._manufacturer_pids.get(esta_id, {}).get( pid_value, None) return pid def GetName(self, pid_name, esta_id=None): """Look up a PIDs by name. Args: pid_name: The name of the PID, e.g. 'DEVICE_INFO' esta_id: The 2-byte esta / manufacturer ID. Returns: A Pid object, or None if no PID was found. """ pid = self._name_to_pid.get(pid_name) if not pid: pid = self._manufacturer_names_to_pids.get(esta_id, {}).get( pid_name, None) return pid def NameToValue(self, pid_name, esta_id=None): """A helper method to convert a PID name to a PID value Args: pid_name: The name of the PID, e.g. 'DEVICE_INFO' esta_id: The 2-byte esta / manufacturer ID. Returns: The value for this PID, or None if it wasn't found. """ pid = self.GetName(pid_name) if pid: return pid.value return pid def _PidProtoToObject(self, pid_pb): """Convert the protobuf representation of a PID to a PID object. Args: pid_pb: The protobuf version of the pid Returns: A PIDStore.PID object. """ def BuildList(field_name): if not pid_pb.HasField(field_name): return None try: group = self._FrameFormatToGroup(getattr(pid_pb, field_name)) except PidStructureException as e: raise PidStructureException( "The structure for the %s in %s isn't valid: %s" % (field_name, pid_pb.name, e)) return group discovery_request = BuildList('discovery_request') discovery_response = BuildList('discovery_response') get_request = BuildList('get_request') get_response = BuildList('get_response') set_request = BuildList('set_request') set_response = BuildList('set_response') discovery_validators = [] if pid_pb.HasField('discovery_sub_device_range'): discovery_validators.append(self._SubDeviceRangeToValidator( pid_pb.discovery_sub_device_range)) get_validators = [] if pid_pb.HasField('get_sub_device_range'): get_validators.append(self._SubDeviceRangeToValidator( pid_pb.get_sub_device_range)) set_validators = [] if pid_pb.HasField('set_sub_device_range'): set_validators.append(self._SubDeviceRangeToValidator( pid_pb.set_sub_device_range)) return Pid(pid_pb.name, pid_pb.value, discovery_request, discovery_response, get_request, get_response, set_request, set_response, discovery_validators, get_validators, set_validators) def _FrameFormatToGroup(self, frame_format): """Convert a frame format to a group.""" atoms = [] for field in frame_format.field: atoms.append(self._FieldToAtom(field)) return Group('', atoms, min_size=1, max_size=1) def _FieldToAtom(self, field): """Convert a PID proto field message into an atom.""" field_name = str(field.name) args = {'labels': [], 'ranges': [], } if field.HasField('max_size'): args['max_size'] = field.max_size if field.HasField('min_size'): args['min_size'] = field.min_size if field.HasField('multiplier'): args['multiplier'] = field.multiplier for label in field.label: args['labels'].append((label.value, label.label)) for allowed_value in field.range: args['ranges'].append(Range(allowed_value.min, allowed_value.max)) if field.type == Pids_pb2.BOOL: return Bool(field_name) elif field.type == Pids_pb2.INT8: return Int8(field_name, **args) elif field.type == Pids_pb2.UINT8: return UInt8(field_name, **args) elif field.type == Pids_pb2.INT16: return Int16(field_name, **args) elif field.type == Pids_pb2.UINT16: return UInt16(field_name, **args) elif field.type == Pids_pb2.INT32: return Int32(field_name, **args) elif field.type == Pids_pb2.UINT32: return UInt32(field_name, **args) elif field.type == Pids_pb2.IPV4: return IPV4(field_name, **args) elif field.type == Pids_pb2.MAC: return MACAtom(field_name, **args) elif field.type == Pids_pb2.UID: return UIDAtom(field_name, **args) elif field.type == Pids_pb2.GROUP: if not field.field: raise InvalidPidFormat('Missing child fields for %s' % field_name) atoms = [] for child_field in field.field: atoms.append(self._FieldToAtom(child_field)) return Group(field_name, atoms, **args) elif field.type == Pids_pb2.STRING: return String(field_name, **args) def _SubDeviceRangeToValidator(self, range): """Convert a sub device range to a validator.""" if range == Pids_pb2.ROOT_DEVICE: return RootDeviceValidator elif range == Pids_pb2.ROOT_OR_ALL_SUBDEVICE: return SubDeviceValidator elif range == Pids_pb2.ROOT_OR_SUBDEVICE: return NonBroadcastSubDeviceValidator elif range == Pids_pb2.ONLY_SUBDEVICES: return SpecificSubDeviceValidator _pid_store = None def GetStore(location=None, only_files=()): """Get the instance of the PIDStore. Args: location: The location to load the store from. If not specified it uses the location defined in PidStoreLocation.py only_files: Load a subset of the files in the location. Returns: An instance of PidStore. """ global _pid_store if not _pid_store: _pid_store = PidStore() if not location: location = PidStoreLocation.location pid_files = [] for file_name in os.listdir(location): if not file_name.endswith('.proto'): continue if only_files and file_name not in only_files: continue pid_files.append(os.path.join(location, file_name)) _pid_store.Load(pid_files) REQUIRED_PIDS = [ 'DEVICE_INFO', 'QUEUED_MESSAGE', 'SUPPORTED_PARAMETERS' ] for pid in REQUIRED_PIDS: if not _pid_store.GetName(pid): raise MissingPLASAPIDs( 'Could not find %s in PID datastore, check the directory contains ' 'the PLASA PIDs.' % pid) return _pid_store ola-0.10.5.nojsmin/python/ola/ClientWrapper.py0000644000175000017500000002010713023355232020703 0ustar wouterwouter# This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library 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 # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # ClientWrapper.py # Copyright (C) 2005 Simon Newton import array import datetime import fcntl import heapq import logging import os import select import termios import threading import traceback from ola.OlaClient import OlaClient """A simple client wrapper for the OlaClient.""" __author__ = 'nomis52@gmail.com (Simon Newton)' class _Event(object): """An _Event represents a timer scheduled to expire in the future. Args: time_ms: the number of ms before this event fires callback: the callable to run """ def __init__(self, time_ms, callback): self._run_at = (datetime.datetime.now() + datetime.timedelta(milliseconds=time_ms)) self._callback = callback def __cmp__(self, other): return cmp(self._run_at, other._run_at) def TimeLeft(self, now): """Get the time remaining before this event triggers. Returns: The number of seconds (as a float) before this event fires. """ time_delta = self._run_at - now seconds = time_delta.seconds + time_delta.days * 24 * 3600 seconds += time_delta.microseconds / 10.0 ** 6 return seconds def HasExpired(self, now): """Return true if this event has expired.""" return self._run_at < now def Run(self): """Run the callback.""" self._callback() class SelectServer(object): """Similar to include/ola/io/SelectServer.h Manages I/O and Events. This class isn't thread safe, apart from Execute and Stop. """ def __init__(self): self._quit = False self._ss_thread_id = self._GetThreadID() # heap of _Event objects, ordered by time-to-expiry self._events = [] heapq.heapify(self._events) # sockets to track self._read_descriptors = {} self._write_descriptors = {} self._error_descriptors = {} # functions to run in the SelectServer self._functions = [] self._function_list_lock = threading.Lock() # the pipe used to wake up select() from other threads self._local_socket = os.pipe() def __del__(self): os.close(self._local_socket[0]) os.close(self._local_socket[1]) def Execute(self, f): """Execute a function from within the SelectServer. Can be called from any thread. Args: f: The callable to run """ self._function_list_lock.acquire() self._functions.append(f) # can write anything here, this wakes up the select() call os.write(self._local_socket[1], 'a') self._function_list_lock.release() def Terminate(self): """Terminate this SelectServer. Can be called from any thread.""" if self._ss_thread_id == self._GetThreadID(): self._Stop() else: self.Execute(self._Stop) def Reset(self): self._quit = False def StopIfNoEvents(self): if len(self._events) == 0: self._quit = True def AddReadDescriptor(self, fd, callback): """Add a descriptor to the read FD Set. Args: fd: the descriptor to add callback: the callback to run when this descriptor is ready. """ self._read_descriptors[fd] = callback def RemoveReadDescriptor(self, fd): """Remove a socket from the read FD Set. Args: fd: the descriptor to remove """ if fd in self._read_descriptors: del self._read_descriptors[fd] def AddWriteDescriptor(self, fd, callback): """Add a socket to the write FD Set. Args: fd: the descriptor to add callback: the callback to run when this descriptor is ready. """ self._write_descriptors[fd] = callback def RemoveWriteDescriptor(self, fd): """Remove a socket from the write FD Set. Args: fd: the descriptor to remove """ if fd in self._write_descriptors: del self._write_descriptors[fd] def AddErrorDescriptor(self, fd, callback): """Add a descriptor to the error FD Set. Args: fd: the descriptor to add callback: the callback to run when this descriptor is ready. """ self._error_descriptors[fd] = callback def Run(self): """Run the SelectServer. This doesn't return until Terminate() is called. Returns: False if the calling thread isn't the one that created the select server. """ if self._ss_thread_id != self._GetThreadID(): logging.critical( 'SelectServer called in a thread other than the owner. ' 'Owner %d, caller %d' % (self._ss_thread_id, self._GetThreadID())) traceback.print_stack() # Add the internal descriptor, see comments below self.AddReadDescriptor(self._local_socket[0], self._DrainAndExecute) self._quit = False while not self._quit: # default to 1s sleep sleep_time = 1 now = datetime.datetime.now() self._CheckTimeouts(now) if len(self._events): sleep_time = min(1.0, self._events[0].TimeLeft(now)) i, o, e = select.select(self._read_descriptors.keys(), self._write_descriptors.keys(), self._error_descriptors.keys(), sleep_time) now = datetime.datetime.now() self._CheckTimeouts(now) self._CheckDescriptors(i, self._read_descriptors) self._CheckDescriptors(o, self._write_descriptors) self._CheckDescriptors(e, self._error_descriptors) # remove the internal socket from the read set to avoid a circular # reference which in turn breaks garbage collection (and leaks the socket # descriptors). self.RemoveReadDescriptor(self._local_socket[0]) def AddEvent(self, time_in_ms, callback): """Schedule an event to run in the future. Args: time_in_ms: An interval in milliseconds when this should run. callback: The function to run. """ event = _Event(time_in_ms, callback) heapq.heappush(self._events, event) def _CheckTimeouts(self, now): """Execute any expired timeouts.""" while len(self._events): event = self._events[0] if event.HasExpired(now): event.Run() else: break heapq.heappop(self._events) def _CheckDescriptors(self, ready_set, all_descriptors): runnables = [] for fd, runnable in all_descriptors.items(): if fd in ready_set: runnables.append(runnable) for runnable in runnables: runnable() def _GetThreadID(self): return threading.currentThread().ident def _Stop(self): self._quit = True def _DrainAndExecute(self): "Run all the queued functions.""" # drain socket buf_ = array.array('i', [0]) if fcntl.ioctl(self._local_socket[0], termios.FIONREAD, buf_, 1) == -1: return os.read(self._local_socket[0], buf_[0]) self._function_list_lock.acquire() functions = list(self._functions) self._functions = [] self._function_list_lock.release() for f in functions: f() class ClientWrapper(object): def __init__(self): self._ss = SelectServer() self._client = OlaClient() self._ss.AddReadDescriptor(self._client.GetSocket(), self._client.SocketReady) def Stop(self): self._ss.Terminate() def StopIfNoEvents(self): self._ss.StopIfNoEvents() def Reset(self): self._ss.Reset() def Client(self): return self._client def Run(self): self._ss.Run() def AddEvent(self, time_in_ms, callback): """Schedule an event to run in the future. Args: time_in_ms: An interval in milliseconds when this should run. callback: The function to run. """ self._ss.AddEvent(time_in_ms, callback) ola-0.10.5.nojsmin/python/ola/RDMConstants.py0000644000175000017500000002727713023355232020462 0ustar wouterwouter# This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library 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 # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # RDMConstants.py # Copyright (C) 2010 Simon Newton """Constants defined in E1.20 (RDM).""" __author__ = 'nomis52@gmail.com (Simon Newton)' RDM_ZERO_FOOTPRINT_DMX_ADDRESS = 0xFFFF RDM_MANUFACTURER_PID_MIN = 0x8000 RDM_MANUFACTURER_PID_MAX = 0xFFDF RDM_MANUFACTURER_SD_MIN = 0x8000 RDM_MANUFACTURER_SD_MAX = 0xFFDF RDM_MAX_STRING_LENGTH = 32 RDM_INTERFACE_INDEX_MIN = 1 RDM_INTERFACE_INDEX_MAX = 0xFFFFFF00 RDM_MIN_HOSTNAME_LENGTH = 1 RDM_MAX_HOSTNAME_LENGTH = 63 RDM_MAX_DOMAIN_NAME_LENGTH = 231 RDM_DNS_NAME_SERVER_MAX_INDEX = 2 def _ReverseDict(input): output = {} for key, value in input.items(): output[value] = key return output SENSOR_TYPES = { 'SENSOR_TEMPERATURE': 0x00, 'SENSOR_VOLTAGE': 0x01, 'SENSOR_CURRENT': 0x02, 'SENSOR_FREQUENCY': 0x03, 'SENSOR_RESISTANCE': 0x04, 'SENSOR_POWER': 0x05, 'SENSOR_MASS': 0x06, 'SENSOR_LENGTH': 0x07, 'SENSOR_AREA': 0x08, 'SENSOR_VOLUME': 0x09, 'SENSOR_DENSITY': 0x0A, 'SENSOR_VELOCITY': 0x0B, 'SENSOR_ACCELERATION': 0x0C, 'SENSOR_FORCE': 0x0D, 'SENSOR_ENERGY': 0x0E, 'SENSOR_PRESSURE': 0x0F, 'SENSOR_TIME': 0x10, 'SENSOR_ANGLE': 0x11, 'SENSOR_POSITION_X': 0x12, 'SENSOR_POSITION_Y': 0x13, 'SENSOR_POSITION_Z': 0x14, 'SENSOR_ANGULAR_VELOCITY': 0x15, 'SENSOR_LUMINOUS_INTENSITY': 0x16, 'SENSOR_LUMINOUS_FLUX': 0x17, 'SENSOR_ILLUMINANCE': 0x18, 'SENSOR_CHROMINANCE_RED': 0x19, 'SENSOR_CHROMINANCE_GREEN': 0x1A, 'SENSOR_CHROMINANCE_BLUE': 0x1B, 'SENSOR_CONTACTS': 0x1C, 'SENSOR_MEMORY': 0x1D, 'SENSOR_ITEMS': 0x1E, 'SENSOR_HUMIDITY': 0x1F, 'SENSOR_COUNTER_16BIT': 0x20, 'SENSOR_OTHER': 0x7F, } SENSOR_TYPE_TO_NAME = _ReverseDict(SENSOR_TYPES) UNITS = { 'UNITS_NONE': 0x00, 'UNITS_CENTIGRADE': 0x01, 'UNITS_VOLTS_DC': 0x02, 'UNITS_VOLTS_AC_PEAK': 0x03, 'UNITS_VOLTS_AC_RMS': 0x04, 'UNITS_AMPERE_DC': 0x05, 'UNITS_AMPERE_AC_PEAK': 0x06, 'UNITS_AMPERE_AC_RMS': 0x07, 'UNITS_HERTZ': 0x08, 'UNITS_OHM': 0x09, 'UNITS_WATT': 0x0A, 'UNITS_KILOGRAM': 0x0B, 'UNITS_METERS': 0x0C, 'UNITS_METERS_SQUARED': 0x0D, 'UNITS_METERS_CUBED': 0x0E, 'UNITS_KILOGRAMMES_PER_METER_CUBED': 0x0F, 'UNITS_METERS_PER_SECOND': 0x10, 'UNITS_METERS_PER_SECOND_SQUARED': 0x11, 'UNITS_NEWTON': 0x12, 'UNITS_JOULE': 0x13, 'UNITS_PASCAL': 0x14, 'UNITS_SECOND': 0x15, 'UNITS_DEGREE': 0x16, 'UNITS_STERADIAN': 0x17, 'UNITS_CANDELA': 0x18, 'UNITS_LUMEN': 0x19, 'UNITS_LUX': 0x1A, 'UNITS_IRE': 0x1B, 'UNITS_BYTE': 0x1C, } UNIT_TO_NAME = _ReverseDict(UNITS) PREFIXES = { 'PREFIX_NONE': 0x00, 'PREFIX_DECI': 0x01, 'PREFIX_CENTI': 0x02, 'PREFIX_MILLI': 0x03, 'PREFIX_MICRO': 0x04, 'PREFIX_NANO': 0x05, 'PREFIX_PICO': 0x06, 'PREFIX_FEMPTO': 0x07, 'PREFIX_ATTO': 0x08, 'PREFIX_ZEPTO': 0x09, 'PREFIX_YOCTO': 0x0A, 'PREFIX_DECA': 0x11, 'PREFIX_HECTO': 0x12, 'PREFIX_KILO': 0x13, 'PREFIX_MEGA': 0x14, 'PREFIX_GIGA': 0x15, 'PREFIX_TERRA': 0x16, 'PREFIX_PETA': 0x17, 'PREFIX_EXA': 0x18, 'PREFIX_ZETTA': 0x19, 'PREFIX_YOTTA': 0x1A, } PREFIX_TO_NAME = _ReverseDict(PREFIXES) PRODUCT_CATEGORIES = { 'PRODUCT_CATEGORY_NOT_DECLARED': 0x0000, 'PRODUCT_CATEGORY_FIXTURE': 0x0100, 'PRODUCT_CATEGORY_FIXTURE_FIXED': 0x0101, 'PRODUCT_CATEGORY_FIXTURE_MOVING_YOKE': 0x0102, 'PRODUCT_CATEGORY_FIXTURE_MOVING_MIRROR': 0x0103, 'PRODUCT_CATEGORY_FIXTURE_OTHER': 0x01FF, 'PRODUCT_CATEGORY_FIXTURE_ACCESSORY': 0x0200, 'PRODUCT_CATEGORY_FIXTURE_ACCESSORY_COLOR': 0x0201, 'PRODUCT_CATEGORY_FIXTURE_ACCESSORY_YOKE': 0x0202, 'PRODUCT_CATEGORY_FIXTURE_ACCESSORY_MIRROR': 0x0203, 'PRODUCT_CATEGORY_FIXTURE_ACCESSORY_EFFECT': 0x0204, 'PRODUCT_CATEGORY_FIXTURE_ACCESSORY_BEAM': 0x0205, 'PRODUCT_CATEGORY_FIXTURE_ACCESSORY_OTHER': 0x02FF, 'PRODUCT_CATEGORY_PROJECTOR': 0x0300, 'PRODUCT_CATEGORY_PROJECTOR_FIXED': 0x0301, 'PRODUCT_CATEGORY_PROJECTOR_MOVING_YOKE': 0x0302, 'PRODUCT_CATEGORY_PROJECTOR_MOVING_MIRROR': 0x0303, 'PRODUCT_CATEGORY_PROJECTOR_OTHER': 0x03FF, 'PRODUCT_CATEGORY_ATMOSPHERIC': 0x0400, 'PRODUCT_CATEGORY_ATMOSPHERIC_EFFECT': 0x0401, 'PRODUCT_CATEGORY_ATMOSPHERIC_PYRO': 0x0402, 'PRODUCT_CATEGORY_ATMOSPHERIC_OTHER': 0x04FF, 'PRODUCT_CATEGORY_DIMMER': 0x0500, 'PRODUCT_CATEGORY_DIMMER_AC_INCANDESCENT': 0x0501, 'PRODUCT_CATEGORY_DIMMER_AC_FLUORESCENT': 0x0502, 'PRODUCT_CATEGORY_DIMMER_AC_COLDCATHODE': 0x0503, 'PRODUCT_CATEGORY_DIMMER_AC_NONDIM': 0x0504, 'PRODUCT_CATEGORY_DIMMER_AC_ELV': 0x0505, 'PRODUCT_CATEGORY_DIMMER_AC_OTHER': 0x0506, 'PRODUCT_CATEGORY_DIMMER_DC_LEVEL': 0x0507, 'PRODUCT_CATEGORY_DIMMER_DC_PWM': 0x0508, 'PRODUCT_CATEGORY_DIMMER_CS_LED': 0x0509, 'PRODUCT_CATEGORY_DIMMER_OTHER': 0x05FF, 'PRODUCT_CATEGORY_POWER': 0x0600, 'PRODUCT_CATEGORY_POWER_CONTROL': 0x0601, 'PRODUCT_CATEGORY_POWER_SOURCE': 0x0602, 'PRODUCT_CATEGORY_POWER_OTHER': 0x06FF, 'PRODUCT_CATEGORY_SCENIC': 0x0700, 'PRODUCT_CATEGORY_SCENIC_DRIVE': 0x0701, 'PRODUCT_CATEGORY_SCENIC_OTHER': 0x07FF, 'PRODUCT_CATEGORY_DATA': 0x0800, 'PRODUCT_CATEGORY_DATA_DISTRIBUTION': 0x0801, 'PRODUCT_CATEGORY_DATA_CONVERSION': 0x0802, 'PRODUCT_CATEGORY_DATA_OTHER': 0x08FF, 'PRODUCT_CATEGORY_AV': 0x0900, 'PRODUCT_CATEGORY_AV_AUDIO': 0x0901, 'PRODUCT_CATEGORY_AV_VIDEO': 0x0902, 'PRODUCT_CATEGORY_AV_OTHER': 0x09FF, 'PRODUCT_CATEGORY_MONITOR': 0x0A00, 'PRODUCT_CATEGORY_MONITOR_ACLINEPOWER': 0x0A01, 'PRODUCT_CATEGORY_MONITOR_DCPOWER': 0x0A02, 'PRODUCT_CATEGORY_MONITOR_ENVIRONMENTAL': 0x0A03, 'PRODUCT_CATEGORY_MONITOR_OTHER': 0x0AFF, 'PRODUCT_CATEGORY_CONTROL': 0x7000, 'PRODUCT_CATEGORY_CONTROL_CONTROLLER': 0x7001, 'PRODUCT_CATEGORY_CONTROL_BACKUPDEVICE': 0x7002, 'PRODUCT_CATEGORY_CONTROL_OTHER': 0x70FF, 'PRODUCT_CATEGORY_TEST': 0x7100, 'PRODUCT_CATEGORY_TEST_EQUIPMENT': 0x7101, 'PRODUCT_CATEGORY_TEST_EQUIPMENT_OTHER': 0x71FF, 'PRODUCT_CATEGORY_OTHER': 0x7FFF, } PRODUCT_CATEGORY_TO_NAME = _ReverseDict(PRODUCT_CATEGORIES) PRODUCT_DETAIL_IDS = { 'PRODUCT_DETAIL_NOT_DECLARED': 0x0000, 'PRODUCT_DETAIL_ARC': 0x0001, 'PRODUCT_DETAIL_METAL_HALIDE': 0x0002, 'PRODUCT_DETAIL_INCANDESCENT': 0x0003, 'PRODUCT_DETAIL_LED': 0x0004, 'PRODUCT_DETAIL_FLUROESCENT': 0x0005, 'PRODUCT_DETAIL_COLDCATHODE': 0x0006, 'PRODUCT_DETAIL_ELECTROLUMINESCENT': 0x0007, 'PRODUCT_DETAIL_LASER': 0x0008, 'PRODUCT_DETAIL_FLASHTUBE': 0x0009, 'PRODUCT_DETAIL_COLORSCROLLER': 0x0100, 'PRODUCT_DETAIL_COLORWHEEL': 0x0101, 'PRODUCT_DETAIL_COLORCHANGE': 0x0102, 'PRODUCT_DETAIL_IRIS_DOUSER': 0x0103, 'PRODUCT_DETAIL_DIMMING_SHUTTER': 0x0104, 'PRODUCT_DETAIL_PROFILE_SHUTTER': 0x0105, 'PRODUCT_DETAIL_BARNDOOR_SHUTTER': 0x0106, 'PRODUCT_DETAIL_EFFECTS_DISC': 0x0107, 'PRODUCT_DETAIL_GOBO_ROTATOR': 0x0108, 'PRODUCT_DETAIL_VIDEO': 0x0200, 'PRODUCT_DETAIL_SLIDE': 0x0201, 'PRODUCT_DETAIL_FILM': 0x0202, 'PRODUCT_DETAIL_OILWHEEL': 0x0203, 'PRODUCT_DETAIL_LCDGATE': 0x0204, 'PRODUCT_DETAIL_FOGGER_GLYCOL': 0x0300, 'PRODUCT_DETAIL_FOGGER_MINERALOIL': 0x0301, 'PRODUCT_DETAIL_FOGGER_WATER': 0x0302, 'PRODUCT_DETAIL_CO2': 0x0303, 'PRODUCT_DETAIL_LN2': 0x0304, 'PRODUCT_DETAIL_BUBBLE': 0x0305, 'PRODUCT_DETAIL_FLAME_PROPANE': 0x0306, 'PRODUCT_DETAIL_FLAME_OTHER': 0x0307, 'PRODUCT_DETAIL_OLEFACTORY_STIMULATOR': 0x0308, 'PRODUCT_DETAIL_SNOW': 0x0309, 'PRODUCT_DETAIL_WATER_JET': 0x030A, 'PRODUCT_DETAIL_WIND': 0x030B, 'PRODUCT_DETAIL_CONFETTI': 0x030C, 'PRODUCT_DETAIL_HAZARD': 0x030D, 'PRODUCT_DETAIL_PHASE_CONTROL': 0x0400, 'PRODUCT_DETAIL_REVERSE_PHASE_CONTROL': 0x0401, 'PRODUCT_DETAIL_SINE': 0x0402, 'PRODUCT_DETAIL_PWM': 0x0403, 'PRODUCT_DETAIL_DC': 0x0404, 'PRODUCT_DETAIL_HFBALLAST': 0x0405, 'PRODUCT_DETAIL_HFHV_NEONBALLAST': 0x0406, 'PRODUCT_DETAIL_HFHV_EL': 0x0407, 'PRODUCT_DETAIL_MHR_BALLAST': 0x0408, 'PRODUCT_DETAIL_BITANGLE_MODULATION': 0x0409, 'PRODUCT_DETAIL_FREQUENCY_MODULATION': 0x040A, 'PRODUCT_DETAIL_HIGHFREQUENCY_12V': 0x040B, 'PRODUCT_DETAIL_RELAY_MECHANICAL': 0x040C, 'PRODUCT_DETAIL_RELAY_ELECTRONIC': 0x040D, 'PRODUCT_DETAIL_SWITCH_ELECTRONIC': 0x040E, 'PRODUCT_DETAIL_CONTACTOR': 0x040F, 'PRODUCT_DETAIL_MIRRORBALL_ROTATOR': 0x0500, 'PRODUCT_DETAIL_OTHER_ROTATOR': 0x0501, 'PRODUCT_DETAIL_KABUKI_DROP': 0x0502, 'PRODUCT_DETAIL_CURTAIN': 0x0503, 'PRODUCT_DETAIL_LINESET': 0x0504, 'PRODUCT_DETAIL_MOTOR_CONTROL': 0x0505, 'PRODUCT_DETAIL_DAMPER_CONTROL': 0x0506, 'PRODUCT_DETAIL_SPLITTER': 0x0600, 'PRODUCT_DETAIL_ETHERNET_NODE': 0x0601, 'PRODUCT_DETAIL_MERGE': 0x0602, 'PRODUCT_DETAIL_DATAPATCH': 0x0603, 'PRODUCT_DETAIL_WIRELESS_LINK': 0x0604, 'PRODUCT_DETAIL_PROTOCOL_CONVERTOR': 0x0701, 'PRODUCT_DETAIL_ANALOG_DEMULTIPLEX': 0x0702, 'PRODUCT_DETAIL_ANALOG_MULTIPLEX': 0x0703, 'PRODUCT_DETAIL_SWITCH_PANEL': 0x0704, 'PRODUCT_DETAIL_ROUTER': 0x0800, 'PRODUCT_DETAIL_FADER': 0x0801, 'PRODUCT_DETAIL_MIXER': 0x0802, 'PRODUCT_DETAIL_CHANGEOVER_MANUAL': 0x0900, 'PRODUCT_DETAIL_CHANGEOVER_AUTO': 0x0901, 'PRODUCT_DETAIL_TEST': 0x0902, 'PRODUCT_DETAIL_GFI_RCD': 0x0A00, 'PRODUCT_DETAIL_BATTERY': 0x0A01, 'PRODUCT_DETAIL_CONTROLLABLE_BREAKER': 0x0A02, 'PRODUCT_DETAIL_OTHER': 0x7FFF, } PRODUCT_DETAIL_IDS_TO_NAME = _ReverseDict(PRODUCT_DETAIL_IDS) SLOT_TYPES = { 'ST_PRIMARY': 0x00, 'ST_SEC_FINE': 0x01, 'ST_SEC_TIMING': 0x02, 'ST_SEC_SPEED': 0x03, 'ST_SEC_CONTROL': 0x04, 'ST_SEC_INDEX': 0x05, 'ST_SEC_ROTATION': 0x06, 'ST_SEC_INDEX_ROTATE': 0x07, 'ST_SEC_UNDEFINED': 0xFF, } SLOT_TYPE_TO_NAME = _ReverseDict(SLOT_TYPES) SLOT_DEFINITIONS = { 'SD_INTENSITY': 0x0001, 'SD_INTENSITY_MASTER': 0x0002, 'SD_PAN': 0x0101, 'SD_TILT': 0x0102, 'SD_COLOR_WHEEL': 0x0201, 'SD_COLOR_SUB_CYAN': 0x0202, 'SD_COLOR_SUB_YELLOW': 0x0203, 'SD_COLOR_SUB_MAGENTA': 0x0204, 'SD_COLOR_ADD_RED': 0x0205, 'SD_COLOR_ADD_GREEN': 0x0206, 'SD_COLOR_ADD_BLUE': 0x0207, 'SD_COLOR_CORRECTION': 0x0208, 'SD_COLOR_SCROLL': 0x0209, 'SD_COLOR_SEMAPHORE': 0x0210, 'SD_COLOR_ADD_AMBER': 0x0211, 'SD_COLOR_ADD_WHITE': 0x0212, 'SD_COLOR_ADD_WARM_WHITE': 0x0213, 'SD_COLOR_ADD_COOL_WHITE': 0x0214, 'SD_COLOR_SUB_UV': 0x0215, 'SD_COLOR_HUE': 0x0216, 'SD_COLOR_SATURATION': 0x0217, 'SD_STATIC_GOBO_WHEEL': 0x0301, 'SD_ROTO_GOBO_WHEEL': 0x0302, 'SD_PRISM_WHEEL': 0x0303, 'SD_EFFECTS_WHEEL': 0x0304, 'SD_BEAM_SIZE_IRIS': 0x0401, 'SD_EDGE': 0x0402, 'SD_FROST': 0x0403, 'SD_STROBE': 0x0404, 'SD_ZOOM': 0x0405, 'SD_FRAMING_SHUTTER': 0x0406, 'SD_SHUTTER_ROTATE': 0x0407, 'SD_DOUSER': 0x0408, 'SD_BARN_DOOR': 0x0409, 'SD_LAMP_CONTROL': 0x0501, 'SD_FIXTURE_CONTROL': 0x0502, 'SD_FIXTURE_SPEED': 0x0503, 'SD_MACRO': 0x0504, 'SD_POWER_CONTROL': 0x0505, 'SD_FAN_CONTROL': 0x0506, 'SD_HEATER_CONTROL': 0x0507, 'SD_FOUNTAIN_CONTROL': 0x0508, 'SD_UNDEFINED': 0xFFFF, } SLOT_DEFINITION_TO_NAME = _ReverseDict(SLOT_DEFINITIONS) PRESET_PROGRAMMED = { 'PRESET_NOT_PROGRAMMED': 0x00, 'PRESET_PROGRAMMED': 0x01, 'PRESET_PROGRAMMED_READ_ONLY': 0x02, } PRESET_PROGRAMMER_TO_NAME = _ReverseDict(PRESET_PROGRAMMED) MERGE_MODE = { 'MERGEMODE_DEFAULT': 0x00, 'MERGEMODE_HTP': 0x01, 'MERGEMODE_LTP': 0x02, 'MERGEMODE_DMX_ONLY': 0x03, 'MERGEMODE_OTHER': 0xFF, } MERGE_MODE_TO_NAME = _ReverseDict(MERGE_MODE) INTERFACE_HARDWARE_TYPE_ETHERNET = 0x0001 ola-0.10.5.nojsmin/python/ola/OlaClient.py0000644000175000017500000012512513023355232020004 0ustar wouterwouter# This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library 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 # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # OlaClient.py # Copyright (C) 2005 Simon Newton import array import socket import struct from ola.rpc.StreamRpcChannel import StreamRpcChannel from ola.rpc.SimpleRpcController import SimpleRpcController from ola import Ola_pb2 from ola.UID import UID """The client used to communicate with the Ola Server.""" __author__ = 'nomis52@gmail.com (Simon Newton)' """The port that the OLA server listens on.""" OLA_PORT = 9010 class Error(Exception): """The base error class.""" class OLADNotRunningException(Error): """Thrown if we try to connect and olad isn't running.""" class Plugin(object): """Represents a plugin. Attributes: id: the id of this plugin name: the name of this plugin active: whether this plugin is active enabled: whether this plugin is enabled """ def __init__(self, plugin_id, name, active, enabled): self._id = plugin_id self._name = name self._active = active self._enabled = enabled @property def id(self): return self._id @property def name(self): return self._name @property def active(self): return self._active @property def enabled(self): return self._enabled @staticmethod def FromProtobuf(plugin_pb): return Plugin(plugin_pb.plugin_id, plugin_pb.name, plugin_pb.active, plugin_pb.enabled) def __repr__(self): s = 'Plugin(id={id}, name="{name}", active={active}, enabled={enabled})' return s.format(id=self.id, name=self.name, active=self.active, enabled=self.enabled) def __lt__(self, other): return self.id < other.id def __eq__(self, other): return self.id == other.id # These 4 could be replaced by functools.total_ordering when support # for 2.6 is dropped. def __le__(self, other): return self.id <= other.id def __gt__(self, other): return self.id > other.id def __ge__(self, other): return self.id >= other.id def __ne__(self, other): return self.id != other.id # Populate the Plugin class attributes from the protobuf for value in Ola_pb2._PLUGINIDS.values: setattr(Plugin, value.name, value.number) class Device(object): """Represents a device. Attributes: id: the unique id of this device alias: the integer alias for this device name: the name of this device plugin_id: the plugin that this device belongs to input_ports: a list of Input Port objects output_ports: a list of Output Port objects """ def __init__(self, device_id, alias, name, plugin_id, input_ports, output_ports): self._id = device_id self._alias = alias self._name = name self._plugin_id = plugin_id self._input_ports = sorted(input_ports) self._output_ports = sorted(output_ports) @property def id(self): return self._id @property def alias(self): return self._alias @property def name(self): return self._name @property def plugin_id(self): return self._plugin_id @property def input_ports(self): return self._input_ports @property def output_ports(self): return self._output_ports @staticmethod def FromProtobuf(device_pb): input_ports = [Port.FromProtobuf(x) for x in device_pb.input_port] output_ports = [Port.FromProtobuf(x) for x in device_pb.output_port] return Device(device_pb.device_id, device_pb.device_alias, device_pb.device_name, device_pb.plugin_id, input_ports, output_ports) def __repr__(self): s = 'Device(id="{id}", alias={alias}, name="{name}", ' \ 'plugin_id={plugin_id}, {nr_inputs} inputs, {nr_outputs} outputs)' return s.format(id=self.id, alias=self.alias, name=self.name, plugin_id=self.plugin_id, nr_inputs=len(self.input_ports), nr_outputs=len(self.output_ports)) def __lt__(self, other): return self.alias < other.alias def __eq__(self, other): return self.alias == other.alias # These 3 could be replaced by functools.total_ordering when support # for 2.6 is dropped. def __le__(self, other): return self.alias <= other.alias def __gt__(self, other): return self.alias > other.alias def __ge__(self, other): return self.alias >= other.alias def __ne__(self, other): return self.alias != other.alias class Port(object): """Represents a port. Attributes: id: the unique id of this port universe: the universe that this port belongs to active: True if this port is active description: the description of the port supports_rdm: if the port supports RDM """ def __init__(self, port_id, universe, active, description, supports_rdm): self._id = port_id self._universe = universe self._active = active self._description = description self._supports_rdm = supports_rdm @property def id(self): return self._id @property def universe(self): return self._universe @property def active(self): return self._active @property def description(self): return self._description @property def supports_rdm(self): return self._supports_rdm @staticmethod def FromProtobuf(port_pb): universe = port_pb.universe if port_pb.HasField('universe') else None return Port(port_pb.port_id, universe, port_pb.active, port_pb.description, port_pb.supports_rdm) def __repr__(self): s = 'Port(id={id}, universe={universe}, active={active}, ' \ 'description="{desc}", supports_rdm={supports_rdm})' return s.format(id=self.id, universe=self.universe, active=self.active, desc=self.description, supports_rdm=self.supports_rdm) def __lt__(self, other): return self.id < other.id def __eq__(self, other): return self.id == other.id # These 4 could be replaced by functools.total_ordering when support # for 2.6 is dropped. def __le__(self, other): return self.id <= other.id def __gt__(self, other): return self.id > other.id def __ge__(self, other): return self.id >= other.id def __ne__(self, other): return self.id != other.id class Universe(object): """Represents a universe. Attributes: id: the integer universe id name: the name of this universe merge_mode: the merge mode this universe is using """ LTP = Ola_pb2.LTP HTP = Ola_pb2.HTP def __init__(self, universe_id, name, merge_mode, input_ports, output_ports): self._id = universe_id self._name = name self._merge_mode = merge_mode self._input_ports = sorted(input_ports) self._output_ports = sorted(output_ports) @property def id(self): return self._id @property def name(self): return self._name @property def merge_mode(self): return self._merge_mode @property def input_ports(self): return self._input_ports @property def output_ports(self): return self._output_ports @staticmethod def FromProtobuf(universe_pb): input_ports = [Port.FromProtobuf(x) for x in universe_pb.input_ports] output_ports = [Port.FromProtobuf(x) for x in universe_pb.output_ports] return Universe(universe_pb.universe, universe_pb.name, universe_pb.merge_mode, input_ports, output_ports) def __repr__(self): merge_mode = 'LTP' if self.merge_mode == Universe.LTP else 'HTP' s = 'Universe(id={id}, name="{name}", merge_mode={merge_mode})' return s.format(id=self.id, name=self.name, merge_mode=merge_mode) def __lt__(self, other): return self.id < other.id def __eq__(self, other): return self.id == other.id # These 4 could be replaced by functools.total_ordering when support # for 2.6 is dropped. def __le__(self, other): return self.id <= other.id def __gt__(self, other): return self.id > other.id def __ge__(self, other): return self.id >= other.id def __ne__(self, other): return self.id != other.id class RequestStatus(object): """Represents the status of an reqeust. Attributes: state: the state of the operation message: an error message if it failed """ SUCCESS, FAILED, CANCELLED = range(3) def __init__(self, controller): if controller.Failed(): self._state = self.FAILED self._message = controller.ErrorText() elif controller.IsCanceled(): self._state = self.CANCELLED self._message = controller.ErrorText() else: self._state = self.SUCCESS self._message = None def Succeeded(self): """Returns true if this request succeeded.""" return self._state == self.SUCCESS @property def state(self): return self._state @property def message(self): return self._message class RDMNack(object): NACK_SYMBOLS_TO_VALUES = { 'NR_UNKNOWN_PID': (0, 'Unknown PID'), 'NR_FORMAT_ERROR': (1, 'Format Error'), 'NR_HARDWARE_FAULT': (2, 'Hardware fault'), 'NR_PROXY_REJECT': (3, 'Proxy reject'), 'NR_WRITE_PROTECT': (4, 'Write protect'), 'NR_UNSUPPORTED_COMMAND_CLASS': (5, 'Unsupported command class'), 'NR_DATA_OUT_OF_RANGE': (6, 'Data out of range'), 'NR_BUFFER_FULL': (7, 'Buffer full'), 'NR_PACKET_SIZE_UNSUPPORTED': (8, 'Packet size unsupported'), 'NR_SUB_DEVICE_OUT_OF_RANGE': (9, 'Sub device out of range'), 'NR_PROXY_BUFFER_FULL': (10, 'Proxy buffer full'), } # this is populated below _CODE_TO_OBJECT = {} def __init__(self, nack_value, description): self._value = nack_value self._description = description @property def value(self): return self._value @property def description(self): return self._description def __repr__(self): s = 'RDMNack(value={value}, desc="{desc}")' return s.format(value=self.value, desc=self.description) def __lt__(self, other): return self.value < other.value def __eq__(self, other): return self.value == other.value # These 4 could be replaced by functools.total_ordering when support # for 2.6 is dropped. def __le__(self, other): return self.value <= other.value def __gt__(self, other): return self.value > other.value def __ge__(self, other): return self.value >= other.value def __ne__(self, other): return self.value != other.value @classmethod def LookupCode(cls, code): obj = cls._CODE_TO_OBJECT.get(code, None) if not obj: obj = RDMNack(code, 'Unknown') return obj for symbol, (value, description) in RDMNack.NACK_SYMBOLS_TO_VALUES.items(): nack = RDMNack(value, description) setattr(RDMNack, symbol, nack) RDMNack._CODE_TO_OBJECT[value] = nack class RDMFrame(object): """The raw data in an RDM frame. The timing attributes may be 0 if the plugin does not provide timing information. All timing data is in nano-seconds. Attributes: data: The raw byte data. response_delay: The time between the request and the response. break_time: The break duration. mark_time: The mark duration. data_time: The data time. """ def __init__(self, frame): self._data = frame.raw_response self._response_delay = frame.timing.response_delay self._break_time = frame.timing.break_time self._mark_time = frame.timing.mark_time self._data_time = frame.timing.data_time @property def data(self): return self._data @property def response_delay(self): return self._response_delay @property def break_time(self): return self._break_time @property def mark_time(self): return self._mark_time @property def data_time(self): return self._data_time class RDMResponse(object): """Represents a RDM Response. Failures can occur at many layers, the recommended way for dealing with responses is: Check .status.Succeeded(), if not true this indicates a rpc or server error. Check .response_code, if not RDM_COMPLETED_OK, it indicates a problem with the RDM transport layer or malformed response. If .response_code is RDM_COMPLETED_OK, .sub_device, .command_class, .pid, .queued_messages hold the properties of the response. Then check .response_type: if .response_type is ACK: .data holds the param data of the response. If .response_type is ACK_TIMER: .ack_timer: holds the number of ms before the response should be available. If .response_type is NACK_REASON: .nack_reason holds the reason for nack'ing Attributes: status: The RequestStatus object for this request / response response_code: The response code for the RDM request response_type: The response type (ACK, ACK_TIMER, NACK_REASON) for the request. sub_device: The sub device that sent the response command_class: pid: data: queued_messages: The number of queued messages the remain. nack_reason: If the response type was NACK_REASON, this is the reason for the NACK. ack_timer: If the response type was ACK_TIMER, this is the number of ms to wait before checking for queued messages. transaction_number: frames: A list of RDM frames that made up this response. """ RESPONSE_CODES_TO_STRING = { Ola_pb2.RDM_COMPLETED_OK: 'Ok', Ola_pb2.RDM_WAS_BROADCAST: 'Request was broadcast', Ola_pb2.RDM_FAILED_TO_SEND: 'Failed to send request', Ola_pb2.RDM_TIMEOUT: 'Response Timeout', Ola_pb2.RDM_INVALID_RESPONSE: 'Invalid Response', Ola_pb2.RDM_UNKNOWN_UID: 'Unknown UID', Ola_pb2.RDM_CHECKSUM_INCORRECT: 'Incorrect Checksum', Ola_pb2.RDM_TRANSACTION_MISMATCH: 'Transaction number mismatch', Ola_pb2.RDM_SUB_DEVICE_MISMATCH: 'Sub device mismatch', Ola_pb2.RDM_SRC_UID_MISMATCH: 'Source UID in response doesn\'t match', Ola_pb2.RDM_DEST_UID_MISMATCH: ( 'Destination UID in response doesn\'t match'), Ola_pb2.RDM_WRONG_SUB_START_CODE: 'Incorrect sub start code', Ola_pb2.RDM_PACKET_TOO_SHORT: ( 'RDM response was smaller than the minimum size'), Ola_pb2.RDM_PACKET_LENGTH_MISMATCH: ( 'The length field of packet didn\'t match length received'), Ola_pb2.RDM_PARAM_LENGTH_MISMATCH: ( 'The parameter length exceeds the remaining packet size'), Ola_pb2.RDM_INVALID_COMMAND_CLASS: ( 'The command class was not one of GET_RESPONSE or SET_RESPONSE'), Ola_pb2.RDM_COMMAND_CLASS_MISMATCH: ( 'The command class didn\'t match the request'), Ola_pb2.RDM_INVALID_RESPONSE_TYPE: ( 'The response type was not ACK, ACK_OVERFLOW, ACK_TIMER or NACK'), Ola_pb2.RDM_PLUGIN_DISCOVERY_NOT_SUPPORTED: ( 'The DISCOVERY Command Class is not supported by this controller'), Ola_pb2.RDM_DUB_RESPONSE: ( 'Discovery Unique Branch response') } def __init__(self, controller, response): """ Create a new RDMResponse object. Args: controller: The RpcController response: A RDMResponse proto message. """ self._frames = [] self.status = RequestStatus(controller) if self.status.Succeeded() and response is not None: self._response_code = response.response_code self._response_type = response.response_type self._queued_messages = response.message_count self._transaction_number = response.transaction_number self.sub_device = response.sub_device self.command_class = response.command_class self.pid = response.param_id self.data = response.data for frame in response.raw_frame: self._frames.append(RDMFrame(frame)) # we populate these below if required self._nack_reason = None self._ack_timer = None if (self.status.Succeeded() and self._response_code == Ola_pb2.RDM_COMPLETED_OK): # check for ack timer or nack if self._response_type == Ola_pb2.RDM_NACK_REASON: nack_value = self._get_short_from_data(response.data) if nack_value is None: self._response_code = Ola_pb2.RDM_INVALID_RESPONSE else: self._nack_reason = RDMNack.LookupCode(nack_value) elif self._response_type == Ola_pb2.RDM_ACK_TIMER: self._ack_timer = self._get_short_from_data(response.data) if self._ack_timer is None: self._response_code = Ola_pb2.RDM_INVALID_RESPONSE @property def response_code(self): return self._response_code def ResponseCodeAsString(self): return self.RESPONSE_CODES_TO_STRING.get(self._response_code, 'Unknown') @property def response_type(self): return self._response_type @property def queued_messages(self): return self._queued_messages @property def nack_reason(self): return self._nack_reason @property def transaction_number(self): return self._transaction_number @property def frames(self): return self._frames @property def raw_response(self): """The list of byte strings in the response packets.""" data = [] for frame in self._frames: data.append(frame.data) return data def WasAcked(self): """Returns true if this RDM request returned a ACK response.""" return (self.status.Succeeded() and self.response_code == OlaClient.RDM_COMPLETED_OK and self.response_type == OlaClient.RDM_ACK) @property def ack_timer(self): return 100 * self._ack_timer def __repr__(self): if self.response_code != Ola_pb2.RDM_COMPLETED_OK: s = 'RDMResponse(error="{error}")' return s.format(error=self.ResponseCodeAsString()) if self.response_type == OlaClient.RDM_ACK: s = 'RDMResponse(type=ACK, command_class={cmd})' return s.format(cmd=self._command_class()) elif self.response_type == OlaClient.RDM_ACK_TIMER: s = 'RDMResponse(type=ACK_TIMER, ack_timer={timer} ms, ' \ 'command_class={cmd})' return s.format(timer=self.ack_timer, cmd=self._command_class()) elif self.response_type == OlaClient.RDM_NACK_REASON: s = 'RDMResponse(type=NACK, reason="{reason}")' return s.format(reason=self.nack_reason.description) else: s = 'RDMResponse(type="Unknown")' return s def _get_short_from_data(self, data): """Try to unpack the binary data into a short. Args: data: the binary data Returns: value: None if the unpacking failed """ try: return struct.unpack('!h', data)[0] except struct.error: return None def _command_class(self): if self.command_class == OlaClient.RDM_GET_RESPONSE: return 'GET' elif self.command_class == OlaClient.RDM_SET_RESPONSE: return 'SET' elif self.command_class == OlaClient.RDM_DISCOVERY_RESPONSE: return 'DISCOVERY' else: return "UNKNOWN_CC" class OlaClient(Ola_pb2.OlaClientService): """The client used to communicate with olad.""" def __init__(self, our_socket=None, close_callback=None): """Create a new client. Args: socket: the socket to use for communications, if not provided one is created. close_callback: A callable to run if the socket is closed """ self._socket = our_socket if self._socket is None: self._socket = socket.socket() try: self._socket.connect(('localhost', 9010)) except socket.error: raise OLADNotRunningException('Failed to connect to olad') self._close_callback = close_callback self._channel = StreamRpcChannel(self._socket, self, self._SocketClosed) self._stub = Ola_pb2.OlaServerService_Stub(self._channel) self._universe_callbacks = {} def GetSocket(self): """Returns the socket used to communicate with the server.""" return self._socket def SocketReady(self): """Called when the socket has new data.""" self._channel.SocketReady() def _SocketClosed(self): """Called by the RPCChannel if the socket is closed.""" try: self._socket.shutdown(socket.SHUT_RDWR) except socket.error: pass self._socket.close() self._socket = None if self._close_callback: self._close_callback() def FetchPlugins(self, callback): """Fetch the list of plugins. Args: callback: the function to call once complete, takes two arguments, a RequestStatus object and a list of Plugin objects Returns: True if the request was sent, False otherwise. """ if self._socket is None: return False controller = SimpleRpcController() request = Ola_pb2.PluginListRequest() try: self._stub.GetPlugins( controller, request, lambda x, y: self._GetPluginsComplete(callback, x, y)) except socket.error: raise OLADNotRunningException() return True def PluginDescription(self, callback, plugin_id): """Fetch the description of a plugin. Args: callback: the function to call once complete, takes two arguments, a RequestStatus object and the plugin description text. plugin_id: the id of the plugin Returns: True if the request was sent, False otherwise. """ if self._socket is None: return False controller = SimpleRpcController() request = Ola_pb2.PluginDescriptionRequest() request.plugin_id = plugin_id try: self._stub.GetPluginDescription( controller, request, lambda x, y: self._PluginDescriptionComplete(callback, x, y)) except socket.error: raise OLADNotRunningException() return True def FetchDevices(self, callback, plugin_filter=Plugin.OLA_PLUGIN_ALL): """Fetch a list of devices from the server. Args: callback: The function to call once complete, takes two arguments, a RequestStatus object and a list of Device objects. filter: a plugin id to filter by Returns: True if the request was sent, False otherwise. """ if self._socket is None: return False controller = SimpleRpcController() request = Ola_pb2.DeviceInfoRequest() request.plugin_id = plugin_filter try: self._stub.GetDeviceInfo( controller, request, lambda x, y: self._DeviceInfoComplete(callback, x, y)) except socket.error: raise OLADNotRunningException() return True def FetchUniverses(self, callback): """Fetch a list of universes from the server Args: callback: The function to call once complete, takes two arguments, a RequestStatus object and a list of Universe objects. Returns: True if the request was sent, False otherwise. """ if self._socket is None: return False controller = SimpleRpcController() request = Ola_pb2.OptionalUniverseRequest() try: self._stub.GetUniverseInfo( controller, request, lambda x, y: self._UniverseInfoComplete(callback, x, y)) except socket.error: raise OLADNotRunningException() return True def FetchDmx(self, universe, callback): """Fetch DMX data from the server Args: universe: the universe to fetch the data for callback: The function to call once complete, takes three arguments, a RequestStatus object, a universe number and a list of dmx data. Returns: True if the request was sent, False otherwise. """ if self._socket is None: return False controller = SimpleRpcController() request = Ola_pb2.UniverseRequest() request.universe = universe try: self._stub.GetDmx(controller, request, lambda x, y: self._GetDmxComplete(callback, x, y)) except socket.error: raise OLADNotRunningException() return True def SendDmx(self, universe, data, callback=None): """Send DMX data to the server Args: universe: the universe to send the data for data: An array object with the DMX data callback: The function to call once complete, takes one argument, a RequestStatus object. Returns: True if the request was sent, False otherwise. """ if self._socket is None: return False controller = SimpleRpcController() request = Ola_pb2.DmxData() request.universe = universe request.data = data.tostring() try: self._stub.UpdateDmxData( controller, request, lambda x, y: self._AckMessageComplete(callback, x, y)) except socket.error: raise OLADNotRunningException() return True def SetUniverseName(self, universe, name, callback=None): """Set the name of a universe. Args: universe: the universe to set the name of name: the new name for the universe callback: The function to call once complete, takes one argument, a RequestStatus object. Returns: True if the request was sent, False otherwise. """ if self._socket is None: return False controller = SimpleRpcController() request = Ola_pb2.UniverseNameRequest() request.universe = universe request.name = name try: self._stub.SetUniverseName( controller, request, lambda x, y: self._AckMessageComplete(callback, x, y)) except socket.error: raise OLADNotRunningException() return True def SetUniverseMergeMode(self, universe, merge_mode, callback=None): """Set the merge mode of a universe. Args: universe: the universe to set the merge mode of merge_mode: either Universe.HTP or Universe.LTP callback: The function to call once complete, takes one argument, a RequestStatus object. Returns: True if the request was sent, False otherwise. """ if self._socket is None: return False controller = SimpleRpcController() request = Ola_pb2.MergeModeRequest() request.universe = universe request.merge_mode = merge_mode try: self._stub.SetMergeMode( controller, request, lambda x, y: self._AckMessageComplete(callback, x, y)) except socket.error: raise OLADNotRunningException() return True def RegisterUniverse(self, universe, action, data_callback, callback=None): """Register to receive dmx updates for a universe. Args: universe: the universe to register to action: OlaClient.REGISTER or OlaClient.UNREGISTER data_callback: the function to be called when there is new data, passed a single argument of type array. callback: The function to call once complete, takes one argument, a RequestStatus object. Returns: True if the request was sent, False otherwise. """ if self._socket is None: return False controller = SimpleRpcController() request = Ola_pb2.RegisterDmxRequest() request.universe = universe request.action = action try: self._stub.RegisterForDmx( controller, request, lambda x, y: self._AckMessageComplete(callback, x, y)) except socket.error: raise OLADNotRunningException() if action == self.PATCH: self._universe_callbacks[universe] = data_callback elif universe in self._universe_callbacks: del self._universe_callbacks[universe] return True def PatchPort(self, device_alias, port, is_output, action, universe, callback=None): """Patch a port to a universe. Args: device_alias: the alias of the device of which to patch a port port: the id of the port is_output: select the input or output port action: OlaClient.PATCH or OlaClient.UNPATCH universe: the universe to set the name of callback: The function to call once complete, takes one argument, a RequestStatus object. Returns: True if the request was sent, False otherwise. """ if self._socket is None: return False controller = SimpleRpcController() request = Ola_pb2.PatchPortRequest() request.device_alias = device_alias request.port_id = port request.action = action request.is_output = is_output request.universe = universe try: self._stub.PatchPort( controller, request, lambda x, y: self._AckMessageComplete(callback, x, y)) except socket.error: raise OLADNotRunningException() return True def ConfigureDevice(self, device_alias, request_data, callback): """Send a device config request. Args: device_alias: the alias of the device to configure request_data: the request to send to the device callback: The function to call once complete, takes two arguments, a RequestStatus object and a response. Returns: True if the request was sent, False otherwise. """ if self._socket is None: return False controller = SimpleRpcController() request = Ola_pb2.DeviceConfigRequest() request.device_alias = device_alias request.data = request_data try: self._stub.ConfigureDevice( controller, request, lambda x, y: self._ConfigureDeviceComplete(callback, x, y)) except socket.error: raise OLADNotRunningException() return True def SendTimeCode(self, time_code_type, hours, minutes, seconds, frames, callback=None): """Send Time Code Data. Args: time_code_type: One of OlaClient.TIMECODE_FILM, OlaClient.TIMECODE_EBU, OlaClient.TIMECODE_DF or OlaClient.TIMECODE_SMPTE hours: the hours minutes: the minutes seconds: the seconds frames: the frame count callback: The function to call once complete, takes one argument, a RequestStatus object. Returns: True if the request was sent, False otherwise. """ if self._socket is None: return False controller = SimpleRpcController() request = Ola_pb2.TimeCode() request.type = time_code_type request.hours = hours request.minutes = minutes request.seconds = seconds request.frames = frames try: self._stub.SendTimeCode( controller, request, lambda x, y: self._AckMessageComplete(callback, x, y)) except socket.error: raise OLADNotRunningException() return True def UpdateDmxData(self, controller, request, callback): """Called when we receive new DMX data. Args: controller: An RpcController object reqeust: A DmxData message callback: The callback to run once complete Returns: True if the request was sent, False otherwise. """ if self._socket is None: return False if request.universe in self._universe_callbacks: data = array.array('B') data.fromstring(request.data) self._universe_callbacks[request.universe](data) response = Ola_pb2.Ack() callback(response) return True def FetchUIDList(self, universe, callback): """Used to get a list of UIDs for a particular universe. Args: universe: The universe to get the UID list for. callback: The function to call once complete, takes two arguments, a RequestStatus object and a iterable of UIDs. Returns: True if the request was sent, False otherwise. """ if self._socket is None: return False controller = SimpleRpcController() request = Ola_pb2.UniverseRequest() request.universe = universe try: self._stub.GetUIDs(controller, request, lambda x, y: self._FetchUIDsComplete(callback, x, y)) except socket.error: raise OLADNotRunningException() return True def RunRDMDiscovery(self, universe, full, callback): """Triggers RDM discovery for a universe. Args: universe: The universe to run discovery for. full: true to use full discovery, false for incremental (if supported) callback: The function to call once complete, takes one argument, a RequestStatus object. Returns: True if the request was sent, False otherwise. """ if self._socket is None: return False controller = SimpleRpcController() request = Ola_pb2.DiscoveryRequest() request.universe = universe request.full = full try: self._stub.ForceDiscovery( controller, request, lambda x, y: self._FetchUIDsComplete(callback, x, y)) except socket.error: raise OLADNotRunningException() return True def RDMGet(self, universe, uid, sub_device, param_id, callback, data='', include_frames=False): """Send an RDM get command. Args: universe: The universe to get the UID list for. uid: A UID object sub_device: The sub device index param_id: the param ID callback: The function to call once complete, takes a RDMResponse object data: the data to send include_frames: True if the response should include the raw frame data. Returns: True if the request was sent, False otherwise. """ if self._socket is None: return False return self._RDMMessage(universe, uid, sub_device, param_id, callback, data, include_frames) def RDMSet(self, universe, uid, sub_device, param_id, callback, data='', include_frames=False): """Send an RDM set command. Args: universe: The universe to get the UID list for. uid: A UID object sub_device: The sub device index param_id: the param ID callback: The function to call once complete, takes a RDMResponse object data: the data to send include_frames: True if the response should include the raw frame data. Returns: True if the request was sent, False otherwise. """ if self._socket is None: return False return self._RDMMessage(universe, uid, sub_device, param_id, callback, data, include_frames, set=True) def SendRawRDMDiscovery(self, universe, uid, sub_device, param_id, callback, data='', include_frames=False): """Send an RDM Discovery command. Unless you're writing RDM tests you shouldn't need to use this. Args: universe: The universe to get the UID list for. uid: A UID object sub_device: The sub device index param_id: the param ID callback: The function to call once complete, takes a RDMResponse object data: the data to send include_frames: True if the response should include the raw frame data. Returns: True if the request was sent, False otherwise. """ if self._socket is None: return False controller = SimpleRpcController() request = Ola_pb2.RDMDiscoveryRequest() request.universe = universe request.uid.esta_id = uid.manufacturer_id request.uid.device_id = uid.device_id request.sub_device = sub_device request.param_id = param_id request.data = data request.include_raw_response = True request.include_raw_response = include_frames try: self._stub.RDMDiscoveryCommand( controller, request, lambda x, y: self._RDMCommandComplete(callback, x, y)) except socket.error: raise OLADNotRunningException() return True def GetCandidatePorts(self, callback, universe=None): """Send a GetCandidatePorts request. The result is similar to FetchDevices (GetDeviceInfo), except that returned devices will only contain ports available for patching to the given universe. If universe is None, then the devices will list their ports available for patching to a potential new universe. Args: callback: The function to call once complete, takes a RequestStatus object and a list of Device objects. universe: The universe to get the candidate ports for. If unspecified, return the candidate ports for a new universe. Returns: True if the request was sent, False otherwise. """ if self._socket is None: return False controller = SimpleRpcController() request = Ola_pb2.OptionalUniverseRequest() if universe is not None: request.universe = universe try: # GetCandidatePorts works very much like GetDeviceInfo, so we can re-use # its complete method. self._stub.GetCandidatePorts( controller, request, lambda x, y: self._DeviceInfoComplete(callback, x, y)) except socket.error: raise OLADNotRunningException() return True def _RDMMessage(self, universe, uid, sub_device, param_id, callback, data, include_frames, set=False): controller = SimpleRpcController() request = Ola_pb2.RDMRequest() request.universe = universe request.uid.esta_id = uid.manufacturer_id request.uid.device_id = uid.device_id request.sub_device = sub_device request.param_id = param_id request.data = data request.is_set = set request.include_raw_response = include_frames try: self._stub.RDMCommand( controller, request, lambda x, y: self._RDMCommandComplete(callback, x, y)) except socket.error: raise OLADNotRunningException() return True def _GetPluginsComplete(self, callback, controller, response): """Called when the list of plugins is returned. Args: callback: the callback to run controller: an RpcController response: a PluginInfoReply message. """ if not callback: return status = RequestStatus(controller) plugins = None if status.Succeeded(): plugins = sorted([Plugin.FromProtobuf(p) for p in response.plugin]) callback(status, plugins) def _PluginDescriptionComplete(self, callback, controller, response): """Called when the plugin description is returned. Args: callback: the callback to run controller: an RpcController response: a PluginInfoReply message. """ if not callback: return status = RequestStatus(controller) description = None if status.Succeeded(): description = response.description callback(status, description) def _DeviceInfoComplete(self, callback, controller, response): """Called when the Device info request returns. Args: callback: the callback to run controller: an RpcController response: a DeviceInfoReply message. """ if not callback: return status = RequestStatus(controller) devices = None if status.Succeeded(): devices = [] for device in response.device: input_ports = [] output_ports = [] for port in device.input_port: input_ports.append(Port.FromProtobuf(port)) for port in device.output_port: output_ports.append(Port.FromProtobuf(port)) devices.append(Device(device.device_id, device.device_alias, device.device_name, device.plugin_id, input_ports, output_ports)) callback(status, devices) def _UniverseInfoComplete(self, callback, controller, response): """Called when the Universe info request returns. Args: callback: the callback to run controller: an RpcController response: a UniverseInfoReply message. """ if not callback: return status = RequestStatus(controller) universes = None if status.Succeeded(): universes = [Universe.FromProtobuf(u) for u in response.universe] callback(status, universes) def _GetDmxComplete(self, callback, controller, response): """Called when the Universe info request returns. Args: callback: the callback to run controller: an RpcController response: a UniverseInfoReply message. """ if not callback: return status = RequestStatus(controller) data = None universe = None if status.Succeeded(): data = array.array('B') data.fromstring(response.data) universe = response.universe callback(status, universe, data) def _AckMessageComplete(self, callback, controller, response): """Called when an rpc that returns an Ack completes. Args: callback: the callback to run controller: an RpcController response: an Ack message. """ if not callback: return status = RequestStatus(controller) callback(status) def _ConfigureDeviceComplete(self, callback, controller, response): """Called when a ConfigureDevice request completes. Args: callback: the callback to run controller: an RpcController response: an DeviceConfigReply message. """ if not callback: return status = RequestStatus(controller) data = None if status.Succeeded(): data = response.data callback(status, data) def _FetchUIDsComplete(self, callback, controller, response): """Called when a FetchUIDList request completes. Args: callback: the callback to run controller: an RpcController response: an UIDListReply message. """ if not callback: return status = RequestStatus(controller) uids = None if status.Succeeded(): uids = [] for uid in response.uid: uids.append(UID(uid.esta_id, uid.device_id)) uids.sort() callback(status, uids) def _RDMCommandComplete(self, callback, controller, response): """Called when a RDM request completes. Args: callback: the callback to run controller: an RpcController response: an RDMResponse message. """ if not callback: return callback(RDMResponse(controller, response)) # Populate the patch & register actions for value in Ola_pb2._PATCHACTION.values: setattr(OlaClient, value.name, value.number) for value in Ola_pb2._REGISTERACTION.values: setattr(OlaClient, value.name, value.number) # populate time code enums for value in Ola_pb2._TIMECODETYPE.values: setattr(OlaClient, value.name, value.number) # populate the RDM response codes & types for value in Ola_pb2._RDMRESPONSECODE.values: setattr(OlaClient, value.name, value.number) for value in Ola_pb2._RDMRESPONSETYPE.values: setattr(OlaClient, value.name, value.number) for value in Ola_pb2._RDMCOMMANDCLASS.values: setattr(OlaClient, value.name, value.number) ola-0.10.5.nojsmin/python/ola/rpc/0000755000175000017500000000000013155164170016343 5ustar wouterwouterola-0.10.5.nojsmin/python/ola/rpc/Makefile.mk0000644000175000017500000000231213023355232020402 0ustar wouterwouter# ola python client # Python modules. ################################################## if BUILD_PYTHON_LIBS rpcpythondir = $(pkgpythondir)/rpc nodist_rpcpython_PYTHON = python/ola/rpc/Rpc_pb2.py rpcpython_PYTHON = python/ola/rpc/SimpleRpcController.py \ python/ola/rpc/StreamRpcChannel.py \ python/ola/rpc/__init__.py built_sources += python/ola/rpc/Rpc_pb2.py endif python/ola/rpc/Rpc_pb2.py: common/rpc/Rpc.proto mkdir -p python/ola/rpc $(PROTOC) --python_out python/ola/rpc -I ${top_srcdir}/common/rpc/ ${top_srcdir}/common/rpc/Rpc.proto # TESTS ################################################## if BUILD_PYTHON_LIBS test_scripts += python/ola/rpc/SimpleRpcControllerTest.sh endif dist_check_SCRIPTS += python/ola/rpc/SimpleRpcControllerTest.py python/ola/rpc/SimpleRpcControllerTest.sh: python/ola/rpc/Makefile.mk mkdir -p python/ola/rpc echo "export PYTHONPATH=${top_builddir}/python:${top_srcdir}/python; $(PYTHON) ${srcdir}/python/ola/rpc/SimpleRpcControllerTest.py; exit \$$?" > python/ola/rpc/SimpleRpcControllerTest.sh chmod +x python/ola/rpc/SimpleRpcControllerTest.sh CLEANFILES += python/ola/rpc/SimpleRpcControllerTest.sh \ python/ola/rpc/*.pyc ola-0.10.5.nojsmin/python/ola/rpc/SimpleRpcControllerTest.py0000755000175000017500000000444313023355232023522 0ustar wouterwouter#!/usr/bin/env python # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library 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 # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # SimpleRpcControllerTest.py # Copyright (C) 2005 Simon Newton import unittest from SimpleRpcController import SimpleRpcController """Test cases for the SimpleRpcController.""" __author__ = 'nomis52@gmail.com (Simon Newton)' class SimpleRpcControllerTest(unittest.TestCase): def setUp(self): self.callback_run = False def Callback(self): self.callback_run = True def testSimpleRpcController(self): controller = SimpleRpcController() self.assertFalse(controller.Failed()) self.assertFalse(controller.IsCanceled()) self.assertEqual(None, controller.ErrorText()) self.assertFalse(self.callback_run) # cancel controller.NotifyOnCancel(self.Callback) controller.StartCancel() self.assertFalse(controller.Failed()) self.assertFalse(not controller.IsCanceled()) self.assertEqual(None, controller.ErrorText()) self.assertFalse(not self.callback_run) self.callback_run = False controller.Reset() self.assertFalse(controller.Failed()) self.assertFalse(controller.IsCanceled()) self.assertEqual(None, controller.ErrorText()) # fail failure_string = 'foo' controller.SetFailed(failure_string) self.assertFalse(not controller.Failed()) self.assertFalse(controller.IsCanceled()) self.assertEqual(failure_string, controller.ErrorText()) controller.Reset() self.assertFalse(controller.Failed()) self.assertFalse(controller.IsCanceled()) self.assertEqual(None, controller.ErrorText()) self.assertFalse(self.callback_run) if __name__ == '__main__': unittest.main() ola-0.10.5.nojsmin/python/ola/rpc/StreamRpcChannel.py0000644000175000017500000002575313023355232022115 0ustar wouterwouter# This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library 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 # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # StreamRpcChannel.py # Copyright (C) 2005 Simon Newton import logging import struct from google.protobuf import service from ola.rpc import Rpc_pb2 from ola.rpc.SimpleRpcController import SimpleRpcController """A RpcChannel that works over a TCP socket.""" __author__ = 'nomis52@gmail.com (Simon Newton)' class OutstandingRequest(object): """These represent requests on the server side that haven't completed yet.""" def __init__(self, request_id, controller): self.controller = controller self.id = request_id class OutstandingResponse(object): """These represent requests on the client side that haven't completed yet.""" def __init__(self, response_id, controller, callback, reply_class): self.callback = callback self.controller = controller self.id = response_id self.reply = None self.reply_class = reply_class class StreamRpcChannel(service.RpcChannel): """Implements a RpcChannel over a TCP socket.""" PROTOCOL_VERSION = 1 VERSION_MASK = 0xf0000000 SIZE_MASK = 0x0fffffff RECEIVE_BUFFER_SIZE = 8192 def __init__(self, socket, service_impl, close_callback=None): """Create a new StreamRpcChannel. Args: socket: the socket to communicate on service: the service to route incoming requests to """ self._service = service_impl self._socket = socket self._sequence = 0 self._outstanding_requests = {} self._outstanding_responses = {} self._buffer = [] # The received data self._expected_size = None # The size of the message we're receiving self._skip_message = False # Skip the current message self._close_callback = close_callback def SocketReady(self): """Read data from the socket and handle when we get a full message. Returns: True if the socket remains connected, False if it was closed. """ data = self._socket.recv(self.RECEIVE_BUFFER_SIZE) if data == '': logging.info('OLAD Server Socket closed') if self._close_callback is not None: self._close_callback() return False self._buffer.append(data) self._ProcessIncomingData() return True def CallMethod(self, method, controller, request, response_pb, done): """Call a method. Don't use this directly, use the Stub object. Args: method: The MethodDescriptor to call controller: An RpcController object request: The request message response: The response class done: A closure to call once complete. """ message = Rpc_pb2.RpcMessage() message.type = Rpc_pb2.REQUEST message.id = self._sequence message.name = method.name message.buffer = request.SerializeToString() self._SendMessage(message) self._sequence += 1 if message.id in self._outstanding_responses: # fail any outstanding response with the same id, not the best approach # but it'll do for now. logging.warning('Response %d already pending, failing now', message.id) response = self._outstanding_responses[message.id] response.controller.SetFailed('Duplicate request found') self._InvokeCallback(response) response = OutstandingResponse(message.id, controller, done, response_pb) self._outstanding_responses[message.id] = response def RequestComplete(self, request, response): """This is called on the server side when a request has completed. Args: request: the OutstandingRequest object that has completed. response: the response to send to the client """ message = Rpc_pb2.RpcMessage() if request.controller.Failed(): self._SendRequestFailed(request) return message.type = Rpc_pb2.RESPONSE message.id = request.id message.buffer = response.SerializeToString() self._SendMessage(message) del self._outstanding_requests[request.id] def _EncodeHeader(self, size): """Encode a version and size into a header. Args: size: the size of the rpc message Returns: The header field """ header = (self.PROTOCOL_VERSION << 28) & self.VERSION_MASK header |= size & self.SIZE_MASK return struct.pack('=L', header) def _DecodeHeader(self, header): """Decode a header into the version and size. Args: header: the received header Return: A tuple in the form (version, size) """ return ((header & self.VERSION_MASK) >> 28, header & self.SIZE_MASK) def _SendMessage(self, message): """Send an RpcMessage. Args: message: An RpcMessage object. Returns: True if the send succeeded, False otherwise. """ data = message.SerializeToString() # combine into one buffer to send so we avoid sending two packets data = self._EncodeHeader(len(data)) + data sent_bytes = self._socket.send(data) if sent_bytes != len(data): logging.warning('Failed to send full datagram') return False return True def _SendRequestFailed(self, request): """Send a response indiciating this request failed. Args: request: An OutstandingRequest object. """ message = Rpc_pb2.RpcMessage() message.type = Rpc_pb2.RESPONSE_FAILED message.id = request.id message.buffer = request.controller.ErrorText() self._SendMessage(message) del self._outstanding_requests[request.id] def _SendNotImplemented(self, message_id): """Send a not-implemented response. Args: message_id: The message number. """ message = Rpc_pb2.RpcMessage message.type = Rpc_pb2.RESPONSE_NOT_IMPLEMENTED message.id = message_id self._SendMessage(message) def _GrabData(self, size): """Fetch the next N bytes of data from the buffer. Args: size: the amount of data to fetch. Returns: The next size bytes of data, or None if there isn't enough. """ data_size = sum([len(s) for s in self._buffer]) if data_size < size: return None data = [] size_left = size while size_left > 0: chunk = self._buffer.pop(0) if len(chunk) > size_left: # we only want part of it data.append(chunk[0:size_left]) self._buffer.insert(0, chunk[size_left:]) size_left = 0 else: data.append(chunk) size_left -= len(chunk) return b''.join(data) def _ProcessIncomingData(self): """Process the received data.""" while True: if not self._expected_size: # this is a new msg raw_header = self._GrabData(4) if not raw_header: # not enough data yet return header = struct.unpack('=L', raw_header)[0] version, size = self._DecodeHeader(header) if version != self.PROTOCOL_VERSION: logging.warning('Protocol mismatch: %d != %d', version, self.PROTOCOL_VERSION) self._skip_message = True self._expected_size = size data = self._GrabData(self._expected_size) if not data: # not enough data yet return if not self._skip_message: self._HandleNewMessage(data) self._expected_size = 0 self._skip_message = 0 def _HandleNewMessage(self, data): """Handle a new Message. Args: data: A chunk of data representing a RpcMessage """ message = Rpc_pb2.RpcMessage() message.ParseFromString(data) if message.type in self.MESSAGE_HANDLERS: self.MESSAGE_HANDLERS[message.type](self, message) else: logging.warning('Not sure of message type %d', message.type()) def _HandleRequest(self, message): """Handle a Request message. Args: message: The RpcMessage object. """ if not self._service: logging.warning('No service registered') return descriptor = self._service.GetDescriptor() method = descriptor.FindMethodByName(message.name) if not method: logging.warning('Failed to get method descriptor for %s', message.name) self._SendNotImplemented(message.id) return request_pb = self._service.GetRequestClass(method)() request_pb.ParseFromString(message.buffer) controller = SimpleRpcController() request = OutstandingRequest(message.id, controller) if message.id in self._outstanding_requests: logging.warning('Duplicate request for %d', message.id) self._SendRequestFailed(message.id) self._outstanding_requests[message.id] = request self._service.CallMethod(method, request.controller, request_pb, lambda x: self.RequestComplete(request, x)) def _HandleResponse(self, message): """Handle a Response message. Args: message: The RpcMessage object. """ response = self._outstanding_responses.get(message.id, None) if response: response.reply = response.reply_class() response.reply.ParseFromString(message.buffer) self._InvokeCallback(response) def _HandleCanceledResponse(self, message): """Handle a Not Implemented message. Args: message: The RpcMessage object. """ logging.warning('Received a canceled response') response = self._outstanding_responses.get(message.id, None) if response: response.controller.SetFailed(message.buffer) self._InvokeCallback(response) def _HandleFailedReponse(self, message): """Handle a Failed Response message. Args: message: The RpcMessage object. """ response = self._outstanding_responses.get(message.id, None) if response: response.controller.SetFailed(message.buffer) self._InvokeCallback(response) def _HandleNotImplemented(self, message): """Handle a Not Implemented message. Args: message: The RpcMessage object. """ logging.warning('Received a non-implemented response') response = self._outstanding_responses.get(message.id, None) if response: response.controller.SetFailed('Not Implemented') self._InvokeCallback(response) def _InvokeCallback(self, response): """Run the callback and delete the outstanding response. Args: response: the resoponse to run. """ response.callback(response.controller, response.reply) del self._outstanding_responses[response.id] MESSAGE_HANDLERS = { Rpc_pb2.REQUEST: _HandleRequest, Rpc_pb2.RESPONSE: _HandleResponse, Rpc_pb2.RESPONSE_CANCEL: _HandleCanceledResponse, Rpc_pb2.RESPONSE_FAILED: _HandleFailedReponse, Rpc_pb2.RESPONSE_NOT_IMPLEMENTED: _HandleNotImplemented, } ola-0.10.5.nojsmin/python/ola/rpc/SimpleRpcController.py0000644000175000017500000000310613023355232022652 0ustar wouterwouter# This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library 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 # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # SimpleRpcController.py # Copyright (C) 2005 Simon Newton from google.protobuf import service """An implementation of the RpcController interface.""" __author__ = 'nomis52@gmail.com (Simon Newton)' class SimpleRpcController(service.RpcController): """See google.protobuf.service.RpcController for documentation.""" def __init__(self): self.Reset() def Reset(self): self._failed = False self._cancelled = False self._error = None self._callback = None def Failed(self): return self._failed def ErrorText(self): return self._error def StartCancel(self): self._cancelled = True if self._callback: self._callback() def SetFailed(self, reason): self._failed = True self._error = reason def IsCanceled(self): return self._cancelled def NotifyOnCancel(self, callback): self._callback = callback ola-0.10.5.nojsmin/python/ola/rpc/__init__.py0000644000175000017500000000000013023355232020435 0ustar wouterwouterola-0.10.5.nojsmin/python/ola/DUBDecoderTest.py0000755000175000017500000000377313023355232020701 0ustar wouterwouter#!/usr/bin/env python # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library 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 # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # DUBDecoderTest.py # Copyright (C) Simon Newton import unittest from ola.DUBDecoder import DecodeResponse """Test cases for the DUBDecoder class.""" __author__ = 'nomis52@gmail.com (Simon Newton)' class UIDTest(unittest.TestCase): TEST_DATA = [ 0xfe, 0xfe, 0xfe, 0xfe, 0xaa, 0xaa, 0x55, 0xab, 0xf5, 0xaa, 0x55, 0xaa, 0x57, 0xaa, 0x55, 0xaa, 0x75, 0xae, 0x57, 0xbf, 0xfd ] TEST_BAD_DATA = [ 0xfe, 0xfe, 0xfe, 0xfe, 0xaa, 0xaa, 0x55, 0xab, 0xf5, 0xaa, 0x55, 0xaa, 0x57, 0xaa, 0x55, 0xaa, 0x75, 0xae, 0x57, 0xbf, 0xff # invalid checksum ] def testInvalid(self): # we stick to methods in 2.6 for now self.assertEqual(None, DecodeResponse(bytearray())) self.assertEqual(None, DecodeResponse([0])) self.assertEqual(None, DecodeResponse([0, 0, 0])) self.assertEqual(None, DecodeResponse(self.TEST_DATA[0:-1])) self.assertEqual(None, DecodeResponse(self.TEST_DATA[4:])) self.assertEqual(None, DecodeResponse(self.TEST_BAD_DATA)) def testValidResponse(self): uid = DecodeResponse(self.TEST_DATA) self.assertNotEqual(None, uid) self.assertEqual(0x00a1, uid.manufacturer_id) self.assertEqual(0x00020020, uid.device_id) if __name__ == '__main__': unittest.main() ola-0.10.5.nojsmin/python/ola/MACAddressTest.py0000755000175000017500000000577213023355232020710 0ustar wouterwouter#!/usr/bin/env python # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library 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 # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # MACAddressTest.py # Copyright (C) 2013 Peter Newman import sys import unittest from ola.MACAddress import MACAddress """Test cases for the MACAddress class.""" __author__ = 'nomis52@gmail.com (Simon Newton)' class MACAddressTest(unittest.TestCase): def testBasic(self): mac = MACAddress(bytearray([0x01, 0x23, 0x45, 0x67, 0x89, 0xab])) self.assertEqual(b'\x01\x23\x45\x67\x89\xab', bytes(mac.mac_address)) self.assertEqual('01:23:45:67:89:ab', str(mac)) # Python 3 does not allow sorting of incompatible types. # We don't use sys.version_info.major to support Python 2.6. if sys.version_info[0] == 2: self.assertTrue(mac > None) mac2 = MACAddress(bytearray([0x01, 0x23, 0x45, 0x67, 0x89, 0xcd])) self.assertTrue(mac2 > mac) mac3 = MACAddress(bytearray([0x01, 0x23, 0x45, 0x67, 0x88, 0xab])) self.assertTrue(mac > mac3) macs = [mac, mac2, mac3] self.assertEqual([mac3, mac, mac2], sorted(macs)) def testFromString(self): self.assertEqual(None, MACAddress.FromString('')) self.assertEqual(None, MACAddress.FromString('abc')) self.assertEqual(None, MACAddress.FromString(':')) self.assertEqual(None, MACAddress.FromString('0:1:2')) self.assertEqual(None, MACAddress.FromString('12345:1234')) mac = MACAddress.FromString('01:23:45:67:89:ab') self.assertTrue(mac) self.assertEqual(b'\x01\x23\x45\x67\x89\xab', bytes(mac.mac_address)) self.assertEqual('01:23:45:67:89:ab', str(mac)) mac2 = MACAddress.FromString('98.76.54.fe.dc.ba') self.assertTrue(mac2) self.assertEqual(b'\x98\x76\x54\xfe\xdc\xba', bytes(mac2.mac_address)) self.assertEqual('98:76:54:fe:dc:ba', str(mac2)) def testSorting(self): m1 = MACAddress(bytearray([0x48, 0x45, 0xff, 0xff, 0xff, 0xfe])) m2 = MACAddress(bytearray([0x48, 0x45, 0x00, 0x00, 0x02, 0x2e])) m3 = MACAddress(bytearray([0x48, 0x44, 0x00, 0x00, 0x02, 0x2e])) m4 = MACAddress(bytearray([0x48, 0x46, 0x00, 0x00, 0x02, 0x2e])) macs = sorted([m1, m2, m3, m4]) self.assertEqual([m3, m2, m1, m4], macs) def testEquals(self): m1 = MACAddress(bytearray([0x48, 0x45, 0xff, 0xff, 0xff, 0xfe])) m2 = MACAddress(bytearray([0x48, 0x45, 0xff, 0xff, 0xff, 0xfe])) self.assertEqual(m1, m2) if __name__ == '__main__': unittest.main() ola-0.10.5.nojsmin/python/ola/DUBDecoder.py0000644000175000017500000000345713023355232020035 0ustar wouterwouter# This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library 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 # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # DUBDecoder.py # Copyright (C) 2012 Simon Newton import itertools from ola.UID import UID """Decodes a DUB response.""" __author__ = 'nomis52@gmail.com (Simon Newton)' def DecodeResponse(data): """Decode a DUB response. Args: data: an iterable of data like a bytearray Returns: The UID that responded, or None if the response wasn't valid. """ # min length is 18 bytes if len(data) < 18: return None # must start with 0xfe if data[0] != 0xfe: return None data = list(itertools.dropwhile(lambda x: x == 0xfe, data)) if len(data) < 17 or data[0] != 0xaa: return None data = data[1:] checksum = 0 for b in data[0:12]: checksum += b packet_checksum = ( (data[12] & data[13]) << 8 | (data[14] & data[15]) ) if checksum != packet_checksum: return None manufacturer_id = ( (data[0] & data[1]) << 8 | (data[2] & data[3]) ) device_id = ( (data[4] & data[5]) << 24 | (data[6] & data[7]) << 16 | (data[8] & data[9]) << 8 | (data[10] & data[11]) ) return UID(manufacturer_id, device_id) ola-0.10.5.nojsmin/python/ola/MACAddress.py0000644000175000017500000000505013023355232020032 0ustar wouterwouter# This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library 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 # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # MACAddress.py # Copyright (C) 2013 Peter Newman """The MACAddress class.""" __author__ = 'nomis52@gmail.com (Simon Newton)' MAC_ADDRESS_LENGTH = 6 class Error(Exception): """Base Error Class.""" class MACAddress(object): """Represents a MAC Address.""" def __init__(self, mac_address): """Create a new MAC Address object. Args: mac_address: The byte array representation of the MAC Address, e.g. bytearray([0x01, 0x23, 0x45, 0x67, 0x89 0xab]). """ self._mac_address = mac_address @property def mac_address(self): return self._mac_address def __str__(self): return ':'.join(format(x, '02x') for x in self._mac_address) def __hash__(self): return hash(str(self)) def __repr__(self): return self.__str__() def __cmp__(self, other): if other is None: return 1 return cmp(self.mac_address, other.mac_address) def __lt__(self, other): return self.mac_address < other.mac_address def __eq__(self, other): if other is None: return False return self.mac_address == other.mac_address @staticmethod def FromString(mac_address_str): """Create a new MAC Address from a string. Args: mac_address_str: The string representation of the MAC Address, e.g. 01:23:45:67:89:ab or 98.76.54.fe.dc.ba. """ parts = mac_address_str.split(':') if len(parts) != MAC_ADDRESS_LENGTH: parts = mac_address_str.split('.') if len(parts) != MAC_ADDRESS_LENGTH: return None try: address = bytearray([int(parts[0], 16), int(parts[1], 16), int(parts[2], 16), int(parts[3], 16), int(parts[4], 16), int(parts[5], 16)]) except ValueError: return None return MACAddress(address) ola-0.10.5.nojsmin/python/ola/__init__.py0000644000175000017500000000000013023355232017651 0ustar wouterwouterola-0.10.5.nojsmin/python/examples/0000755000175000017500000000000013155164170016622 5ustar wouterwouterola-0.10.5.nojsmin/python/examples/ola_rdm_discover.py0000755000175000017500000000504313023355232022507 0ustar wouterwouter#!/usr/bin/env python # 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # ola_rdm_discover.py # Copyright (C) 2010 Simon Newton '''Show the UIDs for a universe.''' import getopt import textwrap import sys from ola.ClientWrapper import ClientWrapper __author__ = 'nomis52@gmail.com (Simon Newton)' def Usage(): print(textwrap.dedent("""\ Usage: ola_rdm_discover.py --universe [--force_discovery] Fetch the UID list for a universe. -h, --help Display this help message and exit. -f, --full Full RDM Discovery for this universe. -i, --incremental Incremental RDM Discovery for this universe. -u, --universe Universe number.""")) def main(): try: opts, args = getopt.getopt(sys.argv[1:], 'fjiu:', ['help', 'full', 'incremental', 'universe=']) except getopt.GetoptError as err: print(str(err)) Usage() sys.exit(2) universe = None full_discovery = False incremental_discovery = False for o, a in opts: if o in ('-h', '--help'): Usage() sys.exit() elif o in ('-f', '--full'): full_discovery = True elif o in ('-i', '--incremental'): incremental_discovery = True elif o in ('-u', '--universe'): universe = int(a) if not universe: Usage() sys.exit() if incremental_discovery and full_discovery: print('Only one of --incremental or --full can be specified') sys.exit() wrapper = ClientWrapper() client = wrapper.Client() def show_uids(state, uids): if state.Succeeded(): for uid in uids: print(str(uid)) wrapper.Stop() if full_discovery: client.RunRDMDiscovery(universe, True, show_uids) elif incremental_discovery: client.RunRDMDiscovery(universe, False, show_uids) else: client.FetchUIDList(universe, show_uids) wrapper.Run() if __name__ == '__main__': main() ola-0.10.5.nojsmin/python/examples/Makefile.mk0000644000175000017500000000114013023355232020657 0ustar wouterwouter# example python scripts dist_noinst_SCRIPTS += \ python/examples/ola_artnet_params.py \ python/examples/ola_candidate_ports.py \ python/examples/ola_devices.py \ python/examples/ola_patch_unpatch.py \ python/examples/ola_plugin_info.py \ python/examples/ola_rdm_discover.py \ python/examples/ola_rdm_get.py \ python/examples/ola_recv_dmx.py \ python/examples/ola_send_dmx.py \ python/examples/ola_simple_fade.py \ python/examples/ola_universe_info.py \ python/examples/rdm_compare.py \ python/examples/rdm_snapshot.py CLEANFILES += python/examples/*.pyc ola-0.10.5.nojsmin/python/examples/rdm_snapshot.py0000755000175000017500000004057413023355232021705 0ustar wouterwouter#!/usr/bin/env python # 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # rdm_snapshot.py # Copyright (C) 2012 Simon Newton import getopt import logging import pickle import pprint import sys import textwrap from ola import PidStore from ola.ClientWrapper import ClientWrapper from ola.OlaClient import OlaClient, RDMNack from ola.RDMAPI import RDMAPI from ola.UID import UID '''Quick script to collect the settings from a rig.''' __author__ = 'nomis52@gmail.com (Simon Newton)' class Error(Exception): """Base exception class.""" class DiscoveryException(Error): """Raised when discovery fails.""" class SaveException(Error): """Raised when we can't write to the output file.""" class LoadException(Error): """Raised when we can't write to the output file.""" class ConfigReader(object): """A controller that fetches data for responders.""" (EMPTYING_QUEUE, DMX_START_ADDRESS, DEVICE_LABEL, PERSONALITY) = range(4) def __init__(self, wrapper, pid_store): self.wrapper = wrapper self.pid_store = pid_store self.client = self.wrapper.Client() self.rdm_api = RDMAPI(self.client, self.pid_store) def Run(self, universe, skip_queued_messages): """Run the collector. Args: universe: The universe to collect skip_queued_messages: """ self.universe = universe self.skip_queued_messages = skip_queued_messages self._ResetData() self.client.RunRDMDiscovery(self.universe, True, self._HandleUIDList) self.wrapper.Run() return self.data def _ResetData(self): """Reset the internal data structures.""" self.uids = [] self.uid = None # the current uid we're fetching from self.outstanding_pid = None self.work_state = None # uid: {'start_address': '', 'personality': '', 'label': ''} self.data = {} def _GetPid(self, pid): self.rdm_api.Get(self.universe, self.uid, PidStore.ROOT_DEVICE, pid, self._RDMRequestComplete) logging.debug('Sent %s request' % pid) self.outstanding_pid = pid def _HandleUIDList(self, state, uids): """Called when the UID list arrives.""" if not state.Succeeded(): raise DiscoveryException(state.message) found_uids = set() for uid in uids: found_uids.add(uid) logging.debug(uid) self.uids = list(found_uids) self._FetchNextUID() def _HandleResponse(self, unpacked_data): logging.debug(unpacked_data) if self.work_state == self.DMX_START_ADDRESS: self._HandleStartAddress(unpacked_data) elif self.work_state == self.DEVICE_LABEL: self._HandleDeviceLabel(unpacked_data) elif self.work_state == self.PERSONALITY: self._HandlePersonality(unpacked_data) def _HandleStartAddress(self, data): """Called when we get a DMX_START_ADDRESS response.""" this_device = self.data.setdefault(str(self.uid), {}) this_device['dmx_start_address'] = data['dmx_address'] self._NextState() def _HandleDeviceLabel(self, data): """Called when we get a DEVICE_LABEL response.""" this_device = self.data.setdefault(str(self.uid), {}) this_device['label'] = data['label'] self._NextState() def _HandlePersonality(self, data): """Called when we get a DMX_PERSONALITY response.""" this_device = self.data.setdefault(str(self.uid), {}) this_device['personality'] = data['current_personality'] self._NextState() def _NextState(self): """Move to the next state of information fetching.""" if self.work_state == self.EMPTYING_QUEUE: # fetch start address pid = self.pid_store.GetName('DMX_START_ADDRESS') self._GetPid(pid) self.work_state = self.DMX_START_ADDRESS elif self.work_state == self.DMX_START_ADDRESS: # fetch device label pid = self.pid_store.GetName('DEVICE_LABEL') self._GetPid(pid) self.work_state = self.DEVICE_LABEL elif self.work_state == self.DEVICE_LABEL: # fetch personality pid = self.pid_store.GetName('DMX_PERSONALITY') self._GetPid(pid) self.work_state = self.PERSONALITY else: # this one is done, onto the next UID self._FetchNextUID() def _FetchNextUID(self): """Start fetching the info for the next UID.""" if not self.uids: self.wrapper.Stop() return self.uid = self.uids.pop() self.personalities = [] self.sensors = [] logging.debug('Fetching data for %s' % self.uid) self.work_state = self.EMPTYING_QUEUE if self.skip_queued_messages: # proceed to the fetch now self._NextState() else: self._FetchQueuedMessages() def _FetchNextPersonality(self): """Fetch the info for the next personality, or proceed to the next state if there are none left. """ if self.personalities: personality_index = self.personalities.pop(0) pid = self.pid_store.GetName('DMX_PERSONALITY_DESCRIPTION') self.rdm_api.Get(self.universe, self.uid, PidStore.ROOT_DEVICE, pid, self._RDMRequestComplete, [personality_index]) logging.debug('Sent DMX_PERSONALITY_DESCRIPTION request') self.outstanding_pid = pid else: self._NextState() def _FetchNextSensor(self): """Fetch the info for the next sensor, or proceed to the next state if there are none left. """ if self.sensors: sensor_index = self.sensors.pop(0) pid = self.pid_store.GetName('SENSOR_DEFINITION') self.rdm_api.Get(self.universe, self.uid, PidStore.ROOT_DEVICE, pid, self._RDMRequestComplete, [sensor_index]) logging.debug('Sent SENSOR_DEFINITION request') self.outstanding_pid = pid else: self._NextState() def _FetchQueuedMessages(self): """Fetch messages until the queue is empty.""" pid = self.pid_store.GetName('QUEUED_MESSAGE') self.rdm_api.Get(self.universe, self.uid, PidStore.ROOT_DEVICE, pid, self._QueuedMessageComplete, ['advisory']) logging.debug('Sent GET QUEUED_MESSAGE') def _QueuedMessageFound(self): if self.work_state == self.EMPTYING_QUEUE: self._FetchQueuedMessages() def _RDMRequestComplete(self, response, unpacked_data, unpack_exception): if not self._CheckForAckOrNack(response): return # at this stage the response is either a ack or nack if response.response_type == OlaClient.RDM_NACK_REASON: print('Got nack with reason for PID %d: %s' % (response.pid, response.nack_reason)) self._NextState() elif unpack_exception: print(unpack_exception) self.wrapper.Stop() else: self._HandleResponse(unpacked_data) def _QueuedMessageComplete(self, response, unpacked_data, unpack_exception): """Called when a queued message is returned.""" if not self._CheckForAckOrNack(response): return if response.response_type == OlaClient.RDM_NACK_REASON: if (self.outstanding_pid and response.command_class == OlaClient.RDM_GET_RESPONSE and response.pid == self.outstanding_pid.value): # we found what we were looking for print("found, but nacked") self.outstanding_pid = None self._NextState() elif (response.nack_reason == RDMNack.NR_UNKNOWN_PID and response.pid == self.pid_store.GetName('QUEUED_MESSAGE').value): logging.debug('Device doesn\'t support queued messages') self._NextState() else: print('Got nack for 0x%04hx with reason: %s' % ( response.pid, response.nack_reason)) elif unpack_exception: print('Invalid Param data: %s' % unpack_exception) else: status_messages_pid = self.pid_store.GetName('STATUS_MESSAGES') queued_message_pid = self.pid_store.GetName('QUEUED_MESSAGE') if (response.pid == status_messages_pid.value and unpacked_data.get('messages', []) == []): logging.debug('Got back empty list of STATUS_MESSAGES') self._NextState() return elif response.pid == queued_message_pid.value: logging.debug('Got back QUEUED_MESSAGE, this is a bad responder') self._NextState() return logging.debug('Got pid 0x%hx' % response.pid) if self.outstanding_pid and response.pid == self.outstanding_pid.value: self._HandleResponse(unpacked_data) else: self._FetchQueuedMessages() def _CheckForAckOrNack(self, response): """Check for all the different error conditions. Returns: True if this response was an ACK or NACK, False for all other cases. """ if not response.status.Succeeded(): print(response.status.message) self.wrapper.Stop() return False if response.response_code != OlaClient.RDM_COMPLETED_OK: print(response.ResponseCodeAsString()) self.wrapper.Stop() return False if response.response_type == OlaClient.RDM_ACK_TIMER: # schedule the fetch logging.debug('Got ack timer for %d ms' % response.ack_timer) self.wrapper.AddEvent(response.ack_timer, self._FetchQueuedMessages) return False return True class ConfigWriter(object): """A controller that applies configuration to a universe.""" (DMX_START_ADDRESS, DEVICE_LABEL, PERSONALITY, COMPLETE) = range(4) def __init__(self, wrapper, pid_store): self.wrapper = wrapper self.pid_store = pid_store self.client = self.wrapper.Client() self.rdm_api = RDMAPI(self.client, self.pid_store) def Run(self, universe, configuration): """Run the collector. Args: universe: The universe to collect configuration: The config to apply """ self.universe = universe self.configuration = configuration self.uids = list(configuration.keys()) self.client.RunRDMDiscovery(self.universe, True, self._HandleUIDList) self.wrapper.Run() def _HandleUIDList(self, state, uids): """Called when the UID list arrives.""" if not state.Succeeded(): raise DiscoveryException(state.message) found_uids = set() for uid in uids: found_uids.add(uid) logging.debug(uid) for uid in self.configuration.keys(): if uid not in found_uids: print('Device %s has been removed' % uid) self._SetNextUID() def _SetNextUID(self): """Start setting the info for the next UID.""" if not self.uids: self.wrapper.Stop() return self.uid = self.uids.pop() print('Doing %s' % self.uid) self.work_state = self.DMX_START_ADDRESS self._NextState() def _NextState(self): """Move to the next state of information fetching.""" if self.work_state == self.DMX_START_ADDRESS: address = self.configuration[self.uid].get('dmx_start_address') self.work_state = self.DEVICE_LABEL if address is not None: pid = self.pid_store.GetName('DMX_START_ADDRESS') self._SetPid(pid, [address]) return if self.work_state == self.DEVICE_LABEL: label = self.configuration[self.uid].get('label') self.work_state = self.PERSONALITY if label is not None: pid = self.pid_store.GetName('DEVICE_LABEL') self._SetPid(pid, [label]) return if self.work_state == self.PERSONALITY: personality = self.configuration[self.uid].get('personality') self.work_state = self.COMPLETE if personality is not None: pid = self.pid_store.GetName('DMX_PERSONALITY') self._SetPid(pid, [personality]) return # this one is done, onto the next UID self._SetNextUID() def _SetPid(self, pid, values): self.rdm_api.Set(self.universe, self.uid, PidStore.ROOT_DEVICE, pid, self._RDMRequestComplete, values) logging.debug('Sent %s request' % pid) self.outstanding_pid = pid def _RDMRequestComplete(self, response, unpacked_data, unpack_exception): if not response.status.Succeeded(): print(response.status.message) self.wrapper.Stop() return if response.response_code != OlaClient.RDM_COMPLETED_OK: print(response.ResponseCodeAsString()) self.wrapper.Stop() return if response.response_type == OlaClient.RDM_ACK_TIMER: # schedule the fetch logging.debug('Got ack timer for %d ms' % response.ack_timer) self.wrapper.AddEvent(response.ack_timer, self._FetchQueuedMessages) return # at this stage the response is either a ack or nack if response.response_type == OlaClient.RDM_NACK_REASON: print('Got nack with reason: %s' % response.nack_reason) self._NextState() def Usage(): print("Usage: rdm_snapshot.py --universe [--input ] " "[--output ]\n") print(textwrap.dedent("""\ Save and restore RDM settings for a universe. This includes the start address, personality and device label. Fetch and save a configuration: rdm_snapshot.py -u 1 --output /tmp/save Restore configuration: rdm_snapshot.py -u 1 --input /tmp/save -d, --debug Print extra debug info. -h, --help Display this help message and exit. -i, --input File to read configuration from. -p, --pid-location The directory to read PID definitions from. -o, --output File to save configuration to. --skip-queued-messages Don't attempt to fetch queued messages for the device. -u, --universe Universe number.""")) def WriteToFile(filename, output): try: log_file = open(filename, 'w') except IOError as e: raise SaveException( 'Failed to write to %s: %s' % (filename, e.message)) pickle.dump(output, log_file) logging.info('Wrote log file %s' % (log_file.name)) log_file.close() def ReadFile(filename): try: f = open(filename, 'rb') except IOError as e: raise LoadException(e) raw_data = pickle.load(f) f.close() data = {} for uid, settings in raw_data.items(): data[UID.FromString(uid)] = settings return data def main(): try: opts, args = getopt.getopt( sys.argv[1:], 'dhi:o:p:u:', ['debug', 'help', 'input=', 'skip-queued-messages', 'output=', 'pid-location=', 'universe=']) except getopt.GetoptError as err: print(str(err)) Usage() sys.exit(2) universe = None output_file = None input_file = None pid_location = None level = logging.INFO skip_queued_messages = False for o, a in opts: if o in ('-d', '--debug'): level = logging.DEBUG elif o in ('-h', '--help'): Usage() sys.exit() elif o in ('-i', '--input'): input_file = a elif o in ('--skip-queued-messages'): skip_queued_messages = True elif o in ('-o', '--output'): output_file = a elif o in ('-p', '--pid-location',): pid_location = a elif o in ('-u', '--universe'): universe = int(a) if universe is None: Usage() sys.exit() if input_file and output_file: print('Only one of --input and --output can be provided.') sys.exit() logging.basicConfig( level=level, format='%(message)s') client_wrapper = ClientWrapper() pid_store = PidStore.GetStore(pid_location) if input_file: configuration = ReadFile(input_file) if configuration: writer = ConfigWriter(client_wrapper, pid_store) writer.Run(universe, configuration) else: controller = ConfigReader(client_wrapper, pid_store) data = controller.Run(universe, skip_queued_messages) if output_file: WriteToFile(output_file, data) else: pprint.pprint(data) if __name__ == '__main__': main() ola-0.10.5.nojsmin/python/examples/ola_patch_unpatch.py0000755000175000017500000000475513023355232022661 0ustar wouterwouter#!/usr/bin/env python # 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # ola_patch_unpatch.py # Copyright (C) 2015 Simon Marchi """Patch and unpatch ports.""" from __future__ import print_function from ola.ClientWrapper import ClientWrapper from ola.OlaClient import OlaClient import argparse import sys __author__ = 'simon.marchi@polymtl.ca (Simon Marchi)' wrapper = None def ParseArgs(): description = 'Patch or unpatch an OLA port.' argparser = argparse.ArgumentParser(description=description) argparser.add_argument('--device', '-d', metavar='DEV', type=int, required=True) argparser.add_argument('--port', '-p', metavar='PORT', type=int, required=True) argparser.add_argument('--universe', '-u', metavar='UNI', type=int, required=True) argparser.add_argument('--mode', '-m', choices=['input', 'output'], required=True) argparser.add_argument('--action', '-a', choices=['patch', 'unpatch'], required=True) return argparser.parse_args() def PatchPortCallback(status): if status.Succeeded(): print('Success!') else: print('Error: %s' % status.message, file=sys.stderr) wrapper.Stop() def main(): args = ParseArgs() device = args.device port = args.port is_output = args.mode == 'output' action = OlaClient.PATCH if args.action == 'patch' else OlaClient.UNPATCH universe = args.universe global wrapper wrapper = ClientWrapper() client = wrapper.Client() client.PatchPort(device, port, is_output, action, universe, PatchPortCallback) wrapper.Run() if __name__ == '__main__': main() ola-0.10.5.nojsmin/python/examples/ola_plugin_info.py0000755000175000017500000000444313023355232022343 0ustar wouterwouter#!/usr/bin/env python # 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # ola_plugin_info.py # Copyright (C) 2005 Simon Newton """Lists the loaded plugins.""" from __future__ import print_function from ola.ClientWrapper import ClientWrapper import getopt import textwrap import sys __author__ = 'nomis52@gmail.com (Simon Newton)' wrapper = None def Usage(): print(textwrap.dedent(""" Usage: ola_plugin_info.py [--plugin ] Display a list of plugins, or a description for a particular plugin. -h, --help Display this help message and exit. -p, --plugin Plugin ID number.""")) def Plugins(status, plugins): if status.Succeeded(): for plugin in plugins: print('%d %s' % (plugin.id, plugin.name)) else: print('Error: %s' % status.message, file=sys.stderr) global wrapper if wrapper: wrapper.Stop() def PluginDescription(status, description): if status.Succeeded(): print(description) else: print('Error: %s' % status.message, file=sys.stderr) global wrapper if wrapper: wrapper.Stop() def main(): try: opts, args = getopt.getopt(sys.argv[1:], "hp:", ["help", "plugin="]) except getopt.GetoptError as err: print(str(err)) Usage() sys.exit(2) plugin = None for o, a in opts: if o in ("-h", "--help"): Usage() sys.exit() elif o in ("-p", "--plugin"): plugin = int(a) global wrapper wrapper = ClientWrapper() client = wrapper.Client() if plugin is not None: client.PluginDescription(PluginDescription, plugin) else: client.FetchPlugins(Plugins) wrapper.Run() if __name__ == "__main__": main() ola-0.10.5.nojsmin/python/examples/ola_devices.py0000755000175000017500000000334313023355232021452 0ustar wouterwouter#!/usr/bin/env python # 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # ola_devices.py # Copyright (C) 2005 Simon Newton """Lists the devices / ports.""" from __future__ import print_function from ola.ClientWrapper import ClientWrapper import sys __author__ = 'nomis52@gmail.com (Simon Newton)' wrapper = None def RDMString(port): if port.supports_rdm: return ', RDM supported' return '' def Devices(status, devices): if status.Succeeded(): for device in sorted(devices): print('Device %d: %s' % (device.alias, device.name)) print('Input ports:') for port in device.input_ports: print(' port %d, %s%s' % (port.id, port.description, RDMString(port))) print('Output ports:') for port in device.output_ports: print(' port %d, %s%s' % (port.id, port.description, RDMString(port))) else: print('Error: %s' % status.message, file=sys.stderr) global wrapper if wrapper: wrapper.Stop() def main(): global wrapper wrapper = ClientWrapper() client = wrapper.Client() client.FetchDevices(Devices) wrapper.Run() ola-0.10.5.nojsmin/python/examples/ola_recv_dmx.py0000755000175000017500000000332113023355232021633 0ustar wouterwouter#!/usr/bin/env python # 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # ola_recv_dmx.py # Copyright (C) 2005 Simon Newton """Receive DMX data.""" import getopt import textwrap import sys from ola.ClientWrapper import ClientWrapper __author__ = 'nomis52@gmail.com (Simon Newton)' def NewData(data): print(data) def Usage(): print(textwrap.dedent(""" Usage: ola_recv_dmx.py --universe Display the DXM512 data for the universe. -h, --help Display this help message and exit. -u, --universe Universe number.""")) def main(): try: opts, args = getopt.getopt(sys.argv[1:], "hu:", ["help", "universe="]) except getopt.GetoptError as err: print(str(err)) Usage() sys.exit(2) universe = 1 for o, a in opts: if o in ("-h", "--help"): Usage() sys.exit() elif o in ("-u", "--universe"): universe = int(a) wrapper = ClientWrapper() client = wrapper.Client() client.RegisterUniverse(universe, client.REGISTER, NewData) wrapper.Run() if __name__ == "__main__": main() ola-0.10.5.nojsmin/python/examples/ola_simple_fade.py0000755000175000017500000000510013023355232022271 0ustar wouterwouter#!/usr/bin/env python # 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # ola_simple_fade.py # Copyright (C) 2014 Sean Sill from array import array from ola.ClientWrapper import ClientWrapper from ola.DMXConstants import DMX_MIN_SLOT_VALUE, DMX_MAX_SLOT_VALUE, \ DMX_UNIVERSE_SIZE __author__ = 'Sean Sill' """ This script fades DMX_DATA_SIZE channels from 0 to 255. It serves as an example of how to use AddEvent to schedule dmx data updates from python To view data, use the web interface or patch an output device to the same universe """ UPDATE_INTERVAL = 25 # In ms, this comes about to ~40 frames a second SHUTDOWN_INTERVAL = 10000 # in ms, This is 10 seconds DMX_DATA_SIZE = 100 UNIVERSE = 1 class SimpleFadeController(object): def __init__(self, universe, update_interval, client_wrapper, dmx_data_size=DMX_UNIVERSE_SIZE): dmx_data_size = min(dmx_data_size, DMX_UNIVERSE_SIZE) self._universe = universe self._update_interval = update_interval self._data = array('B', [DMX_MIN_SLOT_VALUE] * dmx_data_size) self._wrapper = client_wrapper self._client = client_wrapper.Client() self._wrapper.AddEvent(self._update_interval, self.UpdateDmx) def UpdateDmx(self): """ This function gets called periodically based on UPDATE_INTERVAL """ for i in range(len(self._data)): self._data[i] = (self._data[i] + 1) % DMX_MAX_SLOT_VALUE # Send the DMX data self._client.SendDmx(self._universe, self._data) # For more information on Add Event, reference the OlaClient # Add our event again so it becomes periodic self._wrapper.AddEvent(self._update_interval, self.UpdateDmx) if __name__ == '__main__': wrapper = ClientWrapper() controller = SimpleFadeController(UNIVERSE, UPDATE_INTERVAL, wrapper, DMX_DATA_SIZE) # Call it initially wrapper.AddEvent(SHUTDOWN_INTERVAL, wrapper.Stop) # Start the wrapper wrapper.Run() ola-0.10.5.nojsmin/python/examples/rdm_compare.py0000755000175000017500000001213713023355232021466 0ustar wouterwouter#!/usr/bin/env python # 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # rdm_compare.py # Copyright (C) 2012 Simon Newton import getopt import os import pickle import sys import tempfile import textwrap import webbrowser from ola.UID import UID '''Compare the RDM configurations saves with rdm_snapshot.py''' __author__ = 'nomis52@gmail.com (Simon Newton)' class Error(Exception): """Base exception class.""" class LoadException(Error): """Raised when we can't write to the output file.""" def Usage(): print(textwrap.dedent("""\ Usage: rdm_compare.py Compare two RDM configurations saved with rdm_snapshot. Flags: -h, --help Display this help message and exit.""")) def ReadFile(filename): try: f = open(filename, 'rb') except IOError as e: raise LoadException(e) raw_data = pickle.load(f) f.close() data = {} for uid, settings in raw_data.items(): data[UID.FromString(uid)] = settings return data def TransformKey(key): tokens = key.split('_') output = [] for t in tokens: if t == 'dmx': output.append('DMX') else: output.append(t.capitalize()) return ' '.join(output) def Diff(configuration1, configuration2): """Return the added and removed devices.""" added = set() changed = [] removed = set() for uid, config1 in configuration1.items(): config2 = configuration2.get(uid) if config2 is None: removed.add(uid) continue fields = ['label', 'dmx_start_address', 'personality'] for field in fields: value1 = config1.get(field) value2 = config2.get(field) if value1 != value2: changed.append((uid, TransformKey(field), value1, value2)) for uid in configuration2: if uid not in configuration1: added.add(uid) return added, changed, removed def AddList(output, uids, title): if not uids: return output.append('

%s

    ' % title) for uid in uids: output.append('
  • %s
  • ' % uid) output.append('
') def DiffInBrowser(configuration1, configuration2): """Diff the configurations and output a HTML page.""" added, changed, removed = Diff(configuration1, configuration2) output = [] output.append(textwrap.dedent("""\ RDM Comparator

RDM Comparator

""")) AddList(output, added, 'Devices Added') AddList(output, removed, 'Devices Removed') if changed: output.append('

Device Changes

') output.append(' ') output.append(' ' '') for row in changed: output.append(' ') output.append('' % row) output.append(' ') output.append('
UIDFieldOldNew
%s%s%s%s
') output.append(textwrap.dedent("""\ """)) fd, filename = tempfile.mkstemp('.html') f = os.fdopen(fd, 'w') f.write('\n'.join(output)) f.close() # open in new tab if possible webbrowser.open('file://%s' % filename, new=2) def DiffToStdout(configuration1, configuration2): """Diff the configurations and write to STDOUT.""" added, changed, removed = Diff(configuration1, configuration2) for uid in added: print('Device %s was added' % uid) for uid in removed: print('Device %s was removed' % uid) for uid, human_field, value1, value2 in changed: print('%s: %s changed from %s to %s' % (uid, human_field, value1, value2)) def main(): try: opts, args = getopt.getopt( sys.argv[1:], 'hb', ['help', 'browser']) except getopt.GetoptError as err: print(str(err)) Usage() sys.exit(2) use_browser = False if len(args) != 2: Usage() sys.exit() for o, a in opts: if o in ('-h', '--help'): Usage() sys.exit() elif o in ('-b', '--browser'): use_browser = True configuration1 = ReadFile(args[0]) configuration2 = ReadFile(args[1]) if use_browser: DiffInBrowser(configuration1, configuration2) else: DiffToStdout(configuration1, configuration2) if __name__ == '__main__': main() ola-0.10.5.nojsmin/python/examples/ola_universe_info.py0000755000175000017500000000347713023355232022713 0ustar wouterwouter#!/usr/bin/env python # 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # ola_universe_info.py # Copyright (C) 2005 Simon Newton """Lists the active universes.""" from __future__ import print_function from ola.ClientWrapper import ClientWrapper from ola.OlaClient import Universe import sys __author__ = 'nomis52@gmail.com (Simon Newton)' wrapper = None def Universes(status, universes): if status.Succeeded(): for uni in universes: print('Universe %d' % uni.id) print(' - Name: %s' % uni.name) print(' - Merge mode: %s' % ( ('LTP' if uni.merge_mode == Universe.LTP else 'HTP'))) if len(uni.input_ports) > 0: print(' - Input ports:') for p in uni.input_ports: print(' - %s' % p) if len(uni.output_ports) > 0: print(' - Output ports:') for p in uni.output_ports: print(' - %s' % p) else: print('Error: %s' % status.message, file=sys.stderr) global wrapper if wrapper: wrapper.Stop() def main(): global wrapper wrapper = ClientWrapper() client = wrapper.Client() client.FetchUniverses(Universes) wrapper.Run() if __name__ == '__main__': main() ola-0.10.5.nojsmin/python/examples/ola_candidate_ports.py0000755000175000017500000000412313023355232023170 0ustar wouterwouter#!/usr/bin/env python # 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # ola_candidate_ports.py # Copyright (C) 2015 Simon Marchi """List candidate ports for patching.""" from __future__ import print_function from ola.ClientWrapper import ClientWrapper import argparse import sys __author__ = 'simon.marchi@polymtl.ca (Simon Marchi)' def ParseArgs(): desc = 'Show the candidate ports to patch to a universe.' argparser = argparse.ArgumentParser(description=desc) argparser.add_argument('--universe', '-u', type=int, help='Universe for which to get the candidates.') return argparser.parse_args() def GetCandidatePortsCallback(status, devices): if status.Succeeded(): for device in devices: print('Device {d.alias}: {d.name}'.format(d=device)) print('Candidate input ports:') for port in device.input_ports: s = ' port {p.id}, {p.description}, supports RDM: ' \ '{p.supports_rdm}' print(s.format(p=port)) print('Candidate output ports:') for port in device.output_ports: s = ' port {p.id}, {p.description}, supports RDM: ' \ '{p.supports_rdm}' print(s.format(p=port)) else: print('Error: %s' % status.message, file=sys.stderr) args = ParseArgs() universe = args.universe wrapper = ClientWrapper() client = wrapper.Client() client.GetCandidatePorts(GetCandidatePortsCallback, universe) wrapper.Run() ola-0.10.5.nojsmin/python/examples/ola_send_dmx.py0000755000175000017500000000306113023355232021626 0ustar wouterwouter#!/usr/bin/env python # 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # ola_send_dmx.py # Copyright (C) 2005 Simon Newton """Send some DMX data.""" from __future__ import print_function from ola.ClientWrapper import ClientWrapper import array import sys __author__ = 'nomis52@gmail.com (Simon Newton)' wrapper = None def DmxSent(status): if status.Succeeded(): print('Success!') else: print('Error: %s' % status.message, file=sys.stderr) global wrapper if wrapper: wrapper.Stop() def main(): universe = 1 data = array.array('B') # append first dmx-value data.append(10) # append second dmx-value data.append(50) # append third dmx-value data.append(255) global wrapper wrapper = ClientWrapper() client = wrapper.Client() # send 1 dmx frame with values for channels 1-3 client.SendDmx(universe, data, DmxSent) wrapper.Run() if __name__ == '__main__': main() ola-0.10.5.nojsmin/python/examples/ola_rdm_get.py0000755000175000017500000003440713023355232021456 0ustar wouterwouter#!/usr/bin/env python # 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # ola_rdm_get.py # Copyright (C) 2010 Simon Newton '''Get a PID from a UID.''' import cmd import getopt import os.path import readline import sys import textwrap from ola import PidStore from ola.ClientWrapper import ClientWrapper from ola.OlaClient import OlaClient, RDMNack from ola.RDMAPI import RDMAPI from ola.UID import UID __author__ = 'nomis52@gmail.com (Simon Newton)' def Usage(): print(textwrap.dedent("""\ Usage: ola_rdm_get.py --universe --uid Get the value of a pid for a device. Use 'ola_rdm_get --list-pids' to get a list of pids. -d, --sub-device target a particular sub device (default is 0) -h, --help display this help message and exit. -i, --interactive interactive mode -l, --list-pids display a list of pids -p, --pid-location the directory to read PID definitions from --uid the UID to send to -u, --universe Universe number.""")) wrapper = None class ResponsePrinter(object): def __init__(self): self.pid_store = PidStore.GetStore() # we can provide custom printers for PIDs below self._handlers = { 'SUPPORTED_PARAMETERS': self.SupportedParameters, 'PROXIED_DEVICES': self.ProxiedDevices, } def PrintResponse(self, uid, pid_value, response_data): pid = self.pid_store.GetPid(pid_value, uid.manufacturer_id) if pid is None: print('PID: 0x%04hx' % pid_value) self.Default(uid, response_data) else: print('PID: %s' % pid) if pid.name in self._handlers: self._handlers[pid.name](uid, response_data) else: self.Default(uid, response_data) def SupportedParameters(self, uid, response_data): params = sorted([p['param_id'] for p in response_data['params']]) for pid_value in params: pid = self.pid_store.GetPid(pid_value, uid.manufacturer_id) if pid: print(pid) else: print('0x%hx' % pid_value) def ProxiedDevices(self, uid, response_data): uids = [] for uid_data in response_data['uids']: uids.append(UID(uid_data['manufacturer_id'], uid_data['device_id'])) for uid in sorted(uids): print(uid) def Default(self, uid, response_data): if isinstance(response_data, dict): for key, value in response_data.items(): print('%s: %r' % (key, value)) else: print(response_data) class InteractiveModeController(cmd.Cmd): """Interactive mode!""" def __init__(self, universe, uid, sub_device, pid_location): """Create a new InteractiveModeController. Args: universe: uid: sub_device: pid_location: """ cmd.Cmd.__init__(self) self._universe = universe self._uid = uid self._sub_device = sub_device self.pid_store = PidStore.GetStore(pid_location) self.wrapper = ClientWrapper() self.client = self.wrapper.Client() self.rdm_api = RDMAPI(self.client, self.pid_store) self._uids = [] self._response_printer = ResponsePrinter() # tuple of (sub_device, command_class, pid) self._outstanding_request = None self.prompt = '> ' def emptyline(self): pass def do_exit(self, s): """Exit the interpreter.""" return True def do_EOF(self, s): print('') return self.do_exit('') def do_uid(self, line): """Sets the active UID.""" args = line.split() if len(args) != 1: print('*** Requires a single UID argument') return uid = UID.FromString(args[0]) if uid is None: print('*** Invalid UID') return if uid not in self._uids: print('*** UID not found') return self._uid = uid print('Fetching queued messages...') self._FetchQueuedMessages() self.wrapper.Run() def complete_uid(self, text, line, start_index, end_index): tokens = line.split() if len(tokens) > 1 and text == '': return [] uids = [str(uid) for uid in self._uids if str(uid).startswith(text)] return uids def do_subdevice(self, line): """Sets the sub device.""" args = line.split() if len(args) != 1: print('*** Requires a single int argument') return try: sub_device = int(args[0]) except ValueError: print('*** Requires a single int argument') return if sub_device < 0 or sub_device > PidStore.ALL_SUB_DEVICES: print('*** Argument must be between 0 and 0x%hx' % PidStore.ALL_SUB_DEVICES) return self._sub_device = sub_device def do_print(self, l): """Prints the current universe, UID and sub device.""" print(textwrap.dedent("""\ Universe: %d UID: %s Sub Device: %d""" % ( self._universe, self._uid, self._sub_device))) def do_uids(self, l): """List the UIDs for this universe.""" self.client.FetchUIDList(self._universe, self._DisplayUids) self.wrapper.Run() def _DisplayUids(self, state, uids): self._uids = [] if state.Succeeded(): self._UpdateUids(uids) for uid in uids: print(str(uid)) self.wrapper.Stop() def do_full_discovery(self, l): """Run full RDM discovery for this universe.""" self.client.RunRDMDiscovery(self._universe, True, self._DiscoveryDone) self.wrapper.Run() def do_incremental_discovery(self, l): """Run incremental RDM discovery for this universe.""" self.client.RunRDMDiscovery(self._universe, False, self._DiscoveryDone) self.wrapper.Run() def _DiscoveryDone(self, state, uids): if state.Succeeded(): self._UpdateUids(uids) self.wrapper.Stop() def _UpdateUids(self, uids): self._uids = [] for uid in uids: self._uids.append(uid) def do_list(self, line): """List the pids available.""" names = [] for pid in self.pid_store.Pids(): names.append('%s (0x%04hx)' % (pid.name.lower(), pid.value)) if self._uid: for pid in self.pid_store.ManufacturerPids(self._uid.manufacturer_id): names.append('%s (0x%04hx)' % (pid.name.lower(), pid.value)) names.sort() print('\n'.join(names)) def do_queued(self, line): """Fetch all the queued messages.""" self._FetchQueuedMessages() self.wrapper.Run() def do_get(self, line): """Send a GET command.""" self.GetOrSet(PidStore.RDM_GET, line) def complete_get(self, text, line, start_index, end_index): return self.CompleteGetOrSet(PidStore.RDM_GET, text, line) def do_set(self, line): """Send a SET command.""" self.GetOrSet(PidStore.RDM_SET, line) def complete_set(self, text, line, start_index, end_index): return self.CompleteGetOrSet(PidStore.RDM_SET, text, line) def CompleteGetOrSet(self, request_type, text, line): if len(line.split(' ')) > 2: return [] pids = [pid for pid in self.pid_store.Pids() if pid.name.lower().startswith(text)] if self._uid: for pid in self.pid_store.ManufacturerPids(self._uid.manufacturer_id): if pid.name.lower().startswith(text): pids.append(pid) # now check if this type of request is supported pid_names = sorted([pid.name.lower() for pid in pids if pid.RequestSupported(request_type)]) return pid_names def GetOrSet(self, request_type, line): if self._uid is None: print('*** No UID selected, use the uid command') return args = line.split() command = 'get' if request_type == PidStore.RDM_SET: command = 'set' if len(args) < 1: print('%s [args]' % command) return pid = None try: pid = self.pid_store.GetPid(int(args[0], 0), self._uid.manufacturer_id) except ValueError: pid = self.pid_store.GetName(args[0].upper(), self._uid.manufacturer_id) if pid is None: print('*** Unknown pid %s' % args[0]) return if not pid.RequestSupported(request_type): print('*** PID does not support command') return if request_type == PidStore.RDM_SET: method = self.rdm_api.Set else: method = self.rdm_api.Get try: if method(self._universe, self._uid, self._sub_device, pid, self._RDMRequestComplete, args[1:]): self._outstanding_request = (self._sub_device, request_type, pid) self.wrapper.Run() except PidStore.ArgsValidationError as e: args, help_string = pid.GetRequestDescription(request_type) print('Usage: %s %s %s' % (command, pid.name.lower(), args)) print(help_string) print('') print('*** %s' % e) return def _FetchQueuedMessages(self): """Fetch messages until the queue is empty.""" pid = self.pid_store.GetName('QUEUED_MESSAGE', self._uid.manufacturer_id) self.rdm_api.Get(self._universe, self._uid, PidStore.ROOT_DEVICE, pid, self._QueuedMessageComplete, ['error']) def _RDMRequestComplete(self, response, unpacked_data, unpack_exception): if not self._CheckForAckOrNack(response): return # at this stage the response is either a ack or nack self._outstanding_request = None self.wrapper.Stop() if response.response_type == OlaClient.RDM_NACK_REASON: print('Got nack with reason: %s' % response.nack_reason) elif unpack_exception: print(unpack_exception) else: self._response_printer.PrintResponse(self._uid, response.pid, unpacked_data) if response.queued_messages: print('%d queued messages remain' % response.queued_messages) def _QueuedMessageComplete(self, response, unpacked_data, unpack_exception): if not self._CheckForAckOrNack(response): return if response.response_type == OlaClient.RDM_NACK_REASON: if (self._outstanding_request and response.sub_device == self._outstanding_request[0] and response.command_class == self._outstanding_request[1] and response.pid == self._outstanding_request[2].value): # we found what we were looking for self._outstanding_request = None self.wrapper.StopIfNoEvents() elif (response.nack_reason == RDMNack.NR_UNKNOWN_PID and response.pid == self.pid_store.GetName('QUEUED_MESSAGE').value): print('Device doesn\'t support queued messages') self.wrapper.StopIfNoEvents() else: print('Got nack for 0x%04hx with reason: %s' % ( response.pid, response.nack_reason)) elif unpack_exception: print('Invalid Param data: %s' % unpack_exception) else: status_messages_pid = self.pid_store.GetName('STATUS_MESSAGES') if (response.pid == status_messages_pid.value and unpacked_data.get('messages', []) == []): self.wrapper.StopIfNoEvents() return self._response_printer.PrintResponse(self._uid, response.pid, unpacked_data) if response.queued_messages: self._FetchQueuedMessages() else: self.wrapper.StopIfNoEvents() def _CheckForAckOrNack(self, response): """Check for all the different error conditions. Returns: True if this response was an ACK or NACK, False for all other cases. """ if not response.status.Succeeded(): print(response.status.message) self.wrapper.Stop() return False if response.response_code != OlaClient.RDM_COMPLETED_OK: print(response.ResponseCodeAsString()) self.wrapper.Stop() return False if response.response_type == OlaClient.RDM_ACK_TIMER: # schedule the fetch self.wrapper.AddEvent(response.ack_timer, self._FetchQueuedMessages) return False return True def main(): readline.set_completer_delims(' \t') try: opts, args = getopt.getopt(sys.argv[1:], 'd:hilp:u:', ['sub-device=', 'help', 'interactive', 'list-pids', 'pid-location=', 'uid=', 'universe=']) except getopt.GetoptError as err: print(str(err)) Usage() sys.exit(2) universe = None uid = None sub_device = 0 list_pids = False pid_location = None interactive_mode = False for o, a in opts: if o in ('-d', '--sub-device'): sub_device = int(a) elif o in ('-h', '--help'): Usage() sys.exit() elif o in ('-i', '--interactive'): interactive_mode = True elif o in ('-l', '--list-pids'): list_pids = True elif o in ('--uid',): uid = UID.FromString(a) elif o in ('-p', '--pid-location',): pid_location = a elif o in ('-u', '--universe'): universe = int(a) if universe is None and not list_pids: Usage() sys.exit() if not uid and not list_pids and not interactive_mode: Usage() sys.exit() # try to load the PID store so we fail early if we're missing PIDs try: PidStore.GetStore(pid_location) except PidStore.MissingPLASAPIDs as e: print e sys.exit() controller = InteractiveModeController(universe, uid, sub_device, pid_location) if interactive_mode: sys.stdout.write('Available Uids:\n') controller.onecmd('uids') controller.cmdloop() sys.exit() if list_pids: controller.onecmd('list') sys.exit() if len(args) == 0: Usage() sys.exit() request_type = 'get' if os.path.basename(sys.argv[0]) == 'ola_rdm_set.py': request_type = 'set' controller.onecmd('%s %s' % (request_type, ' '.join(args))) if __name__ == '__main__': main() ola-0.10.5.nojsmin/python/examples/ola_artnet_params.py0000755000175000017500000000350613023355232022671 0ustar wouterwouter#!/usr/bin/env python # 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # ola_artnet_params.py # Copyright (C) 2005 Simon Newton """Fetch some ArtNet parameters.""" from __future__ import print_function from ola.ClientWrapper import ClientWrapper from ola import ArtNetConfigMessages_pb2 import sys __author__ = 'nomis52@gmail.com (Simon Newton)' def ArtNetConfigureReply(status, response): if status.Succeeded(): reply = ArtNetConfigMessages_pb2.Reply() reply.ParseFromString(response) print('Short Name: %s' % reply.options.short_name) print('Long Name: %s' % reply.options.long_name) print('Subnet: %d' % reply.options.subnet) else: print('Error: %s' % status.message, file=sys.stderr) global wrapper if wrapper: wrapper.Stop() def main(): # Set this appropriately device_alias = 1 global wrapper wrapper = ClientWrapper() client = wrapper.Client() artnet_request = ArtNetConfigMessages_pb2.Request() artnet_request.type = artnet_request.ARTNET_OPTIONS_REQUEST client.ConfigureDevice(device_alias, artnet_request.SerializeToString(), ArtNetConfigureReply) wrapper.Run() if __name__ == '__main__': main() ola-0.10.5.nojsmin/common/0000755000175000017500000000000013155164170014753 5ustar wouterwouterola-0.10.5.nojsmin/common/math/0000755000175000017500000000000013155164170015704 5ustar wouterwouterola-0.10.5.nojsmin/common/math/Makefile.mk0000644000175000017500000000017013023355232017743 0ustar wouterwouter# LIBRARIES ################################################## common_libolacommon_la_SOURCES += common/math/Random.cpp ola-0.10.5.nojsmin/common/math/Random.cpp0000644000175000017500000000360713023355232017631 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Random.cpp * Random number generator * Copyright (C) 2012 Simon Newton */ #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #include #include #include #ifdef HAVE_RANDOM #include #endif // HAVE_RANDOM #include "ola/Clock.h" #include "ola/math/Random.h" namespace ola { namespace math { #ifdef HAVE_RANDOM std::default_random_engine generator_; #endif // HAVE_RANDOM void InitRandom() { Clock clock; TimeStamp now; clock.CurrentTime(&now); uint64_t seed = (static_cast(now.MicroSeconds()) << 32) + static_cast(getpid()); #ifdef HAVE_RANDOM generator_.seed(seed); #elif defined(_WIN32) srand(seed); #else srandom(seed); #endif // HAVE_RANDOM } int Random(int lower, int upper) { #ifdef HAVE_RANDOM std::uniform_int_distribution distribution(lower, upper); return distribution(generator_); #elif defined(_WIN32) return (lower + (rand() % (upper - lower + 1))); // NOLINT(runtime/threadsafe_fn) #else return (lower + (random() % (upper - lower + 1))); #endif // HAVE_RANDOM } } // namespace math } // namespace ola ola-0.10.5.nojsmin/common/Makefile.mk0000644000175000017500000000204013023355232017010 0ustar wouterwouterlib_LTLIBRARIES += common/libolacommon.la # Variables the included files can append to # ------------------------------------------ common_libolacommon_la_CXXFLAGS = $(COMMON_PROTOBUF_CXXFLAGS) common_libolacommon_la_LIBADD = common_libolacommon_la_SOURCES = nodist_common_libolacommon_la_SOURCES = # ------------------------------------------ if USING_WIN32 common_libolacommon_la_LIBADD += -lWs2_32 -lIphlpapi endif include common/base/Makefile.mk include common/dmx/Makefile.mk include common/export_map/Makefile.mk include common/file/Makefile.mk include common/http/Makefile.mk include common/io/Makefile.mk include common/math/Makefile.mk include common/messaging/Makefile.mk include common/network/Makefile.mk include common/protocol/Makefile.mk include common/rdm/Makefile.mk include common/rpc/Makefile.mk include common/strings/Makefile.mk include common/system/Makefile.mk include common/testing/Makefile.mk include common/thread/Makefile.mk include common/timecode/Makefile.mk include common/utils/Makefile.mk include common/web/Makefile.mk ola-0.10.5.nojsmin/common/system/0000755000175000017500000000000013155164170016277 5ustar wouterwouterola-0.10.5.nojsmin/common/system/Makefile.mk0000644000175000017500000000024413023355232020340 0ustar wouterwouter# LIBRARIES ################################################## common_libolacommon_la_SOURCES += \ common/system/Limits.cpp \ common/system/SystemUtils.cpp ola-0.10.5.nojsmin/common/system/SystemUtils.cpp0000644000175000017500000000337213023355232021310 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SystemUtils.cpp * System Helper methods. * Copyright (C) 2013 Peter Newman */ #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include "ola/Logging.h" #include "ola/system/SystemUtils.h" namespace ola { namespace system { bool LoadAverage(load_averages average, double *value) { #ifdef HAVE_GETLOADAVG if (average >= NUMBER_LOAD_AVERAGES) { return false; } double averages[NUMBER_LOAD_AVERAGES]; uint8_t returned; returned = getloadavg(averages, NUMBER_LOAD_AVERAGES); if (returned != NUMBER_LOAD_AVERAGES) { OLA_WARN << "getloadavg only returned " << static_cast(returned) << " values, expecting " << static_cast(NUMBER_LOAD_AVERAGES) << " values"; return false; } else { *value = averages[average]; return true; } #else // No getloadavg, do something else if Windows? OLA_WARN << "getloadavg not supported, can't fetch value"; (void) average; *value = 0; return false; #endif // HAVE_GETLOADAVG } } // namespace system } // namespace ola ola-0.10.5.nojsmin/common/system/Limits.cpp0000644000175000017500000000274613023355232020250 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Limits.cpp * Functions that deal with system limits (rlimits) * Copyright (C) 2014 Simon Newton */ #ifndef _WIN32 #include "ola/system/Limits.h" #include #include #include #include "ola/Logging.h" namespace ola { namespace system { bool GetRLimit(int resource, struct rlimit *lim) { int r = getrlimit(resource, lim); if (r) { OLA_WARN << "getrlimit(" << resource << "): " << strerror(errno); return false; } return true; } bool SetRLimit(int resource, const struct rlimit &lim) { int r = setrlimit(resource, &lim); if (r) { OLA_WARN << "setrlimit(" << resource << "): " << strerror(errno); return false; } return true; } } // namespace system } // namespace ola #endif // _WIN32 ola-0.10.5.nojsmin/common/web/0000755000175000017500000000000013134123610015517 5ustar wouterwouterola-0.10.5.nojsmin/common/web/ParserTest.cpp0000644000175000017500000005040613023355232020330 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * ParserTest.cpp * Unittest for the Json Parser. * Copyright (C) 2014 Simon Newton */ #include #include #include #include "ola/web/Json.h" #include "ola/web/JsonLexer.h" #include "ola/web/JsonParser.h" #include "ola/web/JsonWriter.h" #include "ola/testing/TestUtils.h" using ola::web::JsonArray; using ola::web::JsonBool; using ola::web::JsonInt; using ola::web::JsonLexer; using ola::web::JsonNull; using ola::web::JsonObject; using ola::web::JsonParser; using ola::web::JsonString; using ola::web::JsonUInt; using ola::web::JsonValue; using ola::web::JsonWriter; using std::auto_ptr; using std::string; class JsonParserTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(JsonParserTest); CPPUNIT_TEST(testParseBool); CPPUNIT_TEST(testParseNull); CPPUNIT_TEST(testParseString); CPPUNIT_TEST(testParseNumber); CPPUNIT_TEST(testArray); CPPUNIT_TEST(testObject); CPPUNIT_TEST(testInvalidInput); CPPUNIT_TEST(testStressTests); CPPUNIT_TEST_SUITE_END(); public: void testParseBool(); void testParseNull(); void testParseString(); void testParseNumber(); void testArray(); void testObject(); void testInvalidInput(); void testStressTests(); }; CPPUNIT_TEST_SUITE_REGISTRATION(JsonParserTest); void JsonParserTest::testParseBool() { string error; auto_ptr value(JsonParser::Parse(" true ", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("true"), JsonWriter::AsString(*value.get())); // no whitespace value.reset(JsonParser::Parse("true", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("true"), JsonWriter::AsString(*value.get())); // tabs value.reset(JsonParser::Parse("\ttrue\r\n", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("true"), JsonWriter::AsString(*value.get())); // false values value.reset(JsonParser::Parse("false", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("false"), JsonWriter::AsString(*value.get())); } void JsonParserTest::testParseNull() { string error; auto_ptr value(JsonParser::Parse(" null ", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("null"), JsonWriter::AsString(*value.get())); } void JsonParserTest::testParseString() { string error; auto_ptr value(JsonParser::Parse("\"test\"", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("\"test\""), JsonWriter::AsString(*value.get())); // test a missing " value.reset(JsonParser::Parse("\"test", &error)); OLA_ASSERT_NULL(value.get()); // test escaping value.reset(JsonParser::Parse("\"test\\\" escape\"", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("\"test\\\" escape\""), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("\"
\n\\n
\"", &error)); OLA_ASSERT_NOT_NULL(value.get()); /* OLA_ASSERT_EQ(string("\"
\n\\n
\""), JsonWriter::AsString(*value.get())); */ } void JsonParserTest::testParseNumber() { string error; auto_ptr value(JsonParser::Parse(" 0", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("0"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse(" -0", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("0"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse(" 1 ", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("1"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("4096 ", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("4096"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse(" -1", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("-1"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse(" -345", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("-345"), JsonWriter::AsString(*value.get())); // Decimals value.reset(JsonParser::Parse(" 0.0", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("0"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse(" 0.1", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("0.1"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("0.123456", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("0.123456"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("-0.123456", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("-0.123456"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("3.14159", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("3.14159"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("-3.14159", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("-3.14159"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("-17.079", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("-17.079"), JsonWriter::AsString(*value.get())); // Exponents value.reset(JsonParser::Parse("0e1", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("0"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("0e-2", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("0"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("-0E1", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("0"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("-0e-3", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("0"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("1E4", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("1e4"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("5e-4", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("5e-4"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("912E-2", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("912e-2"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("-23e4", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("-23e4"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("-912E-2", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("-912e-2"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("14e0", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("14"), JsonWriter::AsString(*value.get())); // exponents with decimals value.reset(JsonParser::Parse("-3.1e2", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("-3.1e2"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("3.14E3", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("3.14e3"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("3.14e-1", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("3.14e-1"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("-2.718e-1", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("-2.718e-1"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse(" -0.2718E+2 ", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("-0.2718e2"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("-0.2718e-1 ", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("-0.2718e-1"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("0.2718e+1", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("0.2718e1"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("0.2718e-2 ", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("0.2718e-2"), JsonWriter::AsString(*value.get())); // Invalid inputs value.reset(JsonParser::Parse("-", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("1e", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("1E", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("1e-", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("1E-", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("1e+", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("1E+", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("-", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("a", &error)); OLA_ASSERT_NULL(value.get()); } void JsonParserTest::testArray() { string error; auto_ptr value(JsonParser::Parse(" [ ]", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("[]"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("[ 1] ", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("[1]"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("[ true,\tfalse ,null ] ", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("[true, false, null]"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("[ 1\n, 2 \t, 3,4 ] ", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("[1, 2, 3, 4]"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse( "[\"test]\", 1, [\"nested\"], 4] ", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("[\n \"test]\",\n 1,\n [\"nested\"],\n 4\n]"), JsonWriter::AsString(*value.get())); // Invalid input value.reset(JsonParser::Parse("[abc] ", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("[,] ", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse(" [\n, ] ", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse(" [", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse(" [1", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse(" [1,", &error)); OLA_ASSERT_NULL(value.get()); } void JsonParserTest::testObject() { string error; auto_ptr value(JsonParser::Parse("{}", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("{}"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("{\"key\" : 1} ", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("{\n \"key\": 1\n}"), JsonWriter::AsString(*value.get())); // Multiple keys value.reset(JsonParser::Parse( "{\"key1\" : 1, \"key2\" : 2} ", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("{\n \"key1\": 1,\n \"key2\": 2\n}"), JsonWriter::AsString(*value.get())); // Nested value.reset(JsonParser::Parse( "{\"key1\" : 1, \"key2\" : {\"age\": 24}} ", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ( string("{\n \"key1\": 1,\n \"key2\": {\n \"age\": 24\n }\n}"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse( "{\"key1\" : 1, \"key2\" : [1, 2 ] } ", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("{\n \"key1\": 1,\n \"key2\": [1, 2]\n}"), JsonWriter::AsString(*value.get())); // double key test value.reset(JsonParser::Parse("{\"key\" : 1, \"key\" : 2} ", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("{\n \"key\": 2\n}"), JsonWriter::AsString(*value.get())); // trailing comma test. This is outside the standard, but seems to be // commonly used. /* value.reset(JsonParser::Parse("{\"key\" : 1, } ", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("{\n \"key\": 2\n}"), JsonWriter::AsString(*value.get())); */ value.reset(JsonParser::Parse("{", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("{1", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("{true", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("{\"", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("{\"key", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("{\"key\"", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("{\"key\":", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("{\"key\" : }", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("{'key': 1}", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse( "{\"default\": {\"pets\": [1, 2, {null}]}}}", &error)); OLA_ASSERT_NULL(value.get()); } void JsonParserTest::testInvalidInput() { string error; auto_ptr value(JsonParser::Parse(" ", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("TRUE", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("FALSE", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("NULL", &error)); OLA_ASSERT_NULL(value.get()); } /** * From https://code.google.com/p/json-smart/wiki/FeaturesTests * Some of these overlap with the ones above. */ void JsonParserTest::testStressTests() { string error; auto_ptr value(JsonParser::Parse("{}", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("{}"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("{ \"v\":\"1\"}", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("{\n \"v\": \"1\"\n}"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("{ \"v\":\"1\"\r\n}", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("{\n \"v\": \"1\"\n}"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("{ \"v\":1}", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("{\n \"v\": 1\n}"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("{ \"v\":\"ab'c\"}", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("{\n \"v\": \"ab'c\"\n}"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("{ \"PI\":3.141E-10}", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("{\n \"PI\": 3.141e-10\n}"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("{ \"PI\":3.141e-10}", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("{\n \"PI\": 3.141e-10\n}"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("{ \"v\":12345123456789}", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("{\n \"v\": 12345123456789\n}"), JsonWriter::AsString(*value.get())); /* // We don't pass the big-int test. value.reset(JsonParser::Parse("{ \"v\":123456789123456789123456789}", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("{\n \"v\": 123456789123456789123456789\n}"), JsonWriter::AsString(*value.get())); */ value.reset(JsonParser::Parse("[ 1,2,3,4]", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("[1, 2, 3, 4]"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("[ \"1\",\"2\",\"3\",\"4\"]", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("[\"1\", \"2\", \"3\", \"4\"]"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("[ { }, { }, []]", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("[\n {},\n {},\n []\n]"), JsonWriter::AsString(*value.get())); /* value.reset(JsonParser::Parse("{ \"v\":\"\u2000\u20ff\"}", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("{\n \"v\": \"\"\n}"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("{ \"v\":\"\u2000\u20FF\"}", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("{\n \"v\": \"\"\n}"), JsonWriter::AsString(*value.get())); */ value.reset(JsonParser::Parse("{ \"a\":\"hp://foo\"}", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("{\n \"a\": \"hp:\\/\\/foo\"\n}"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("{ \"a\":null}", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("{\n \"a\": null\n}"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("{ \"a\":true}", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("{\n \"a\": true\n}"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("{ \"a\" : true }", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("{\n \"a\": true\n}"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse( "{ \"v\" : 1.7976931348623157E308}", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("{\n \"v\": 1.7976931348623157e308\n}"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse( "{ \"v\" : 1.79E08}", &error)); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("{\n \"v\": 1.79e8\n}"), JsonWriter::AsString(*value.get())); value.reset(JsonParser::Parse("{'X' : 's }", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("{\"X\" : \"s }", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("{'X", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("{\"X", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("{ \"v\":'ab\"c'}", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("{ \"v\":str}", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("{ \"v\":It's'Work}", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("{ a:1234}", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("[ a,bc]", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("{ \"v\":s1 s2}", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("{ \"v\":s1 s2 }", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("{ \"a\":\"foo.bar\"}#toto", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("{ 'value':'string'}", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("{v:15-55}", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("{v:15%}", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("{v:15.06%}", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("{ \"v\":s1' s2}", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("{ \"v\":s1\" \"s2}", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("{ \"NaN\":NaN}", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("[ a},b]", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("[ a:,b]", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("{ a,b:123}", &error)); OLA_ASSERT_NULL(value.get()); value.reset(JsonParser::Parse("{ a]b:123}", &error)); OLA_ASSERT_NULL(value.get()); } ola-0.10.5.nojsmin/common/web/Makefile.mk0000644000175000017500000000717213023355232017600 0ustar wouterwouterdist_noinst_DATA += \ common/web/testdata/allof.test \ common/web/testdata/anyof.test \ common/web/testdata/arrays.test \ common/web/testdata/basic-keywords.test \ common/web/testdata/definitions.test \ common/web/testdata/integers.test \ common/web/testdata/misc.test \ common/web/testdata/not.test \ common/web/testdata/objects.test \ common/web/testdata/oneof.test \ common/web/testdata/schema.json \ common/web/testdata/strings.test \ common/web/testdata/type.test # LIBRARIES ################################################ noinst_LTLIBRARIES += common/web/libolaweb.la common_web_libolaweb_la_SOURCES = \ common/web/Json.cpp \ common/web/JsonData.cpp \ common/web/JsonLexer.cpp \ common/web/JsonParser.cpp \ common/web/JsonPatch.cpp \ common/web/JsonPatchParser.cpp \ common/web/JsonPointer.cpp \ common/web/JsonSchema.cpp \ common/web/JsonSections.cpp \ common/web/JsonTypes.cpp \ common/web/JsonWriter.cpp \ common/web/PointerTracker.cpp \ common/web/PointerTracker.h \ common/web/SchemaErrorLogger.cpp \ common/web/SchemaErrorLogger.h \ common/web/SchemaKeywords.cpp \ common/web/SchemaKeywords.h \ common/web/SchemaParseContext.cpp \ common/web/SchemaParseContext.h \ common/web/SchemaParser.cpp \ common/web/SchemaParser.h if USING_WIN32 #Work around limitations with Windows library linking common_web_libolaweb_la_LIBADD = common/libolacommon.la endif # TESTS ################################################ # Patch test names are abbreviated to prevent Windows' UAC from blocking them. test_programs += \ common/web/JsonTester \ common/web/ParserTester \ common/web/PtchParserTester \ common/web/PtchTester \ common/web/PointerTester \ common/web/PointerTrackerTester \ common/web/SchemaParserTester \ common/web/SchemaTester \ common/web/SectionsTester COMMON_WEB_TEST_LDADD = $(COMMON_TESTING_LIBS) \ common/web/libolaweb.la common_web_JsonTester_SOURCES = common/web/JsonTest.cpp common_web_JsonTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_web_JsonTester_LDADD = $(COMMON_WEB_TEST_LDADD) common_web_ParserTester_SOURCES = common/web/ParserTest.cpp common_web_ParserTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_web_ParserTester_LDADD = $(COMMON_WEB_TEST_LDADD) common_web_PtchParserTester_SOURCES = common/web/PatchParserTest.cpp common_web_PtchParserTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_web_PtchParserTester_LDADD = $(COMMON_WEB_TEST_LDADD) common_web_PtchTester_SOURCES = common/web/PatchTest.cpp common_web_PtchTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_web_PtchTester_LDADD = $(COMMON_WEB_TEST_LDADD) common_web_PointerTester_SOURCES = common/web/PointerTest.cpp common_web_PointerTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_web_PointerTester_LDADD = $(COMMON_WEB_TEST_LDADD) common_web_PointerTrackerTester_SOURCES = common/web/PointerTrackerTest.cpp common_web_PointerTrackerTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_web_PointerTrackerTester_LDADD = $(COMMON_WEB_TEST_LDADD) common_web_SchemaParserTester_SOURCES = common/web/SchemaParserTest.cpp common_web_SchemaParserTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_web_SchemaParserTester_LDADD = $(COMMON_WEB_TEST_LDADD) common_web_SchemaTester_SOURCES = common/web/SchemaTest.cpp common_web_SchemaTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_web_SchemaTester_LDADD = $(COMMON_WEB_TEST_LDADD) common_web_SectionsTester_SOURCES = common/web/SectionsTest.cpp common_web_SectionsTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_web_SectionsTester_LDADD = $(COMMON_WEB_TEST_LDADD) ola-0.10.5.nojsmin/common/web/SchemaParser.h0000644000175000017500000000713313023355232020255 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SchemaParser.h * Constructs a JsonSchema. * Copyright (C) 2014 Simon Newton */ #ifndef COMMON_WEB_SCHEMAPARSER_H_ #define COMMON_WEB_SCHEMAPARSER_H_ #include #include #include #include "common/web/PointerTracker.h" #include "common/web/SchemaErrorLogger.h" #include "common/web/SchemaParseContext.h" #include "ola/base/Macro.h" #include "ola/web/JsonLexer.h" #include "ola/web/JsonPointer.h" namespace ola { namespace web { /** * @brief Build the tree of validators and a SchemaDefinitions object from a * JSON Schema. * * The SchemaParser is an implementation of JsonParserInterface. As the * JsonLexer encounters each token, it calls the appropriate method on the * SchemaParser. The SchemaParser maintains a stack of contexts, each of which * corresponds to a different part of the JSON schema. As objects / arrays are * opened / closed, new contexts are added / removed from the context stack. */ class SchemaParser : public JsonParserInterface { public: /** * @brief Create a new SchemaParser. */ SchemaParser(); /** * @brief Clean up */ ~SchemaParser(); // Methods from JsonParserInterface void Begin(); void End(); void String(const std::string &value); void Number(uint32_t value); void Number(int32_t value); void Number(uint64_t value); void Number(int64_t value); void Number(const JsonDouble::DoubleRepresentation &rep); void Number(double value); void Bool(bool value); void Null(); void OpenArray(); void CloseArray(); void OpenObject(); void ObjectKey(const std::string &key); void CloseObject(); void SetError(const std::string &error); /** * @brief Check if the schema was valid. * @return true if the schema was valid, false otherwise. */ bool IsValidSchema(); /** * @brief Get the error message. */ std::string Error() const; /** * @brief Claim the RootValidator that was created by parsing the schema. * @returns A new Validator, or NULL if the schema wasn't valid. Ownership of * the validtor is transferred to the caller. */ ValidatorInterface* ClaimRootValidator(); /** * @brief Claim the SchemaDefinitions that were created by parsing the schema. * @returns A SchemaDefinitions object, or NULL if the schema wasn't valid. * Ownership of the SchemaDefinitions is transferred to the caller. */ SchemaDefinitions* ClaimSchemaDefs(); private: std::auto_ptr m_schema_defs; std::auto_ptr m_root_context; std::auto_ptr m_root_validator; std::stack m_context_stack; JsonPointer m_pointer; PointerTracker m_pointer_tracker; SchemaErrorLogger m_error_logger; template void HandleNumber(T t); DISALLOW_COPY_AND_ASSIGN(SchemaParser); }; } // namespace web } // namespace ola #endif // COMMON_WEB_SCHEMAPARSER_H_ ola-0.10.5.nojsmin/common/web/SchemaParseContext.h0000644000175000017500000003777513023355232021457 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SchemaParseContext.h * Stores the state required as we walk the JSON schema document. * Copyright (C) 2014 Simon Newton */ #ifndef COMMON_WEB_SCHEMAPARSECONTEXT_H_ #define COMMON_WEB_SCHEMAPARSECONTEXT_H_ #include #include #include #include #include #include #include "common/web/PointerTracker.h" #include "common/web/SchemaErrorLogger.h" #include "common/web/SchemaKeywords.h" #include "ola/web/JsonSchema.h" #include "ola/web/JsonParser.h" #include "ola/web/OptionalItem.h" namespace ola { namespace web { class ArrayOfSchemaContext; class ArrayOfStringsContext; class DefinitionsParseContext; class DependencyParseContext; class JsonValueContext; class PropertiesParseContext; class SchemaParseContext; /** * @brief The interface all SchemaParseContext classes inherit from. */ class SchemaParseContextInterface { public: SchemaParseContextInterface() {} virtual ~SchemaParseContextInterface() {} virtual void String(SchemaErrorLogger *logger, const std::string &value) = 0; virtual void Number(SchemaErrorLogger *logger, uint32_t value) = 0; virtual void Number(SchemaErrorLogger *logger, int32_t value) = 0; virtual void Number(SchemaErrorLogger *logger, uint64_t value) = 0; virtual void Number(SchemaErrorLogger *logger, int64_t value) = 0; virtual void Number(SchemaErrorLogger *logger, double value) = 0; virtual void Bool(SchemaErrorLogger *logger, bool value) = 0; virtual void Null(SchemaErrorLogger *logger) = 0; virtual SchemaParseContextInterface* OpenArray(SchemaErrorLogger *logger) = 0; virtual void CloseArray(SchemaErrorLogger *logger) = 0; virtual SchemaParseContextInterface* OpenObject( SchemaErrorLogger *logger) = 0; virtual void ObjectKey(SchemaErrorLogger *logger, const std::string &key) = 0; virtual void CloseObject(SchemaErrorLogger *logger) = 0; }; /** * @brief A SchemaParseContext that keeps track of the last keyword / property * seen. */ class ObjectParseContext : public SchemaParseContextInterface { public: ObjectParseContext() {} /** * @brief Called when we encouter a property */ void ObjectKey(SchemaErrorLogger*, const std::string &keyword) { m_keyword.Set(keyword); } protected: /** * */ std::string TakeKeyword() { std::string keyword = m_keyword.Value(); m_keyword.Reset(); return keyword; } /** * */ const std::string& Keyword() const { return m_keyword.Value(); } private: OptionalItem m_keyword; }; /** * @brief A SchemaParseContext that reports errors for all types. * * This is intended to be sub-classed for contexts that only accept a subset of * types. */ class StrictTypedParseContext : public ObjectParseContext { public: StrictTypedParseContext() {} void String(SchemaErrorLogger *logger, const std::string &value); void Number(SchemaErrorLogger *logger, uint32_t value); void Number(SchemaErrorLogger *logger, int32_t value); void Number(SchemaErrorLogger *logger, uint64_t value); void Number(SchemaErrorLogger *logger, int64_t value); void Number(SchemaErrorLogger *logger, double value); void Bool(SchemaErrorLogger *logger, bool value); void Null(SchemaErrorLogger *logger); SchemaParseContextInterface* OpenArray(SchemaErrorLogger *logger); void CloseArray(SchemaErrorLogger *logger); SchemaParseContextInterface* OpenObject(SchemaErrorLogger *logger); void CloseObject(SchemaErrorLogger *logger); private: void ReportErrorForType(SchemaErrorLogger *logger, JsonType type); DISALLOW_COPY_AND_ASSIGN(StrictTypedParseContext); }; /** * @brief The context for schema definitions. * * See section 5.5.7 of the draft. Definitions are a way of describing commonly * used elements of a JSON document. */ class DefinitionsParseContext : public StrictTypedParseContext { public: /** * @brief Create a new DefinitionsParseContext. * @param definitions the SchemaDefinitions cache, ownership is not * transferred. * * As each definition is parsed, it's added to the SchemaDefinitions object. */ explicit DefinitionsParseContext(SchemaDefinitions *definitions) : StrictTypedParseContext(), m_schema_defs(definitions) { } SchemaParseContextInterface* OpenObject(SchemaErrorLogger *logger); void CloseObject(SchemaErrorLogger *logger); private: SchemaDefinitions *m_schema_defs; std::auto_ptr m_current_schema; DISALLOW_COPY_AND_ASSIGN(DefinitionsParseContext); }; /** * @brief */ class SchemaParseContext : public SchemaParseContextInterface { public: /** * @brief Create a new SchemaParseContext * @param definitions the SchemaDefinitions cache, ownership is not * transferred. */ explicit SchemaParseContext(SchemaDefinitions *definitions) : m_schema_defs(definitions), m_keyword(SCHEMA_UNKNOWN), m_type(JSON_UNDEFINED) { } /** * @brief Return the ValidatorInterface for this context. * * Ownership of the ValidatorInterface is transferred to the caller. * @returns A new ValidatorInterface or NULL if it was not possible to * construct a validator. */ ValidatorInterface* GetValidator(SchemaErrorLogger *logger); void ObjectKey(SchemaErrorLogger *logger, const std::string &keyword); void String(SchemaErrorLogger *logger, const std::string &value); void Number(SchemaErrorLogger *logger, uint32_t value); void Number(SchemaErrorLogger *logger, int32_t value); void Number(SchemaErrorLogger *logger, uint64_t value); void Number(SchemaErrorLogger *logger, int64_t value); void Number(SchemaErrorLogger *logger, double value); void Bool(SchemaErrorLogger *logger, bool value); void Null(SchemaErrorLogger *logger); SchemaParseContextInterface* OpenArray(SchemaErrorLogger *logger); void CloseArray(SchemaErrorLogger *logger); SchemaParseContextInterface* OpenObject(SchemaErrorLogger *logger); void CloseObject(SchemaErrorLogger *logger); private: SchemaDefinitions *m_schema_defs; // Set to the last keyword reported to ObjectKey() SchemaKeyword m_keyword; // Members are arranged according to the order in which they appear in the // draft standard. // Common keywords OptionalItem m_id; OptionalItem m_schema; // 5.1 Number / integer keywords OptionalItem m_exclusive_maximum; OptionalItem m_exclusive_minimum; std::auto_ptr m_maximum; std::auto_ptr m_minimum; std::auto_ptr m_multiple_of; // 5.2 String keywords // TODO(simon): Implement pattern support? OptionalItem m_pattern; OptionalItem m_max_length; OptionalItem m_min_length; // 5.3 Array keywords // 'additionalItems' can be either a bool or a schema OptionalItem m_additional_items; std::auto_ptr m_additional_items_context; // 'items' can be either a json schema, or an array of json schema. std::auto_ptr m_items_single_context; std::auto_ptr m_items_context_array; OptionalItem m_max_items; OptionalItem m_min_items; OptionalItem m_unique_items; // 5.4 Object keywords OptionalItem m_max_properties; OptionalItem m_min_properties; std::auto_ptr m_required_items; std::auto_ptr m_dependency_context; // 5.5 Keywords for multiple instance types JsonType m_type; std::auto_ptr m_enum_context; std::auto_ptr m_allof_context; std::auto_ptr m_anyof_context; std::auto_ptr m_oneof_context; std::auto_ptr m_not_context; // 6. Metadata keywords OptionalItem m_description; OptionalItem m_title; std::auto_ptr m_default_value; std::auto_ptr m_default_value_context; OptionalItem m_ref_schema; // TODO(simon): Implement format support? OptionalItem m_format; std::auto_ptr m_definitions_context; std::auto_ptr m_properties_context; OptionalItem m_additional_properties; std::auto_ptr m_additional_properties_context; void ProcessPositiveInt(SchemaErrorLogger *logger, uint64_t value); template void ProcessInt(SchemaErrorLogger *logger, T t); bool AddNumberConstraints(IntegerValidator *validator, SchemaErrorLogger *logger); BaseValidator* BuildArrayValidator(SchemaErrorLogger *logger); BaseValidator* BuildObjectValidator(SchemaErrorLogger *logger); BaseValidator* BuildStringValidator(SchemaErrorLogger *logger); static bool ValidTypeForKeyword(SchemaErrorLogger *logger, SchemaKeyword keyword, JsonType type); // Verify that type == expected_type. If it doesn't report an error to the // logger. static bool CheckTypeAndLog(SchemaErrorLogger *logger, SchemaKeyword keyword, JsonType type, JsonType expected_type); // Same as above but the type can be either expected_type1 or expected_type2 static bool CheckTypeAndLog(SchemaErrorLogger *logger, SchemaKeyword keyword, JsonType type, JsonType expected_type1, JsonType expected_type2); DISALLOW_COPY_AND_ASSIGN(SchemaParseContext); }; /** * @brief */ class PropertiesParseContext : public StrictTypedParseContext { public: explicit PropertiesParseContext(SchemaDefinitions *definitions) : StrictTypedParseContext(), m_schema_defs(definitions) { } ~PropertiesParseContext(); void AddPropertyValidators(ObjectValidator *object_validator, SchemaErrorLogger *logger); SchemaParseContextInterface* OpenObject(SchemaErrorLogger *logger); private: typedef std::map SchemaMap; SchemaDefinitions *m_schema_defs; SchemaMap m_property_contexts; DISALLOW_COPY_AND_ASSIGN(PropertiesParseContext); }; /** * @brief Parse the array of objects in an 'items' property. */ class ArrayOfSchemaContext : public StrictTypedParseContext { public: explicit ArrayOfSchemaContext(SchemaDefinitions *definitions) : m_schema_defs(definitions) { } ~ArrayOfSchemaContext(); /** * @brief Populate a vector with validators for the elements in 'items' * @param logger The logger to use. * @param[out] validators A vector fill with new validators. Ownership of the * validators is transferred to the caller. */ void GetValidators(SchemaErrorLogger *logger, ValidatorInterface::ValidatorList *validators); SchemaParseContextInterface* OpenObject(SchemaErrorLogger *logger); private: typedef std::vector ItemSchemas; SchemaDefinitions *m_schema_defs; ItemSchemas m_item_schemas; DISALLOW_COPY_AND_ASSIGN(ArrayOfSchemaContext); }; /** * @brief The context for an array of strings. * * This is used for the required property and for property dependencies. */ class ArrayOfStringsContext : public StrictTypedParseContext { public: typedef std::set StringSet; ArrayOfStringsContext() {} /** * @brief Return the strings in the string array */ void GetStringSet(StringSet *stringd); void String(SchemaErrorLogger *logger, const std::string &value); private: StringSet m_items; DISALLOW_COPY_AND_ASSIGN(ArrayOfStringsContext); }; /** * @brief The context for a default value. * * Default values can be any JSON type. This context simply * passes the events through to a JsonParser in order to construct the * JsonValue. */ class JsonValueContext : public SchemaParseContextInterface { public: JsonValueContext(); const JsonValue* ClaimValue(SchemaErrorLogger *logger); void String(SchemaErrorLogger *logger, const std::string &value); void Number(SchemaErrorLogger *logger, uint32_t value); void Number(SchemaErrorLogger *logger, int32_t value); void Number(SchemaErrorLogger *logger, uint64_t value); void Number(SchemaErrorLogger *logger, int64_t value); void Number(SchemaErrorLogger *logger, double value); void Bool(SchemaErrorLogger *logger, bool value); void Null(SchemaErrorLogger *logger); SchemaParseContextInterface* OpenArray(SchemaErrorLogger *logger); void CloseArray(SchemaErrorLogger *logger); SchemaParseContextInterface* OpenObject(SchemaErrorLogger *logger); void ObjectKey(SchemaErrorLogger *logger, const std::string &key); void CloseObject(SchemaErrorLogger *logger); private: JsonParser m_parser; DISALLOW_COPY_AND_ASSIGN(JsonValueContext); }; /** * @brief The context for an array of JsonValues. * * This is used for the enum property. Items in the array can be any JSON type. */ class ArrayOfJsonValuesContext : public SchemaParseContextInterface { public: ArrayOfJsonValuesContext() {} ~ArrayOfJsonValuesContext(); void AddEnumsToValidator(BaseValidator *validator); void String(SchemaErrorLogger *logger, const std::string &value); void Number(SchemaErrorLogger *logger, uint32_t value); void Number(SchemaErrorLogger *logger, int32_t value); void Number(SchemaErrorLogger *logger, uint64_t value); void Number(SchemaErrorLogger *logger, int64_t value); void Number(SchemaErrorLogger *logger, double value); void Bool(SchemaErrorLogger *logger, bool value); void Null(SchemaErrorLogger *logger); SchemaParseContextInterface* OpenArray(SchemaErrorLogger *logger); void CloseArray(SchemaErrorLogger *logger); SchemaParseContextInterface* OpenObject(SchemaErrorLogger *logger); void ObjectKey(SchemaErrorLogger*, const std::string &) {} void CloseObject(SchemaErrorLogger *logger); bool Empty() const { return m_enums.empty(); } private: std::vector m_enums; std::auto_ptr m_value_context; void CheckForDuplicateAndAdd(SchemaErrorLogger *logger, const JsonValue *value); DISALLOW_COPY_AND_ASSIGN(ArrayOfJsonValuesContext); }; /** * @brief The context for a dependency object. * * A dependency object contains key : value pairs. The key is the name of a * property that may exist in the instance. The value is either an array of * strings or an object. */ class DependencyParseContext : public StrictTypedParseContext { public: explicit DependencyParseContext(SchemaDefinitions *definitions) : m_schema_defs(definitions) {} ~DependencyParseContext(); void AddDependenciesToValidator(ObjectValidator *validator); SchemaParseContextInterface* OpenArray(SchemaErrorLogger *logger); void CloseArray(SchemaErrorLogger *logger); SchemaParseContextInterface* OpenObject(SchemaErrorLogger *logger); void CloseObject(SchemaErrorLogger *logger); private: typedef std::set StringSet; typedef std::map SchemaDependencies; typedef std::map PropertyDependencies; SchemaDefinitions *m_schema_defs; std::auto_ptr m_property_context; std::auto_ptr m_schema_context; PropertyDependencies m_property_dependencies; SchemaDependencies m_schema_dependencies; DISALLOW_COPY_AND_ASSIGN(DependencyParseContext); }; } // namespace web } // namespace ola #endif // COMMON_WEB_SCHEMAPARSECONTEXT_H_ ola-0.10.5.nojsmin/common/web/JsonWriter.cpp0000644000175000017500000000653413023355232020345 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * JsonWriter.cpp * Serialize JSON data. * Copyright (C) 2012 Simon Newton */ #include #include "ola/StringUtils.h" #include "ola/stl/STLUtils.h" #include "ola/web/JsonWriter.h" namespace ola { namespace web { using std::ostream; using std::ostringstream; using std::string; void JsonWriter::Write(ostream *output, const JsonValue &obj) { JsonWriter writer(output); obj.Accept(&writer); } string JsonWriter::AsString(const JsonValue &obj) { ostringstream str; JsonWriter writer(&str); obj.Accept(&writer); return str.str(); } void JsonWriter::Visit(const JsonString &value) { *m_output << '"' << EscapeString(EncodeString(value.Value())) << '"'; } void JsonWriter::Visit(const JsonBool &value) { *m_output << (value.Value() ? "true" : "false"); } void JsonWriter::Visit(const JsonNull &) { *m_output << "null"; } void JsonWriter::Visit(const JsonRawValue &value) { *m_output << value.Value(); } void JsonWriter::Visit(const JsonObject &value) { if (value.IsEmpty()) { *m_output << "{}"; return; } string old_separator = m_separator; m_separator = ""; m_indent += DEFAULT_INDENT; *m_output << "{\n"; value.VisitProperties(this); m_indent -= DEFAULT_INDENT; *m_output << "\n" << string(m_indent, ' '); *m_output << "}"; m_separator = old_separator; } void JsonWriter::Visit(const JsonArray &value) { *m_output << "["; string default_separator = ", "; if (value.IsComplexType()) { m_indent += DEFAULT_INDENT; *m_output << "\n" << string(m_indent, ' '); default_separator = ",\n"; default_separator.append(m_indent, ' '); } string separator; for (unsigned int i = 0; i < value.Size(); i++) { *m_output << separator; value.ElementAt(i)->Accept(this); separator = default_separator; } if (value.IsComplexType()) { *m_output << "\n"; m_indent -= DEFAULT_INDENT; *m_output << string(m_indent, ' '); } *m_output << "]"; } void JsonWriter::Visit(const JsonUInt &value) { *m_output << value.Value(); } void JsonWriter::Visit(const JsonUInt64 &value) { *m_output << value.Value(); } void JsonWriter::Visit(const JsonInt &value) { *m_output << value.Value(); } void JsonWriter::Visit(const JsonInt64 &value) { *m_output << value.Value(); } void JsonWriter::Visit(const JsonDouble &value) { *m_output << value.ToString(); } void JsonWriter::VisitProperty(const string &property, const JsonValue &value) { *m_output << m_separator << string(m_indent, ' ') << "\"" << EscapeString(property) << "\": "; value.Accept(this); m_separator = ",\n"; } } // namespace web } // namespace ola ola-0.10.5.nojsmin/common/web/JsonPatchParser.cpp0000644000175000017500000002026613134123277021310 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * JsonPatchParser.cpp * Create a JsonPatchSet from a string. * Copyright (C) 2014 Simon Newton */ #include "ola/web/JsonPatchParser.h" #define __STDC_LIMIT_MACROS // for UINT8_MAX & friends #include #include #include "ola/Logging.h" #include "ola/stl/STLUtils.h" #include "ola/web/Json.h" #include "ola/web/JsonLexer.h" #include "ola/base/Macro.h" namespace ola { namespace web { using std::string; const char JsonPatchParser::kPatchListError[] = "A JSON Patch document must be an array"; const char JsonPatchParser::kPatchElementError[] = "Elements within a JSON Patch array must be objects"; const char JsonPatchParser::kMissingPath[] = "Missing path specifier"; const char JsonPatchParser::kMissingValue[] = "Missing or invalid value"; const char JsonPatchParser::kMissingFrom[] = "Missing from specifier"; const char JsonPatchParser::kAddOp[] = "add"; const char JsonPatchParser::kCopyOp[] = "copy"; const char JsonPatchParser::kFromKey[] = "from"; const char JsonPatchParser::kMoveOp[] = "move"; const char JsonPatchParser::kOpKey[] = "op"; const char JsonPatchParser::kPathKey[] = "path"; const char JsonPatchParser::kRemoveOp[] = "remove"; const char JsonPatchParser::kReplaceOp[] = "replace"; const char JsonPatchParser::kTestOp[] = "test"; const char JsonPatchParser::kValueKey[] = "value"; void JsonPatchParser::Begin() { m_parser_depth = 0; m_error = ""; m_key = ""; m_state = TOP; m_parser.Begin(); } void JsonPatchParser::End() { if (m_state != TOP) { SetError("Invalid JSON data"); } } void JsonPatchParser::String(const string &value) { switch (m_state) { case TOP: SetError(kPatchListError); break; case PATCH_LIST: SetError(kPatchElementError); break; case PATCH: HandlePatchString(value); break; case VALUE: m_parser.String(value); break; } } void JsonPatchParser::Number(uint32_t value) { HandleNumber(value); } void JsonPatchParser::Number(int32_t value) { HandleNumber(value); } void JsonPatchParser::Number(uint64_t value) { HandleNumber(value); } void JsonPatchParser::Number(int64_t value) { HandleNumber(value); } void JsonPatchParser::Number(const JsonDouble::DoubleRepresentation &rep) { HandleNumber(rep); } void JsonPatchParser::Number(double value) { HandleNumber(value); } void JsonPatchParser::Bool(bool value) { switch (m_state) { case TOP: SetError(kPatchListError); break; case PATCH_LIST: SetError(kPatchElementError); break; case PATCH: if (m_key == kValueKey) { m_value.reset(new JsonBool(value)); } break; case VALUE: m_parser.Bool(value); break; } } void JsonPatchParser::Null() { switch (m_state) { case TOP: SetError(kPatchListError); break; case PATCH_LIST: SetError(kPatchElementError); break; case PATCH: if (m_key == kValueKey) { m_value.reset(new JsonNull()); } break; case VALUE: m_parser.Null(); break; } } void JsonPatchParser::OpenArray() { switch (m_state) { case TOP: m_state = PATCH_LIST; break; case PATCH_LIST: SetError(kPatchElementError); break; case PATCH: m_parser_depth = 0; m_state = VALUE; // fall through OLA_FALLTHROUGH case VALUE: m_parser_depth++; m_parser.OpenArray(); break; } } void JsonPatchParser::CloseArray() { switch (m_state) { case TOP: break; case PATCH_LIST: m_state = TOP; break; case PATCH: break; case VALUE: m_parser.CloseArray(); m_parser_depth--; if (m_parser_depth == 0) { if (m_key == kValueKey) { m_value.reset(m_parser.ClaimRoot()); } m_state = PATCH; } } } void JsonPatchParser::OpenObject() { switch (m_state) { case TOP: SetError(kPatchListError); break; case PATCH_LIST: m_state = PATCH; m_value.reset(); m_path.Reset(); m_op = ""; m_from.Reset(); break; case PATCH: m_parser_depth = 0; m_state = VALUE; // fall through OLA_FALLTHROUGH case VALUE: m_parser_depth++; m_parser.OpenObject(); break; } } void JsonPatchParser::ObjectKey(const std::string &key) { if (m_state == VALUE) { m_parser.ObjectKey(key); } else { m_key = key; } } void JsonPatchParser::CloseObject() { switch (m_state) { case TOP: break; case PATCH_LIST: break; case PATCH: m_state = PATCH_LIST; HandlePatch(); break; case VALUE: m_parser.CloseObject(); m_parser_depth--; if (m_parser_depth == 0) { if (m_key == kValueKey) { m_value.reset(m_parser.ClaimRoot()); } m_state = PATCH; } break; } } void JsonPatchParser::SetError(const string &error) { if (m_error.empty()) { m_error = error; } } string JsonPatchParser::GetError() const { return m_error; } bool JsonPatchParser::IsValid() const { return m_error.empty(); } template void JsonPatchParser::HandleNumber(const T &value) { switch (m_state) { case TOP: SetError(kPatchListError); break; case PATCH_LIST: SetError(kPatchElementError); break; case PATCH: if (m_key == kValueKey) { m_value.reset(JsonValue::NewValue(value)); } break; case VALUE: m_parser.Number(value); break; } } void JsonPatchParser::HandlePatchString(const std::string &value) { if (m_key == kOpKey) { m_op = value; } else if (m_key == kFromKey) { m_from.Set(value); } else if (m_key == kPathKey) { m_path.Set(value); } else if (m_key == kValueKey) { m_value.reset(new JsonString(value)); } } void JsonPatchParser::HandlePatch() { if (!m_path.IsSet()) { SetError(kMissingPath); return; } if (m_op == kAddOp) { if (!m_value.get()) { SetError(kMissingValue); return; } m_patch_set->AddOp( new JsonPatchAddOp(JsonPointer(m_path.Value()), m_value.release())); } else if (m_op == kRemoveOp) { m_patch_set->AddOp(new JsonPatchRemoveOp(JsonPointer(m_path.Value()))); } else if (m_op == kReplaceOp) { if (!m_value.get()) { SetError(kMissingValue); return; } m_patch_set->AddOp( new JsonPatchReplaceOp(JsonPointer(m_path.Value()), m_value.release())); } else if (m_op == kMoveOp) { if (!m_from.IsSet()) { SetError(kMissingFrom); return; } m_patch_set->AddOp( new JsonPatchMoveOp(JsonPointer(m_from.Value()), JsonPointer(m_path.Value()))); } else if (m_op == kCopyOp) { if (!m_from.IsSet()) { SetError(kMissingFrom); return; } m_patch_set->AddOp( new JsonPatchCopyOp(JsonPointer(m_from.Value()), JsonPointer(m_path.Value()))); } else if (m_op == kTestOp) { if (!m_value.get()) { SetError(kMissingValue); return; } m_patch_set->AddOp( new JsonPatchTestOp(JsonPointer(m_path.Value()), m_value.release())); } else { SetError("Invalid or missing 'op'"); } } bool JsonPatchParser::Parse(const std::string &input, JsonPatchSet *patch_set, std::string *error) { JsonPatchParser parser(patch_set); bool ok = JsonLexer::Parse(input, &parser) && parser.IsValid(); if (!ok) { *error = parser.GetError(); } return ok; } } // namespace web } // namespace ola ola-0.10.5.nojsmin/common/web/JsonData.cpp0000644000175000017500000000314513023355232017735 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * JsonData.cpp * Copyright (C) 2014 Simon Newton */ #include "ola/web/JsonData.h" #include #include "ola/web/Json.h" #include "ola/web/JsonPatch.h" namespace ola { namespace web { using std::string; bool JsonData::SetValue(JsonValue *value) { if (IsValid(value)) { m_value.reset(value); return true; } else { delete value; return false; } } bool JsonData::Apply(const JsonPatchSet &patch) { JsonValue *new_value = NULL; if (m_value.get()) { new_value = m_value->Clone(); } // now apply the patch bool ok = patch.Apply(&new_value) && IsValid(new_value); if (ok) { m_value.reset(new_value); } else { delete new_value; } return ok; } bool JsonData::IsValid(const JsonValue *value) { if (!m_schema) { return true; } value->Accept(m_schema); return m_schema->IsValid(); } } // namespace web } // namespace ola ola-0.10.5.nojsmin/common/web/SchemaErrorLogger.cpp0000644000175000017500000000267613023355232021614 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SchemaErrorLogger.cpp * Captures errors while parsing the schema. * Copyright (C) 2014 Simon Newton */ #include "common/web/SchemaErrorLogger.h" #include #include namespace ola { namespace web { bool SchemaErrorLogger::HasError() const { return !m_first_error.str().empty(); } std::string SchemaErrorLogger::ErrorString() const { return m_first_error.str(); } std::ostream& SchemaErrorLogger::Error() { if (m_first_error.str().empty()) { m_first_error << m_pointer->ToString() << ": "; return m_first_error; } else { return m_extra_errors; } } void SchemaErrorLogger::Reset() { m_first_error.str(""); m_extra_errors.str(""); } } // namespace web } // namespace ola ola-0.10.5.nojsmin/common/web/JsonPointer.cpp0000644000175000017500000000710413023355232020503 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * JsonPointer.cpp * An implementation of RFC 6901. * Copyright (C) 2014 Simon Newton */ #include #include "ola/web/JsonPointer.h" #include "ola/StringUtils.h" namespace ola { namespace web { using std::string; using std::vector; JsonPointer::JsonPointer() : m_is_valid(true) { } JsonPointer::JsonPointer(const JsonPointer &other) : m_is_valid(other.m_is_valid), m_tokens(other.m_tokens) { } JsonPointer::JsonPointer(const string &path) : m_is_valid(true) { if (path.empty()) { return; } if (path[0] != '/') { m_is_valid = false; return; } Tokens escaped_tokens; StringSplit(path.substr(1), &escaped_tokens, "/"); Tokens::const_iterator iter = escaped_tokens.begin(); for (; iter != escaped_tokens.end(); ++iter) { m_tokens.push_back(UnEscapeString(*iter)); } } bool JsonPointer::operator==(const JsonPointer &other) const { return m_tokens == other.m_tokens; } void JsonPointer::Push(const string &token) { m_tokens.push_back(token); } void JsonPointer::Pop() { if (!m_tokens.empty()) { m_tokens.pop_back(); } } string JsonPointer::ToString() const { string path; if (!m_tokens.empty()) { Tokens::const_iterator iter = m_tokens.begin(); path.push_back('/'); while (iter != m_tokens.end()) { path.append(EscapeString(*iter++)); if (iter != m_tokens.end()) { path.push_back('/'); } } } return path; } bool JsonPointer::IsPrefixOf(const JsonPointer &other) const { if (!(IsValid() && other.IsValid())) { return false; } Tokens::const_iterator our_iter = m_tokens.begin(); Tokens::const_iterator other_iter = other.m_tokens.begin(); for (; our_iter != m_tokens.end() && other_iter != other.m_tokens.end(); our_iter++, other_iter++) { if (*our_iter != *other_iter) { return false; } } return other_iter != other.m_tokens.end(); } string JsonPointer::EscapeString(const string &input) { string escaped_property; escaped_property.reserve(input.size()); for (string::const_iterator iter = input.begin(); iter != input.end(); ++iter) { switch (*iter) { case '~': escaped_property.push_back(*iter); escaped_property.push_back('0'); break; case '/': escaped_property.push_back('~'); escaped_property.push_back('1'); break; default: escaped_property.push_back(*iter); } } return escaped_property; } string JsonPointer::UnEscapeString(const string &input) { string token = input; size_t pos = 0; // Section 4 of the RFC explains why we do it in this order. while ((pos = token.find("~1")) != string::npos) { token[pos] = '/'; token.erase(pos + 1, 1); } while ((pos = token.find("~0")) != string::npos) { token[pos] = '~'; token.erase(pos + 1, 1); } return token; } } // namespace web } // namespace ola ola-0.10.5.nojsmin/common/web/JsonTest.cpp0000644000175000017500000004257613023355232020016 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * JsonTest.cpp * Unittest for Json classses. * Copyright (C) 2012 Simon Newton */ #include #include #include #include #include "ola/testing/TestUtils.h" #include "ola/web/Json.h" #include "ola/web/JsonPointer.h" #include "ola/web/JsonWriter.h" using ola::web::JsonArray; using ola::web::JsonBool; using ola::web::JsonDouble; using ola::web::JsonInt64; using ola::web::JsonInt; using ola::web::JsonNull; using ola::web::JsonObject; using ola::web::JsonPointer; using ola::web::JsonRawValue; using ola::web::JsonString; using ola::web::JsonUInt64; using ola::web::JsonUInt; using ola::web::JsonValue; using ola::web::JsonWriter; using std::string; using std::vector; class JsonTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(JsonTest); CPPUNIT_TEST(testString); CPPUNIT_TEST(testIntegerValues); CPPUNIT_TEST(testNumberValues); CPPUNIT_TEST(testRaw); CPPUNIT_TEST(testBool); CPPUNIT_TEST(testNull); CPPUNIT_TEST(testSimpleArray); CPPUNIT_TEST(testEmptyObject); CPPUNIT_TEST(testSimpleObject); CPPUNIT_TEST(testComplexObject); CPPUNIT_TEST(testEquality); CPPUNIT_TEST(testIntInequality); CPPUNIT_TEST(testMultipleOf); CPPUNIT_TEST(testLookups); CPPUNIT_TEST(testClone); CPPUNIT_TEST_SUITE_END(); public: void testString(); void testIntegerValues(); void testNumberValues(); void testRaw(); void testBool(); void testNull(); void testSimpleArray(); void testEmptyObject(); void testSimpleObject(); void testComplexObject(); void testEquality(); void testIntInequality(); void testMultipleOf(); void testLookups(); void testClone(); }; CPPUNIT_TEST_SUITE_REGISTRATION(JsonTest); /* * Test a string. */ void JsonTest::testString() { JsonString value("foo"); string expected = "\"foo\""; OLA_ASSERT_EQ(expected, JsonWriter::AsString(value)); // test escaping JsonString value2("foo\"bar\""); expected = "\"foo\\\"bar\\\"\""; OLA_ASSERT_EQ(expected, JsonWriter::AsString(value2)); } /* * Test ints. */ void JsonTest::testIntegerValues() { JsonUInt uint_value(10); string expected = "10"; OLA_ASSERT_EQ(expected, JsonWriter::AsString(uint_value)); JsonInt int_value(-10); expected = "-10"; OLA_ASSERT_EQ(expected, JsonWriter::AsString(int_value)); } /* * Test numbers (doubles). */ void JsonTest::testNumberValues() { // For JsonDouble constructed with a double, the string representation // depends on the platform. For example 1.23-e2 could be any of 1.23-e2, // 0.00123 or 1.23e-002. // So we skip this test. JsonDouble d1(12.234); OLA_ASSERT_EQ(12.234, d1.Value()); JsonDouble d2(-1.23e-12); OLA_ASSERT_EQ(-1.23e-12, d2.Value()); // For JsonDouble created using DoubleRepresentation, the string will be // well defined, but the Value() may differ. Just do our best here. JsonDouble::DoubleRepresentation rep1 = { false, 12, 1, 345, 0 }; JsonDouble d3(rep1); OLA_ASSERT_EQ(string("12.0345"), JsonWriter::AsString(d3)); OLA_ASSERT_EQ(12.0345, d3.Value()); JsonDouble::DoubleRepresentation rep2 = { true, 345, 3, 789, 2 }; JsonDouble d4(rep2); OLA_ASSERT_EQ(string("-345.000789e2"), JsonWriter::AsString(d4)); OLA_ASSERT_DOUBLE_EQ(-345.000789e2, d4.Value(), 0.001); JsonDouble::DoubleRepresentation rep3 = { true, 345, 3, 0, -2 }; JsonDouble d5(rep3); OLA_ASSERT_EQ(string("-345e-2"), JsonWriter::AsString(d5)); OLA_ASSERT_EQ(-3.45, d5.Value()); JsonDouble::DoubleRepresentation rep4 = { false, 2, 0, 1, 0 }; JsonDouble d6(rep4); OLA_ASSERT_EQ(string("2.1"), JsonWriter::AsString(d6)); OLA_ASSERT_EQ(2.1, d6.Value()); } /* * Test raw. * This is used by the web DMX console */ void JsonTest::testRaw() { // A printable character JsonRawValue value("\x41"); string expected = "\x41"; OLA_ASSERT_EQ(expected, JsonWriter::AsString(value)); // And an unprintable one JsonRawValue value2("\x7f"); expected = "\x7f"; OLA_ASSERT_EQ(expected, JsonWriter::AsString(value2)); } /* * Test bools. */ void JsonTest::testBool() { JsonBool true_value(true); string expected = "true"; OLA_ASSERT_EQ(expected, JsonWriter::AsString(true_value)); JsonBool false_value(false); expected = "false"; OLA_ASSERT_EQ(expected, JsonWriter::AsString(false_value)); } /* * Test a null. */ void JsonTest::testNull() { JsonNull value; string expected = "null"; OLA_ASSERT_EQ(expected, JsonWriter::AsString(value)); } /* * Test a simple array. * Json arrays can be mixed types. */ void JsonTest::testSimpleArray() { JsonArray array; array.Append(); array.Append(true); array.Append(1); array.Append("foo"); array.Append(10); array.Append(-10); string expected = "[null, true, 1, \"foo\", 10, -10]"; OLA_ASSERT_EQ(expected, JsonWriter::AsString(array)); } /* * Test an empty object. */ void JsonTest::testEmptyObject() { JsonObject object; string expected = "{}"; OLA_ASSERT_EQ(expected, JsonWriter::AsString(object)); } /* * Test a simple object. */ void JsonTest::testSimpleObject() { JsonObject object; object.Add("age", 10); object.Add("name", "simon"); object.Add("male", true); string expected = ( "{\n" " \"age\": 10,\n" " \"male\": true,\n" " \"name\": \"simon\"\n" "}"); OLA_ASSERT_EQ(expected, JsonWriter::AsString(object)); } /* * Test a complex object. */ void JsonTest::testComplexObject() { JsonObject object; object.Add("age", 10); object.Add("name", "simon"); object.Add("male", true); JsonArray *array = object.AddArray("lucky numbers"); array->Append(2); array->Append(5); string expected = ( "{\n" " \"age\": 10,\n" " \"lucky numbers\": [2, 5],\n" " \"male\": true,\n" " \"name\": \"simon\"\n" "}"); OLA_ASSERT_EQ(expected, JsonWriter::AsString(object)); } /* * Test for equality. */ void JsonTest::testEquality() { JsonString string1("foo"); JsonString string2("foo"); JsonString string3("bar"); JsonBool bool1(true); JsonBool bool2(false); JsonNull null1; JsonDouble double1(1.0); JsonDouble double2(1.0); JsonDouble double3(2.1); JsonUInt uint1(10); JsonUInt uint2(99); JsonInt int1(10); JsonInt int2(99); JsonInt int3(-99); JsonInt64 int64_1(-99); JsonInt64 int64_2(10); JsonInt64 int64_3(99); JsonUInt64 uint64_1(10); JsonUInt64 uint64_2(99); vector all_values; all_values.push_back(&string1); all_values.push_back(&string2); all_values.push_back(&string3); all_values.push_back(&bool1); all_values.push_back(&bool2); all_values.push_back(&null1); all_values.push_back(&double1); all_values.push_back(&double2); all_values.push_back(&double3); all_values.push_back(&uint1); all_values.push_back(&uint2); all_values.push_back(&int1); all_values.push_back(&int2); all_values.push_back(&int3); all_values.push_back(&int64_1); all_values.push_back(&int64_2); all_values.push_back(&int64_3); all_values.push_back(&uint64_1); all_values.push_back(&uint64_2); OLA_ASSERT_EQ(string1, string2); OLA_ASSERT_NE(string1, string3); OLA_ASSERT_NE(bool1, bool2); OLA_ASSERT_EQ(double1, double2); OLA_ASSERT_NE(double1, double3); OLA_ASSERT_NE(uint1, uint2); OLA_ASSERT_NE(uint1, uint2); // Test the tricky cases: OLA_ASSERT(int1 == uint1); OLA_ASSERT(int2 == uint2); OLA_ASSERT(uint1 == int64_2); OLA_ASSERT(uint2 == int64_3); OLA_ASSERT(int3 == int64_1); OLA_ASSERT(uint1 == uint64_1); OLA_ASSERT(uint2 == uint64_2); OLA_ASSERT(int1 == uint64_1); OLA_ASSERT(int2 == uint64_2); OLA_ASSERT(int64_2 == uint64_1); OLA_ASSERT(int64_3 == uint64_2); // Test Array equality. JsonArray array1; array1.Append(true); array1.Append(1); array1.Append("foo"); JsonArray array2; array2.Append(true); array2.Append(1); array2.Append("foo"); array2.Append(-1); JsonArray array3; array3.Append(true); array3.Append(1); array3.Append("bar"); all_values.push_back(&array1); all_values.push_back(&array2); all_values.push_back(&array3); OLA_ASSERT_FALSE(array1 == array2); OLA_ASSERT_FALSE(array1 == array3); // Object equality JsonObject object1; object1.Add("age", 10); object1.Add("name", "simon"); object1.Add("male", true); JsonObject object2; object1.Add("age", 10); object1.Add("name", "simon"); object1.Add("male", true); object1.Add("nationality", "Australia"); JsonObject object3; object3.Add("age", 10); object3.Add("name", "james"); object3.Add("male", true); all_values.push_back(&object1); all_values.push_back(&object2); all_values.push_back(&object3); OLA_ASSERT_FALSE(object1 == object2); OLA_ASSERT_FALSE(object1 == object3); // verify identity equality for (unsigned int i = 0; i < all_values.size(); ++i) { OLA_ASSERT(*(all_values[i]) == *(all_values[i])); } } /* * Test for integer / number inequality. */ void JsonTest::testIntInequality() { JsonDouble double1(1.0); JsonDouble double2(1.0); JsonDouble double3(11.1); JsonUInt uint1(10); JsonUInt uint2(99); JsonInt int1(10); JsonInt int2(99); JsonInt int3(-99); JsonInt64 int64_1(-99); JsonInt64 int64_2(10); JsonInt64 int64_3(99); JsonUInt64 uint64_1(10); JsonUInt64 uint64_2(99); OLA_ASSERT_LT(double1, double3); OLA_ASSERT_LTE(double1, double2); OLA_ASSERT_LTE(double1, double3); OLA_ASSERT_GT(double3, double1); OLA_ASSERT_GTE(double3, double1); OLA_ASSERT_GTE(double2, double1); OLA_ASSERT_LT(double1, uint1); OLA_ASSERT_LT(double1, int1); OLA_ASSERT_LT(double1, int64_2); OLA_ASSERT_LT(double1, uint64_1); OLA_ASSERT_LT(uint1, double3); OLA_ASSERT_LT(int1, double3); OLA_ASSERT_LT(int64_1, double3); OLA_ASSERT_LT(int64_2, double3); OLA_ASSERT_LT(uint64_1, double3); OLA_ASSERT_LT(uint1, uint2); OLA_ASSERT_LTE(uint1, uint1); OLA_ASSERT_LT(int1, int2); OLA_ASSERT_LTE(int1, int1); OLA_ASSERT_LT(int3, int1); OLA_ASSERT_LT(uint64_1, uint64_2); OLA_ASSERT_LTE(uint64_1, uint64_1); OLA_ASSERT_LT(int64_1, int64_2); OLA_ASSERT_LTE(int64_1, int64_1); OLA_ASSERT_LT(int64_2, int64_3); OLA_ASSERT_LT(uint64_1, uint2); OLA_ASSERT_LTE(uint64_1, uint1); OLA_ASSERT_LT(int64_1, int1); OLA_ASSERT_LTE(int64_1, int3); OLA_ASSERT_LT(uint1, uint64_2); OLA_ASSERT_LTE(uint1, uint64_1); OLA_ASSERT_LT(int3, int64_2); OLA_ASSERT_LTE(int3, int64_1); OLA_ASSERT_LT(int3, uint1); OLA_ASSERT_LTE(int1, uint1); OLA_ASSERT_LT(int64_1, uint1); OLA_ASSERT_LTE(int64_2, uint1); OLA_ASSERT_LT(uint1, int2); OLA_ASSERT_LTE(uint1, int1); OLA_ASSERT_LT(uint64_1, int2); OLA_ASSERT_LTE(uint64_1, int1); OLA_ASSERT_LT(int3, uint64_1); OLA_ASSERT_LTE(int1, uint64_1); OLA_ASSERT_LT(int64_1, uint64_1); OLA_ASSERT_LTE(int64_2, uint64_1); OLA_ASSERT_LT(uint1, int64_3); OLA_ASSERT_LTE(uint1, int64_2); OLA_ASSERT_LT(uint64_1, int64_3); OLA_ASSERT_LTE(uint64_1, int64_2); } /* * Test for mulitpleOf */ void JsonTest::testMultipleOf() { JsonDouble double1(10.0); JsonDouble double2(5); JsonDouble double3(11.0); JsonUInt uint1(10); JsonUInt uint2(5); JsonUInt uint3(11); JsonInt int1(10); JsonInt int2(5); JsonInt int3(11); JsonInt64 int64_1(10); JsonInt64 int64_2(5); JsonInt64 int64_3(11); JsonUInt64 uint64_1(10); JsonUInt64 uint64_2(5); JsonUInt64 uint64_3(11); OLA_ASSERT(double1.MultipleOf(double2)); OLA_ASSERT(double1.MultipleOf(uint2)); OLA_ASSERT(double1.MultipleOf(int2)); OLA_ASSERT(double1.MultipleOf(uint64_2)); OLA_ASSERT(double1.MultipleOf(int64_2)); OLA_ASSERT(uint1.MultipleOf(double2)); OLA_ASSERT(uint1.MultipleOf(uint2)); OLA_ASSERT(uint1.MultipleOf(int2)); OLA_ASSERT(uint1.MultipleOf(uint64_2)); OLA_ASSERT(uint1.MultipleOf(int64_2)); OLA_ASSERT(int1.MultipleOf(double2)); OLA_ASSERT(int1.MultipleOf(uint2)); OLA_ASSERT(int1.MultipleOf(int2)); OLA_ASSERT(int1.MultipleOf(uint64_2)); OLA_ASSERT(int1.MultipleOf(int64_2)); OLA_ASSERT(int64_1.MultipleOf(double2)); OLA_ASSERT(int64_1.MultipleOf(uint2)); OLA_ASSERT(int64_1.MultipleOf(int2)); OLA_ASSERT(int64_1.MultipleOf(uint64_2)); OLA_ASSERT(int64_1.MultipleOf(int64_2)); OLA_ASSERT(uint64_1.MultipleOf(double2)); OLA_ASSERT(uint64_1.MultipleOf(uint2)); OLA_ASSERT(uint64_1.MultipleOf(int2)); OLA_ASSERT(uint64_1.MultipleOf(uint64_2)); OLA_ASSERT(uint64_1.MultipleOf(int64_2)); OLA_ASSERT_FALSE(double3.MultipleOf(double2)); OLA_ASSERT_FALSE(double3.MultipleOf(uint2)); OLA_ASSERT_FALSE(double3.MultipleOf(int2)); OLA_ASSERT_FALSE(double3.MultipleOf(uint64_2)); OLA_ASSERT_FALSE(double3.MultipleOf(int64_2)); OLA_ASSERT_FALSE(uint3.MultipleOf(double2)); OLA_ASSERT_FALSE(uint3.MultipleOf(uint2)); OLA_ASSERT_FALSE(uint3.MultipleOf(int2)); OLA_ASSERT_FALSE(uint3.MultipleOf(uint64_2)); OLA_ASSERT_FALSE(uint3.MultipleOf(int64_2)); OLA_ASSERT_FALSE(int3.MultipleOf(double2)); OLA_ASSERT_FALSE(int3.MultipleOf(uint2)); OLA_ASSERT_FALSE(int3.MultipleOf(int2)); OLA_ASSERT_FALSE(int3.MultipleOf(uint64_2)); OLA_ASSERT_FALSE(int3.MultipleOf(int64_2)); OLA_ASSERT_FALSE(int64_3.MultipleOf(double2)); OLA_ASSERT_FALSE(int64_3.MultipleOf(uint2)); OLA_ASSERT_FALSE(int64_3.MultipleOf(int2)); OLA_ASSERT_FALSE(int64_3.MultipleOf(uint64_2)); OLA_ASSERT_FALSE(int64_3.MultipleOf(int64_2)); OLA_ASSERT_FALSE(uint64_3.MultipleOf(double2)); OLA_ASSERT_FALSE(uint64_3.MultipleOf(uint2)); OLA_ASSERT_FALSE(uint64_3.MultipleOf(int2)); OLA_ASSERT_FALSE(uint64_3.MultipleOf(uint64_2)); OLA_ASSERT_FALSE(uint64_3.MultipleOf(int64_2)); } /* * Test looking up a value with a pointer. */ void JsonTest::testLookups() { JsonPointer empty_pointer; JsonPointer invalid_pointer("/invalid/path"); JsonPointer name_pointer("/name"); JsonString string1("foo"); OLA_ASSERT_EQ(reinterpret_cast(&string1), string1.LookupElement(empty_pointer)); OLA_ASSERT_EQ(reinterpret_cast(NULL), string1.LookupElement(invalid_pointer)); // Now try an object JsonString *name_value = new JsonString("simon"); JsonObject object; object.Add("age", 10); object.AddValue("name", name_value); object.Add("male", true); object.Add("", "foo"); OLA_ASSERT_EQ(reinterpret_cast(&object), object.LookupElement(empty_pointer)); OLA_ASSERT_EQ(reinterpret_cast(name_value), object.LookupElement(name_pointer)); OLA_ASSERT_EQ(reinterpret_cast(NULL), object.LookupElement(invalid_pointer)); // Now try an array JsonArray *array = new JsonArray(); JsonString *string2 = new JsonString("cat"); JsonString *string3 = new JsonString("dog"); JsonString *string4 = new JsonString("mouse"); array->AppendValue(string2); array->AppendValue(string3); array->AppendValue(string4); JsonPointer first("/0"); JsonPointer middle("/1"); JsonPointer last("/2"); JsonPointer one_past_last("/-"); JsonPointer invalid("/a"); OLA_ASSERT_EQ(reinterpret_cast(array), array->LookupElement(empty_pointer)); OLA_ASSERT_EQ(reinterpret_cast(NULL), array->LookupElement(invalid_pointer)); OLA_ASSERT_EQ(reinterpret_cast(string2), array->LookupElement(first)); OLA_ASSERT_EQ(reinterpret_cast(string3), array->LookupElement(middle)); OLA_ASSERT_EQ(reinterpret_cast(string4), array->LookupElement(last)); OLA_ASSERT_EQ(reinterpret_cast(NULL), array->LookupElement(one_past_last)); OLA_ASSERT_EQ(reinterpret_cast(NULL), array->LookupElement(invalid)); // now a nested case object.AddValue("pets", array); JsonPointer first_pet("/pets/0"); OLA_ASSERT_EQ(reinterpret_cast(string2), object.LookupElement(first_pet)); } /* * Test that clone() works. */ void JsonTest::testClone() { JsonString string1("foo"); JsonBool bool1(true); JsonNull null1; JsonDouble double1(1.0); JsonUInt uint1(10); JsonInt int1(10); JsonInt64 int64_1(-99); JsonUInt64 uint64_1(10); JsonObject object; object.Add("age", 10); object.Add("name", "simon"); object.Add("male", true); object.Add("", "foo"); JsonArray array; array.Append(true); array.Append(1); array.Append("bar"); vector all_values; all_values.push_back(&string1); all_values.push_back(&bool1); all_values.push_back(&null1); all_values.push_back(&double1); all_values.push_back(&uint1); all_values.push_back(&int1); all_values.push_back(&int64_1); all_values.push_back(&uint64_1); all_values.push_back(&object); all_values.push_back(&array); for (unsigned int i = 0; i < all_values.size(); ++i) { std::auto_ptr value(all_values[i]->Clone()); OLA_ASSERT(*(value.get()) == *(all_values[i])); } } ola-0.10.5.nojsmin/common/web/SchemaErrorLogger.h0000644000175000017500000000425013023355232021247 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SchemaErrorLogger.h * Captures errors while parsing the schema. * Copyright (C) 2014 Simon Newton */ #ifndef COMMON_WEB_SCHEMAERRORLOGGER_H_ #define COMMON_WEB_SCHEMAERRORLOGGER_H_ #include #include #include #include "ola/web/JsonPointer.h" namespace ola { namespace web { /** * @brief The SchemaErrorLogger captures errors while parsing the schema. * * The SchemaErrorLogger allows schema parsing errors to be logged. It prepends * the error with the value of the JsonPointer so users have a decent idea of * where the error occured in the JSON document. */ class SchemaErrorLogger { public: /** * @brief Create a new SchemaErrorLogger. * @param pointer the JsonPointer to use when logging error messages */ explicit SchemaErrorLogger(JsonPointer *pointer) : m_pointer(pointer) {} /** * @brief Check if there was an error logged. */ bool HasError() const; /** * @brief Return the first error * @returns The first error, or the empty string if no error was reported. */ std::string ErrorString() const; /** * @brief Log an error. */ std::ostream& Error(); /** * @brief Clear the saved errors. */ void Reset(); private: std::ostringstream m_first_error; std::ostringstream m_extra_errors; JsonPointer *m_pointer; DISALLOW_COPY_AND_ASSIGN(SchemaErrorLogger); }; } // namespace web } // namespace ola #endif // COMMON_WEB_SCHEMAERRORLOGGER_H_ ola-0.10.5.nojsmin/common/web/JsonSections.cpp0000644000175000017500000000645513023355232020662 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * JsonSections.cpp * This builds the json string for the web UI. * Copyright (C) 2010 Simon Newton */ #include #include #include #include #include #include "ola/web/JsonSections.h" #include "ola/Logging.h" #include "ola/web/Json.h" #include "ola/web/JsonWriter.h" #include "ola/StringUtils.h" namespace ola { namespace web { using std::endl; using std::pair; using std::string; using std::vector; using ola::EscapeString; void GenericItem::PopulateItem(JsonObject *item) const { if (!m_button_text.empty()) item->Add("button", m_button_text); if (!m_id.empty()) item->Add("id", m_id); item->Add("description", m_description); item->Add("type", Type()); SetValue(item); SetExtraProperties(item); } void UIntItem::SetExtraProperties(JsonObject *item) const { if (m_min_set) item->Add("min", m_min); if (m_max_set) item->Add("max", m_max); } void SelectItem::AddItem(const string &label, const string &value) { pair p(label, value); m_values.push_back(p); } void SelectItem::AddItem(const string &label, unsigned int value) { AddItem(label, IntToString(value)); } void SelectItem::SetValue(JsonObject *item) const { JsonArray *options = item->AddArray("value"); vector >::const_iterator iter = m_values.begin(); for (; iter != m_values.end(); ++iter) { JsonObject *option = options->AppendObject(); option->Add("label", iter->first); option->Add("value", iter->second); } } /** * Create a new section response */ JsonSection::JsonSection(bool allow_refresh) : m_allow_refresh(allow_refresh), m_error(""), m_save_button_text("") { } /** * Cleanup */ JsonSection::~JsonSection() { vector::const_iterator iter = m_items.begin(); for (; iter != m_items.end(); ++iter) { delete *iter; } } /** * Add an item to this section, ownership is transferred. */ void JsonSection::AddItem(const GenericItem *item) { m_items.push_back(item); } /* * Return the section as a string. */ string JsonSection::AsString() const { JsonObject json; json.Add("refresh", m_allow_refresh); json.Add("error", m_error); if (!m_save_button_text.empty()) json.Add("save_button", m_save_button_text); JsonArray *items = json.AddArray("items"); vector::const_iterator iter = m_items.begin(); for (; iter != m_items.end(); ++iter) { JsonObject *item = items->AppendObject(); (*iter)->PopulateItem(item); } return JsonWriter::AsString(json); } } // namespace web } // namespace ola ola-0.10.5.nojsmin/common/web/SchemaKeywords.h0000644000175000017500000000417513023355232020633 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SchemaKeywords.h * The keywords used in JSON Schema. * Copyright (C) 2014 Simon Newton */ #ifndef COMMON_WEB_SCHEMAKEYWORDS_H_ #define COMMON_WEB_SCHEMAKEYWORDS_H_ #include namespace ola { namespace web { /** * @brief The list of valid JSon Schema keywords. */ enum SchemaKeyword { SCHEMA_UNKNOWN, /**< Keywords we don't understand */ SCHEMA_ID, SCHEMA_SCHEMA, SCHEMA_REF, SCHEMA_TITLE, SCHEMA_DESCRIPTION, SCHEMA_DEFAULT, SCHEMA_FORMAT, SCHEMA_MULTIPLEOF, SCHEMA_MAXIMUM, SCHEMA_EXCLUSIVE_MAXIMUM, SCHEMA_MINIMUM, SCHEMA_EXCLUSIVE_MINIMUM, SCHEMA_MAX_LENGTH, SCHEMA_MIN_LENGTH, SCHEMA_PATTERN, SCHEMA_ADDITIONAL_ITEMS, SCHEMA_ITEMS, SCHEMA_MAX_ITEMS, SCHEMA_MIN_ITEMS, SCHEMA_UNIQUE_ITEMS, SCHEMA_MAX_PROPERTIES, SCHEMA_MIN_PROPERTIES, SCHEMA_REQUIRED, SCHEMA_ADDITIONAL_PROPERTIES, SCHEMA_DEFINITIONS, SCHEMA_PROPERTIES, SCHEMA_PATTERN_PROPERTIES, SCHEMA_DEPENDENCIES, SCHEMA_ENUM, SCHEMA_TYPE, SCHEMA_ALL_OF, SCHEMA_ANY_OF, SCHEMA_ONE_OF, SCHEMA_NOT, }; /** * Return the string used by the SchemaKeyword. */ std::string KeywordToString(SchemaKeyword keyword); /** * @brief Map a string to a SchemaKeyword. * @returns the SchemaKeyword corresponding to the string, or SCHEMA_UNDEFINED. */ SchemaKeyword LookupKeyword(const std::string& keyword); } // namespace web } // namespace ola #endif // COMMON_WEB_SCHEMAKEYWORDS_H_ ola-0.10.5.nojsmin/common/web/SchemaKeywords.cpp0000644000175000017500000001232513023355232021162 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SchemaKeywords.cpp * The keywords used in JSON Schema. * Copyright (C) 2014 Simon Newton */ #include "common/web/SchemaKeywords.h" #include namespace ola { namespace web { using std::string; string KeywordToString(SchemaKeyword keyword) { switch (keyword) { case SCHEMA_ID: return "id"; case SCHEMA_SCHEMA: return "$schema"; case SCHEMA_REF: return "$ref"; case SCHEMA_TITLE: return "title"; case SCHEMA_DESCRIPTION: return "description"; case SCHEMA_DEFAULT: return "default"; case SCHEMA_FORMAT: return "format"; case SCHEMA_MULTIPLEOF: return "multipleOf"; case SCHEMA_MAXIMUM: return "maximum"; case SCHEMA_EXCLUSIVE_MAXIMUM: return "exclusiveMaximum"; case SCHEMA_MINIMUM: return "minimum"; case SCHEMA_EXCLUSIVE_MINIMUM: return "exclusiveMinimum"; case SCHEMA_MAX_LENGTH: return "maxLength"; case SCHEMA_MIN_LENGTH: return "minLength"; case SCHEMA_PATTERN: return "pattern"; case SCHEMA_ADDITIONAL_ITEMS: return "additionalItems"; case SCHEMA_ITEMS: return "items"; case SCHEMA_MAX_ITEMS: return "maxItems"; case SCHEMA_MIN_ITEMS: return "minItems"; case SCHEMA_UNIQUE_ITEMS: return "uniqueItems"; case SCHEMA_MAX_PROPERTIES: return "maxProperties"; case SCHEMA_MIN_PROPERTIES: return "minProperties"; case SCHEMA_REQUIRED: return "required"; case SCHEMA_ADDITIONAL_PROPERTIES: return "additionalProperties"; case SCHEMA_DEFINITIONS: return "definitions"; case SCHEMA_PROPERTIES: return "properties"; case SCHEMA_PATTERN_PROPERTIES: return "patternProperties"; case SCHEMA_DEPENDENCIES: return "dependencies"; case SCHEMA_ENUM: return "enum"; case SCHEMA_TYPE: return "type"; case SCHEMA_ALL_OF: return "allOf"; case SCHEMA_ANY_OF: return "anyOf"; case SCHEMA_ONE_OF: return "oneOf"; case SCHEMA_NOT: return "not"; case SCHEMA_UNKNOWN: default: return ""; } } SchemaKeyword LookupKeyword(const string& keyword) { if (keyword == "id") { return SCHEMA_ID; } else if (keyword == "$schema") { return SCHEMA_SCHEMA; } else if (keyword == "$ref") { return SCHEMA_REF; } else if (keyword == "title") { return SCHEMA_TITLE; } else if (keyword == "description") { return SCHEMA_DESCRIPTION; } else if (keyword == "default") { return SCHEMA_DEFAULT; } else if (keyword == "format") { return SCHEMA_FORMAT; } else if (keyword == "multipleOf") { return SCHEMA_MULTIPLEOF; } else if (keyword == "maximum") { return SCHEMA_MAXIMUM; } else if (keyword == "exclusiveMaximum") { return SCHEMA_EXCLUSIVE_MAXIMUM; } else if (keyword == "minimum") { return SCHEMA_MINIMUM; } else if (keyword == "exclusiveMinimum") { return SCHEMA_EXCLUSIVE_MINIMUM; } else if (keyword == "maxLength") { return SCHEMA_MAX_LENGTH; } else if (keyword == "minLength") { return SCHEMA_MIN_LENGTH; } else if (keyword == "pattern") { return SCHEMA_PATTERN; } else if (keyword == "additionalItems") { return SCHEMA_ADDITIONAL_ITEMS; } else if (keyword == "items") { return SCHEMA_ITEMS; } else if (keyword == "maxItems") { return SCHEMA_MAX_ITEMS; } else if (keyword == "minItems") { return SCHEMA_MIN_ITEMS; } else if (keyword == "uniqueItems") { return SCHEMA_UNIQUE_ITEMS; } else if (keyword == "maxProperties") { return SCHEMA_MAX_PROPERTIES; } else if (keyword == "minProperties") { return SCHEMA_MIN_PROPERTIES; } else if (keyword == "required") { return SCHEMA_REQUIRED; } else if (keyword == "additionalProperties") { return SCHEMA_ADDITIONAL_PROPERTIES; } else if (keyword == "definitions") { return SCHEMA_DEFINITIONS; } else if (keyword == "properties") { return SCHEMA_PROPERTIES; } else if (keyword == "patternProperties") { return SCHEMA_PATTERN_PROPERTIES; } else if (keyword == "dependencies") { return SCHEMA_DEPENDENCIES; } else if (keyword == "enum") { return SCHEMA_ENUM; } else if (keyword == "type") { return SCHEMA_TYPE; } else if (keyword == "allOf") { return SCHEMA_ALL_OF; } else if (keyword == "anyOf") { return SCHEMA_ANY_OF; } else if (keyword == "oneOf") { return SCHEMA_ONE_OF; } else if (keyword == "not") { return SCHEMA_NOT; } else { return SCHEMA_UNKNOWN; } } } // namespace web } // namespace ola ola-0.10.5.nojsmin/common/web/JsonParser.cpp0000644000175000017500000001304413023355232020317 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * JsonParser.cpp * A Json Parser. * Copyright (C) 2014 Simon Newton */ #include "ola/web/JsonParser.h" #define __STDC_LIMIT_MACROS // for UINT8_MAX & friends #include #include #include "ola/Logging.h" #include "ola/stl/STLUtils.h" #include "ola/web/Json.h" #include "ola/web/JsonLexer.h" namespace ola { namespace web { using std::string; void JsonParser::Begin() { m_error = ""; m_root.reset(); m_key = ""; STLEmptyStack(&m_container_stack); STLEmptyStack(&m_array_stack); STLEmptyStack(&m_object_stack); } void JsonParser::End() { if (!m_container_stack.empty()) { OLA_WARN << "Json container stack is not empty"; } STLEmptyStack(&m_container_stack); if (!m_array_stack.empty()) { OLA_WARN << "JsonArray stack is not empty"; } STLEmptyStack(&m_array_stack); if (!m_object_stack.empty()) { OLA_WARN << "JsonObject stack is not empty"; } STLEmptyStack(&m_object_stack); } void JsonParser::String(const string &value) { AddValue(new JsonString(value)); } void JsonParser::Number(uint32_t value) { AddValue(new JsonUInt(value)); } void JsonParser::Number(int32_t value) { AddValue(new JsonInt(value)); } void JsonParser::Number(uint64_t value) { AddValue(new JsonUInt64(value)); } void JsonParser::Number(int64_t value) { AddValue(new JsonInt64(value)); } void JsonParser::Number(const JsonDouble::DoubleRepresentation &rep) { AddValue(new JsonDouble(rep)); } void JsonParser::Number(double value) { AddValue(new JsonDouble(value)); } void JsonParser::Bool(bool value) { AddValue(new JsonBool(value)); } void JsonParser::Null() { AddValue(new JsonNull()); } void JsonParser::OpenArray() { if (m_container_stack.empty()) { m_array_stack.push(new JsonArray()); m_root.reset(m_array_stack.top()); } else if (m_container_stack.top() == ARRAY && !m_array_stack.empty()) { m_array_stack.push(m_array_stack.top()->AppendArray()); } else if (m_container_stack.top() == OBJECT && !m_object_stack.empty()) { m_array_stack.push(m_object_stack.top()->AddArray(m_key)); m_key = ""; } else { OLA_WARN << "Can't find where to start array"; m_error = "Internal error"; } m_container_stack.push(ARRAY); } void JsonParser::CloseArray() { if (m_container_stack.empty() || m_container_stack.top() != ARRAY || m_array_stack.empty()) { OLA_WARN << "Mismatched CloseArray()"; m_error = "Internal error"; return; } m_container_stack.pop(); m_array_stack.pop(); } void JsonParser::OpenObject() { if (m_container_stack.empty()) { m_object_stack.push(new JsonObject()); m_root.reset(m_object_stack.top()); } else if (m_container_stack.top() == ARRAY && !m_array_stack.empty()) { m_object_stack.push(m_array_stack.top()->AppendObject()); } else if (m_container_stack.top() == OBJECT && !m_object_stack.empty()) { m_object_stack.push(m_object_stack.top()->AddObject(m_key)); m_key = ""; } else { OLA_WARN << "Can't find where to start object"; m_error = "Internal error"; } m_container_stack.push(OBJECT); } void JsonParser::ObjectKey(const string &key) { if (!m_key.empty()) { OLA_WARN << "Json Key should be empty, was " << key; } m_key = key; } void JsonParser::CloseObject() { if (m_container_stack.empty() || m_container_stack.top() != OBJECT || m_object_stack.empty()) { OLA_WARN << "Mismatched CloseObject()"; m_error = "Internal error"; return; } m_container_stack.pop(); m_object_stack.pop(); } void JsonParser::SetError(const string &error) { m_error = error; } string JsonParser::GetError() const { return m_error; } JsonValue *JsonParser::GetRoot() { return m_root.get(); } JsonValue *JsonParser::ClaimRoot() { if (m_error.empty()) { return m_root.release(); } else { return NULL; } } void JsonParser::AddValue(JsonValue *value) { if (!m_container_stack.empty() && m_container_stack.top() == ARRAY) { if (m_array_stack.empty()) { OLA_WARN << "Missing JsonArray, parsing is broken!"; m_error = "Internal error"; delete value; } else { m_array_stack.top()->Append(value); } } else if (!m_container_stack.empty() && m_container_stack.top() == OBJECT) { if (m_object_stack.empty()) { OLA_WARN << "Missing JsonObject, parsing is broken!"; m_error = "Internal error"; delete value; } else { m_object_stack.top()->AddValue(m_key, value); m_key = ""; } } else if (!m_root.get()) { m_root.reset(value); return; } else { OLA_WARN << "Parse stack broken"; m_error = "Internal error"; delete value; } } JsonValue* JsonParser::Parse(const string &input, string *error) { JsonParser parser; if (JsonLexer::Parse(input, &parser)) { return parser.ClaimRoot(); } else { *error = parser.GetError(); return NULL; } } } // namespace web } // namespace ola ola-0.10.5.nojsmin/common/web/SchemaTest.cpp0000644000175000017500000007751213023355232020303 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SchemaTest.cpp * Unittest for the Json Schema. * Copyright (C) 2014 Simon Newton */ #include #include #include #include #include #include "ola/Logging.h" #include "ola/testing/TestUtils.h" #include "ola/web/Json.h" #include "ola/web/JsonParser.h" #include "ola/web/JsonSchema.h" using ola::web::AllOfValidator; using ola::web::AnyOfValidator; using ola::web::ArrayValidator; using ola::web::BoolValidator; using ola::web::ConjunctionValidator; using ola::web::IntegerValidator; using ola::web::JsonBool; using ola::web::JsonDouble; using ola::web::JsonInt; using ola::web::JsonNull; using ola::web::JsonParser; using ola::web::JsonString; using ola::web::JsonString; using ola::web::JsonUInt; using ola::web::JsonUInt; using ola::web::JsonValue; using ola::web::MaximumConstraint; using ola::web::MinimumConstraint; using ola::web::MultipleOfConstraint; using ola::web::NotValidator; using ola::web::NullValidator; using ola::web::NumberValidator; using ola::web::ObjectValidator; using ola::web::OneOfValidator; using ola::web::ReferenceValidator; using ola::web::SchemaDefinitions; using ola::web::StringValidator; using ola::web::WildcardValidator; using std::auto_ptr; using std::set; using std::string; using std::vector; class JsonSchemaTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(JsonSchemaTest); CPPUNIT_TEST(testWildcardValidator); CPPUNIT_TEST(testReferenceValidator); CPPUNIT_TEST(testStringValidator); CPPUNIT_TEST(testBoolValidator); CPPUNIT_TEST(testNullValidator); CPPUNIT_TEST(testIntegerValidator); CPPUNIT_TEST(testNumberValidator); CPPUNIT_TEST(testObjectValidator); CPPUNIT_TEST(testArrayValidator); CPPUNIT_TEST(testAllOfValidator); CPPUNIT_TEST(testAnyOfValidator); CPPUNIT_TEST(testOneOfValidator); CPPUNIT_TEST(testNotValidator); CPPUNIT_TEST(testEnums); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void testWildcardValidator(); void testReferenceValidator(); void testStringValidator(); void testBoolValidator(); void testNullValidator(); void testIntegerValidator(); void testNumberValidator(); void testObjectValidator(); void testArrayValidator(); void testAllOfValidator(); void testAnyOfValidator(); void testOneOfValidator(); void testNotValidator(); void testEnums(); private: auto_ptr m_bool_value; auto_ptr m_empty_array; auto_ptr m_empty_object; auto_ptr m_int_value; auto_ptr m_long_string_value; auto_ptr m_null_value; auto_ptr m_number_value; auto_ptr m_string_value; auto_ptr m_uint_value; }; CPPUNIT_TEST_SUITE_REGISTRATION(JsonSchemaTest); void JsonSchemaTest::setUp() { string error; m_bool_value.reset(new JsonBool(true)); m_empty_array.reset(JsonParser::Parse("[]", &error)); m_empty_object.reset(JsonParser::Parse("{}", &error)); m_int_value.reset(new JsonInt(-12)); m_long_string_value.reset(new JsonString("This is a longer string")); m_null_value.reset(new JsonNull()); m_number_value.reset(new JsonDouble(1.2)); m_string_value.reset(new JsonString("foo")); m_uint_value.reset(new JsonUInt(4)); } void JsonSchemaTest::testWildcardValidator() { WildcardValidator wildcard_validator; m_bool_value->Accept(&wildcard_validator); OLA_ASSERT_TRUE(wildcard_validator.IsValid()); m_empty_array->Accept(&wildcard_validator); OLA_ASSERT_TRUE(wildcard_validator.IsValid()); m_empty_object->Accept(&wildcard_validator); OLA_ASSERT_TRUE(wildcard_validator.IsValid()); m_int_value->Accept(&wildcard_validator); OLA_ASSERT_TRUE(wildcard_validator.IsValid()); m_null_value->Accept(&wildcard_validator); OLA_ASSERT_TRUE(wildcard_validator.IsValid()); m_number_value->Accept(&wildcard_validator); OLA_ASSERT_TRUE(wildcard_validator.IsValid()); m_string_value->Accept(&wildcard_validator); OLA_ASSERT_TRUE(wildcard_validator.IsValid()); m_uint_value->Accept(&wildcard_validator); OLA_ASSERT_TRUE(wildcard_validator.IsValid()); } void JsonSchemaTest::testReferenceValidator() { const string key = "#/definitions/testing"; SchemaDefinitions definitions; definitions.Add(key, new IntegerValidator()); ReferenceValidator validator(&definitions, key); m_int_value->Accept(&validator); OLA_ASSERT_TRUE(validator.IsValid()); m_uint_value->Accept(&validator); OLA_ASSERT_TRUE(validator.IsValid()); m_bool_value->Accept(&validator); OLA_ASSERT_FALSE(validator.IsValid()); m_empty_array->Accept(&validator); OLA_ASSERT_FALSE(validator.IsValid()); m_empty_object->Accept(&validator); OLA_ASSERT_FALSE(validator.IsValid()); m_null_value->Accept(&validator); OLA_ASSERT_FALSE(validator.IsValid()); m_number_value->Accept(&validator); OLA_ASSERT_FALSE(validator.IsValid()); m_string_value->Accept(&validator); OLA_ASSERT_FALSE(validator.IsValid()); } void JsonSchemaTest::testStringValidator() { StringValidator basic_string_validator((StringValidator::Options())); m_string_value->Accept(&basic_string_validator); OLA_ASSERT_TRUE(basic_string_validator.IsValid()); m_long_string_value->Accept(&basic_string_validator); OLA_ASSERT_TRUE(basic_string_validator.IsValid()); m_bool_value->Accept(&basic_string_validator); OLA_ASSERT_FALSE(basic_string_validator.IsValid()); m_empty_array->Accept(&basic_string_validator); OLA_ASSERT_FALSE(basic_string_validator.IsValid()); m_empty_object->Accept(&basic_string_validator); OLA_ASSERT_FALSE(basic_string_validator.IsValid()); m_int_value->Accept(&basic_string_validator); OLA_ASSERT_FALSE(basic_string_validator.IsValid()); m_null_value->Accept(&basic_string_validator); OLA_ASSERT_FALSE(basic_string_validator.IsValid()); m_number_value->Accept(&basic_string_validator); OLA_ASSERT_FALSE(basic_string_validator.IsValid()); m_uint_value->Accept(&basic_string_validator); OLA_ASSERT_FALSE(basic_string_validator.IsValid()); // test a string with a min length StringValidator::Options min_length_options; min_length_options.min_length = 5; StringValidator min_length_string_validator(min_length_options); m_string_value->Accept(&min_length_string_validator); OLA_ASSERT_FALSE(min_length_string_validator.IsValid()); m_long_string_value->Accept(&min_length_string_validator); OLA_ASSERT_TRUE(min_length_string_validator.IsValid()); // test a string with a max length StringValidator::Options max_length_options; max_length_options.max_length = 10; StringValidator max_length_string_validator(max_length_options); m_string_value->Accept(&max_length_string_validator); OLA_ASSERT_TRUE(max_length_string_validator.IsValid()); m_long_string_value->Accept(&max_length_string_validator); OLA_ASSERT_FALSE(max_length_string_validator.IsValid()); } void JsonSchemaTest::testBoolValidator() { BoolValidator bool_validator; m_bool_value->Accept(&bool_validator); OLA_ASSERT_TRUE(bool_validator.IsValid()); m_empty_array->Accept(&bool_validator); OLA_ASSERT_FALSE(bool_validator.IsValid()); m_empty_object->Accept(&bool_validator); OLA_ASSERT_FALSE(bool_validator.IsValid()); m_int_value->Accept(&bool_validator); OLA_ASSERT_FALSE(bool_validator.IsValid()); m_null_value->Accept(&bool_validator); OLA_ASSERT_FALSE(bool_validator.IsValid()); m_number_value->Accept(&bool_validator); OLA_ASSERT_FALSE(bool_validator.IsValid()); m_string_value->Accept(&bool_validator); OLA_ASSERT_FALSE(bool_validator.IsValid()); m_uint_value->Accept(&bool_validator); OLA_ASSERT_FALSE(bool_validator.IsValid()); } void JsonSchemaTest::testNullValidator() { NullValidator null_validator; m_null_value->Accept(&null_validator); OLA_ASSERT_TRUE(null_validator.IsValid()); m_bool_value->Accept(&null_validator); OLA_ASSERT_FALSE(null_validator.IsValid()); m_empty_array->Accept(&null_validator); OLA_ASSERT_FALSE(null_validator.IsValid()); m_empty_object->Accept(&null_validator); OLA_ASSERT_FALSE(null_validator.IsValid()); m_int_value->Accept(&null_validator); OLA_ASSERT_FALSE(null_validator.IsValid()); m_number_value->Accept(&null_validator); OLA_ASSERT_FALSE(null_validator.IsValid()); m_string_value->Accept(&null_validator); OLA_ASSERT_FALSE(null_validator.IsValid()); m_uint_value->Accept(&null_validator); OLA_ASSERT_FALSE(null_validator.IsValid()); } void JsonSchemaTest::testIntegerValidator() { IntegerValidator integer_validator; m_int_value->Accept(&integer_validator); OLA_ASSERT_TRUE(integer_validator.IsValid()); m_uint_value->Accept(&integer_validator); OLA_ASSERT_TRUE(integer_validator.IsValid()); m_bool_value->Accept(&integer_validator); OLA_ASSERT_FALSE(integer_validator.IsValid()); m_empty_array->Accept(&integer_validator); OLA_ASSERT_FALSE(integer_validator.IsValid()); m_empty_object->Accept(&integer_validator); OLA_ASSERT_FALSE(integer_validator.IsValid()); m_null_value->Accept(&integer_validator); OLA_ASSERT_FALSE(integer_validator.IsValid()); m_number_value->Accept(&integer_validator); OLA_ASSERT_FALSE(integer_validator.IsValid()); m_string_value->Accept(&integer_validator); OLA_ASSERT_FALSE(integer_validator.IsValid()); // Now test some constraints. // Maximum IntegerValidator max_int_validator, exclusive_max_int_validator; max_int_validator.AddConstraint(new MaximumConstraint( new JsonInt(4), false)); exclusive_max_int_validator.AddConstraint(new MaximumConstraint( new JsonInt(4), true)); auto_ptr int_value1(new JsonInt(3)); auto_ptr int_value2(new JsonInt(-11)); auto_ptr int_value3(new JsonInt(-13)); auto_ptr uint_value1(new JsonInt(5)); // closed maximum int_value1->Accept(&max_int_validator); OLA_ASSERT_TRUE(max_int_validator.IsValid()); int_value2->Accept(&max_int_validator); OLA_ASSERT_TRUE(max_int_validator.IsValid()); int_value3->Accept(&max_int_validator); OLA_ASSERT_TRUE(max_int_validator.IsValid()); m_int_value->Accept(&max_int_validator); OLA_ASSERT_TRUE(max_int_validator.IsValid()); m_uint_value->Accept(&max_int_validator); OLA_ASSERT_TRUE(max_int_validator.IsValid()); uint_value1->Accept(&max_int_validator); OLA_ASSERT_FALSE(max_int_validator.IsValid()); // open maximum int_value1->Accept(&exclusive_max_int_validator); OLA_ASSERT_TRUE(exclusive_max_int_validator.IsValid()); int_value2->Accept(&exclusive_max_int_validator); OLA_ASSERT_TRUE(exclusive_max_int_validator.IsValid()); int_value3->Accept(&exclusive_max_int_validator); OLA_ASSERT_TRUE(exclusive_max_int_validator.IsValid()); m_int_value->Accept(&exclusive_max_int_validator); OLA_ASSERT_TRUE(exclusive_max_int_validator.IsValid()); m_uint_value->Accept(&exclusive_max_int_validator); OLA_ASSERT_FALSE(exclusive_max_int_validator.IsValid()); uint_value1->Accept(&max_int_validator); OLA_ASSERT_FALSE(max_int_validator.IsValid()); // Minimum IntegerValidator min_int_validator, exclusive_min_int_validator; min_int_validator.AddConstraint(new MinimumConstraint( new JsonInt(-12), false)); exclusive_min_int_validator.AddConstraint(new MinimumConstraint( new JsonInt(-12), true)); // closed minimum int_value1->Accept(&min_int_validator); OLA_ASSERT_TRUE(min_int_validator.IsValid()); int_value2->Accept(&min_int_validator); OLA_ASSERT_TRUE(min_int_validator.IsValid()); int_value3->Accept(&min_int_validator); OLA_ASSERT_FALSE(min_int_validator.IsValid()); m_int_value->Accept(&min_int_validator); OLA_ASSERT_TRUE(min_int_validator.IsValid()); m_uint_value->Accept(&min_int_validator); OLA_ASSERT_TRUE(min_int_validator.IsValid()); // open minimum int_value1->Accept(&exclusive_min_int_validator); OLA_ASSERT_TRUE(exclusive_min_int_validator.IsValid()); int_value2->Accept(&exclusive_min_int_validator); OLA_ASSERT_TRUE(exclusive_min_int_validator.IsValid()); int_value3->Accept(&exclusive_min_int_validator); OLA_ASSERT_FALSE(exclusive_min_int_validator.IsValid()); m_int_value->Accept(&exclusive_min_int_validator); OLA_ASSERT_FALSE(exclusive_min_int_validator.IsValid()); m_uint_value->Accept(&exclusive_min_int_validator); OLA_ASSERT_TRUE(exclusive_min_int_validator.IsValid()); // MultipleOf IntegerValidator multiple_of_validator; multiple_of_validator.AddConstraint( new MultipleOfConstraint(new JsonInt(2))); int_value1->Accept(&multiple_of_validator); OLA_ASSERT_FALSE(multiple_of_validator.IsValid()); int_value2->Accept(&multiple_of_validator); OLA_ASSERT_FALSE(multiple_of_validator.IsValid()); int_value3->Accept(&multiple_of_validator); OLA_ASSERT_FALSE(multiple_of_validator.IsValid()); m_int_value->Accept(&multiple_of_validator); OLA_ASSERT_TRUE(multiple_of_validator.IsValid()); m_uint_value->Accept(&multiple_of_validator); OLA_ASSERT_TRUE(multiple_of_validator.IsValid()); auto_ptr int_value4(new JsonInt(4)); auto_ptr int_value5(new JsonInt(8)); auto_ptr int_value6(new JsonInt(-4)); int_value4->Accept(&multiple_of_validator); OLA_ASSERT_TRUE(multiple_of_validator.IsValid()); int_value5->Accept(&multiple_of_validator); OLA_ASSERT_TRUE(multiple_of_validator.IsValid()); int_value6->Accept(&multiple_of_validator); OLA_ASSERT_TRUE(multiple_of_validator.IsValid()); } void JsonSchemaTest::testNumberValidator() { NumberValidator integer_validator; m_int_value->Accept(&integer_validator); OLA_ASSERT_TRUE(integer_validator.IsValid()); m_uint_value->Accept(&integer_validator); OLA_ASSERT_TRUE(integer_validator.IsValid()); m_number_value->Accept(&integer_validator); OLA_ASSERT_TRUE(integer_validator.IsValid()); m_bool_value->Accept(&integer_validator); OLA_ASSERT_FALSE(integer_validator.IsValid()); m_empty_array->Accept(&integer_validator); OLA_ASSERT_FALSE(integer_validator.IsValid()); m_empty_object->Accept(&integer_validator); OLA_ASSERT_FALSE(integer_validator.IsValid()); m_null_value->Accept(&integer_validator); OLA_ASSERT_FALSE(integer_validator.IsValid()); m_string_value->Accept(&integer_validator); OLA_ASSERT_FALSE(integer_validator.IsValid()); } void JsonSchemaTest::testObjectValidator() { ObjectValidator object_validator((ObjectValidator::Options())); m_empty_object->Accept(&object_validator); OLA_ASSERT_TRUE(object_validator.IsValid()); m_bool_value->Accept(&object_validator); OLA_ASSERT_FALSE(object_validator.IsValid()); m_empty_array->Accept(&object_validator); OLA_ASSERT_FALSE(object_validator.IsValid()); m_int_value->Accept(&object_validator); OLA_ASSERT_FALSE(object_validator.IsValid()); m_number_value->Accept(&object_validator); OLA_ASSERT_FALSE(object_validator.IsValid()); m_number_value->Accept(&object_validator); OLA_ASSERT_FALSE(object_validator.IsValid()); m_string_value->Accept(&object_validator); OLA_ASSERT_FALSE(object_validator.IsValid()); m_uint_value->Accept(&object_validator); OLA_ASSERT_FALSE(object_validator.IsValid()); string error; auto_ptr object1(JsonParser::Parse("{\"a\": 1}", &error)); auto_ptr object2( JsonParser::Parse("{\"a\": 1, \"b\": 2}", &error)); auto_ptr object3( JsonParser::Parse("{\"a\": 1, \"b\": 2, \"c\": 3}", &error)); auto_ptr object4( JsonParser::Parse("{\"a\": 1, \"b\": true, \"c\": 3}", &error)); auto_ptr object5( JsonParser::Parse("{\"a\": 1, \"b\": 2, \"c\": false}", &error)); // test maxProperties ObjectValidator::Options max_properties_options; max_properties_options.max_properties = 1; ObjectValidator max_properties_validator(max_properties_options); m_empty_object->Accept(&max_properties_validator); OLA_ASSERT_TRUE(max_properties_validator.IsValid()); object1->Accept(&max_properties_validator); OLA_ASSERT_TRUE(max_properties_validator.IsValid()); object2->Accept(&max_properties_validator); OLA_ASSERT_FALSE(max_properties_validator.IsValid()); // test minProperties ObjectValidator::Options min_properties_options; min_properties_options.min_properties = 2; ObjectValidator min_properties_validator(min_properties_options); m_empty_object->Accept(&min_properties_validator); OLA_ASSERT_FALSE(min_properties_validator.IsValid()); object1->Accept(&min_properties_validator); OLA_ASSERT_FALSE(min_properties_validator.IsValid()); object2->Accept(&min_properties_validator); OLA_ASSERT_TRUE(min_properties_validator.IsValid()); object3->Accept(&min_properties_validator); OLA_ASSERT_TRUE(min_properties_validator.IsValid()); // test required set required_properties; required_properties.insert("c"); ObjectValidator::Options required_properties_options; required_properties_options.SetRequiredProperties(required_properties); ObjectValidator required_properties_validator(required_properties_options); m_empty_object->Accept(&required_properties_validator); OLA_ASSERT_FALSE(required_properties_validator.IsValid()); object1->Accept(&required_properties_validator); OLA_ASSERT_FALSE(required_properties_validator.IsValid()); object2->Accept(&required_properties_validator); OLA_ASSERT_FALSE(required_properties_validator.IsValid()); object3->Accept(&required_properties_validator); OLA_ASSERT_TRUE(required_properties_validator.IsValid()); // test dependencies // property dependencies first set dependencies; // If we have b, then c is required dependencies.insert("c"); ObjectValidator dependency_validator((ObjectValidator::Options())); dependency_validator.AddPropertyDependency("b", dependencies); m_empty_object->Accept(&dependency_validator); OLA_ASSERT_TRUE(dependency_validator.IsValid()); object1->Accept(&dependency_validator); OLA_ASSERT_TRUE(dependency_validator.IsValid()); object2->Accept(&dependency_validator); OLA_ASSERT_FALSE(dependency_validator.IsValid()); object3->Accept(&dependency_validator); OLA_ASSERT_TRUE(dependency_validator.IsValid()); // schema dependency // If c is present, b must be a bool ObjectValidator *sub_validator = new ObjectValidator((ObjectValidator::Options())); sub_validator->AddValidator("b", new BoolValidator()); ObjectValidator schema_dependency_validator((ObjectValidator::Options())); schema_dependency_validator.AddSchemaDependency("c", sub_validator); m_empty_object->Accept(&schema_dependency_validator); OLA_ASSERT_TRUE(schema_dependency_validator.IsValid()); object1->Accept(&schema_dependency_validator); OLA_ASSERT_TRUE(schema_dependency_validator.IsValid()); object2->Accept(&schema_dependency_validator); OLA_ASSERT_TRUE(schema_dependency_validator.IsValid()); object3->Accept(&schema_dependency_validator); OLA_ASSERT_FALSE(schema_dependency_validator.IsValid()); object4->Accept(&schema_dependency_validator); OLA_ASSERT_TRUE(schema_dependency_validator.IsValid()); // test properties // check b is a int ObjectValidator property_validator((ObjectValidator::Options())); property_validator.AddValidator("b", new IntegerValidator()); m_empty_object->Accept(&property_validator); OLA_ASSERT_TRUE(property_validator.IsValid()); object1->Accept(&property_validator); OLA_ASSERT_TRUE(property_validator.IsValid()); object2->Accept(&property_validator); OLA_ASSERT_TRUE(property_validator.IsValid()); object3->Accept(&property_validator); OLA_ASSERT_TRUE(property_validator.IsValid()); object4->Accept(&property_validator); OLA_ASSERT_FALSE(property_validator.IsValid()); // Now check a is also an int, and prevent any other properties ObjectValidator::Options no_additional_properties_options; no_additional_properties_options.SetAdditionalProperties(false); ObjectValidator property_validator2(no_additional_properties_options); property_validator2.AddValidator("b", new IntegerValidator()); property_validator2.AddValidator("a", new IntegerValidator()); m_empty_object->Accept(&property_validator2); OLA_ASSERT_TRUE(property_validator2.IsValid()); object1->Accept(&property_validator2); OLA_ASSERT_TRUE(property_validator2.IsValid()); object2->Accept(&property_validator2); OLA_ASSERT_TRUE(property_validator2.IsValid()); object3->Accept(&property_validator2); OLA_ASSERT_FALSE(property_validator2.IsValid()); object4->Accept(&property_validator2); OLA_ASSERT_FALSE(property_validator2.IsValid()); ObjectValidator::Options allow_additional_properties_options; allow_additional_properties_options.SetAdditionalProperties(true); ObjectValidator property_validator3(allow_additional_properties_options); property_validator3.AddValidator("b", new IntegerValidator()); property_validator3.AddValidator("a", new IntegerValidator()); m_empty_object->Accept(&property_validator3); OLA_ASSERT_TRUE(property_validator3.IsValid()); object1->Accept(&property_validator3); OLA_ASSERT_TRUE(property_validator3.IsValid()); object2->Accept(&property_validator3); OLA_ASSERT_TRUE(property_validator3.IsValid()); object3->Accept(&property_validator3); OLA_ASSERT_TRUE(property_validator3.IsValid()); object4->Accept(&property_validator3); OLA_ASSERT_FALSE(property_validator3.IsValid()); // try an additionalProperty validator ObjectValidator property_validator4((ObjectValidator::Options())); property_validator4.AddValidator("a", new IntegerValidator()); property_validator4.AddValidator("b", new IntegerValidator()); property_validator4.SetAdditionalValidator(new IntegerValidator()); m_empty_object->Accept(&property_validator4); OLA_ASSERT_TRUE(property_validator4.IsValid()); object1->Accept(&property_validator4); OLA_ASSERT_TRUE(property_validator4.IsValid()); object2->Accept(&property_validator4); OLA_ASSERT_TRUE(property_validator4.IsValid()); object3->Accept(&property_validator4); OLA_ASSERT_TRUE(property_validator4.IsValid()); object4->Accept(&property_validator4); OLA_ASSERT_FALSE(property_validator4.IsValid()); object5->Accept(&property_validator4); OLA_ASSERT_FALSE(property_validator4.IsValid()); } void JsonSchemaTest::testArrayValidator() { ArrayValidator array_validator(NULL, NULL, ArrayValidator::Options()); m_empty_array->Accept(&array_validator); OLA_ASSERT_TRUE(array_validator.IsValid()); m_bool_value->Accept(&array_validator); OLA_ASSERT_FALSE(array_validator.IsValid()); m_empty_object->Accept(&array_validator); OLA_ASSERT_FALSE(array_validator.IsValid()); m_int_value->Accept(&array_validator); OLA_ASSERT_FALSE(array_validator.IsValid()); m_number_value->Accept(&array_validator); OLA_ASSERT_FALSE(array_validator.IsValid()); m_number_value->Accept(&array_validator); OLA_ASSERT_FALSE(array_validator.IsValid()); m_string_value->Accept(&array_validator); OLA_ASSERT_FALSE(array_validator.IsValid()); m_uint_value->Accept(&array_validator); OLA_ASSERT_FALSE(array_validator.IsValid()); string error; auto_ptr small_array(JsonParser::Parse("[1]", &error)); auto_ptr medium_array(JsonParser::Parse("[1, 2]", &error)); auto_ptr large_array(JsonParser::Parse("[1, 2, 3]", &error)); auto_ptr duplicate_items_array( JsonParser::Parse("[1, 2, 1]", &error)); // test maxItems ArrayValidator::Options max_options; max_options.max_items = 2; ArrayValidator max_items_validator(NULL, NULL, max_options); m_empty_array->Accept(&max_items_validator); OLA_ASSERT_TRUE(max_items_validator.IsValid()); small_array->Accept(&max_items_validator); OLA_ASSERT_TRUE(max_items_validator.IsValid()); medium_array->Accept(&max_items_validator); OLA_ASSERT_TRUE(max_items_validator.IsValid()); large_array->Accept(&max_items_validator); OLA_ASSERT_FALSE(max_items_validator.IsValid()); // test minItems ArrayValidator::Options min_options; min_options.min_items = 2; ArrayValidator min_items_validator(NULL, NULL, min_options); m_empty_array->Accept(&min_items_validator); OLA_ASSERT_FALSE(min_items_validator.IsValid()); small_array->Accept(&min_items_validator); OLA_ASSERT_FALSE(min_items_validator.IsValid()); medium_array->Accept(&min_items_validator); OLA_ASSERT_TRUE(min_items_validator.IsValid()); large_array->Accept(&min_items_validator); OLA_ASSERT_TRUE(min_items_validator.IsValid()); // test uniqueItems ArrayValidator::Options unique_items_options; unique_items_options.unique_items = true; ArrayValidator unique_items_validator(NULL, NULL, unique_items_options); m_empty_array->Accept(&unique_items_validator); OLA_ASSERT_TRUE(unique_items_validator.IsValid()); small_array->Accept(&unique_items_validator); OLA_ASSERT_TRUE(unique_items_validator.IsValid()); medium_array->Accept(&unique_items_validator); OLA_ASSERT_TRUE(unique_items_validator.IsValid()); large_array->Accept(&unique_items_validator); OLA_ASSERT_TRUE(unique_items_validator.IsValid()); duplicate_items_array->Accept(&unique_items_validator); OLA_ASSERT_FALSE(unique_items_validator.IsValid()); } void JsonSchemaTest::testAllOfValidator() { // 1 <= x <= 5 IntegerValidator *range1 = new IntegerValidator(); range1->AddConstraint( new MinimumConstraint(new JsonInt(1), false)); range1->AddConstraint( new MaximumConstraint(new JsonInt(5), false)); // 4 <= x <= 8 IntegerValidator *range2 = new IntegerValidator(); range2->AddConstraint( new MinimumConstraint(new JsonInt(4), false)); range2->AddConstraint( new MaximumConstraint(new JsonInt(8), false)); ConjunctionValidator::ValidatorList validators; validators.push_back(range1); validators.push_back(range2); AllOfValidator all_of_validator(&validators); m_string_value->Accept(&all_of_validator); OLA_ASSERT_FALSE(all_of_validator.IsValid()); m_long_string_value->Accept(&all_of_validator); OLA_ASSERT_FALSE(all_of_validator.IsValid()); m_bool_value->Accept(&all_of_validator); OLA_ASSERT_FALSE(all_of_validator.IsValid()); m_empty_array->Accept(&all_of_validator); OLA_ASSERT_FALSE(all_of_validator.IsValid()); m_empty_object->Accept(&all_of_validator); OLA_ASSERT_FALSE(all_of_validator.IsValid()); m_int_value->Accept(&all_of_validator); OLA_ASSERT_FALSE(all_of_validator.IsValid()); m_null_value->Accept(&all_of_validator); OLA_ASSERT_FALSE(all_of_validator.IsValid()); m_number_value->Accept(&all_of_validator); OLA_ASSERT_FALSE(all_of_validator.IsValid()); m_uint_value->Accept(&all_of_validator); OLA_ASSERT_TRUE(all_of_validator.IsValid()); // 4 } void JsonSchemaTest::testAnyOfValidator() { ConjunctionValidator::ValidatorList validators; validators.push_back(new StringValidator((StringValidator::Options()))); validators.push_back(new BoolValidator()); validators.push_back(new NullValidator()); AnyOfValidator any_of_validator(&validators); m_string_value->Accept(&any_of_validator); OLA_ASSERT_TRUE(any_of_validator.IsValid()); m_long_string_value->Accept(&any_of_validator); OLA_ASSERT_TRUE(any_of_validator.IsValid()); m_bool_value->Accept(&any_of_validator); OLA_ASSERT_TRUE(any_of_validator.IsValid()); m_null_value->Accept(&any_of_validator); OLA_ASSERT_TRUE(any_of_validator.IsValid()); m_empty_array->Accept(&any_of_validator); OLA_ASSERT_FALSE(any_of_validator.IsValid()); m_empty_object->Accept(&any_of_validator); OLA_ASSERT_FALSE(any_of_validator.IsValid()); m_int_value->Accept(&any_of_validator); OLA_ASSERT_FALSE(any_of_validator.IsValid()); m_number_value->Accept(&any_of_validator); OLA_ASSERT_FALSE(any_of_validator.IsValid()); m_uint_value->Accept(&any_of_validator); OLA_ASSERT_FALSE(any_of_validator.IsValid()); } void JsonSchemaTest::testOneOfValidator() { // 1 <= x <= 5 IntegerValidator *range1 = new IntegerValidator(); range1->AddConstraint( new MinimumConstraint(new JsonInt(1), false)); range1->AddConstraint( new MaximumConstraint(new JsonInt(5), false)); // 4 <= x <= 8 IntegerValidator *range2 = new IntegerValidator(); range2->AddConstraint( new MinimumConstraint(new JsonInt(4), false)); range2->AddConstraint( new MaximumConstraint(new JsonInt(8), false)); ConjunctionValidator::ValidatorList validators; validators.push_back(range1); validators.push_back(range2); OneOfValidator one_of_validator(&validators); m_bool_value->Accept(&one_of_validator); OLA_ASSERT_FALSE(one_of_validator.IsValid()); m_empty_array->Accept(&one_of_validator); OLA_ASSERT_FALSE(one_of_validator.IsValid()); m_empty_object->Accept(&one_of_validator); OLA_ASSERT_FALSE(one_of_validator.IsValid()); m_int_value->Accept(&one_of_validator); OLA_ASSERT_FALSE(one_of_validator.IsValid()); m_null_value->Accept(&one_of_validator); OLA_ASSERT_FALSE(one_of_validator.IsValid()); m_number_value->Accept(&one_of_validator); OLA_ASSERT_FALSE(one_of_validator.IsValid()); m_string_value->Accept(&one_of_validator); OLA_ASSERT_FALSE(one_of_validator.IsValid()); m_uint_value->Accept(&one_of_validator); OLA_ASSERT_FALSE(one_of_validator.IsValid()); auto_ptr int_value1(new JsonInt(3)); auto_ptr int_value2(new JsonInt(5)); auto_ptr int_value3(new JsonInt(6)); int_value1->Accept(&one_of_validator); OLA_ASSERT_TRUE(one_of_validator.IsValid()); int_value2->Accept(&one_of_validator); OLA_ASSERT_FALSE(one_of_validator.IsValid()); int_value3->Accept(&one_of_validator); OLA_ASSERT_TRUE(one_of_validator.IsValid()); } void JsonSchemaTest::testNotValidator() { NotValidator not_validator(new BoolValidator()); // Anything but a bool m_bool_value->Accept(¬_validator); OLA_ASSERT_FALSE(not_validator.IsValid()); m_empty_array->Accept(¬_validator); OLA_ASSERT_TRUE(not_validator.IsValid()); m_empty_object->Accept(¬_validator); OLA_ASSERT_TRUE(not_validator.IsValid()); m_int_value->Accept(¬_validator); OLA_ASSERT_TRUE(not_validator.IsValid()); m_null_value->Accept(¬_validator); OLA_ASSERT_TRUE(not_validator.IsValid()); m_number_value->Accept(¬_validator); OLA_ASSERT_TRUE(not_validator.IsValid()); m_string_value->Accept(¬_validator); OLA_ASSERT_TRUE(not_validator.IsValid()); m_uint_value->Accept(¬_validator); OLA_ASSERT_TRUE(not_validator.IsValid()); } void JsonSchemaTest::testEnums() { StringValidator string_validator((StringValidator::Options())); string_validator.AddEnumValue(new JsonString("foo")); string_validator.AddEnumValue(new JsonString("bar")); JsonString bar_value("bar"); JsonString baz_value("baz"); m_string_value->Accept(&string_validator); OLA_ASSERT_TRUE(string_validator.IsValid()); m_long_string_value->Accept(&string_validator); OLA_ASSERT_FALSE(string_validator.IsValid()); bar_value.Accept(&string_validator); OLA_ASSERT_TRUE(string_validator.IsValid()); baz_value.Accept(&string_validator); OLA_ASSERT_FALSE(string_validator.IsValid()); IntegerValidator integer_validator; integer_validator.AddEnumValue(new JsonInt(1)); integer_validator.AddEnumValue(new JsonInt(2)); integer_validator.AddEnumValue(new JsonInt(4)); JsonInt int_value1(2); JsonInt int_value2(3); JsonInt uint_value1(2); JsonInt uint_value2(3); m_int_value->Accept(&integer_validator); OLA_ASSERT_FALSE(integer_validator.IsValid()); m_uint_value->Accept(&integer_validator); OLA_ASSERT_TRUE(integer_validator.IsValid()); int_value1.Accept(&integer_validator); OLA_ASSERT_TRUE(integer_validator.IsValid()); int_value2.Accept(&integer_validator); OLA_ASSERT_FALSE(integer_validator.IsValid()); uint_value1.Accept(&integer_validator); OLA_ASSERT_TRUE(integer_validator.IsValid()); uint_value2.Accept(&integer_validator); OLA_ASSERT_FALSE(integer_validator.IsValid()); } ola-0.10.5.nojsmin/common/web/testdata/0000755000175000017500000000000013134123603017332 5ustar wouterwouterola-0.10.5.nojsmin/common/web/testdata/misc.test0000644000175000017500000000027113023355232021170 0ustar wouterwouter=== POSITIVE === // Verify we strip keys we don't recognise / support, even if they are in the // standard. { "pattern": "[cat]", "type": "string" } -------- { "type": "string" } ola-0.10.5.nojsmin/common/web/testdata/anyof.test0000644000175000017500000000077113023355232021356 0ustar wouterwouter=== POSITIVE === // This value can be a bool or a string with the value "true" or "false". { "anyOf": [ { "type": "boolean" }, { "enum": ["true", "false"], "type": "string" } ] } === NEGATIVE === { "anyOf": [] } === NEGATIVE === { "anyOf": null } === NEGATIVE === { "anyOf": false } === NEGATIVE === { "anyOf": "foo" } === NEGATIVE === { "anyOf": 1 } === NEGATIVE === { "anyOf": -1 } === NEGATIVE === { "anyOf": 1.2 } === NEGATIVE === { "anyOf": {} } ola-0.10.5.nojsmin/common/web/testdata/allof.test0000644000175000017500000000072713023355232021340 0ustar wouterwouter=== POSITIVE === // This value can be a bool or a string with the value "true" or "false". { "allOf": [ { "type": "string" }, { "default": "foo" } ] } === NEGATIVE === { "allOf": [] } === NEGATIVE === { "allOf": null } === NEGATIVE === { "allOf": false } === NEGATIVE === { "allOf": "foo" } === NEGATIVE === { "allOf": 1 } === NEGATIVE === { "allOf": -1 } === NEGATIVE === { "allOf": 1.2 } === NEGATIVE === { "allOf": {} } ola-0.10.5.nojsmin/common/web/testdata/definitions.test0000644000175000017500000000171513023355232022554 0ustar wouterwouter=== POSITIVE === { "definitions": { "positiveInteger": { "minimum": 0, "type": "integer" }, "positiveIntegerDefault0": { "allOf": [ { "$ref": "#\/definitions\/positiveInteger" }, { "default": 0 } ] }, "schemaArray": { "items": { "$ref": "#" }, "minItems": 1, "type": "array" }, "simpleTypes": { "enum": ["array", "boolean", "integer", "null", "number", "object", "string"] }, "stringArray": { "items": { "type": "string" }, "minItems": 1, "type": "array", "uniqueItems": true } } } === NEGATIVE === { "definitions": [] } === NEGATIVE === { "definitions": null } === NEGATIVE === { "definitions": false } === NEGATIVE === { "definitions": "foo" } === NEGATIVE === { "definitions": 1 } === NEGATIVE === { "definitions": -1 } === NEGATIVE === { "definitions": 1.2 } ola-0.10.5.nojsmin/common/web/testdata/strings.test0000644000175000017500000000230613023355232021727 0ustar wouterwouter=== POSITIVE === { "type": "string" } // Test maxLength === POSITIVE === { "maxLength": 0, "type": "string" } === POSITIVE === { "maxLength": 1, "type": "string" } === POSITIVE === { "maxLength": 32, "type": "string" } === NEGATIVE === { "type": "string", "maxLength": null } === NEGATIVE === { "type": "string", "maxLength": -1 } === NEGATIVE === { "type": "string", "maxLength": 1.2 } === NEGATIVE === { "type": "string", "maxLength": "foo" } === NEGATIVE === { "type": "string", "maxLength": [] } === NEGATIVE === { "type": "string", "maxLength": {} } // Test minLength === POSITIVE === { "minLength": 0, "type": "string" } -------- // minLength defaults to 0, so we remove it { "type": "string" } === POSITIVE === { "minLength": 1, "type": "string" } === POSITIVE === { "minLength": 32, "type": "string" } === NEGATIVE === { "type": "string", "minLength": null } === NEGATIVE === { "type": "string", "minLength": -1 } === NEGATIVE === { "type": "string", "minLength": 1.2 } === NEGATIVE === { "type": "string", "minLength": "foo" } === NEGATIVE === { "type": "string", "minLength": [] } === NEGATIVE === { "type": "string", "minLength": {} } ola-0.10.5.nojsmin/common/web/testdata/not.test0000644000175000017500000000050113023355232021031 0ustar wouterwouter=== POSITIVE === // Anything but an int. { "not": { "type": "integer" } } === NEGATIVE === { "not": [] } === NEGATIVE === { "not": null } === NEGATIVE === { "not": false } === NEGATIVE === { "not": "foo" } === NEGATIVE === { "not": 1 } === NEGATIVE === { "not": -1 } === NEGATIVE === { "not": 1.2 } ola-0.10.5.nojsmin/common/web/testdata/oneof.test0000644000175000017500000000101413023355232021337 0ustar wouterwouter=== POSITIVE === // An int between 1 and 10 or 99 and 101 { "oneOf": [ { "maximum": 10, "minimum": 1, "type": "integer" }, { "maximum": 101, "minimum": 99, "type": "integer" } ] } === NEGATIVE === { "oneOf": [] } === NEGATIVE === { "oneOf": null } === NEGATIVE === { "oneOf": false } === NEGATIVE === { "oneOf": "foo" } === NEGATIVE === { "oneOf": 1 } === NEGATIVE === { "oneOf": -1 } === NEGATIVE === { "oneOf": 1.2 } === NEGATIVE === { "oneOf": {} } ola-0.10.5.nojsmin/common/web/testdata/arrays.test0000644000175000017500000001003713023355232021537 0ustar wouterwouter// Items === NEGATIVE === { "type": "array", "items": null } === NEGATIVE === { "type": "array", "items": true } === NEGATIVE === { "type": "array", "items": false } === NEGATIVE === { "type": "array", "items": "foo" } === NEGATIVE === { "type": "array", "items": 1 } === NEGATIVE === { "type": "array", "items": -1 } === NEGATIVE === { "type": "array", "items": [null] } === NEGATIVE === { "type": "array", "items": [false] } === NEGATIVE === { "type": "array", "items": ["foo"] } === NEGATIVE === { "type": "array", "items": [1] } === NEGATIVE === { "type": "array", "items": [-1] } === NEGATIVE === { "type": "array", "items": [[]] } === POSITIVE === // Tests with 'items' missing and 'additionalItems' taking various values { "type": "array" } === POSITIVE === { "additionalItems": true, "type": "array" } === POSITIVE === { "additionalItems": false, "type": "array" } === POSITIVE === { "additionalItems": {}, "type": "array" } === POSITIVE === { "additionalItems": { "type": "number" }, "type": "array" } // Tests with 'items' present as an object === POSITIVE === { "items": {}, "type": "array" } === POSITIVE === { "additionalItems": true, "items": {}, "type": "array" } === POSITIVE === { "additionalItems": false, "items": {}, "type": "array" } === POSITIVE === { "additionalItems": { "type": "string" }, "items": { "type": "number" }, "type": "array" } // Tests with 'items' as an array === POSITIVE === { "items": [], "type": "array" } === POSITIVE === { "items": [{}, {}, {}], "type": "array" } === POSITIVE === { "additionalItems": false, "items": [], "type": "array" } === POSITIVE === { "additionalItems": false, "items": [{}, {}], "type": "array" } === POSITIVE === { "additionalItems": true, "items": [], "type": "array" } === POSITIVE === { "additionalItems": {}, "items": [{}, {}, {}], "type": "array" } === POSITIVE === { "items": { "$ref": "#" }, "type": "array" } === POSITIVE === // Nested Arrays { "items": { "items": [ { "type": "boolean" } ], "type": "array" }, "maxItems": 1, "minItems": 5, "type": "array" } // min / max Items === POSITIVE === { "description": "List of names", "items": {}, "maxItems": 1, "minItems": 5, "title": "names", "type": "array" } === POSITIVE === { "items": {}, "minItems": 0, "type": "array" } -------- { "items": {}, "type": "array" } === NEGATIVE === { "items": {}, "maxItems": null, "type": "array" } === NEGATIVE === { "items": {}, "maxItems": 1.2, "type": "array" } === NEGATIVE === { "items": {}, "maxItems": -2, "type": "array" } === NEGATIVE === { "items": {}, "maxItems": "foo", "type": "array" } === NEGATIVE === { "items": {}, "maxItems": [], "type": "array" } === NEGATIVE === { "items": {}, "maxItems": {}, "type": "array" } === NEGATIVE === { "items": {}, "minItems": null, "type": "array" } === NEGATIVE === { "items": {}, "minItems": 1.2, "type": "array" } === NEGATIVE === { "items": {}, "minItems": -1, "type": "array" } === NEGATIVE === { "items": {}, "minItems": "foo", "type": "array" } === NEGATIVE === { "items": {}, "minItems": [], "type": "array" } === NEGATIVE === { "items": {}, "minItems": {}, "type": "array" } // uniqueItems === POSITIVE === { "items": {}, "type": "array", "uniqueItems": true } === POSITIVE === { "items": {}, "type": "array", "uniqueItems": false } -------- { "items": {}, "type": "array" } === NEGATIVE === { "items": {}, "type": "array", "uniqueItems": 2 } === NEGATIVE === { "items": {}, "type": "array", "uniqueItems": -1 } === NEGATIVE === { "items": {}, "type": "array", "uniqueItems": 1.2 } === NEGATIVE === { "items": {}, "type": "array", "uniqueItems": null } === NEGATIVE === { "items": {}, "type": "array", "uniqueItems": "foo" } === NEGATIVE === { "items": {}, "type": "array", "uniqueItems": [] } === NEGATIVE === { "items": {}, "type": "array", "uniqueItems": {} } ola-0.10.5.nojsmin/common/web/testdata/integers.test0000644000175000017500000000726613023355232022070 0ustar wouterwouter=== POSITIVE === { "type": "integer" } // maximum & exclusiveMaximum === POSITIVE === { "maximum": 10, "type": "integer" } === POSITIVE === { "exclusiveMaximum": true, "maximum": -10, "type": "integer" } === POSITIVE === { "exclusiveMaximum": false, "maximum": 2.1, "type": "integer" } === NEGATIVE === { "exclusiveMaximum": 1, "maximum": 2.1, "type": "integer" } === NEGATIVE === { "exclusiveMaximum": null, "maximum": 2.1, "type": "integer" } === NEGATIVE === { "exclusiveMaximum": 1.2, "maximum": 2.1, "type": "integer" } === NEGATIVE === { "exclusiveMaximum": "foo", "maximum": 2.1, "type": "integer" } === NEGATIVE === { "exclusiveMaximum": [], "maximum": 2.1, "type": "integer" } === NEGATIVE === { "exclusiveMaximum": {}, "maximum": 2.1, "type": "integer" } === NEGATIVE === { "maximum": null, "type": "integer" } === NEGATIVE === { "maximum": false, "type": "integer" } === NEGATIVE === { "maximum": "foo", "type": "integer" } === NEGATIVE === { "maximum": [], "type": "integer" } === NEGATIVE === { "maximum": {}, "type": "integer" } // exclusiveMaximum without maximum isn't valid === NEGATIVE === { "exclusiveMaximum": true, "type": "integer" } // minimum & exclusiveMinimum === POSITIVE === { "minimum": 10, "type": "integer" } === POSITIVE === { "exclusiveMinimum": true, "minimum": -10, "type": "integer" } === POSITIVE === { "exclusiveMinimum": false, "minimum": 2.1, "type": "integer" } === NEGATIVE === { "exclusiveMinimum": null, "minimum": 2.1, "type": "integer" } === NEGATIVE === { "exclusiveMinimum": 1, "minimum": 2.1, "type": "integer" } === NEGATIVE === { "exclusiveMinimum": [], "minimum": 2.1, "type": "integer" } === NEGATIVE === { "exclusiveMinimum": {}, "minimum": 2.1, "type": "integer" } === NEGATIVE === { "exclusiveMinimum": "foo", "minimum": 2.1, "type": "integer" } === NEGATIVE === { "minimum": null, "type": "integer" } === NEGATIVE === { "minimum": false, "type": "integer" } === NEGATIVE === { "minimum": "foo", "type": "integer" } === NEGATIVE === { "minimum": [], "type": "integer" } === NEGATIVE === { "minimum": {}, "type": "integer" } // exclusiveMinimum without minimum isn't valid === NEGATIVE === { "exclusiveMinimum": true, "type": "integer" } // multipleOf === POSITIVE === { "multipleOf": 10, "type": "integer" } === POSITIVE === { "multipleOf": 2.1, "type": "integer" } === NEGATIVE === { "multipleOf": -1, "type": "integer" } === NEGATIVE === { "multipleOf": -1.1, "type": "integer" } === NEGATIVE === { "multipleOf": null, "type": "integer" } === NEGATIVE === { "multipleOf": false, "type": "integer" } === NEGATIVE === { "multipleOf": [], "type": "integer" } === NEGATIVE === { "multipleOf": {}, "type": "integer" } === NEGATIVE === { "multipleOf": "foo", "type": "integer" } // Enums === POSITIVE === { "enum": [1, 2, 4], "type": "integer" } === POSITIVE === { "enum": [true, false], "type": "boolean" } === POSITIVE === { "enum": ["cat", "dog", "rat"], "type": "string" } === NEGATIVE === { "enum": null, "type": "integer" } === NEGATIVE === { "enum": "foo", "type": "integer" } === NEGATIVE === { "enum": 1, "type": "integer" } === NEGATIVE === { "enum": -1, "type": "integer" } === NEGATIVE === { "enum": 1.2, "type": "integer" } === NEGATIVE === { "enum": false, "type": "integer" } === NEGATIVE === { "enum": {}, "type": "integer" } === NEGATIVE === // enum must have at least one item { "enum": [], "type": "integer" } // duplicates aren't allowed === NEGATIVE === { "enum": [1, 1, 0], "type": "integer" } === NEGATIVE === { "enum": ["cat", "cat"], "type": "string" } ola-0.10.5.nojsmin/common/web/testdata/type.test0000644000175000017500000000101413023355232021212 0ustar wouterwouter=== POSITIVE === { "type": "array" } === POSITIVE === { "type": "boolean" } === POSITIVE === { "type": "integer" } === POSITIVE === { "type": "null" } === POSITIVE === { "type": "number" } === POSITIVE === { "type": "object" } === POSITIVE === { "type": "string" } === NEGATIVE === { "type": null } === NEGATIVE === { "type": "foo" } === NEGATIVE === { "type": true } === NEGATIVE === { "type": 1 } === NEGATIVE === { "type": -1 } === NEGATIVE === { "type": 1.2 } === NEGATIVE === { "type": {} } ola-0.10.5.nojsmin/common/web/testdata/objects.test0000644000175000017500000001151413023355232021670 0ustar wouterwouter=== POSITIVE === { "type": "object" } === POSITIVE === { "maxProperties": 3, "minProperties": 1, "type": "object" } // Max properties tests === POSITIVE === { "maxProperties": 3, "type": "object" } // Negative Max properties tests === NEGATIVE === { "maxProperties": false, "type": "object" } === NEGATIVE === { "maxProperties": -1, "type": "object" } === NEGATIVE === { "maxProperties": 1.2, "type": "object" } === NEGATIVE === { "maxProperties": "foo", "type": "object" } === NEGATIVE === { "maxProperties": null, "type": "object" } === NEGATIVE === { "maxProperties": [], "type": "object" } === NEGATIVE === { "maxProperties": {}, "type": "object" } // Min properties tests === POSITIVE === { "minProperties": 1, "type": "object" } // Negative Min properties tests === NEGATIVE === { "minProperties": false, "type": "object" } === NEGATIVE === { "minProperties": -1, "type": "object" } === NEGATIVE === { "minProperties": 1.2, "type": "object" } === NEGATIVE === { "minProperties": "foo", "type": "object" } === NEGATIVE === { "minProperties": null, "type": "object" } === NEGATIVE === { "minProperties": [], "type": "object" } === NEGATIVE === { "minProperties": {}, "type": "object" } // Required tests === POSITIVE === { "required": [], "type": "object" } === POSITIVE === { "required": ["foo"], "type": "object" } // Negative required tests === NEGATIVE === { "required": null, "type": "object" } === NEGATIVE === { "required": true, "type": "object" } === NEGATIVE === { "required": "foo", "type": "object" } === NEGATIVE === { "required": 1, "type": "object" } === NEGATIVE === { "required": -1, "type": "object" } === NEGATIVE === { "required": 1.2, "type": "object" } === NEGATIVE === { "required": {}, "type": "object" } === NEGATIVE === { "required": [1], "type": "object" } === NEGATIVE === { "required": ["foo", "foo"], "type": "object" } // dependency tesets // First up is property dependencies. === POSITIVE === { "dependencies": { "foo": ["bar"] }, "type": "object" } === POSITIVE === { "dependencies": { "foo": ["bar", "baz"] }, "type": "object" } // Now test schema dependencies. === POSITIVE === { "dependencies": { "foo": {} }, "type": "object" } === POSITIVE === { "dependencies": { "foo": { "maxProperties": 2, "type": "object" } }, "type": "object" } // Negative dependencies tests === NEGATIVE === { "dependencies": 1, "type": "object" } === NEGATIVE === { "dependencies": -1, "type": "object" } === NEGATIVE === { "dependencies": 1.2, "type": "object" } === NEGATIVE === { "dependencies": null "type": "object" } === NEGATIVE === { "dependencies": false, "type": "object" } === NEGATIVE === { "dependencies": [], "type": "object" } === NEGATIVE === { "dependencies": { "foo": [] }, "type": "object" } === NEGATIVE === { "dependencies": { "foo": ["bar", "bar"] }, "type": "object" } // properties test === POSITIVE === { "properties": { "name": {} }, "type": "object" } === POSITIVE === { "properties": { "age": { "type": "integer" }, "name": { "type": "string" } }, "type": "object" } // Negative properties test === NEGATIVE === { "properties": null, "type": "object" } === NEGATIVE === { "properties": "foo", "type": "object" } === NEGATIVE === { "properties": 1, "type": "object" } === NEGATIVE === { "properties": -1, "type": "object" } === NEGATIVE === { "properties": 1.2, "type": "object" } === NEGATIVE === { "properties": [], "type": "object" } === NEGATIVE === { "properties": { "name": null }, "type": "object" } === NEGATIVE === { "properties": { "name": "foo" }, "type": "object" } === NEGATIVE === { "properties": { "name": 1 }, "type": "object" } === NEGATIVE === { "properties": { "name": -1 }, "type": "object" } === NEGATIVE === { "properties": { "name": 1.2 }, "type": "object" } === NEGATIVE === { "properties": { "name": [] }, "type": "object" } // additionalProperties test === POSITIVE === { "additionalProperties": true, "type": "object" } === POSITIVE === { "additionalProperties": false, "type": "object" } === POSITIVE === { "additionalProperties": {}, "type": "object" } === POSITIVE === { "additionalProperties": { "type": "number" }, "type": "object" } // Negative additionalProperties test === NEGATIVE === { "additionalProperties": null, "type": "object" } === NEGATIVE === { "additionalProperties": "foo", "type": "object" } === NEGATIVE === { "additionalProperties": 1, "type": "object" } === NEGATIVE === { "additionalProperties": -1, "type": "object" } === NEGATIVE === { "additionalProperties": 1.2, "type": "object" } === NEGATIVE === { "additionalProperties": [], "type": "object" } ola-0.10.5.nojsmin/common/web/testdata/basic-keywords.test0000644000175000017500000000647313023355232023175 0ustar wouterwouter=== POSITIVE === { "$schema": "http:\\\\json-schema.org\\draft-04\\schema#", "description": "just testing", "id": "http:\/\/x.y.z\/rootschema.json#", "title": "test" } === POSITIVE === { "$schema": "http:\\\\json-schema.org\\draft-04\\schema#", "description": "just testing", "id": "http:\/\/x.y.z\/rootschema.json#", "title": "test", "type": "array" } === POSITIVE === { "$schema": "http:\\\\json-schema.org\\draft-04\\schema#", "description": "just testing", "id": "http:\/\/x.y.z\/rootschema.json#", "title": "test", "type": "boolean" } === POSITIVE === { "$schema": "http:\\\\json-schema.org\\draft-04\\schema#", "description": "just testing", "id": "http:\/\/x.y.z\/rootschema.json#", "title": "test", "type": "integer" } === POSITIVE === { "$schema": "http:\\\\json-schema.org\\draft-04\\schema#", "description": "just testing", "id": "http:\/\/x.y.z\/rootschema.json#", "title": "test", "type": "null" } === POSITIVE === { "$schema": "http:\\\\json-schema.org\\draft-04\\schema#", "description": "just testing", "id": "http:\/\/x.y.z\/rootschema.json#", "title": "test", "type": "number" } === POSITIVE === { "$schema": "http:\\\\json-schema.org\\draft-04\\schema#", "description": "just testing", "id": "http:\/\/x.y.z\/rootschema.json#", "title": "test", "type": "object" } === POSITIVE === { "$schema": "http:\\\\json-schema.org\\draft-04\\schema#", "description": "just testing", "id": "http:\/\/x.y.z\/rootschema.json#", "title": "test", "type": "string" } // Negative 'id' tests === NEGATIVE === { "id": [] } === NEGATIVE === { "id": false } === NEGATIVE === { "id": 1 } === NEGATIVE === { "id": -1 } === NEGATIVE === { "id": null } === NEGATIVE === { "id": 1.0 } === NEGATIVE === { "id": {} } // Negative 'schema' tests === NEGATIVE === { "$schema": [] } === NEGATIVE === { "$schema": false } === NEGATIVE === { "$schema": 1 } === NEGATIVE === { "$schema": -1 } === NEGATIVE === { "$schema": null } === NEGATIVE === { "$schema": 1.0 } === NEGATIVE === { "$schema": {} } // Negative 'title' tests === NEGATIVE === { "title": [] } === NEGATIVE === { "title": false } === NEGATIVE === { "title": 1 } === NEGATIVE === { "title": -1 } === NEGATIVE === { "title": null } === NEGATIVE === { "title": 1.0 } === NEGATIVE === { "title": {} } // Negative 'description' tests === NEGATIVE === { "description": [] } === NEGATIVE === { "description": false } === NEGATIVE === { "description": 1 } === NEGATIVE === { "description": -1 } === NEGATIVE === { "description": null } === NEGATIVE === { "description": 1.0 } === NEGATIVE === { "description": {} } // Positive 'default' tests === POSITIVE === { "default": "foo" } === POSITIVE === { "default": true } === POSITIVE === { "default": null } === POSITIVE === { "default": 1 } === POSITIVE === { "default": -1 } === POSITIVE === { "default": 1.2 } === POSITIVE === { "default": [] } === POSITIVE === { "default": [1, 2, 3, null] } === POSITIVE === { "default": {} } === POSITIVE === { "default": { "name": null } } === POSITIVE === { "default": { "pets": [1, 2, {}] } } === NEGATIVE === { "default": foo } === NEGATIVE === { "default": [bar] } === NEGATIVE === { "default": { "foo": } } === NEGATIVE === { "default": { "pets": [1, 2, {null}] } } ola-0.10.5.nojsmin/common/web/testdata/schema.json0000644000175000017500000000766513023355232021505 0ustar wouterwouter=== POSITIVE === { "$schema": "http:\/\/json-schema.org\/draft-04\/schema#", "default": {}, "definitions": { "positiveInteger": { "minimum": 0, "type": "integer" }, "positiveIntegerDefault0": { "allOf": [ { "$ref": "#\/definitions\/positiveInteger" }, { "default": 0 } ] }, "schemaArray": { "items": { "$ref": "#" }, "minItems": 1, "type": "array" }, "simpleTypes": { "enum": ["array", "boolean", "integer", "null", "number", "object", "string"] }, "stringArray": { "items": { "type": "string" }, "minItems": 1, "type": "array", "uniqueItems": true } }, "dependencies": { "exclusiveMaximum": ["maximum"], "exclusiveMinimum": ["minimum"] }, "description": "Core schema meta-schema", "id": "http:\/\/json-schema.org\/draft-04\/schema#", "properties": { "$schema": { "type": "string" }, "additionalItems": { "anyOf": [ { "type": "boolean" }, { "$ref": "#" } ], "default": {} }, "additionalProperties": { "anyOf": [ { "type": "boolean" }, { "$ref": "#" } ], "default": {} }, "allOf": { "$ref": "#\/definitions\/schemaArray" }, "anyOf": { "$ref": "#\/definitions\/schemaArray" }, "default": {}, "definitions": { "additionalProperties": { "$ref": "#" }, "default": {}, "type": "object" }, "dependencies": { "additionalProperties": { "anyOf": [ { "$ref": "#" }, { "$ref": "#\/definitions\/stringArray" } ] }, "type": "object" }, "description": { "type": "string" }, "enum": { "minItems": 1, "type": "array", "uniqueItems": true }, "exclusiveMaximum": { "default": false, "type": "boolean" }, "exclusiveMinimum": { "default": false, "type": "boolean" }, "id": { "type": "string" }, "items": { "anyOf": [ { "$ref": "#" }, { "$ref": "#\/definitions\/schemaArray" } ], "default": {} }, "maxItems": { "$ref": "#\/definitions\/positiveInteger" }, "maxLength": { "$ref": "#\/definitions\/positiveInteger" }, "maxProperties": { "$ref": "#\/definitions\/positiveInteger" }, "maximum": { "type": "number" }, "minItems": { "$ref": "#\/definitions\/positiveIntegerDefault0" }, "minLength": { "$ref": "#\/definitions\/positiveIntegerDefault0" }, "minProperties": { "$ref": "#\/definitions\/positiveIntegerDefault0" }, "minimum": { "type": "number" }, "multipleOf": { "exclusiveMinimum": true, "minimum": 0, "type": "number" }, "not": { "$ref": "#" }, "oneOf": { "$ref": "#\/definitions\/schemaArray" }, "pattern": { "type": "string" }, "patternProperties": { "additionalProperties": { "$ref": "#" }, "default": {}, "type": "object" }, "properties": { "additionalProperties": { "$ref": "#" }, "default": {}, "type": "object" }, "required": { "$ref": "#\/definitions\/stringArray" }, "title": { "type": "string" }, "type": { "anyOf": [ { "$ref": "#\/definitions\/simpleTypes" }, { "items": { "$ref": "#\/definitions\/simpleTypes" }, "minItems": 1, "type": "array", "uniqueItems": true } ] }, "uniqueItems": { "default": false, "type": "boolean" } }, "type": "object" } ola-0.10.5.nojsmin/common/web/SectionsTest.cpp0000644000175000017500000001445313023355232020665 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SectionsTest.cpp * Unittest for JsonSections classses. * Copyright (C) 2010 Simon Newton */ #include #include #include "ola/web/Json.h" #include "ola/web/JsonWriter.h" #include "ola/web/JsonSections.h" #include "ola/testing/TestUtils.h" using std::string; using std::vector; using ola::web::BoolItem; using ola::web::GenericItem; using ola::web::HiddenItem; using ola::web::JsonObject; using ola::web::JsonSection; using ola::web::JsonWriter; using ola::web::SelectItem; using ola::web::StringItem; using ola::web::UIntItem; class JsonSectionsTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(JsonSectionsTest); CPPUNIT_TEST(testStringItem); CPPUNIT_TEST(testUIntItem); CPPUNIT_TEST(testSelectItem); CPPUNIT_TEST(testBoolItem); CPPUNIT_TEST(testHiddenItem); CPPUNIT_TEST(testSection); CPPUNIT_TEST_SUITE_END(); public: void testStringItem(); void testUIntItem(); void testSelectItem(); void testBoolItem(); void testHiddenItem(); void testSection(); private: string ConvertToString(const GenericItem &item); }; CPPUNIT_TEST_SUITE_REGISTRATION(JsonSectionsTest); string JsonSectionsTest::ConvertToString(const GenericItem &item) { JsonObject object; item.PopulateItem(&object); return JsonWriter::AsString(object); } /* * Test the string item */ void JsonSectionsTest::testStringItem() { StringItem item("Foo", "bar"); string expected = "{\n" " \"description\": \"Foo\",\n" " \"type\": \"string\",\n" " \"value\": \"bar\"\n" "}"; OLA_ASSERT_EQ(expected, ConvertToString(item)); StringItem item2("Foo", "bar", "baz"); item2.SetButtonText("Action"); string expected2 = "{\n" " \"button\": \"Action\",\n" " \"description\": \"Foo\",\n" " \"id\": \"baz\",\n" " \"type\": \"string\",\n" " \"value\": \"bar\"\n" "}"; OLA_ASSERT_EQ(expected2, ConvertToString(item2)); StringItem item3("Foo\" bar", "baz\\"); item3.SetButtonText("Action\n"); string expected3 = "{\n" " \"button\": \"Action\\\\x0a\",\n" " \"description\": \"Foo\\\" bar\",\n" " \"type\": \"string\",\n" " \"value\": \"baz\\\\\"\n" "}"; OLA_ASSERT_EQ(expected3, ConvertToString(item3)); } /* * Test the uint item */ void JsonSectionsTest::testUIntItem() { UIntItem item("Foo", 10); string expected = "{\n" " \"description\": \"Foo\",\n" " \"type\": \"uint\",\n" " \"value\": 10\n" "}"; OLA_ASSERT_EQ(expected, ConvertToString(item)); UIntItem item2("Foo", 20, "baz"); item2.SetButtonText("Action"); item2.SetMin(10); string expected2 = "{\n" " \"button\": \"Action\",\n" " \"description\": \"Foo\",\n" " \"id\": \"baz\",\n" " \"min\": 10,\n" " \"type\": \"uint\",\n" " \"value\": 20\n" "}"; OLA_ASSERT_EQ(expected2, ConvertToString(item2)); UIntItem item3("Foo", 20); item3.SetMax(30); string expected3 = "{\n" " \"description\": \"Foo\",\n" " \"max\": 30,\n" " \"type\": \"uint\",\n" " \"value\": 20\n" "}"; OLA_ASSERT_EQ(expected3, ConvertToString(item3)); UIntItem item4("Foo", 20); item4.SetMin(10); item4.SetMax(30); string expected4 = "{\n" " \"description\": \"Foo\",\n" " \"max\": 30,\n" " \"min\": 10,\n" " \"type\": \"uint\",\n" " \"value\": 20\n" "}"; OLA_ASSERT_EQ(expected4, ConvertToString(item4)); } /* * Test the select item */ void JsonSectionsTest::testSelectItem() { SelectItem item("Language", "lang"); item.AddItem("English", "EN"); item.AddItem("German", 2); item.SetSelectedOffset(1); string expected = "{\n" " \"description\": \"Language\",\n" " \"id\": \"lang\",\n" " \"selected_offset\": 1,\n" " \"type\": \"select\",\n" " \"value\": [\n" " {\n" " \"label\": \"English\",\n" " \"value\": \"EN\"\n" " },\n" " {\n" " \"label\": \"German\",\n" " \"value\": \"2\"\n" " }\n" " ]\n" "}"; OLA_ASSERT_EQ(expected, ConvertToString(item)); } /* * Test the bool item */ void JsonSectionsTest::testBoolItem() { BoolItem item("Foo", true, "baz"); string expected = "{\n" " \"description\": \"Foo\",\n" " \"id\": \"baz\",\n" " \"type\": \"bool\",\n" " \"value\": true\n" "}"; OLA_ASSERT_EQ(expected, ConvertToString(item)); BoolItem item2("Foo", false, "baz"); string expected2 = "{\n" " \"description\": \"Foo\",\n" " \"id\": \"baz\",\n" " \"type\": \"bool\",\n" " \"value\": false\n" "}"; OLA_ASSERT_EQ(expected2, ConvertToString(item2)); } /* * Test the hidden item */ void JsonSectionsTest::testHiddenItem() { HiddenItem item("bar", "baz"); item.SetButtonText("Action"); string expected = "{\n" " \"button\": \"Action\",\n" " \"description\": \"\",\n" " \"id\": \"baz\",\n" " \"type\": \"hidden\",\n" " \"value\": \"bar\"\n" "}"; OLA_ASSERT_EQ(expected, ConvertToString(item)); } /* * Test the entire section */ void JsonSectionsTest::testSection() { JsonSection section(false); HiddenItem *item = new HiddenItem("bar\r", "baz"); section.AddItem(item); section.SetSaveButton("Action\\"); string expected = "{\n" " \"error\": \"\",\n" " \"items\": [\n" " {\n" " \"description\": \"\",\n" " \"id\": \"baz\",\n" " \"type\": \"hidden\",\n" " \"value\": \"bar\\\\x0d\"\n" " }\n" " ],\n" " \"refresh\": false,\n" " \"save_button\": \"Action\\\\\"\n" "}"; OLA_ASSERT_EQ(expected, section.AsString()); } ola-0.10.5.nojsmin/common/web/PatchParserTest.cpp0000644000175000017500000003564213023355232021315 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * PatchParserTest.cpp * Unittest for the JSON Patch Parser. * Copyright (C) 2014 Simon Newton */ #include #include "ola/testing/TestUtils.h" #include "ola/web/Json.h" #include "ola/web/JsonData.h" #include "ola/web/JsonParser.h" #include "ola/web/JsonPatch.h" #include "ola/web/JsonPatchParser.h" #include "ola/web/JsonPointer.h" #include "ola/web/JsonWriter.h" #include "ola/Logging.h" using ola::web::JsonArray; using ola::web::JsonObject; using ola::web::JsonParser; using ola::web::JsonPatchAddOp; using ola::web::JsonPatchCopyOp; using ola::web::JsonPatchMoveOp; using ola::web::JsonPatchParser; using ola::web::JsonPatchRemoveOp; using ola::web::JsonPatchReplaceOp; using ola::web::JsonPatchSet; using ola::web::JsonPatchTestOp; using ola::web::JsonData; using ola::web::JsonValue; using ola::web::JsonWriter; using std::auto_ptr; using std::string; class JsonPatchParserTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(JsonPatchParserTest); CPPUNIT_TEST(testInvalid); CPPUNIT_TEST(testAdd); CPPUNIT_TEST(testRemove); CPPUNIT_TEST(testReplace); CPPUNIT_TEST(testMove); CPPUNIT_TEST(testCopy); CPPUNIT_TEST(testTest); CPPUNIT_TEST_SUITE_END(); public: void testInvalid(); void testAdd(); void testRemove(); void testReplace(); void testMove(); void testCopy(); void testTest(); private: void CheckValuesMatch(const std::string &input, const JsonValue *actual); void BuildSampleText(JsonData *text); void CheckInvalid(const string &input); void CheckValid(const string &input, JsonPatchSet *patch_set); }; void JsonPatchParserTest::CheckValuesMatch(const std::string &input, const JsonValue *actual) { string error; auto_ptr expected_value(JsonParser::Parse(input, &error)); if (expected_value.get()) { if (*actual != *expected_value.get()) { OLA_ASSERT_EQ(JsonWriter::AsString(*(expected_value.get())), JsonWriter::AsString(*actual)); } } else { OLA_ASSERT_EQ(expected_value.get(), actual); } } void JsonPatchParserTest::BuildSampleText(JsonData *text) { auto_ptr object(new JsonObject()); object->Add("foo", "bar"); object->Add("baz", false); JsonObject *child_object = new JsonObject(); child_object->Add("bat", 1); object->AddValue("object", child_object); JsonArray *child_array = new JsonArray(); child_array->Append(1); child_array->Append(2); child_array->Append(3); object->AddValue("array", child_array); text->SetValue(object.release()); } void JsonPatchParserTest::CheckInvalid(const string &input) { JsonPatchSet patch_set; string error; OLA_ASSERT_FALSE(JsonPatchParser::Parse(input, &patch_set, &error)); OLA_ASSERT_TRUE(patch_set.Empty()); OLA_ASSERT_NE(string(""), error); } void JsonPatchParserTest::CheckValid(const string &input, JsonPatchSet *patch_set) { string error; OLA_ASSERT_TRUE(JsonPatchParser::Parse(input, patch_set, &error)); OLA_ASSERT_FALSE(patch_set->Empty()); OLA_ASSERT_EQ(string(""), error); } CPPUNIT_TEST_SUITE_REGISTRATION(JsonPatchParserTest); void JsonPatchParserTest::testInvalid() { CheckInvalid(""); CheckInvalid("{}"); CheckInvalid("null"); CheckInvalid("1"); CheckInvalid("\"foo\""); CheckInvalid("true"); CheckInvalid("[null]"); CheckInvalid("[1]"); CheckInvalid("[1.2]"); CheckInvalid("[\"foo\"]"); CheckInvalid("[[]]"); CheckInvalid("[{}]"); CheckInvalid("[{\"op\": \"\"}]"); CheckInvalid("[{\"op\": \"foo\"}]"); } void JsonPatchParserTest::testAdd() { CheckInvalid("[{\"op\": \"add\"}]"); // Invalid and missing paths CheckInvalid("[{\"op\": \"add\", \"path\": null, \"value\": {}}]"); CheckInvalid("[{\"op\": \"add\", \"path\": true, \"value\": {}}]"); CheckInvalid("[{\"op\": \"add\", \"path\": 1, \"value\": {}}]"); CheckInvalid("[{\"op\": \"add\", \"path\": 1.2, \"value\": {}}]"); CheckInvalid("[{\"op\": \"add\", \"path\": {}, \"value\": {}}]"); CheckInvalid("[{\"op\": \"add\", \"path\": [], \"value\": {}}]"); CheckInvalid("[{\"op\": \"add\", \"value\": {}}]"); // Missing value CheckInvalid("[{\"op\": \"add\", \"path\": \"/foo\"}]"); // Valid patches { JsonPatchSet patch_set; CheckValid( "[{\"op\": \"add\", \"path\": \"/foo\", \"value\": {}}]", &patch_set); JsonData text(new JsonObject()); OLA_ASSERT_TRUE(text.Apply(patch_set)); CheckValuesMatch( "{\"foo\": {}}", text.Value()); } // Complex nested value { JsonPatchSet patch_set; CheckValid( "[{\"op\": \"add\", \"path\": \"/foo\", " "\"value\": [{\"foo\": [[]]}] }]", &patch_set); JsonData text(new JsonObject()); OLA_ASSERT_TRUE(text.Apply(patch_set)); CheckValuesMatch( "{\"foo\": [{\"foo\": [[]]}] }", text.Value()); } } void JsonPatchParserTest::testRemove() { CheckInvalid("[{\"op\": \"remove\"}]"); // Invalid and missing paths CheckInvalid("[{\"op\": \"remove\", \"path\": null}]"); CheckInvalid("[{\"op\": \"remove\", \"path\": true}]"); CheckInvalid("[{\"op\": \"remove\", \"path\": 1}]"); CheckInvalid("[{\"op\": \"remove\", \"path\": 1.2}]"); CheckInvalid("[{\"op\": \"remove\", \"path\": {}}]"); CheckInvalid("[{\"op\": \"remove\", \"path\": []}]"); CheckInvalid("[{\"op\": \"remove\"}]"); JsonData text(NULL); BuildSampleText(&text); // Valid patches { JsonPatchSet patch_set; CheckValid( "[{\"op\": \"remove\", \"path\": \"/foo\"}]", &patch_set); OLA_ASSERT_TRUE(text.Apply(patch_set)); CheckValuesMatch( "{\"baz\": false, " " \"object\": {\"bat\": 1}, \"array\": [1,2,3] }", text.Value()); } { JsonPatchSet patch_set; CheckValid( "[{\"op\": \"remove\", \"path\": \"/object\"}," " {\"op\": \"remove\", \"path\": \"/array\"}]", &patch_set); OLA_ASSERT_TRUE(text.Apply(patch_set)); CheckValuesMatch("{\"baz\": false }", text.Value()); } } void JsonPatchParserTest::testReplace() { CheckInvalid("[{\"op\": \"replace\"}]"); // Invalid and missing paths CheckInvalid("[{\"op\": \"replace\", \"path\": null, \"value\": {}}]"); CheckInvalid("[{\"op\": \"replace\", \"path\": true, \"value\": {}}]"); CheckInvalid("[{\"op\": \"replace\", \"path\": 1, \"value\": {}}]"); CheckInvalid("[{\"op\": \"replace\", \"path\": 1.2, \"value\": {}}]"); CheckInvalid("[{\"op\": \"replace\", \"path\": {}, \"value\": {}}]"); CheckInvalid("[{\"op\": \"replace\", \"path\": [], \"value\": {}}]"); CheckInvalid("[{\"op\": \"replace\", \"value\": {}}]"); // Missing value CheckInvalid("[{\"op\": \"replace\", \"path\": \"/foo\"}]"); JsonData text(NULL); BuildSampleText(&text); { JsonPatchSet patch_set; CheckValid( "[{\"op\": \"replace\", \"path\": \"/foo\", \"value\": 42}]", &patch_set); OLA_ASSERT_TRUE(text.Apply(patch_set)); CheckValuesMatch( "{\"foo\": 42, \"baz\": false, " " \"object\": {\"bat\": 1}, \"array\": [1,2,3] }", text.Value()); } { JsonPatchSet patch_set; CheckValid( "[{\"op\": \"replace\", \"path\": \"/foo\", \"value\": true}]", &patch_set); OLA_ASSERT_TRUE(text.Apply(patch_set)); CheckValuesMatch( "{\"foo\": true, \"baz\": false, " " \"object\": {\"bat\": 1}, \"array\": [1,2,3] }", text.Value()); } { JsonPatchSet patch_set; CheckValid( "[{\"op\": \"replace\", \"path\": \"/foo\", \"value\": \"bar\"}]", &patch_set); OLA_ASSERT_TRUE(text.Apply(patch_set)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": false, " " \"object\": {\"bat\": 1}, \"array\": [1,2,3] }", text.Value()); } { JsonPatchSet patch_set; CheckValid( "[{\"op\": \"replace\", \"path\": \"/foo\", \"value\": []}]", &patch_set); OLA_ASSERT_TRUE(text.Apply(patch_set)); CheckValuesMatch( "{\"foo\": [], \"baz\": false, " " \"object\": {\"bat\": 1}, \"array\": [1,2,3] }", text.Value()); } { JsonPatchSet patch_set; CheckValid( "[{\"op\": \"replace\", \"path\": \"/foo\", \"value\": {}}]", &patch_set); OLA_ASSERT_TRUE(text.Apply(patch_set)); CheckValuesMatch( "{\"foo\": {}, \"baz\": false, " " \"object\": {\"bat\": 1}, \"array\": [1,2,3] }", text.Value()); } } void JsonPatchParserTest::testMove() { CheckInvalid("[{\"op\": \"move\"}]"); // Invalid and missing paths CheckInvalid("[{\"op\": \"move\", \"path\": null, \"from\": \"/foo\"}]"); CheckInvalid("[{\"op\": \"move\", \"path\": true, \"from\": \"/foo\"}]"); CheckInvalid("[{\"op\": \"move\", \"path\": 1, \"from\": \"/foo\"}]"); CheckInvalid("[{\"op\": \"move\", \"path\": {}, \"from\": \"/foo\"}]"); CheckInvalid("[{\"op\": \"move\", \"path\": [], \"from\": \"/foo\"}]"); CheckInvalid("[{\"op\": \"move\", \"from\": {}}]"); // Missing or invalid from CheckInvalid("[{\"op\": \"move\", \"path\": \"/foo\"}]"); CheckInvalid("[{\"op\": \"move\", \"path\": \"/foo\", \"from\": null}]"); CheckInvalid("[{\"op\": \"move\", \"path\": \"/foo\", \"from\": true}]"); CheckInvalid("[{\"op\": \"move\", \"path\": \"/foo\", \"from\": 1}]"); CheckInvalid("[{\"op\": \"move\", \"path\": \"/foo\", \"from\": []}]"); CheckInvalid("[{\"op\": \"move\", \"path\": \"/foo\", \"from\": {}}]"); JsonData text(NULL); BuildSampleText(&text); { JsonPatchSet patch_set; CheckValid( "[{\"op\": \"move\", \"path\": \"/foo\", \"from\": \"/baz\"}]", &patch_set); OLA_ASSERT_TRUE(text.Apply(patch_set)); CheckValuesMatch( "{\"foo\": false, " " \"object\": {\"bat\": 1}, \"array\": [1,2,3] }", text.Value()); } { JsonPatchSet patch_set; CheckValid( "[{\"op\": \"move\", \"path\": \"/foo\", \"from\": \"/array/1\"}]", &patch_set); OLA_ASSERT_TRUE(text.Apply(patch_set)); CheckValuesMatch( "{\"foo\": 2, " " \"object\": {\"bat\": 1}, \"array\": [1,3] }", text.Value()); } { JsonPatchSet patch_set; CheckValid( "[{\"op\": \"move\", \"path\": \"/foo\", \"from\": \"/object/bat\"}]", &patch_set); OLA_ASSERT_TRUE(text.Apply(patch_set)); CheckValuesMatch( "{\"foo\": 1, " " \"object\": {}, \"array\": [1,3] }", text.Value()); } } void JsonPatchParserTest::testCopy() { CheckInvalid("[{\"op\": \"copy\"}]"); // Invalid and missing paths CheckInvalid("[{\"op\": \"copy\", \"path\": null, \"from\": \"/foo\"}]"); CheckInvalid("[{\"op\": \"copy\", \"path\": true, \"from\": \"/foo\"}]"); CheckInvalid("[{\"op\": \"copy\", \"path\": 1, \"from\": \"/foo\"}]"); CheckInvalid("[{\"op\": \"copy\", \"path\": {}, \"from\": \"/foo\"}]"); CheckInvalid("[{\"op\": \"copy\", \"path\": [], \"from\": \"/foo\"}]"); CheckInvalid("[{\"op\": \"copy\", \"from\": {}}]"); // Missing or invalid from CheckInvalid("[{\"op\": \"copy\", \"path\": \"/foo\"}]"); CheckInvalid("[{\"op\": \"copy\", \"path\": \"/foo\", \"from\": null}]"); CheckInvalid("[{\"op\": \"copy\", \"path\": \"/foo\", \"from\": true}]"); CheckInvalid("[{\"op\": \"copy\", \"path\": \"/foo\", \"from\": 1}]"); CheckInvalid("[{\"op\": \"copy\", \"path\": \"/foo\", \"from\": []}]"); CheckInvalid("[{\"op\": \"copy\", \"path\": \"/foo\", \"from\": {}}]"); JsonData text(NULL); BuildSampleText(&text); { JsonPatchSet patch_set; CheckValid( "[{\"op\": \"copy\", \"path\": \"/foo\", \"from\": \"/baz\"}]", &patch_set); OLA_ASSERT_TRUE(text.Apply(patch_set)); CheckValuesMatch( "{\"foo\": false, \"baz\": false," " \"object\": {\"bat\": 1}, \"array\": [1,2,3] }", text.Value()); } { JsonPatchSet patch_set; CheckValid( "[{\"op\": \"copy\", \"path\": \"/foo\", \"from\": \"/array/1\"}]", &patch_set); OLA_ASSERT_TRUE(text.Apply(patch_set)); CheckValuesMatch( "{\"foo\": 2, \"baz\": false," " \"object\": {\"bat\": 1}, \"array\": [1,2,3] }", text.Value()); } { JsonPatchSet patch_set; CheckValid( "[{\"op\": \"copy\", \"path\": \"/foo\", \"from\": \"/object/bat\"}]", &patch_set); OLA_ASSERT_TRUE(text.Apply(patch_set)); CheckValuesMatch( "{\"foo\": 1, \"baz\": false," " \"object\": {\"bat\": 1}, \"array\": [1,2,3] }", text.Value()); } } void JsonPatchParserTest::testTest() { CheckInvalid("[{\"op\": \"test\"}]"); // Invalid and missing paths CheckInvalid("[{\"op\": \"test\", \"path\": null, \"value\": {}}]"); CheckInvalid("[{\"op\": \"test\", \"path\": true, \"value\": {}}]"); CheckInvalid("[{\"op\": \"test\", \"path\": 1, \"value\": {}}]"); CheckInvalid("[{\"op\": \"test\", \"path\": 1.2, \"value\": {}}]"); CheckInvalid("[{\"op\": \"test\", \"path\": {}, \"value\": {}}]"); CheckInvalid("[{\"op\": \"test\", \"path\": [], \"value\": {}}]"); CheckInvalid("[{\"op\": \"test\", \"value\": {}}]"); // Missing value CheckInvalid("[{\"op\": \"test\", \"path\": \"/foo\"}]"); JsonData text(NULL); BuildSampleText(&text); { JsonPatchSet patch_set; CheckValid( "[{\"op\": \"test\", \"path\": \"/foo\", \"value\": \"bar\"}]", &patch_set); OLA_ASSERT_TRUE(text.Apply(patch_set)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": false, " " \"object\": {\"bat\": 1}, \"array\": [1,2,3] }", text.Value()); } { JsonPatchSet patch_set; CheckValid( "[{\"op\": \"test\", \"path\": \"/array\", \"value\": [1,2,3]}]", &patch_set); OLA_ASSERT_TRUE(text.Apply(patch_set)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": false, " " \"object\": {\"bat\": 1}, \"array\": [1,2,3] }", text.Value()); } { JsonPatchSet patch_set; CheckValid( "[{\"op\": \"test\", \"path\": \"/object/bat\", \"value\": 1}]", &patch_set); OLA_ASSERT_TRUE(text.Apply(patch_set)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": false, " " \"object\": {\"bat\": 1}, \"array\": [1,2,3] }", text.Value()); } { JsonPatchSet patch_set; CheckValid( "[{\"op\": \"test\", \"path\": \"/baz\", \"value\": false}]", &patch_set); OLA_ASSERT_TRUE(text.Apply(patch_set)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": false, " " \"object\": {\"bat\": 1}, \"array\": [1,2,3] }", text.Value()); } } ola-0.10.5.nojsmin/common/web/SchemaParseContext.cpp0000644000175000017500000007766713023355232022016 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SchemaParseContext.cpp * Stores the state required as we walk the JSON schema document. * Copyright (C) 2014 Simon Newton */ #include "common/web/SchemaParseContext.h" #include #include #include #include #include #include #include #include "ola/Logging.h" #include "ola/StringUtils.h" #include "ola/stl/STLUtils.h" #include "ola/web/Json.h" #include "ola/web/JsonTypes.h" namespace ola { namespace web { namespace { /* * A cool hack to determine if a type is positive. * We do this to avoid: * comparison of unsigned expression >= 0 is always true * warnings. See http://gcc.gnu.org/ml/gcc-help/2010-08/msg00286.html */ template struct positive { bool operator()(const T &x) { return x >= 0; } }; template struct positive{ bool operator()(const T &) { return true; } }; } // namespace using std::auto_ptr; using std::pair; using std::set; using std::string; using std::vector; // DefinitionsParseContext // Used for parsing an object with key : json schema pairs, within 'definitions' SchemaParseContextInterface* DefinitionsParseContext::OpenObject( OLA_UNUSED SchemaErrorLogger *logger) { m_current_schema.reset(new SchemaParseContext(m_schema_defs)); return m_current_schema.get(); } void DefinitionsParseContext::CloseObject(SchemaErrorLogger *logger) { string key = TakeKeyword(); ValidatorInterface *schema = m_current_schema->GetValidator(logger); m_schema_defs->Add(key, schema); m_current_schema.reset(); } // StrictTypedParseContext // Used as a parent class for many of the other contexts. void StrictTypedParseContext::String(SchemaErrorLogger *logger, const string &value) { ReportErrorForType(logger, TypeFromValue(value)); } void StrictTypedParseContext::Number(SchemaErrorLogger *logger, uint32_t value) { ReportErrorForType(logger, TypeFromValue(value)); } void StrictTypedParseContext::Number(SchemaErrorLogger *logger, int32_t value) { ReportErrorForType(logger, TypeFromValue(value)); } void StrictTypedParseContext::Number(SchemaErrorLogger *logger, uint64_t value) { ReportErrorForType(logger, TypeFromValue(value)); } void StrictTypedParseContext::Number(SchemaErrorLogger *logger, int64_t value) { ReportErrorForType(logger, TypeFromValue(value)); } void StrictTypedParseContext::Number(SchemaErrorLogger *logger, double value) { ReportErrorForType(logger, TypeFromValue(value)); } void StrictTypedParseContext::Bool(SchemaErrorLogger *logger, bool value) { ReportErrorForType(logger, TypeFromValue(value)); } void StrictTypedParseContext::Null(SchemaErrorLogger *logger) { ReportErrorForType(logger, JSON_NULL); } SchemaParseContextInterface* StrictTypedParseContext::OpenArray( SchemaErrorLogger *logger) { ReportErrorForType(logger, JSON_ARRAY); return NULL; } void StrictTypedParseContext::CloseArray( OLA_UNUSED SchemaErrorLogger *logger) { } SchemaParseContextInterface* StrictTypedParseContext::OpenObject( SchemaErrorLogger *logger) { ReportErrorForType(logger, JSON_ARRAY); return NULL; } void StrictTypedParseContext::CloseObject( OLA_UNUSED SchemaErrorLogger *logger) { } void StrictTypedParseContext::ReportErrorForType( SchemaErrorLogger *logger, JsonType type) { logger->Error() << "Invalid type '" << JsonTypeToString(type) << "' in 'required', elements must be strings"; } // SchemaParseContext // Used for parsing an object that describes a JSON schema. ValidatorInterface* SchemaParseContext::GetValidator( SchemaErrorLogger *logger) { if (m_ref_schema.IsSet()) { return new ReferenceValidator(m_schema_defs, m_ref_schema.Value()); } BaseValidator *validator = NULL; auto_ptr int_validator; switch (m_type) { case JSON_UNDEFINED: break; case JSON_ARRAY: validator = BuildArrayValidator(logger); break; case JSON_BOOLEAN: validator = new BoolValidator(); break; case JSON_INTEGER: int_validator.reset(new IntegerValidator()); break; case JSON_NULL: validator = new NullValidator(); break; case JSON_NUMBER: int_validator.reset(new NumberValidator()); break; case JSON_OBJECT: validator = BuildObjectValidator(logger); break; case JSON_STRING: validator = BuildStringValidator(logger); break; default: {} } if (int_validator.get()) { if (!AddNumberConstraints(int_validator.get(), logger)) { return NULL; } validator = int_validator.release(); } if (!validator && m_allof_context.get()) { ValidatorInterface::ValidatorList all_of_validators; m_allof_context->GetValidators(logger, &all_of_validators); if (all_of_validators.empty()) { logger->Error() << "allOf must contain at least one schema"; return NULL; } validator = new AllOfValidator(&all_of_validators); } if (!validator && m_anyof_context.get()) { ValidatorInterface::ValidatorList any_of_validators; m_anyof_context->GetValidators(logger, &any_of_validators); if (any_of_validators.empty()) { logger->Error() << "anyOf must contain at least one schema"; return NULL; } validator = new AnyOfValidator(&any_of_validators); } if (!validator && m_oneof_context.get()) { ValidatorInterface::ValidatorList one_of_validators; m_oneof_context->GetValidators(logger, &one_of_validators); if (one_of_validators.empty()) { logger->Error() << "oneOf must contain at least one schema"; return NULL; } validator = new OneOfValidator(&one_of_validators); } if (!validator && m_not_context.get()) { validator = new NotValidator(m_not_context->GetValidator(logger)); } if (validator == NULL) { if (m_type == JSON_UNDEFINED) { validator = new WildcardValidator(); } else { logger->Error() << "Unknown type: " << JsonTypeToString(m_type); return NULL; } } if (m_schema.IsSet()) { validator->SetSchema(m_schema.Value()); m_schema.Reset(); } if (m_id.IsSet()) { validator->SetId(m_id.Value()); m_id.Reset(); } if (m_title.IsSet()) { validator->SetTitle(m_title.Value()); m_title.Reset(); } if (m_description.IsSet()) { validator->SetDescription(m_description.Value()); m_description.Reset(); } if (m_default_value.get()) { validator->SetDefaultValue(m_default_value.release()); } if (m_enum_context.get()) { m_enum_context->AddEnumsToValidator(validator); } return validator; } void SchemaParseContext::ObjectKey(OLA_UNUSED SchemaErrorLogger *logger, const string &keyword) { m_keyword = LookupKeyword(keyword); } void SchemaParseContext::String(SchemaErrorLogger *logger, const string &value) { if (!ValidTypeForKeyword(logger, m_keyword, TypeFromValue(value))) { return; } switch (m_keyword) { case SCHEMA_REF: m_ref_schema.Set(value); break; case SCHEMA_SCHEMA: m_schema.Set(value); break; case SCHEMA_DESCRIPTION: m_description.Set(value); break; case SCHEMA_DEFAULT: m_default_value.reset(new JsonString(value)); break; case SCHEMA_FORMAT: m_format.Set(value); break; case SCHEMA_ID: m_id.Set(value); break; case SCHEMA_TITLE: m_title.Set(value); break; case SCHEMA_TYPE: m_type = StringToJsonType(value); if (m_type == JSON_UNDEFINED) { logger->Error() << "Invalid type: " << value; } break; default: // Nothing, we ignore keywords we don't support. {} } } void SchemaParseContext::Number(SchemaErrorLogger *logger, uint32_t value) { ProcessInt(logger, value); } void SchemaParseContext::Number(SchemaErrorLogger *logger, int32_t value) { ProcessInt(logger, value); } void SchemaParseContext::Number(SchemaErrorLogger *logger, uint64_t value) { ProcessInt(logger, value); } void SchemaParseContext::Number(SchemaErrorLogger *logger, int64_t value) { ProcessInt(logger, value); } void SchemaParseContext::Number(SchemaErrorLogger *logger, double value) { ValidTypeForKeyword(logger, m_keyword, TypeFromValue(value)); switch (m_keyword) { case SCHEMA_DEFAULT: m_default_value.reset(new JsonDouble(value)); break; case SCHEMA_MAXIMUM: m_maximum.reset(JsonValue::NewNumberValue(value)); break; case SCHEMA_MINIMUM: m_minimum.reset(JsonValue::NewNumberValue(value)); break; case SCHEMA_MULTIPLEOF: if (value <= 0) { logger->Error() << KeywordToString(m_keyword) << " can't be negative"; } else { m_multiple_of.reset(JsonValue::NewNumberValue(value)); } return; default: {} } } void SchemaParseContext::Bool(SchemaErrorLogger *logger, bool value) { if (!ValidTypeForKeyword(logger, m_keyword, TypeFromValue(value))) { OLA_INFO << "type was not valid"; return; } switch (m_keyword) { case SCHEMA_DEFAULT: m_default_value.reset(new JsonBool(value)); break; case SCHEMA_EXCLUSIVE_MAXIMUM: m_exclusive_maximum.Set(value); break; case SCHEMA_EXCLUSIVE_MINIMUM: m_exclusive_minimum.Set(value); break; case SCHEMA_UNIQUE_ITEMS: m_unique_items.Set(value); break; case SCHEMA_ADDITIONAL_ITEMS: m_additional_items.Set(value); break; case SCHEMA_ADDITIONAL_PROPERTIES: m_additional_properties.Set(value); default: {} } } void SchemaParseContext::Null(SchemaErrorLogger *logger) { ValidTypeForKeyword(logger, m_keyword, JSON_NULL); switch (m_keyword) { case SCHEMA_DEFAULT: m_default_value.reset(new JsonNull()); break; default: {} } } SchemaParseContextInterface* SchemaParseContext::OpenArray( SchemaErrorLogger *logger) { if (!ValidTypeForKeyword(logger, m_keyword, JSON_ARRAY)) { return NULL; } switch (m_keyword) { case SCHEMA_DEFAULT: m_default_value_context.reset(new JsonValueContext()); m_default_value_context->OpenArray(logger); return m_default_value_context.get(); case SCHEMA_ITEMS: m_items_context_array.reset(new ArrayOfSchemaContext(m_schema_defs)); return m_items_context_array.get(); case SCHEMA_REQUIRED: m_required_items.reset(new ArrayOfStringsContext()); return m_required_items.get(); case SCHEMA_ENUM: m_enum_context.reset(new ArrayOfJsonValuesContext()); return m_enum_context.get(); case SCHEMA_ALL_OF: m_allof_context.reset(new ArrayOfSchemaContext(m_schema_defs)); return m_allof_context.get(); case SCHEMA_ANY_OF: m_anyof_context.reset(new ArrayOfSchemaContext(m_schema_defs)); return m_anyof_context.get(); case SCHEMA_ONE_OF: m_oneof_context.reset(new ArrayOfSchemaContext(m_schema_defs)); return m_oneof_context.get(); default: {} } return NULL; } void SchemaParseContext::CloseArray(SchemaErrorLogger *logger) { if (m_default_value_context.get()) { m_default_value_context->CloseArray(logger); m_default_value.reset(m_default_value_context->ClaimValue(logger)); m_default_value_context.reset(); } if (m_keyword == SCHEMA_ENUM) { if (m_enum_context->Empty()) { logger->Error() << "enum must contain at least one value"; } } } SchemaParseContextInterface* SchemaParseContext::OpenObject( SchemaErrorLogger *logger) { if (!ValidTypeForKeyword(logger, m_keyword, JSON_OBJECT)) { return NULL; } switch (m_keyword) { case SCHEMA_DEFAULT: m_default_value_context.reset(new JsonValueContext()); m_default_value_context->OpenObject(logger); return m_default_value_context.get(); case SCHEMA_DEFINITIONS: m_definitions_context.reset(new DefinitionsParseContext(m_schema_defs)); return m_definitions_context.get(); case SCHEMA_PROPERTIES: m_properties_context.reset(new PropertiesParseContext(m_schema_defs)); return m_properties_context.get(); case SCHEMA_ADDITIONAL_PROPERTIES: m_additional_properties_context.reset( new SchemaParseContext(m_schema_defs)); return m_additional_properties_context.get(); case SCHEMA_ITEMS: m_items_single_context.reset(new SchemaParseContext(m_schema_defs)); return m_items_single_context.get(); case SCHEMA_ADDITIONAL_ITEMS: m_additional_items_context.reset(new SchemaParseContext(m_schema_defs)); return m_additional_items_context.get(); case SCHEMA_DEPENDENCIES: m_dependency_context.reset(new DependencyParseContext(m_schema_defs)); return m_dependency_context.get(); case SCHEMA_NOT: m_not_context.reset(new SchemaParseContext(m_schema_defs)); return m_not_context.get(); default: {} } return NULL; } void SchemaParseContext::CloseObject(SchemaErrorLogger *logger) { if (m_default_value_context.get()) { m_default_value_context->CloseObject(logger); m_default_value.reset(m_default_value_context->ClaimValue(logger)); m_default_value_context.reset(); } } void SchemaParseContext::ProcessPositiveInt( OLA_UNUSED SchemaErrorLogger *logger, uint64_t value) { switch (m_keyword) { case SCHEMA_MULTIPLEOF: m_multiple_of.reset(JsonValue::NewNumberValue(value)); return; case SCHEMA_MIN_ITEMS: m_min_items.Set(value); break; case SCHEMA_MAX_ITEMS: m_max_items.Set(value); break; case SCHEMA_MAX_LENGTH: m_max_length.Set(value); break; case SCHEMA_MIN_LENGTH: m_min_length.Set(value); break; case SCHEMA_MAX_PROPERTIES: m_max_properties.Set(value); break; case SCHEMA_MIN_PROPERTIES: m_min_properties.Set(value); break; default: {} } } template void SchemaParseContext::ProcessInt(SchemaErrorLogger *logger, T value) { if (!ValidTypeForKeyword(logger, m_keyword, TypeFromValue(value))) { return; } switch (m_keyword) { case SCHEMA_DEFAULT: m_default_value.reset(JsonValue::NewValue(value)); return; case SCHEMA_MAXIMUM: m_maximum.reset(JsonValue::NewNumberValue(value)); return; case SCHEMA_MINIMUM: m_minimum.reset(JsonValue::NewNumberValue(value)); return; default: {} } if (positive::is_signed>()(value)) { ProcessPositiveInt(logger, static_cast(value)); return; } logger->Error() << KeywordToString(m_keyword) << " can't be negative"; } bool SchemaParseContext::AddNumberConstraints(IntegerValidator *validator, SchemaErrorLogger *logger) { if (m_exclusive_maximum.IsSet() && !m_maximum.get()) { logger->Error() << "exclusiveMaximum requires maximum to be defined"; return false; } if (m_maximum.get()) { if (m_exclusive_maximum.IsSet()) { validator->AddConstraint(new MaximumConstraint( m_maximum.release(), m_exclusive_maximum.Value())); } else { validator->AddConstraint(new MaximumConstraint(m_maximum.release())); } } if (m_exclusive_minimum.IsSet() && !m_minimum.get()) { logger->Error() << "exclusiveMinimum requires minimum to be defined"; return false; } if (m_minimum.get()) { if (m_exclusive_minimum.IsSet()) { validator->AddConstraint(new MinimumConstraint( m_minimum.release(), m_exclusive_minimum.Value())); } else { validator->AddConstraint(new MinimumConstraint(m_minimum.release())); } } if (m_multiple_of.get()) { validator->AddConstraint(new MultipleOfConstraint(m_multiple_of.release())); } return true; } BaseValidator* SchemaParseContext::BuildArrayValidator( SchemaErrorLogger *logger) { ArrayValidator::Options options; if (m_min_items.IsSet()) { options.min_items = m_min_items.Value(); } if (m_max_items.IsSet()) { options.max_items = m_max_items.Value(); } if (m_unique_items.IsSet()) { options.unique_items = m_unique_items.Value(); } auto_ptr items; auto_ptr additional_items; // items if (m_items_single_context.get() && m_items_context_array.get()) { logger->Error() << "'items' is somehow both a schema and an array!"; return NULL; } else if (m_items_single_context.get()) { // 8.2.3.1 items.reset(new ArrayValidator::Items( m_items_single_context->GetValidator(logger))); } else if (m_items_context_array.get()) { // 8.2.3.2 ValidatorInterface::ValidatorList item_validators; m_items_context_array->GetValidators(logger, &item_validators); items.reset(new ArrayValidator::Items(&item_validators)); } // additionalItems if (m_additional_items_context.get()) { additional_items.reset(new ArrayValidator::AdditionalItems( m_additional_items_context->GetValidator(logger))); } else if (m_additional_items.IsSet()) { additional_items.reset( new ArrayValidator::AdditionalItems(m_additional_items.Value())); } return new ArrayValidator(items.release(), additional_items.release(), options); } BaseValidator* SchemaParseContext::BuildObjectValidator( SchemaErrorLogger* logger) { ObjectValidator::Options options; if (m_max_properties.IsSet()) { options.max_properties = m_max_properties.Value(); } if (m_min_properties.IsSet()) { options.min_properties = m_min_properties.Value(); } if (m_required_items.get()) { set required_properties; m_required_items->GetStringSet(&required_properties); options.SetRequiredProperties(required_properties); } if (m_additional_properties.IsSet()) { options.SetAdditionalProperties(m_additional_properties.Value()); } ObjectValidator *object_validator = new ObjectValidator(options); if (m_additional_properties_context.get()) { object_validator->SetAdditionalValidator( m_additional_properties_context->GetValidator(logger)); } if (m_properties_context.get()) { m_properties_context->AddPropertyValidators(object_validator, logger); } if (m_dependency_context.get()) { m_dependency_context->AddDependenciesToValidator(object_validator); } return object_validator; } BaseValidator* SchemaParseContext::BuildStringValidator( OLA_UNUSED SchemaErrorLogger *logger) { StringValidator::Options options; if (m_max_length.IsSet()) { options.max_length = m_max_length.Value(); } if (m_min_length.IsSet()) { options.min_length = m_min_length.Value(); } return new StringValidator(options); } /* * Verify the type is valid for the given keyword. * If the type isn't valid, an error is logged. * @returns false if the type isn't valid or if the keyword is SCHEMA_UNKNOWN. */ bool SchemaParseContext::ValidTypeForKeyword(SchemaErrorLogger *logger, SchemaKeyword keyword, JsonType type) { switch (keyword) { case SCHEMA_UNKNOWN: return false; case SCHEMA_ID: return CheckTypeAndLog(logger, keyword, type, JSON_STRING); case SCHEMA_SCHEMA: return CheckTypeAndLog(logger, keyword, type, JSON_STRING); case SCHEMA_REF: return CheckTypeAndLog(logger, keyword, type, JSON_STRING); case SCHEMA_TITLE: return CheckTypeAndLog(logger, keyword, type, JSON_STRING); case SCHEMA_DESCRIPTION: return CheckTypeAndLog(logger, keyword, type, JSON_STRING); case SCHEMA_DEFAULT: return true; case SCHEMA_MULTIPLEOF: return CheckTypeAndLog(logger, keyword, type, JSON_INTEGER, JSON_NUMBER); case SCHEMA_MAXIMUM: return CheckTypeAndLog(logger, keyword, type, JSON_INTEGER, JSON_NUMBER); case SCHEMA_EXCLUSIVE_MAXIMUM: return CheckTypeAndLog(logger, keyword, type, JSON_BOOLEAN); case SCHEMA_MINIMUM: return CheckTypeAndLog(logger, keyword, type, JSON_INTEGER, JSON_NUMBER); case SCHEMA_EXCLUSIVE_MINIMUM: return CheckTypeAndLog(logger, keyword, type, JSON_BOOLEAN); case SCHEMA_MAX_LENGTH: return CheckTypeAndLog(logger, keyword, type, JSON_INTEGER); case SCHEMA_MIN_LENGTH: return CheckTypeAndLog(logger, keyword, type, JSON_INTEGER); case SCHEMA_PATTERN: return CheckTypeAndLog(logger, keyword, type, JSON_STRING); case SCHEMA_ADDITIONAL_ITEMS: return CheckTypeAndLog(logger, keyword, type, JSON_BOOLEAN, JSON_OBJECT); case SCHEMA_ITEMS: return CheckTypeAndLog(logger, keyword, type, JSON_ARRAY, JSON_OBJECT); case SCHEMA_MAX_ITEMS: return CheckTypeAndLog(logger, keyword, type, JSON_INTEGER); case SCHEMA_MIN_ITEMS: return CheckTypeAndLog(logger, keyword, type, JSON_INTEGER); case SCHEMA_UNIQUE_ITEMS: return CheckTypeAndLog(logger, keyword, type, JSON_BOOLEAN); case SCHEMA_MAX_PROPERTIES: return CheckTypeAndLog(logger, keyword, type, JSON_INTEGER); case SCHEMA_MIN_PROPERTIES: return CheckTypeAndLog(logger, keyword, type, JSON_INTEGER); case SCHEMA_REQUIRED: return CheckTypeAndLog(logger, keyword, type, JSON_ARRAY); case SCHEMA_ADDITIONAL_PROPERTIES: return CheckTypeAndLog(logger, keyword, type, JSON_BOOLEAN, JSON_OBJECT); case SCHEMA_DEFINITIONS: return CheckTypeAndLog(logger, keyword, type, JSON_OBJECT); case SCHEMA_PROPERTIES: return CheckTypeAndLog(logger, keyword, type, JSON_OBJECT); case SCHEMA_PATTERN_PROPERTIES: return CheckTypeAndLog(logger, keyword, type, JSON_OBJECT); case SCHEMA_DEPENDENCIES: return CheckTypeAndLog(logger, keyword, type, JSON_OBJECT); case SCHEMA_ENUM: return CheckTypeAndLog(logger, keyword, type, JSON_ARRAY); case SCHEMA_TYPE: return CheckTypeAndLog(logger, keyword, type, JSON_STRING, JSON_ARRAY); case SCHEMA_ALL_OF: return CheckTypeAndLog(logger, keyword, type, JSON_ARRAY); case SCHEMA_ANY_OF: return CheckTypeAndLog(logger, keyword, type, JSON_ARRAY); case SCHEMA_ONE_OF: return CheckTypeAndLog(logger, keyword, type, JSON_ARRAY); case SCHEMA_NOT: return CheckTypeAndLog(logger, keyword, type, JSON_OBJECT); default: return false; } } bool SchemaParseContext::CheckTypeAndLog( SchemaErrorLogger *logger, SchemaKeyword keyword, JsonType type, JsonType expected_type) { if (type == expected_type) { return true; } else { logger->Error() << "Invalid type for " << KeywordToString(keyword) << ", got " << JsonTypeToString(type) << ", expected " << JsonTypeToString(expected_type); return false; } } bool SchemaParseContext::CheckTypeAndLog( SchemaErrorLogger *logger, SchemaKeyword keyword, JsonType type, JsonType expected_type1, JsonType expected_type2) { if (type == expected_type1 || type == expected_type2) { return true; } else { logger->Error() << "Invalid type for " << KeywordToString(keyword) << ", got " << JsonTypeToString(type) << ", expected " << JsonTypeToString(expected_type1) << " or " << JsonTypeToString(expected_type2); return false; } } // PropertiesParseContext // Used for parsing an object with key : json schema pairs, within 'properties' void PropertiesParseContext::AddPropertyValidators( ObjectValidator *object_validator, SchemaErrorLogger *logger) { SchemaMap::iterator iter = m_property_contexts.begin(); for (; iter != m_property_contexts.end(); ++iter) { ValidatorInterface *validator = iter->second->GetValidator(logger); if (validator) { object_validator->AddValidator(iter->first, validator); } } } PropertiesParseContext::~PropertiesParseContext() { STLDeleteValues(&m_property_contexts); } SchemaParseContextInterface* PropertiesParseContext::OpenObject( SchemaErrorLogger *logger) { const string key = TakeKeyword(); pair r = m_property_contexts.insert( pair(key, NULL)); if (r.second) { r.first->second = new SchemaParseContext(m_schema_defs); } else { logger->Error() << "Duplicate key " << key; } return r.first->second; } // ArrayOfSchemaContext // Used for parsing an array of JSON schema within 'items' ArrayOfSchemaContext::~ArrayOfSchemaContext() { STLDeleteElements(&m_item_schemas); } void ArrayOfSchemaContext::GetValidators( SchemaErrorLogger *logger, ValidatorInterface::ValidatorList *validators) { ItemSchemas::iterator iter = m_item_schemas.begin(); for (; iter != m_item_schemas.end(); ++iter) { validators->push_back((*iter)->GetValidator(logger)); } } SchemaParseContextInterface* ArrayOfSchemaContext::OpenObject( OLA_UNUSED SchemaErrorLogger *logger) { m_item_schemas.push_back(new SchemaParseContext(m_schema_defs)); return m_item_schemas.back(); } // ArrayOfStringsContext // Used for parsing an array of strings. void ArrayOfStringsContext::GetStringSet(StringSet *items) { *items = m_items; } void ArrayOfStringsContext::String(SchemaErrorLogger *logger, const string &value) { if (!m_items.insert(value).second) { logger->Error() << value << " appeared more than once in the array"; } } // JsonValueContext // Used for parsing a default value. JsonValueContext::JsonValueContext() : SchemaParseContextInterface() { m_parser.Begin(); } const JsonValue* JsonValueContext::ClaimValue(SchemaErrorLogger *logger) { m_parser.End(); const JsonValue *value = m_parser.ClaimRoot(); if (!value) { logger->Error() << " is invalid: " << m_parser.GetError(); } return value; } void JsonValueContext::String(SchemaErrorLogger *, const string &value) { m_parser.String(value); } void JsonValueContext::Number(SchemaErrorLogger *, uint32_t value) { m_parser.Number(value); } void JsonValueContext::Number(SchemaErrorLogger *, int32_t value) { m_parser.Number(value); } void JsonValueContext::Number(SchemaErrorLogger *, uint64_t value) { m_parser.Number(value); } void JsonValueContext::Number(SchemaErrorLogger *, int64_t value) { m_parser.Number(value); } void JsonValueContext::Number(SchemaErrorLogger *, double value) { m_parser.Number(value); } void JsonValueContext::Bool(SchemaErrorLogger *, bool value) { m_parser.Bool(value); } void JsonValueContext::Null(OLA_UNUSED SchemaErrorLogger *logger) { m_parser.Null(); } SchemaParseContextInterface* JsonValueContext::OpenArray( SchemaErrorLogger *) { m_parser.OpenArray(); return this; } void JsonValueContext::CloseArray(OLA_UNUSED SchemaErrorLogger *logger) { m_parser.CloseArray(); } SchemaParseContextInterface* JsonValueContext::OpenObject( SchemaErrorLogger *) { m_parser.OpenObject(); return this; } void JsonValueContext::ObjectKey(SchemaErrorLogger *, const string &key) { m_parser.ObjectKey(key); } void JsonValueContext::CloseObject(OLA_UNUSED SchemaErrorLogger *logger) { m_parser.CloseObject(); } // ArrayOfJsonValuesContext // Used for parsing a list of enums. ArrayOfJsonValuesContext::~ArrayOfJsonValuesContext() { STLDeleteElements(&m_enums); } void ArrayOfJsonValuesContext::AddEnumsToValidator(BaseValidator *validator) { vector::const_iterator iter = m_enums.begin(); for (; iter != m_enums.end(); ++iter) { validator->AddEnumValue(*iter); } m_enums.clear(); } void ArrayOfJsonValuesContext::String(SchemaErrorLogger *logger, const string &value) { CheckForDuplicateAndAdd(logger, JsonValue::NewValue(value)); } void ArrayOfJsonValuesContext::Number(SchemaErrorLogger *logger, uint32_t value) { CheckForDuplicateAndAdd(logger, JsonValue::NewValue(value)); } void ArrayOfJsonValuesContext::Number(SchemaErrorLogger *logger, int32_t value) { CheckForDuplicateAndAdd(logger, JsonValue::NewValue(value)); } void ArrayOfJsonValuesContext::Number(SchemaErrorLogger *logger, uint64_t value) { CheckForDuplicateAndAdd(logger, JsonValue::NewValue(value)); } void ArrayOfJsonValuesContext::Number(SchemaErrorLogger *logger, int64_t value) { CheckForDuplicateAndAdd(logger, JsonValue::NewValue(value)); } void ArrayOfJsonValuesContext::Number(SchemaErrorLogger *logger, double value) { CheckForDuplicateAndAdd(logger, JsonValue::NewValue(value)); } void ArrayOfJsonValuesContext::Bool(SchemaErrorLogger *logger, bool value) { CheckForDuplicateAndAdd(logger, JsonValue::NewValue(value)); } void ArrayOfJsonValuesContext::Null(SchemaErrorLogger *logger) { CheckForDuplicateAndAdd(logger, new JsonNull()); } SchemaParseContextInterface* ArrayOfJsonValuesContext::OpenArray( OLA_UNUSED SchemaErrorLogger *logger) { m_value_context.reset(new JsonValueContext()); return m_value_context.get(); } void ArrayOfJsonValuesContext::CloseArray(SchemaErrorLogger *logger) { CheckForDuplicateAndAdd(logger, m_value_context->ClaimValue(logger)); } SchemaParseContextInterface* ArrayOfJsonValuesContext::OpenObject( OLA_UNUSED SchemaErrorLogger *logger) { m_value_context.reset(new JsonValueContext()); return m_value_context.get(); } void ArrayOfJsonValuesContext::CloseObject(SchemaErrorLogger *logger) { CheckForDuplicateAndAdd(logger, m_value_context->ClaimValue(logger)); } void ArrayOfJsonValuesContext::CheckForDuplicateAndAdd( SchemaErrorLogger *logger, const JsonValue *value) { vector::const_iterator iter = m_enums.begin(); for (; iter != m_enums.end(); ++iter) { if (**iter == *value) { logger->Error() << "Duplicate entries in enum array: " << value; delete value; return; } } m_enums.push_back(value); } // ArrayOfJsonValuesContext // Used for parsing a list of enums. DependencyParseContext::~DependencyParseContext() { STLDeleteValues(&m_schema_dependencies); } void DependencyParseContext::AddDependenciesToValidator( ObjectValidator *validator) { PropertyDependencies::const_iterator prop_iter = m_property_dependencies.begin(); for (; prop_iter != m_property_dependencies.end(); ++prop_iter) { validator->AddPropertyDependency(prop_iter->first, prop_iter->second); } // Check Schema Dependencies SchemaDependencies::const_iterator schema_iter = m_schema_dependencies.begin(); for (; schema_iter != m_schema_dependencies.end(); ++schema_iter) { validator->AddSchemaDependency(schema_iter->first, schema_iter->second); } m_schema_dependencies.clear(); } SchemaParseContextInterface* DependencyParseContext::OpenArray( OLA_UNUSED SchemaErrorLogger *logger) { m_property_context.reset(new ArrayOfStringsContext()); return m_property_context.get(); } void DependencyParseContext::CloseArray(SchemaErrorLogger *logger) { StringSet &properties = m_property_dependencies[Keyword()]; m_property_context->GetStringSet(&properties); if (properties.empty()) { logger->Error() << " property dependency lists must contain at least one item"; } m_property_context.reset(); } SchemaParseContextInterface* DependencyParseContext::OpenObject( OLA_UNUSED SchemaErrorLogger *logger) { m_schema_context.reset(new SchemaParseContext(m_schema_defs)); return m_schema_context.get(); } void DependencyParseContext::CloseObject(SchemaErrorLogger *logger) { STLReplaceAndDelete(&m_schema_dependencies, Keyword(), m_schema_context->GetValidator(logger)); m_schema_context.reset(); } } // namespace web } // namespace ola ola-0.10.5.nojsmin/common/web/PointerTracker.h0000644000175000017500000000663513023355232020642 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * PointerTracker.h * Maintains a JsonPointer from a series of parse events. * Copyright (C) 2014 Simon Newton */ #ifndef COMMON_WEB_POINTERTRACKER_H_ #define COMMON_WEB_POINTERTRACKER_H_ #include #include #include #include #include namespace ola { namespace web { /** * @brief Maintains a Json Pointer (RFC 6901) given a set of Json parse events. * * Given the JSON: * ~~~~~~~~~~~~~~~~~~~~~ { "foo": { "bar": 1, "baz": true }, "bat": [0, 1, 2] } ~~~~~~~~~~~~~~~~~~~~~ * * It has the pointers: * - "" * - "/foo" * - "/foo/bar" * - "/foo/baz" * - "/bat" * - "/bat/0" * - "/bat/1" * - "/bat/2" * * When parsing this example, the order of method invocation should be: * @code JsonPointer pointer; PointerTracker tracker(&pointer); tracker.OpenObject() tracker.SetProperty("foo"); tracker.OpenObject(); tracker.SetProperty("bar"); tracker.SetProperty("baz"); tracker.CloseObject(); tracker.SetProperty("bat"); tracker.OpenArray(); tracker.IncrementIndex(); tracker.IncrementIndex(); tracker.IncrementIndex(); tracker.CloseArray(); tracker.CloseObject(); @endcode */ class PointerTracker { public: explicit PointerTracker(JsonPointer *pointer) : m_pointer(pointer) { } /** * @brief Open a new Object Element */ void OpenObject(); /** * @brief Set the property name within an Object element. * Note if we're not currently in an object element this has no effect. */ void SetProperty(const std::string &property); /** * @brief Close an Object element. * Note if we're not currently in an object element this has no effect. */ void CloseObject(); /** * @brief Open a new Array Element * Note that until IncrementIndex() is called, the array index will be -1. * This is so you can call IncrementIndex() on each element. */ void OpenArray(); /** * @brief Close an Array Element * If we're not currently in an array this doesn't do anything. */ void CloseArray(); /** * @brief Increment an array index. * If we're not current in an array this doesn't do anything. */ void IncrementIndex(); private: enum TokenType { TOKEN_OBJECT, TOKEN_ARRAY, }; struct Token { public: TokenType type; int index; bool property_set; explicit Token(TokenType type) : type(type), index(-1), property_set(false) {} }; JsonPointer *m_pointer; std::vector m_tokens; DISALLOW_COPY_AND_ASSIGN(PointerTracker); }; } // namespace web } // namespace ola #endif // COMMON_WEB_POINTERTRACKER_H_ ola-0.10.5.nojsmin/common/web/JsonTypes.cpp0000644000175000017500000000360713023355232020173 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * JsonTypes.cpp * Utils for dealing with JsonTypes. * Copyright (C) 2014 Simon Newton */ #include #include "ola/web/JsonTypes.h" namespace ola { namespace web { using std::string; string JsonTypeToString(JsonType type) { switch (type) { case JSON_ARRAY: return "array"; case JSON_BOOLEAN: return "boolean"; case JSON_INTEGER: return "integer"; case JSON_NULL: return "null"; case JSON_NUMBER: return "number"; case JSON_OBJECT: return "object"; case JSON_STRING: return "string"; case JSON_UNDEFINED: return ""; default: return "Unknown type"; } } JsonType StringToJsonType(const string &type) { if (type == "array") { return JSON_ARRAY; } else if (type == "boolean") { return JSON_BOOLEAN; } else if (type == "integer") { return JSON_INTEGER; } else if (type == "null") { return JSON_NULL; } else if (type == "number") { return JSON_NUMBER; } else if (type == "object") { return JSON_OBJECT; } else if (type == "string") { return JSON_STRING; } else { return JSON_UNDEFINED; } } } // namespace web } // namespace ola ola-0.10.5.nojsmin/common/web/PointerTest.cpp0000644000175000017500000001377513023355232020524 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * PointerTest.cpp * Unittest for the Json Pointer. * Copyright (C) 2014 Simon Newton */ #include #include "ola/web/JsonPointer.h" #include "ola/testing/TestUtils.h" using ola::web::JsonPointer; using std::string; class JsonPointerTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(JsonPointerTest); CPPUNIT_TEST(testConstructionFrom); CPPUNIT_TEST(testEscaping); CPPUNIT_TEST(testIteration); CPPUNIT_TEST(testPrefix); CPPUNIT_TEST_SUITE_END(); public: void testConstructionFrom(); void testEscaping(); void testIteration(); void testPrefix(); }; CPPUNIT_TEST_SUITE_REGISTRATION(JsonPointerTest); void JsonPointerTest::testConstructionFrom() { JsonPointer pointer1(""); OLA_ASSERT_TRUE(pointer1.IsValid()); OLA_ASSERT_EQ(1u, pointer1.TokenCount()); OLA_ASSERT_EQ(string(""), pointer1.TokenAt(0)); OLA_ASSERT_EQ(string(""), pointer1.ToString()); JsonPointer pointer2("/foo"); OLA_ASSERT_TRUE(pointer2.IsValid()); OLA_ASSERT_EQ(2u, pointer2.TokenCount()); OLA_ASSERT_EQ(string("foo"), pointer2.TokenAt(0)); OLA_ASSERT_EQ(string(""), pointer2.TokenAt(1)); OLA_ASSERT_EQ(string(""), pointer2.TokenAt(2)); OLA_ASSERT_EQ(string("/foo"), pointer2.ToString()); JsonPointer pointer3("/foo/bar/1"); OLA_ASSERT_TRUE(pointer3.IsValid()); OLA_ASSERT_EQ(4u, pointer3.TokenCount()); OLA_ASSERT_EQ(string("foo"), pointer3.TokenAt(0)); OLA_ASSERT_EQ(string("bar"), pointer3.TokenAt(1)); OLA_ASSERT_EQ(string("1"), pointer3.TokenAt(2)); OLA_ASSERT_EQ(string(""), pointer3.TokenAt(3)); OLA_ASSERT_EQ(string("/foo/bar/1"), pointer3.ToString()); JsonPointer pointer4("/1"); OLA_ASSERT_TRUE(pointer4.IsValid()); OLA_ASSERT_EQ(2u, pointer4.TokenCount()); OLA_ASSERT_EQ(string("1"), pointer4.TokenAt(0)); OLA_ASSERT_EQ(string(""), pointer4.TokenAt(1)); OLA_ASSERT_EQ(string("/1"), pointer4.ToString()); JsonPointer pointer5("/-1"); OLA_ASSERT_TRUE(pointer5.IsValid()); OLA_ASSERT_EQ(2u, pointer5.TokenCount()); OLA_ASSERT_EQ(string("-1"), pointer5.TokenAt(0)); OLA_ASSERT_EQ(string(""), pointer5.TokenAt(1)); OLA_ASSERT_EQ(string("/-1"), pointer5.ToString()); JsonPointer invalid_pointer("foo"); OLA_ASSERT_FALSE(invalid_pointer.IsValid()); JsonPointer empty_pointer; OLA_ASSERT_TRUE(empty_pointer.IsValid()); OLA_ASSERT_EQ(1u, empty_pointer.TokenCount()); OLA_ASSERT_EQ(string(""), empty_pointer.TokenAt(0)); OLA_ASSERT_EQ(string(""), empty_pointer.ToString()); } void JsonPointerTest::testEscaping() { JsonPointer pointer1("/a~1b"); OLA_ASSERT_TRUE(pointer1.IsValid()); OLA_ASSERT_EQ(2u, pointer1.TokenCount()); OLA_ASSERT_EQ(string("a/b"), pointer1.TokenAt(0)); OLA_ASSERT_EQ(string(""), pointer1.TokenAt(1)); OLA_ASSERT_EQ(string("/a~1b"), pointer1.ToString()); JsonPointer pointer2("/m~0n"); OLA_ASSERT_TRUE(pointer2.IsValid()); OLA_ASSERT_EQ(2u, pointer2.TokenCount()); OLA_ASSERT_EQ(string("m~n"), pointer2.TokenAt(0)); OLA_ASSERT_EQ(string(""), pointer2.TokenAt(1)); OLA_ASSERT_EQ(string("/m~0n"), pointer2.ToString()); } void JsonPointerTest::testIteration() { JsonPointer pointer1(""); JsonPointer::Iterator iter = pointer1.begin(); OLA_ASSERT_TRUE(iter.IsValid()); OLA_ASSERT_TRUE(iter.AtEnd()); OLA_ASSERT_EQ(string(""), *iter); iter++; OLA_ASSERT_FALSE(iter.AtEnd()); OLA_ASSERT_FALSE(iter.IsValid()); JsonPointer pointer2("/foo"); iter = pointer2.begin(); OLA_ASSERT_TRUE(iter.IsValid()); OLA_ASSERT_FALSE(iter.AtEnd()); OLA_ASSERT_EQ(string("foo"), *iter); iter++; OLA_ASSERT_TRUE(iter.IsValid()); OLA_ASSERT_TRUE(iter.AtEnd()); OLA_ASSERT_EQ(string(""), *iter); iter++; OLA_ASSERT_FALSE(iter.IsValid()); JsonPointer pointer3("/foo/bar/1/-1"); iter = pointer3.begin(); OLA_ASSERT_TRUE(iter.IsValid()); OLA_ASSERT_FALSE(iter.AtEnd()); OLA_ASSERT_EQ(string("foo"), *iter); iter++; OLA_ASSERT_TRUE(iter.IsValid()); OLA_ASSERT_FALSE(iter.AtEnd()); OLA_ASSERT_EQ(string("bar"), *iter); iter++; OLA_ASSERT_TRUE(iter.IsValid()); OLA_ASSERT_FALSE(iter.AtEnd()); OLA_ASSERT_EQ(string("1"), *iter); iter++; OLA_ASSERT_TRUE(iter.IsValid()); OLA_ASSERT_FALSE(iter.AtEnd()); OLA_ASSERT_EQ(string("-1"), *iter); iter++; OLA_ASSERT_TRUE(iter.IsValid()); OLA_ASSERT_TRUE(iter.AtEnd()); OLA_ASSERT_EQ(string(""), *iter); iter++; OLA_ASSERT_FALSE(iter.IsValid()); } void JsonPointerTest::testPrefix() { JsonPointer invalid_pointer("foo"); JsonPointer pointer1("/foo"); JsonPointer pointer2("/foo/bar"); JsonPointer pointer3("/baz"); JsonPointer pointer4(""); OLA_ASSERT_FALSE(invalid_pointer.IsPrefixOf(invalid_pointer)); OLA_ASSERT_FALSE(invalid_pointer.IsPrefixOf(pointer1)); OLA_ASSERT_FALSE(invalid_pointer.IsPrefixOf(pointer2)); OLA_ASSERT_FALSE(invalid_pointer.IsPrefixOf(pointer3)); OLA_ASSERT_TRUE(pointer1.IsPrefixOf(pointer2)); OLA_ASSERT_TRUE(pointer4.IsPrefixOf(pointer1)); OLA_ASSERT_TRUE(pointer4.IsPrefixOf(pointer3)); OLA_ASSERT_FALSE(pointer1.IsPrefixOf(pointer1)); OLA_ASSERT_FALSE(pointer1.IsPrefixOf(pointer3)); OLA_ASSERT_FALSE(pointer1.IsPrefixOf(pointer4)); OLA_ASSERT_FALSE(pointer2.IsPrefixOf(pointer1)); OLA_ASSERT_FALSE(pointer2.IsPrefixOf(pointer2)); OLA_ASSERT_FALSE(pointer2.IsPrefixOf(pointer3)); OLA_ASSERT_FALSE(pointer2.IsPrefixOf(pointer4)); OLA_ASSERT_FALSE(pointer3.IsPrefixOf(pointer4)); } ola-0.10.5.nojsmin/common/web/PointerTrackerTest.cpp0000644000175000017500000001741113023355232022027 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * PointerTrackerTest.cpp * Unittest for the PointerTracker. * Copyright (C) 2014 Simon Newton */ #include #include #include #include #include "ola/testing/TestUtils.h" #include "ola/web/JsonPointer.h" #include "common/web/PointerTracker.h" using ola::web::JsonPointer; using ola::web::PointerTracker; using std::string; class PointerTrackerTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(PointerTrackerTest); CPPUNIT_TEST(testPointer); CPPUNIT_TEST(testErrorConditions); CPPUNIT_TEST(testEscaping); CPPUNIT_TEST_SUITE_END(); public: void testPointer(); void testErrorConditions(); void testEscaping(); }; CPPUNIT_TEST_SUITE_REGISTRATION(PointerTrackerTest); void PointerTrackerTest::testPointer() { JsonPointer pointer; PointerTracker tracker(&pointer); // Basic tests first // {} OLA_ASSERT_EQ(string(""), pointer.ToString()); tracker.OpenObject(); OLA_ASSERT_EQ(string(""), pointer.ToString()); tracker.CloseObject(); // [] tracker.OpenArray(); OLA_ASSERT_EQ(string(""), pointer.ToString()); tracker.CloseArray(); OLA_ASSERT_EQ(string(""), pointer.ToString()); // [ {}, {} ] tracker.OpenArray(); OLA_ASSERT_EQ(string(""), pointer.ToString()); tracker.OpenObject(); OLA_ASSERT_EQ(string("/0"), pointer.ToString()); tracker.CloseObject(); OLA_ASSERT_EQ(string("/0"), pointer.ToString()); tracker.OpenObject(); OLA_ASSERT_EQ(string("/1"), pointer.ToString()); tracker.CloseObject(); OLA_ASSERT_EQ(string("/1"), pointer.ToString()); tracker.CloseArray(); OLA_ASSERT_EQ(string(""), pointer.ToString()); // {"foo": {}} OLA_ASSERT_EQ(string(""), pointer.ToString()); tracker.OpenObject(); OLA_ASSERT_EQ(string(""), pointer.ToString()); tracker.SetProperty("foo"); OLA_ASSERT_EQ(string("/foo"), pointer.ToString()); tracker.OpenObject(); OLA_ASSERT_EQ(string("/foo"), pointer.ToString()); tracker.CloseObject(); OLA_ASSERT_EQ(string("/foo"), pointer.ToString()); tracker.CloseObject(); // {"foo": {"bar": {} } } OLA_ASSERT_EQ(string(""), pointer.ToString()); tracker.OpenObject(); OLA_ASSERT_EQ(string(""), pointer.ToString()); tracker.SetProperty("foo"); OLA_ASSERT_EQ(string("/foo"), pointer.ToString()); tracker.OpenObject(); OLA_ASSERT_EQ(string("/foo"), pointer.ToString()); tracker.SetProperty("bar"); OLA_ASSERT_EQ(string("/foo/bar"), pointer.ToString()); tracker.OpenObject(); OLA_ASSERT_EQ(string("/foo/bar"), pointer.ToString()); tracker.CloseObject(); OLA_ASSERT_EQ(string("/foo/bar"), pointer.ToString()); tracker.CloseObject(); OLA_ASSERT_EQ(string("/foo"), pointer.ToString()); tracker.CloseObject(); OLA_ASSERT_EQ(string(""), pointer.ToString()); /* * The call sequence is based on the following JSON data: * * { * "foo": [ 0, 1, { "bar": null}, true], * "baz": { "bat" : null }, * "cat": [[0, 1], [], false], * } */ OLA_ASSERT_EQ(string(""), pointer.ToString()); tracker.OpenObject(); OLA_ASSERT_EQ(string(""), pointer.ToString()); tracker.SetProperty("foo"); OLA_ASSERT_EQ(string("/foo"), pointer.ToString()); tracker.OpenArray(); OLA_ASSERT_EQ(string("/foo"), pointer.ToString()); tracker.IncrementIndex(); OLA_ASSERT_EQ(string("/foo/0"), pointer.ToString()); tracker.IncrementIndex(); OLA_ASSERT_EQ(string("/foo/1"), pointer.ToString()); tracker.OpenObject(); OLA_ASSERT_EQ(string("/foo/2"), pointer.ToString()); tracker.SetProperty("bar"); OLA_ASSERT_EQ(string("/foo/2/bar"), pointer.ToString()); // No effect, but makes the implementation in the JsonHandler simpler. tracker.IncrementIndex(); OLA_ASSERT_EQ(string("/foo/2/bar"), pointer.ToString()); tracker.CloseObject(); OLA_ASSERT_EQ(string("/foo/2"), pointer.ToString()); tracker.IncrementIndex(); OLA_ASSERT_EQ(string("/foo/3"), pointer.ToString()); tracker.CloseArray(); OLA_ASSERT_EQ(string("/foo"), pointer.ToString()); tracker.SetProperty("baz"); OLA_ASSERT_EQ(string("/baz"), pointer.ToString()); tracker.OpenObject(); OLA_ASSERT_EQ(string("/baz"), pointer.ToString()); tracker.SetProperty("bat"); OLA_ASSERT_EQ(string("/baz/bat"), pointer.ToString()); // No effect, but makes the implementation in the JsonHandler simpler. tracker.IncrementIndex(); OLA_ASSERT_EQ(string("/baz/bat"), pointer.ToString()); tracker.CloseObject(); OLA_ASSERT_EQ(string("/baz"), pointer.ToString()); tracker.SetProperty("cat"); OLA_ASSERT_EQ(string("/cat"), pointer.ToString()); tracker.OpenArray(); OLA_ASSERT_EQ(string("/cat"), pointer.ToString()); tracker.OpenArray(); OLA_ASSERT_EQ(string("/cat/0"), pointer.ToString()); tracker.IncrementIndex(); OLA_ASSERT_EQ(string("/cat/0/0"), pointer.ToString()); tracker.IncrementIndex(); OLA_ASSERT_EQ(string("/cat/0/1"), pointer.ToString()); tracker.CloseArray(); OLA_ASSERT_EQ(string("/cat/0"), pointer.ToString()); tracker.OpenArray(); OLA_ASSERT_EQ(string("/cat/1"), pointer.ToString()); tracker.CloseArray(); OLA_ASSERT_EQ(string("/cat/1"), pointer.ToString()); tracker.IncrementIndex(); OLA_ASSERT_EQ(string("/cat/2"), pointer.ToString()); tracker.CloseArray(); OLA_ASSERT_EQ(string("/cat"), pointer.ToString()); tracker.CloseObject(); OLA_ASSERT_EQ(string(""), pointer.ToString()); } void PointerTrackerTest::testErrorConditions() { JsonPointer pointer; PointerTracker tracker(&pointer); // Close without Opens OLA_ASSERT_EQ(string(""), pointer.ToString()); tracker.CloseObject(); OLA_ASSERT_EQ(string(""), pointer.ToString()); tracker.CloseArray(); OLA_ASSERT_EQ(string(""), pointer.ToString()); // Mismatched open / close types. tracker.OpenObject(); OLA_ASSERT_EQ(string(""), pointer.ToString()); tracker.SetProperty("foo"); OLA_ASSERT_EQ(string("/foo"), pointer.ToString()); tracker.CloseArray(); OLA_ASSERT_EQ(string("/foo"), pointer.ToString()); tracker.CloseObject(); OLA_ASSERT_EQ(string(""), pointer.ToString()); // SetProperty while in an array tracker.OpenArray(); OLA_ASSERT_EQ(string(""), pointer.ToString()); tracker.SetProperty("foo"); OLA_ASSERT_EQ(string(""), pointer.ToString()); tracker.IncrementIndex(); OLA_ASSERT_EQ(string("/0"), pointer.ToString()); } void PointerTrackerTest::testEscaping() { JsonPointer pointer; PointerTracker tracker(&pointer); tracker.OpenObject(); // Examples from RFC 6901 tracker.SetProperty(""); OLA_ASSERT_EQ(string("/"), pointer.ToString()); tracker.SetProperty("a/b"); OLA_ASSERT_EQ(string("/a~1b"), pointer.ToString()); tracker.SetProperty("c%d"); OLA_ASSERT_EQ(string("/c%d"), pointer.ToString()); tracker.SetProperty("e^f"); OLA_ASSERT_EQ(string("/e^f"), pointer.ToString()); tracker.SetProperty("g|h"); OLA_ASSERT_EQ(string("/g|h"), pointer.ToString()); tracker.SetProperty("i\\\\j"); OLA_ASSERT_EQ(string("/i\\\\j"), pointer.ToString()); tracker.SetProperty("k\"l"); OLA_ASSERT_EQ(string("/k\"l"), pointer.ToString()); tracker.SetProperty(" "); OLA_ASSERT_EQ(string("/ "), pointer.ToString()); tracker.SetProperty("m~n"); OLA_ASSERT_EQ(string("/m~0n"), pointer.ToString()); } ola-0.10.5.nojsmin/common/web/PatchTest.cpp0000644000175000017500000006273213023355232020140 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * PatchTest.cpp * Unittest for the Json Patch. * Copyright (C) 2014 Simon Newton */ #include #include "ola/testing/TestUtils.h" #include "ola/web/Json.h" #include "ola/web/JsonData.h" #include "ola/web/JsonPatch.h" #include "ola/web/JsonParser.h" #include "ola/web/JsonWriter.h" #include "ola/web/JsonPointer.h" #include "ola/Logging.h" using ola::web::JsonArray; using ola::web::JsonBool; using ola::web::JsonInt; using ola::web::JsonNull; using ola::web::JsonObject; using ola::web::JsonParser; using ola::web::JsonPatchAddOp; using ola::web::JsonPatchCopyOp; using ola::web::JsonPatchMoveOp; using ola::web::JsonPatchRemoveOp; using ola::web::JsonPatchReplaceOp; using ola::web::JsonPatchSet; using ola::web::JsonPatchTestOp; using ola::web::JsonPointer; using ola::web::JsonString; using ola::web::JsonData; using ola::web::JsonValue; using ola::web::JsonWriter; using std::auto_ptr; using std::string; class JsonPatchTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(JsonPatchTest); CPPUNIT_TEST(testAddOp); CPPUNIT_TEST(testRemoveOp); CPPUNIT_TEST(testReplaceOp); CPPUNIT_TEST(testCopyOp); CPPUNIT_TEST(testMoveOp); CPPUNIT_TEST(testTestOp); CPPUNIT_TEST(testAtomicUpdates); CPPUNIT_TEST_SUITE_END(); public: void testAddOp(); void testRemoveOp(); void testReplaceOp(); void testCopyOp(); void testMoveOp(); void testTestOp(); void testAtomicUpdates(); private: void CheckValuesMatch(const std::string &, const JsonValue *actual); void BuildSampleText(JsonData *text); }; void JsonPatchTest::CheckValuesMatch(const std::string &input, const JsonValue *actual) { string error; auto_ptr expected_value(JsonParser::Parse(input, &error)); if (expected_value.get()) { if (*actual != *expected_value.get()) { OLA_ASSERT_EQ(JsonWriter::AsString(*(expected_value.get())), JsonWriter::AsString(*actual)); } } else { OLA_ASSERT_EQ(expected_value.get(), actual); } } void JsonPatchTest::BuildSampleText(JsonData *text) { auto_ptr object(new JsonObject()); object->Add("foo", "bar"); object->Add("baz", false); JsonObject *child_object = new JsonObject(); child_object->Add("bat", 1); object->AddValue("object", child_object); JsonArray *child_array = new JsonArray(); child_array->Append(1); child_array->Append(2); child_array->Append(3); object->AddValue("array", child_array); text->SetValue(object.release()); } CPPUNIT_TEST_SUITE_REGISTRATION(JsonPatchTest); void JsonPatchTest::testAddOp() { JsonData text(NULL); { JsonPatchSet patch; patch.AddOp(new JsonPatchAddOp(JsonPointer("/foo"), new JsonNull())); OLA_ASSERT_FALSE(text.Apply(patch)); } { JsonPatchSet patch; patch.AddOp(new JsonPatchAddOp(JsonPointer(""), new JsonObject())); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch("{}", text.Value()); } { JsonPatchSet patch; patch.AddOp(new JsonPatchAddOp( JsonPointer("/name"), new JsonString("simon"))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch("{\"name\": \"simon\"}", text.Value()); } // test replace { JsonPatchSet patch; patch.AddOp(new JsonPatchAddOp( JsonPointer("/name"), new JsonString("james"))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch("{\"name\": \"james\"}", text.Value()); } { JsonPatchSet patch; patch.AddOp(new JsonPatchAddOp( JsonPointer("/numbers"), new JsonArray())); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch("{\"name\": \"james\", \"numbers\": []}", text.Value()); } // Append { JsonPatchSet patch; patch.AddOp(new JsonPatchAddOp( JsonPointer("/numbers/-"), new JsonInt(1))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch("{\"name\": \"james\", \"numbers\": [1]}", text.Value()); } // Array replace. { JsonPatchSet patch; patch.AddOp(new JsonPatchAddOp( JsonPointer("/numbers/0"), new JsonInt(2))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch("{\"name\": \"james\", \"numbers\": [2, 1]}", text.Value()); } // out of bounds { JsonPatchSet patch; patch.AddOp(new JsonPatchAddOp( JsonPointer("/numbers/2"), new JsonInt(3))); OLA_ASSERT_FALSE(text.Apply(patch)); CheckValuesMatch("{\"name\": \"james\", \"numbers\": [2, 1]}", text.Value()); } // non-int array index { JsonPatchSet patch; patch.AddOp(new JsonPatchAddOp( JsonPointer("/numbers/bar"), new JsonInt(3))); OLA_ASSERT_FALSE(text.Apply(patch)); CheckValuesMatch("{\"name\": \"james\", \"numbers\": [2, 1]}", text.Value()); } // missing parent { JsonPatchSet patch; patch.AddOp(new JsonPatchAddOp( JsonPointer("/pets/fluffy"), new JsonObject())); OLA_ASSERT_FALSE(text.Apply(patch)); CheckValuesMatch("{\"name\": \"james\", \"numbers\": [2, 1]}", text.Value()); } // add to a leaf node { JsonPatchSet patch; patch.AddOp(new JsonPatchAddOp( JsonPointer("/name/middle"), new JsonNull())); OLA_ASSERT_FALSE(text.Apply(patch)); CheckValuesMatch("{\"name\": \"james\", \"numbers\": [2, 1]}", text.Value()); } // Add a null to an object, this isn't allowed. { JsonPatchSet patch; patch.AddOp(new JsonPatchAddOp(JsonPointer("/foo"), NULL)); OLA_ASSERT_FALSE(text.Apply(patch)); CheckValuesMatch("{\"name\": \"james\", \"numbers\": [2, 1]}", text.Value()); } // Add a null { JsonPatchSet patch; patch.AddOp(new JsonPatchAddOp(JsonPointer(""), NULL)); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch("", text.Value()); } } void JsonPatchTest::testRemoveOp() { JsonData text(NULL); BuildSampleText(&text); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": false, " " \"object\": {\"bat\": 1}, \"array\": [1,2,3] }", text.Value()); // Try removing /object/bat { JsonPatchSet patch; patch.AddOp(new JsonPatchRemoveOp(JsonPointer("/object/bat"))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": false, " " \"object\": {}, \"array\": [1,2,3] }", text.Value()); } // Try removing /array/1 { JsonPatchSet patch; patch.AddOp(new JsonPatchRemoveOp(JsonPointer("/array/1"))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": false, " " \"object\": {}, \"array\": [1,3] }", text.Value()); } // Try removing /array/- { JsonPatchSet patch; patch.AddOp(new JsonPatchRemoveOp(JsonPointer("/array/-"))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": false, " " \"object\": {}, \"array\": [1] }", text.Value()); } // Try removing /array/1 { JsonPatchSet patch; patch.AddOp(new JsonPatchRemoveOp(JsonPointer("/array/1"))); OLA_ASSERT_FALSE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": false, " " \"object\": {}, \"array\": [1] }", text.Value()); } // Try removing /array/- { JsonPatchSet patch; patch.AddOp(new JsonPatchRemoveOp(JsonPointer("/array/-"))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": false, " " \"object\": {}, \"array\": [] }", text.Value()); } // Try removing /array/- { JsonPatchSet patch; patch.AddOp(new JsonPatchRemoveOp(JsonPointer("/array/1"))); OLA_ASSERT_FALSE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": false, " " \"object\": {}, \"array\": [] }", text.Value()); } // Try removing /foo { JsonPatchSet patch; patch.AddOp(new JsonPatchRemoveOp(JsonPointer("/foo"))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch( "{\"baz\": false, \"object\": {}, \"array\": [] }", text.Value()); } // Try removing /array & /object { JsonPatchSet patch; patch.AddOp(new JsonPatchRemoveOp(JsonPointer("/array"))); patch.AddOp(new JsonPatchRemoveOp(JsonPointer("/object"))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch("{\"baz\": false }", text.Value()); } // Try removing something that doesn't exist { JsonPatchSet patch; patch.AddOp(new JsonPatchRemoveOp(JsonPointer("/foo"))); OLA_ASSERT_FALSE(text.Apply(patch)); CheckValuesMatch("{\"baz\": false }", text.Value()); } // Finally remove the entire value. { JsonPatchSet patch; patch.AddOp(new JsonPatchRemoveOp(JsonPointer(""))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch("", text.Value()); } OLA_ASSERT_NULL(text.Value()); // Test we don't crash if we try to remove on an empty value { JsonPatchSet patch; patch.AddOp(new JsonPatchRemoveOp(JsonPointer("/foo"))); OLA_ASSERT_FALSE(text.Apply(patch)); CheckValuesMatch("", text.Value()); } } void JsonPatchTest::testReplaceOp() { JsonData text(NULL); BuildSampleText(&text); // Invalid pointer { JsonPatchSet patch; patch.AddOp(new JsonPatchReplaceOp(JsonPointer("foo"), new JsonString("test"))); OLA_ASSERT_FALSE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": false, " " \"object\": {\"bat\": 1}, \"array\": [1,2,3] }", text.Value()); } // Simple key replace { JsonPatchSet patch; patch.AddOp(new JsonPatchReplaceOp(JsonPointer("/foo"), new JsonString("test"))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"test\", \"baz\": false, " " \"object\": {\"bat\": 1}, \"array\": [1,2,3] }", text.Value()); } // Replace an array index { JsonPatchSet patch; patch.AddOp(new JsonPatchReplaceOp(JsonPointer("/array/1"), new JsonInt(4))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"test\", \"baz\": false, " " \"object\": {\"bat\": 1}, \"array\": [1,4,3] }", text.Value()); } // Replace the last item in the array { JsonPatchSet patch; patch.AddOp(new JsonPatchReplaceOp(JsonPointer("/array/-"), new JsonInt(5))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"test\", \"baz\": false, " " \"object\": {\"bat\": 1}, \"array\": [1,4,5] }", text.Value()); } // Non-int index { JsonPatchSet patch; patch.AddOp(new JsonPatchReplaceOp(JsonPointer("/array/foo"), new JsonInt(5))); OLA_ASSERT_FALSE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"test\", \"baz\": false, " " \"object\": {\"bat\": 1}, \"array\": [1,4,5] }", text.Value()); } // Out-of-range index { JsonPatchSet patch; patch.AddOp(new JsonPatchReplaceOp(JsonPointer("/array/3"), new JsonInt(5))); OLA_ASSERT_FALSE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"test\", \"baz\": false, " " \"object\": {\"bat\": 1}, \"array\": [1,4,5] }", text.Value()); } // Missing parent { JsonPatchSet patch; patch.AddOp(new JsonPatchReplaceOp(JsonPointer("/missing/3"), new JsonInt(5))); OLA_ASSERT_FALSE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"test\", \"baz\": false, " " \"object\": {\"bat\": 1}, \"array\": [1,4,5] }", text.Value()); } // 2 level path { JsonPatchSet patch; patch.AddOp(new JsonPatchReplaceOp(JsonPointer("/object/bat"), new JsonInt(4))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"test\", \"baz\": false, " " \"object\": {\"bat\": 4}, \"array\": [1,4,5] }", text.Value()); } // Missing element { JsonPatchSet patch; patch.AddOp(new JsonPatchReplaceOp(JsonPointer("/object/barrrr"), new JsonInt(4))); OLA_ASSERT_FALSE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"test\", \"baz\": false, " " \"object\": {\"bat\": 4}, \"array\": [1,4,5] }", text.Value()); } // Replace entire array { JsonPatchSet patch; patch.AddOp(new JsonPatchReplaceOp(JsonPointer("/array"), new JsonArray())); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"test\", \"baz\": false, " " \"object\": {\"bat\": 4}, \"array\": [] }", text.Value()); } // Another out-of-range { JsonPatchSet patch; patch.AddOp(new JsonPatchReplaceOp(JsonPointer("/array/0"), new JsonArray())); OLA_ASSERT_FALSE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"test\", \"baz\": false, " " \"object\": {\"bat\": 4}, \"array\": [] }", text.Value()); } // Replace the entire text { JsonPatchSet patch; patch.AddOp(new JsonPatchReplaceOp(JsonPointer(""), new JsonObject())); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch("{}", text.Value()); } // Replace with a NULL { JsonPatchSet patch; patch.AddOp(new JsonPatchReplaceOp(JsonPointer(""), NULL)); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch("", text.Value()); } // Replace a NULL { JsonPatchSet patch; patch.AddOp(new JsonPatchReplaceOp(JsonPointer(""), new JsonObject())); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch("{}", text.Value()); } } void JsonPatchTest::testMoveOp() { JsonData text(NULL); // Move a null value { JsonPatchSet patch; patch.AddOp(new JsonPatchMoveOp(JsonPointer("/foo"), JsonPointer("/foo"))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch("", text.Value()); } BuildSampleText(&text); // Invalid src pointer { JsonPatchSet patch; patch.AddOp(new JsonPatchMoveOp(JsonPointer("foo"), JsonPointer("/foo"))); OLA_ASSERT_FALSE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": false, " " \"object\": {\"bat\": 1}, \"array\": [1,2,3] }", text.Value()); } // Invalid dst pointer { JsonPatchSet patch; patch.AddOp(new JsonPatchMoveOp(JsonPointer("/foo"), JsonPointer("baz"))); OLA_ASSERT_FALSE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": false, " " \"object\": {\"bat\": 1}, \"array\": [1,2,3] }", text.Value()); } // Identity move { JsonPatchSet patch; patch.AddOp(new JsonPatchMoveOp(JsonPointer("/foo"), JsonPointer("/foo"))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": false, " " \"object\": {\"bat\": 1}, \"array\": [1,2,3] }", text.Value()); } // Test prefix handling, you can't move an object into itself { JsonPatchSet patch; patch.AddOp(new JsonPatchMoveOp( JsonPointer("/object"), JsonPointer("/object/bat"))); OLA_ASSERT_FALSE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": false, " " \"object\": {\"bat\": 1}, \"array\": [1,2,3] }", text.Value()); } // Simple move (add) { JsonPatchSet patch; patch.AddOp(new JsonPatchMoveOp(JsonPointer("/foo"), JsonPointer("/bar"))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch( "{\"bar\": \"bar\", \"baz\": false, " " \"object\": {\"bat\": 1}, \"array\": [1,2,3] }", text.Value()); } // Simple move (replace) { JsonPatchSet patch; patch.AddOp(new JsonPatchMoveOp(JsonPointer("/bar"), JsonPointer("/baz"))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch( "{\"baz\": \"bar\", " " \"object\": {\"bat\": 1}, \"array\": [1,2,3] }", text.Value()); } // Replace an inner value with an outer (array) { JsonPatchSet patch; patch.AddOp(new JsonPatchMoveOp( JsonPointer("/array/1"), JsonPointer("/array"))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch( "{\"baz\": \"bar\", " " \"object\": {\"bat\": 1}, \"array\": 2 }", text.Value()); } // Replace an inner value with an outer (object) { JsonPatchSet patch; patch.AddOp(new JsonPatchMoveOp( JsonPointer("/object/bat"), JsonPointer("/object"))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch( "{\"baz\": \"bar\", " " \"object\": 1, \"array\": 2 }", text.Value()); } // Replace the root { JsonPatchSet patch; patch.AddOp(new JsonPatchMoveOp( JsonPointer("/baz"), JsonPointer(""))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch("\"bar\"", text.Value()); } } void JsonPatchTest::testCopyOp() { JsonData text(NULL); // Copy a null value { JsonPatchSet patch; patch.AddOp(new JsonPatchCopyOp(JsonPointer("/foo"), JsonPointer("/foo"))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch("", text.Value()); } BuildSampleText(&text); // Invalid src pointer { JsonPatchSet patch; patch.AddOp(new JsonPatchCopyOp(JsonPointer("foo"), JsonPointer("/foo"))); OLA_ASSERT_FALSE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": false, " " \"object\": {\"bat\": 1}, \"array\": [1,2,3] }", text.Value()); } // Invalid dst pointer { JsonPatchSet patch; patch.AddOp(new JsonPatchCopyOp(JsonPointer("/foo"), JsonPointer("baz"))); OLA_ASSERT_FALSE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": false, " " \"object\": {\"bat\": 1}, \"array\": [1,2,3] }", text.Value()); } // Identity copy { JsonPatchSet patch; patch.AddOp(new JsonPatchCopyOp(JsonPointer("/foo"), JsonPointer("/foo"))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": false, " " \"object\": {\"bat\": 1}, \"array\": [1,2,3] }", text.Value()); } // Basic copy (replace) { JsonPatchSet patch; patch.AddOp(new JsonPatchCopyOp(JsonPointer("/foo"), JsonPointer("/baz"))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": \"bar\", " " \"object\": {\"bat\": 1}, \"array\": [1,2,3] }", text.Value()); } // Basic copy (add) { JsonPatchSet patch; patch.AddOp(new JsonPatchCopyOp(JsonPointer("/foo"), JsonPointer("/qux"))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": \"bar\", \"qux\": \"bar\", " " \"object\": {\"bat\": 1}, \"array\": [1,2,3] }", text.Value()); } // Copy into array { JsonPatchSet patch; patch.AddOp(new JsonPatchCopyOp( JsonPointer("/foo"), JsonPointer("/array/1"))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": \"bar\", \"qux\": \"bar\", " " \"object\": {\"bat\": 1}, \"array\": [1,\"bar\",2, 3] }", text.Value()); } // Copy into object (add) { JsonPatchSet patch; patch.AddOp(new JsonPatchCopyOp( JsonPointer("/foo"), JsonPointer("/object/bar"))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": \"bar\", \"qux\": \"bar\", " " \"object\": {\"bat\": 1, \"bar\": \"bar\"}, " " \"array\": [1,\"bar\",2, 3] }", text.Value()); } // Copy into object (replace) { JsonPatchSet patch; patch.AddOp(new JsonPatchCopyOp( JsonPointer("/foo"), JsonPointer("/object/bat"))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": \"bar\", \"qux\": \"bar\", " " \"object\": {\"bat\": \"bar\", \"bar\": \"bar\"}, " " \"array\": [1,\"bar\",2, 3] }", text.Value()); } // Replace an inner value with the object itself { // First some cleanup { JsonPatchSet patch; patch.AddOp(new JsonPatchRemoveOp(JsonPointer("/object/bar"))); patch.AddOp(new JsonPatchRemoveOp(JsonPointer("/array/1"))); patch.AddOp(new JsonPatchRemoveOp(JsonPointer("/qux"))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": \"bar\", " " \"object\": {\"bat\": \"bar\"}, " " \"array\": [1,2, 3] }", text.Value()); } JsonPatchSet patch; patch.AddOp(new JsonPatchCopyOp( JsonPointer("/object"), JsonPointer("/object/bat"))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": \"bar\", " " \"object\": {\"bat\": { \"bat\": \"bar\"} }, " " \"array\": [1,2, 3] }", text.Value()); } // Replace an object with an inner value. { JsonPatchSet patch; patch.AddOp(new JsonPatchCopyOp( JsonPointer("/object/bat"), JsonPointer("/object"))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": \"bar\", " " \"object\": { \"bat\": \"bar\"}, " " \"array\": [1,2, 3] }", text.Value()); } // Copy an array to itself { JsonPatchSet patch; patch.AddOp(new JsonPatchCopyOp( JsonPointer("/array"), JsonPointer("/array/-"))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": \"bar\", " " \"object\": { \"bat\": \"bar\"}, " " \"array\": [1,2, 3, [1,2,3]] }", text.Value()); } // Replace an array with an inner element { JsonPatchSet patch; patch.AddOp(new JsonPatchCopyOp( JsonPointer("/array/3"), JsonPointer("/array"))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": \"bar\", " " \"object\": { \"bat\": \"bar\"}, " " \"array\": [1,2, 3] }", text.Value()); } // Point to an invalid element (one past the end) { JsonPatchSet patch; patch.AddOp(new JsonPatchCopyOp( JsonPointer("/array/-"), JsonPointer("/array/1"))); OLA_ASSERT_FALSE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": \"bar\", " " \"object\": { \"bat\": \"bar\"}, " " \"array\": [1,2, 3] }", text.Value()); } } void JsonPatchTest::testTestOp() { auto_ptr object(new JsonObject()); object->Add("foo", "bar"); object->Add("baz", true); object->Add("bat", false); auto_ptr original_object(object->Clone()); JsonData text(object.release()); JsonPointer pointer1(""); JsonPointer pointer2("/foo"); JsonPointer pointer3("/baz"); JsonPointer pointer4("/bat"); JsonPatchSet patch1; patch1.AddOp(new JsonPatchTestOp(pointer1, new JsonNull())); OLA_ASSERT_FALSE(text.Apply(patch1)); JsonPatchSet patch2; patch2.AddOp(new JsonPatchTestOp(pointer2, new JsonBool(true))); OLA_ASSERT_FALSE(text.Apply(patch2)); JsonPatchSet patch3; patch3.AddOp(new JsonPatchTestOp(pointer3, new JsonBool(true))); OLA_ASSERT_TRUE(text.Apply(patch3)); JsonPatchSet patch4; patch4.AddOp(new JsonPatchTestOp(pointer4, new JsonBool(true))); OLA_ASSERT_FALSE(text.Apply(patch4)); JsonPatchSet patch5; patch5.AddOp(new JsonPatchTestOp(pointer3, new JsonBool(false))); OLA_ASSERT_FALSE(text.Apply(patch5)); // Now try a multi-element patch JsonPatchSet patch6; patch6.AddOp(new JsonPatchTestOp(pointer3, new JsonBool(true))); patch6.AddOp(new JsonPatchTestOp(pointer4, new JsonBool(false))); OLA_ASSERT_TRUE(text.Apply(patch6)); JsonPatchSet patch7; patch7.AddOp(new JsonPatchTestOp(pointer3, new JsonBool(true))); patch7.AddOp(new JsonPatchTestOp(pointer4, new JsonBool(true))); OLA_ASSERT_FALSE(text.Apply(patch7)); JsonPatchSet patch8; patch8.AddOp(new JsonPatchTestOp(pointer3, new JsonNull())); patch8.AddOp(new JsonPatchTestOp(pointer4, new JsonBool(false))); OLA_ASSERT_FALSE(text.Apply(patch8)); // Finally check an invalid pointer JsonPointer invalid_pointer("foo"); JsonPatchSet patch9; patch9.AddOp(new JsonPatchTestOp(invalid_pointer, new JsonNull())); OLA_ASSERT_FALSE(text.Apply(patch9)); // Check no changes were made OLA_ASSERT_TRUE(*(original_object.get()) == *(text.Value())); } void JsonPatchTest::testAtomicUpdates() { JsonData text(NULL); BuildSampleText(&text); // Test a patch which will never pass. This is from section 5 of the RFC. { JsonPatchSet patch; patch.AddOp(new JsonPatchReplaceOp( JsonPointer("/foo"), new JsonInt(42))); patch.AddOp(new JsonPatchTestOp( JsonPointer("/foo"), new JsonString("C"))); OLA_ASSERT_FALSE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": false, " " \"object\": {\"bat\": 1}, \"array\": [1,2,3] }", text.Value()); } // Now try a test-and-patch sequence { JsonPatchSet patch; patch.AddOp(new JsonPatchTestOp( JsonPointer("/foo"), new JsonString("bar"))); patch.AddOp(new JsonPatchReplaceOp( JsonPointer("/baz"), new JsonBool(true))); OLA_ASSERT_TRUE(text.Apply(patch)); CheckValuesMatch( "{\"foo\": \"bar\", \"baz\": true, " " \"object\": {\"bat\": 1}, \"array\": [1,2,3] }", text.Value()); } } ola-0.10.5.nojsmin/common/web/Json.cpp0000644000175000017500000005200413023355232017141 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Json.cpp * A simple set of classes for generating JSON. * See http://www.json.org/ * Copyright (C) 2012 Simon Newton */ #include #include #include #include "ola/stl/STLUtils.h" #include "ola/web/Json.h" namespace ola { namespace web { using std::ostream; using std::ostringstream; using std::string; namespace { class ObjectCastVisitor : public JsonValueVisitorInterface { public: ObjectCastVisitor() : m_obj(NULL) {} void Visit(JsonString *value) { (void) value; } void Visit(JsonBool *value) { (void) value; } void Visit(JsonNull *value) { (void) value; } void Visit(JsonRawValue *value) { (void) value; } void Visit(JsonObject *value) { m_obj = value; } void Visit(JsonArray *value) { (void) value; } void Visit(JsonUInt *value) { (void) value; } void Visit(JsonUInt64 *value) { (void) value; } void Visit(JsonInt *value) { (void) value; } void Visit(JsonInt64 *value) { (void) value; } void Visit(JsonDouble *value) { (void) value; } JsonObject *Object() { return m_obj; } private: JsonObject *m_obj; }; class ArrayCastVisitor : public JsonValueVisitorInterface { public: ArrayCastVisitor() : m_array(NULL) {} void Visit(JsonString *value) { (void) value; } void Visit(JsonBool *value) { (void) value; } void Visit(JsonNull *value) { (void) value; } void Visit(JsonRawValue *value) { (void) value; } void Visit(JsonObject *value) { (void) value; } void Visit(JsonArray *value) { m_array = value; } void Visit(JsonUInt *value) { (void) value; } void Visit(JsonUInt64 *value) { (void) value; } void Visit(JsonInt *value) { (void) value; } void Visit(JsonInt64 *value) { (void) value; } void Visit(JsonDouble *value) { (void) value; } JsonArray *Array() { return m_array; } private: JsonArray *m_array; }; } // namespace JsonValue* JsonValue::LookupElement(const JsonPointer &pointer) { JsonPointer::Iterator iter = pointer.begin(); return LookupElementWithIter(&iter); } JsonValue* JsonLeafValue::LookupElementWithIter( JsonPointer::Iterator *iterator) { if (!iterator->IsValid() || !iterator->AtEnd()) { return NULL; } (*iterator)++; // increment to move past the end. return this; } // Integer equality functions namespace { /* * This isn't pretty but it works. The original version used * numeric_limits::is_signed, numeric_limits::digits & numeric_limits::is_exact * to reduce the amount of code. However I couldn't get it to work without * signed vs unsigned warnings in gcc. */ template int CompareNumbers(T1 a, T2 b); template <> int CompareNumbers(uint32_t a, uint32_t b) { return (a < b) ? -1 : (a > b); } template <> int CompareNumbers(uint32_t a, int32_t b) { if (b < 0) { return 1; } return (a < static_cast(b)) ? -1 : (a > static_cast(b)); } template <> int CompareNumbers(uint32_t a, uint64_t b) { return (static_cast(a) < b) ? -1 : (static_cast(a) > b); } template <> int CompareNumbers(uint32_t a, int64_t b) { if (b < 0) { return 1; } return (static_cast(a) < b) ? -1 : (static_cast(a) > b); } template <> int CompareNumbers(uint32_t a, double b) { return (static_cast(a) < b) ? -1 : (static_cast(a) > b); } template <> int CompareNumbers(int32_t a, uint32_t b) { if (a < 0) { return -1; } return (static_cast(a) < b) ? -1 : (static_cast(a) > b); } template <> int CompareNumbers(int32_t a, int32_t b) { return (a < b) ? -1 : (a > b); } template <> int CompareNumbers(int32_t a, uint64_t b) { if (a < 0) { return -1; } return (static_cast(a) < b) ? -1 : (static_cast(a) > b); } template <> int CompareNumbers(int32_t a, int64_t b) { return (static_cast(a) < b) ? -1 : (static_cast(a) > b); } template <> int CompareNumbers(int32_t a, double b) { return (static_cast(a) < b) ? -1 : (static_cast(a) > b); } template <> int CompareNumbers(uint64_t a, uint32_t b) { return (a < static_cast(b)) ? -1 : (a > static_cast(b)); } template <> int CompareNumbers(uint64_t a, int32_t b) { if (b < 0) { return 1; } return (a < static_cast(b)) ? -1 : (a > static_cast(b)); } template <> int CompareNumbers(uint64_t a, uint64_t b) { return (a < b) ? -1 : (a > b); } template <> int CompareNumbers(uint64_t a, int64_t b) { if (b < 0) { return 1; } return (a < static_cast(b)) ? -1 : (a > static_cast(b)); } template <> int CompareNumbers(uint64_t a, double b) { return (static_cast(a) < b) ? -1 : (static_cast(a) > b); } template <> int CompareNumbers(int64_t a, uint32_t b) { if (a < 0) { return -1; } return (a < static_cast(b)) ? -1 : (a > static_cast(b)); } template <> int CompareNumbers(int64_t a, int32_t b) { return (static_cast(a) < b) ? -1 : (static_cast(a) > b); } template <> int CompareNumbers(int64_t a, uint64_t b) { if (a < 0) { return -1; } return (static_cast(a) < b) ? -1 : (static_cast(a) > b); } template <> int CompareNumbers(int64_t a, int64_t b) { return (a < b) ? -1 : (a > b); } template <> int CompareNumbers(int64_t a, double b) { return (static_cast(a) < b) ? -1 : (static_cast(a) > b); } template <> int CompareNumbers(double a, uint32_t b) { return (a < static_cast(b)) ? -1 : (a > static_cast(b)); } template <> int CompareNumbers(double a, int32_t b) { return (a < static_cast(b)) ? -1 : (a > static_cast(b)); } template <> int CompareNumbers(double a, uint64_t b) { return (a < static_cast(b)) ? -1 : (a > static_cast(b)); } template <> int CompareNumbers(double a, int64_t b) { return (a < static_cast(b)) ? -1 : (a > static_cast(b)); } template <> int CompareNumbers(double a, double b) { return (a < b) ? -1 : (a > b); } } // namespace // Number equality functions bool JsonUInt::Equals(const JsonInt &other) const { return CompareNumbers(m_value, other.Value()) == 0; } bool JsonUInt::Equals(const JsonUInt64 &other) const { return CompareNumbers(m_value, other.Value()) == 0; } bool JsonUInt::Equals(const JsonInt64 &other) const { return CompareNumbers(m_value, other.Value()) == 0; } bool JsonInt::Equals(const JsonUInt &other) const { return CompareNumbers(m_value, other.Value()) == 0; } bool JsonInt::Equals(const JsonUInt64 &other) const { return CompareNumbers(m_value, other.Value()) == 0; } bool JsonInt::Equals(const JsonInt64 &other) const { return CompareNumbers(m_value, other.Value()) == 0; } bool JsonUInt64::Equals(const JsonUInt &other) const { return CompareNumbers(m_value, other.Value()) == 0; } bool JsonUInt64::Equals(const JsonInt &other) const { return CompareNumbers(m_value, other.Value()) == 0; } bool JsonUInt64::Equals(const JsonInt64 &other) const { return CompareNumbers(m_value, other.Value()) == 0; } bool JsonInt64::Equals(const JsonUInt &other) const { return CompareNumbers(m_value, other.Value()) == 0; } bool JsonInt64::Equals(const JsonInt &other) const { return CompareNumbers(m_value, other.Value()) == 0; } bool JsonInt64::Equals(const JsonUInt64 &other) const { return CompareNumbers(m_value, other.Value()) == 0; } // Number inequality functions int JsonUInt::Compare(const JsonUInt &other) const { return CompareNumbers(m_value, other.Value()); } int JsonUInt::Compare(const JsonInt &other) const { return CompareNumbers(m_value, other.Value()); } int JsonUInt::Compare(const JsonUInt64 &other) const { return CompareNumbers(m_value, other.Value()); } int JsonUInt::Compare(const JsonInt64 &other) const { return CompareNumbers(m_value, other.Value()); } int JsonUInt::Compare(const JsonDouble &other) const { return CompareNumbers(m_value, other.Value()); } int JsonInt::Compare(const JsonUInt &other) const { return CompareNumbers(m_value, other.Value()); } int JsonInt::Compare(const JsonInt &other) const { return CompareNumbers(m_value, other.Value()); } int JsonInt::Compare(const JsonUInt64 &other) const { return CompareNumbers(m_value, other.Value()); } int JsonInt::Compare(const JsonInt64 &other) const { return CompareNumbers(m_value, other.Value()); } int JsonInt::Compare(const JsonDouble &other) const { return CompareNumbers(m_value, other.Value()); } int JsonUInt64::Compare(const JsonUInt &other) const { return CompareNumbers(m_value, other.Value()); } int JsonUInt64::Compare(const JsonInt &other) const { return CompareNumbers(m_value, other.Value()); } int JsonUInt64::Compare(const JsonUInt64 &other) const { return CompareNumbers(m_value, other.Value()); } int JsonUInt64::Compare(const JsonInt64 &other) const { return CompareNumbers(m_value, other.Value()); } int JsonUInt64::Compare(const JsonDouble &other) const { return CompareNumbers(m_value, other.Value()); } int JsonInt64::Compare(const JsonUInt &other) const { return CompareNumbers(m_value, other.Value()); } int JsonInt64::Compare(const JsonInt &other) const { return CompareNumbers(m_value, other.Value()); } int JsonInt64::Compare(const JsonUInt64 &other) const { return CompareNumbers(m_value, other.Value()); } int JsonInt64::Compare(const JsonInt64 &other) const { return CompareNumbers(m_value, other.Value()); } int JsonInt64::Compare(const JsonDouble &other) const { return CompareNumbers(m_value, other.Value()); } int JsonDouble::Compare(const JsonUInt &other) const { return CompareNumbers(m_value, other.Value()); } int JsonDouble::Compare(const JsonInt &other) const { return CompareNumbers(m_value, other.Value()); } int JsonDouble::Compare(const JsonUInt64 &other) const { return CompareNumbers(m_value, other.Value()); } int JsonDouble::Compare(const JsonInt64 &other) const { return CompareNumbers(m_value, other.Value()); } int JsonDouble::Compare(const JsonDouble &other) const { return CompareNumbers(m_value, other.Value()); } bool JsonUInt::FactorOf(const JsonUInt &value) const { return value.Value() % m_value == 0; } bool JsonUInt::FactorOf(const JsonInt &value) const { return value.Value() % m_value == 0; } bool JsonUInt::FactorOf(const JsonUInt64 &value) const { return value.Value() % m_value == 0; } bool JsonUInt::FactorOf(const JsonInt64 &value) const { return value.Value() % m_value == 0; } bool JsonUInt::FactorOf(const JsonDouble &value) const { return fmod(value.Value(), m_value) == 0; } bool JsonInt::FactorOf(const JsonUInt &value) const { return value.Value() % m_value == 0; } bool JsonInt::FactorOf(const JsonInt &value) const { return value.Value() % m_value == 0; } bool JsonInt::FactorOf(const JsonUInt64 &value) const { return value.Value() % m_value == 0; } bool JsonInt::FactorOf(const JsonInt64 &value) const { return value.Value() % m_value == 0; } bool JsonInt::FactorOf(const JsonDouble &value) const { return fmod(value.Value(), m_value) == 0; } bool JsonUInt64::FactorOf(const JsonUInt &value) const { return value.Value() % m_value == 0; } bool JsonUInt64::FactorOf(const JsonInt &value) const { return value.Value() % m_value == 0; } bool JsonUInt64::FactorOf(const JsonUInt64 &value) const { return value.Value() % m_value == 0; } bool JsonUInt64::FactorOf(const JsonInt64 &value) const { return value.Value() % m_value == 0; } bool JsonUInt64::FactorOf(const JsonDouble &value) const { return fmod(value.Value(), m_value) == 0; } bool JsonInt64::FactorOf(const JsonUInt &value) const { return value.Value() % m_value == 0; } bool JsonInt64::FactorOf(const JsonInt &value) const { return value.Value() % m_value == 0; } bool JsonInt64::FactorOf(const JsonUInt64 &value) const { return value.Value() % m_value == 0; } bool JsonInt64::FactorOf(const JsonInt64 &value) const { return value.Value() % m_value == 0; } bool JsonInt64::FactorOf(const JsonDouble &value) const { return fmod(value.Value(), m_value) == 0; } bool JsonDouble::FactorOf(const JsonUInt &value) const { return fmod(value.Value(), m_value) == 0; } bool JsonDouble::FactorOf(const JsonInt &value) const { return fmod(value.Value(), m_value) == 0; } bool JsonDouble::FactorOf(const JsonUInt64 &value) const { return fmod(value.Value(), m_value) == 0; } bool JsonDouble::FactorOf(const JsonInt64 &value) const { return fmod(value.Value(), m_value) == 0; } bool JsonDouble::FactorOf(const JsonDouble &value) const { return fmod(value.Value(), m_value) == 0; } JsonDouble::JsonDouble(double value) : m_value(value) { ostringstream str; str << value; m_as_string = str.str(); } JsonDouble::JsonDouble(const DoubleRepresentation &rep) { AsDouble(rep, &m_value); m_as_string = AsString(rep); } bool JsonDouble::AsDouble(const DoubleRepresentation &rep, double *out) { // TODO(simon): Check the limits here. double d = rep.fractional; while (d >= 1.0) { d /= 10.0; } for (unsigned int i = 0; i < rep.leading_fractional_zeros; i++) { d /= 10; } d += rep.full; d *= pow(10, rep.exponent); if (rep.is_negative && d != 0.0) { d *= -1; } *out = d; return true; } string JsonDouble::AsString(const DoubleRepresentation &rep) { // Populate the string member if (rep.full == 0 && rep.fractional == 0) { return "0"; } ostringstream output; if (rep.is_negative) { output << "-"; } output << rep.full; if (rep.fractional) { output << "."; if (rep.leading_fractional_zeros) { output << string(rep.leading_fractional_zeros, '0'); } output << rep.fractional; } if (rep.exponent) { output << "e" << rep.exponent; } return output.str(); } JsonObject::~JsonObject() { STLDeleteValues(&m_members); } JsonValue* JsonObject::LookupElementWithIter(JsonPointer::Iterator *iterator) { if (!iterator->IsValid()) { return NULL; } if (iterator->AtEnd()) { return this; } const string token = **iterator; (*iterator)++; JsonValue *value = STLFindOrNull(m_members, token); if (value) { return value->LookupElementWithIter(iterator); } else { return NULL; } } bool JsonObject::Equals(const JsonObject &other) const { if (m_members.size() != other.m_members.size()) { return false; } MemberMap::const_iterator our_iter = m_members.begin(); MemberMap::const_iterator other_iter = other.m_members.begin(); for (; our_iter != m_members.end() && other_iter != other.m_members.end(); our_iter++, other_iter++) { if (our_iter->first != other_iter->first || *(our_iter->second) != *(other_iter->second)) { return false; } } return true; } void JsonObject::Add(const string &key, const string &value) { STLReplaceAndDelete(&m_members, key, new JsonString(value)); } void JsonObject::Add(const string &key, const char *value) { Add(key, string(value)); } void JsonObject::Add(const string &key, unsigned int i) { STLReplaceAndDelete(&m_members, key, new JsonUInt(i)); } void JsonObject::Add(const string &key, int i) { STLReplaceAndDelete(&m_members, key, new JsonInt(i)); } void JsonObject::Add(const string &key, double d) { STLReplaceAndDelete(&m_members, key, new JsonDouble(d)); } void JsonObject::Add(const string &key, bool value) { STLReplaceAndDelete(&m_members, key, new JsonBool(value)); } void JsonObject::Add(const string &key) { STLReplaceAndDelete(&m_members, key, new JsonNull()); } void JsonObject::AddRaw(const string &key, const string &value) { STLReplaceAndDelete(&m_members, key, new JsonRawValue(value)); } bool JsonObject::Remove(const string &key) { return STLRemoveAndDelete(&m_members, key); } bool JsonObject::ReplaceValue(const string &key, JsonValue *value) { MemberMap::iterator iter = m_members.find(key); if (iter == m_members.end()) { delete value; return false; } else { delete iter->second; iter->second = value; return true; } } JsonObject* JsonObject::AddObject(const string &key) { JsonObject *obj = new JsonObject(); STLReplaceAndDelete(&m_members, key, obj); return obj; } JsonArray* JsonObject::AddArray(const string &key) { JsonArray *array = new JsonArray(); STLReplaceAndDelete(&m_members, key, array); return array; } void JsonObject::AddValue(const string &key, JsonValue *value) { STLReplaceAndDelete(&m_members, key, value); } JsonValue* JsonObject::Clone() const { JsonObject *object = new JsonObject(); MemberMap::const_iterator iter = m_members.begin(); for (; iter != m_members.end(); ++iter) { object->AddValue(iter->first, iter->second->Clone()); } return object; } void JsonObject::VisitProperties(JsonObjectPropertyVisitor *visitor) const { MemberMap::const_iterator iter = m_members.begin(); for (; iter != m_members.end(); ++iter) { visitor->VisitProperty(iter->first, *(iter->second)); } } JsonArray::~JsonArray() { STLDeleteElements(&m_values); } JsonValue* JsonArray::LookupElementWithIter(JsonPointer::Iterator *iterator) { if (!iterator->IsValid()) { return NULL; } if (iterator->AtEnd()) { return this; } unsigned int index; if (!StringToInt(**iterator, &index, true)) { (*iterator)++; return NULL; } (*iterator)++; if (index < m_values.size()) { return m_values[index]->LookupElementWithIter(iterator); } else { return NULL; } } bool JsonArray::Equals(const JsonArray &other) const { if (m_values.size() != other.m_values.size()) { return false; } ValuesVector::const_iterator our_iter = m_values.begin(); ValuesVector::const_iterator other_iter = other.m_values.begin(); for (; our_iter != m_values.end() && other_iter != other.m_values.end(); our_iter++, other_iter++) { if (**our_iter != **other_iter) { return false; } } return true; } bool JsonArray::RemoveElementAt(uint32_t index) { if (index < m_values.size()) { ValuesVector::iterator iter = m_values.begin() + index; delete *iter; m_values.erase(iter); return true; } return false; } bool JsonArray::ReplaceElementAt(uint32_t index, JsonValue *value) { if (index < m_values.size()) { ValuesVector::iterator iter = m_values.begin() + index; delete *iter; *iter = value; return true; } // Ownership is transferred, so it's up to us to delete it. delete value; return false; } bool JsonArray::InsertElementAt(uint32_t index, JsonValue *value) { if (index < m_values.size()) { ValuesVector::iterator iter = m_values.begin() + index; m_values.insert(iter, value); return true; } // Ownership is transferred, so it's up to us to delete it. delete value; return false; } JsonValue* JsonArray::Clone() const { JsonArray *array = new JsonArray(); ValuesVector::const_iterator iter = m_values.begin(); for (; iter != m_values.end(); iter++) { array->AppendValue((*iter)->Clone()); } return array; } const JsonValue *JsonArray::ElementAt(unsigned int i) const { if (i < m_values.size()) { return m_values[i]; } else { return NULL; } } JsonObject* ObjectCast(JsonValue *value) { // Benchmarks for 100M operations // dynamic_cast<> : 1.8s // Type() method & static_cast<>: 0.39s // typeip(value) == .. & static_cast<> : 0.34s // &typeif(value) == .. &static_cast<>: 0.30s // Visitor pattern : 2.18s // // The visitor pattern is more costly since it requires 2 vtable lookups. // If performance becomes an issue we should consider static_cast<> here. ObjectCastVisitor visitor; value->Accept(&visitor); return visitor.Object(); } JsonArray* ArrayCast(JsonValue *value) { ArrayCastVisitor visitor; value->Accept(&visitor); return visitor.Array(); } // operator<< std::ostream& operator<<(std::ostream &os, const JsonString &value) { return os << value.Value(); } std::ostream& operator<<(std::ostream &os, const JsonUInt &value) { return os << value.Value(); } std::ostream& operator<<(std::ostream &os, const JsonInt &value) { return os << value.Value(); } std::ostream& operator<<(std::ostream &os, const JsonUInt64 &value) { return os << value.Value(); } std::ostream& operator<<(std::ostream &os, const JsonInt64 &value) { return os << value.Value(); } std::ostream& operator<<(std::ostream &os, const JsonDouble &value) { return os << value.Value(); } std::ostream& operator<<(std::ostream &os, const JsonBool &value) { return os << value.Value(); } std::ostream& operator<<(std::ostream &os, const JsonNull &) { return os << "null"; } std::ostream& operator<<(std::ostream &os, const JsonRawValue &value) { return os << value.Value(); } } // namespace web } // namespace ola ola-0.10.5.nojsmin/common/web/SchemaParserTest.cpp0000644000175000017500000002410213023355232021443 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SchemaParserTest.cpp * Unittests for the Json Schema Parser. * This uses testcases from the testdata directory. * Copyright (C) 2014 Simon Newton */ #include #include #include #include #include #include "ola/Logging.h" #include "ola/file/Util.h" #include "ola/testing/TestUtils.h" #include "ola/web/JsonSchema.h" #include "ola/web/JsonWriter.h" using ola::web::JsonObject; using ola::web::JsonSchema; using std::auto_ptr; using std::ostringstream; using std::string; using std::vector; class JsonSchemaParserTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(JsonSchemaParserTest); CPPUNIT_TEST(testPrimitiveTypes); CPPUNIT_TEST(testEmptySchema); CPPUNIT_TEST(testBasicKeywords); CPPUNIT_TEST(testTypes); CPPUNIT_TEST(testIntegers); CPPUNIT_TEST(testStrings); CPPUNIT_TEST(testArrays); CPPUNIT_TEST(testObjects); CPPUNIT_TEST(testMisc); CPPUNIT_TEST(testAllOf); CPPUNIT_TEST(testAnyOf); CPPUNIT_TEST(testOneOf); CPPUNIT_TEST(testNot); CPPUNIT_TEST(testDefinitions); CPPUNIT_TEST(testSchema); CPPUNIT_TEST_SUITE_END(); public: void testPrimitiveTypes(); void testEmptySchema(); void testBasicKeywords(); void testTypes(); void testIntegers(); void testStrings(); void testArrays(); void testObjects(); void testMisc(); void testAllOf(); void testAnyOf(); void testOneOf(); void testNot(); void testDefinitions(); void testSchema(); private: struct TestCase { string input; string expected; }; typedef vector PositiveTests; typedef vector NegativeTests; void ReadTestCases(const string& filename, PositiveTests *positive_tests, NegativeTests *negative_tests); void FinalizePositiveCase(TestCase *test, PositiveTests *positive_tests); void FinalizeNegativeCase(string *test, NegativeTests *negative_tests); void ParseSchemaAndConvertToJson(const string &input, const string &expected); void VerifyFailure(const string &input); void RunTestsInFile(const string &test_file); }; CPPUNIT_TEST_SUITE_REGISTRATION(JsonSchemaParserTest); void JsonSchemaParserTest::FinalizePositiveCase( TestCase *test, PositiveTests *positive_tests) { if (test->input.empty()) { return; } // If no expected string was supplied, it defaults to the input string. if (test->expected.empty()) { test->expected = test->input; } positive_tests->push_back(*test); test->input.clear(); test->expected.clear(); } void JsonSchemaParserTest::FinalizeNegativeCase( string *test, NegativeTests *negative_tests) { if (!test->empty()) { negative_tests->push_back(*test); test->clear(); } } /** * * TestCases are separated by ======== (8 x =) * The input and expected result is separated by -------- (8 x -) * If the input and the expected is the same the -------- can be omitted. */ void JsonSchemaParserTest::ReadTestCases(const string& filename, PositiveTests *positive_tests, NegativeTests *negative_tests) { string file_path; file_path.append(TEST_SRC_DIR); file_path.push_back(ola::file::PATH_SEPARATOR); file_path.append("common"); file_path.push_back(ola::file::PATH_SEPARATOR); file_path.append("web"); file_path.push_back(ola::file::PATH_SEPARATOR); file_path.append("testdata"); file_path.push_back(ola::file::PATH_SEPARATOR); file_path.append(filename); std::ifstream in(file_path.data(), std::ios::in); OLA_ASSERT_TRUE_MSG(in.is_open(), file_path); enum Mode { NEGATIVE_INPUT, POSITIVE_INPUT, POSITIVE_EXPECTED, }; TestCase test_case; string negative_test; Mode mode = POSITIVE_INPUT; const string comment_prefix = "//"; string line; while (getline(in, line)) { if (line.compare(0, comment_prefix.size(), comment_prefix) == 0) { continue; } else if (line == "--------") { mode = POSITIVE_EXPECTED; } else if (line == "=== POSITIVE ===") { FinalizePositiveCase(&test_case, positive_tests); FinalizeNegativeCase(&negative_test, negative_tests); mode = POSITIVE_INPUT; } else if (line == "=== NEGATIVE ===") { FinalizePositiveCase(&test_case, positive_tests); FinalizeNegativeCase(&negative_test, negative_tests); mode = NEGATIVE_INPUT; } else if (mode == POSITIVE_INPUT) { test_case.input.append(line); test_case.input.push_back('\n'); } else if (mode == POSITIVE_EXPECTED) { test_case.expected.append(line); test_case.expected.push_back('\n'); } else if (mode == NEGATIVE_INPUT) { negative_test.append(line); negative_test.push_back('\n'); } } FinalizePositiveCase(&test_case, positive_tests); FinalizeNegativeCase(&negative_test, negative_tests); in.close(); } /** * Parse a JSON schema, confirm there are no errors, serialize back to JSON and * compare with the expected schema. */ void JsonSchemaParserTest::ParseSchemaAndConvertToJson(const string &input, const string &expected) { string error; auto_ptr schema(JsonSchema::FromString(input, &error)); OLA_ASSERT_EQ(string(""), error); OLA_ASSERT_NOT_NULL(schema.get()); auto_ptr schema_json(schema->AsJson()); string actual = ola::web::JsonWriter::AsString(*schema_json); actual.push_back('\n'); OLA_ASSERT_EQ(expected, actual); } /** * Verify that the given schema is invalid */ void JsonSchemaParserTest::VerifyFailure(const string &input) { string error; auto_ptr schema(JsonSchema::FromString(input, &error)); bool failed = !error.empty(); if (!failed) { ostringstream str; str << "Expected schema to fail parsing:\n" << input; OLA_FAIL(str.str()); } } void JsonSchemaParserTest::RunTestsInFile(const string &test_file) { PositiveTests positive_tests; NegativeTests negative_tests; ReadTestCases(test_file, &positive_tests, &negative_tests); OLA_INFO << "Read " << positive_tests.size() << " positive tests, " << negative_tests.size() << " negative tests from " << test_file; PositiveTests::const_iterator iter = positive_tests.begin(); for (; iter != positive_tests.end(); ++iter) { ParseSchemaAndConvertToJson(iter->input, iter->expected); } NegativeTests::const_iterator neg_iter = negative_tests.begin(); for (; neg_iter != negative_tests.end(); ++neg_iter) { VerifyFailure(*neg_iter); } } void JsonSchemaParserTest::testPrimitiveTypes() { string error; auto_ptr schema(JsonSchema::FromString("null", &error)); OLA_ASSERT_NULL(schema.get()); OLA_ASSERT_FALSE(error.empty()); schema.reset(JsonSchema::FromString("1", &error)); OLA_ASSERT_NULL(schema.get()); OLA_ASSERT_FALSE(error.empty()); schema.reset(JsonSchema::FromString("-1", &error)); OLA_ASSERT_NULL(schema.get()); OLA_ASSERT_FALSE(error.empty()); schema.reset(JsonSchema::FromString("true", &error)); OLA_ASSERT_NULL(schema.get()); OLA_ASSERT_FALSE(error.empty()); schema.reset(JsonSchema::FromString("[1, 2]", &error)); OLA_ASSERT_NULL(schema.get()); OLA_ASSERT_FALSE(error.empty()); schema.reset(JsonSchema::FromString("\"foo\"", &error)); OLA_ASSERT_NULL(schema.get()); OLA_ASSERT_FALSE(error.empty()); schema.reset(JsonSchema::FromString("[null, [1], {} ]", &error)); OLA_ASSERT_NULL(schema.get()); OLA_ASSERT_FALSE(error.empty()); } void JsonSchemaParserTest::testEmptySchema() { string error; auto_ptr schema(JsonSchema::FromString("{}", &error)); OLA_ASSERT_NOT_NULL(schema.get()); OLA_ASSERT_TRUE(error.empty()); auto_ptr value(schema->AsJson()); OLA_ASSERT_NOT_NULL(value.get()); OLA_ASSERT_EQ(string("{}"), ola::web::JsonWriter::AsString(*value)); } /** * Verify basic keywords like 'id', '$schema', 'title' & 'description' work * correctly. */ void JsonSchemaParserTest::testBasicKeywords() { RunTestsInFile("basic-keywords.test"); } void JsonSchemaParserTest::testTypes() { RunTestsInFile("type.test"); } /** * Verify integers parse correctly. */ void JsonSchemaParserTest::testIntegers() { RunTestsInFile("integers.test"); } /** * Verify strings parse correctly. */ void JsonSchemaParserTest::testStrings() { RunTestsInFile("strings.test"); } /** * Verify arrays parse correctly. */ void JsonSchemaParserTest::testArrays() { // Test the various combinations of 'items' & 'additionalItems' // items can be either a schema (object) or an array // additionalItems can be either a bool or a schema. RunTestsInFile("arrays.test"); } /** * Verify objects parse correctly. */ void JsonSchemaParserTest::testObjects() { RunTestsInFile("objects.test"); } /** * Various other test cases. */ void JsonSchemaParserTest::testMisc() { RunTestsInFile("misc.test"); } /** * Test allOf */ void JsonSchemaParserTest::testAllOf() { RunTestsInFile("allof.test"); } /** * Test anyOf */ void JsonSchemaParserTest::testAnyOf() { RunTestsInFile("anyof.test"); } /** * Test oneOf */ void JsonSchemaParserTest::testOneOf() { RunTestsInFile("oneof.test"); } /** * Test not */ void JsonSchemaParserTest::testNot() { RunTestsInFile("not.test"); } /** * Test definitions. */ void JsonSchemaParserTest::testDefinitions() { RunTestsInFile("definitions.test"); } void JsonSchemaParserTest::testSchema() { RunTestsInFile("schema.json"); } ola-0.10.5.nojsmin/common/web/JsonPatch.cpp0000644000175000017500000001724413023355232020130 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * JsonPatch.cpp * Implementation of RFC 6902. * Copyright (C) 2014 Simon Newton */ #include "ola/web/JsonPatch.h" #include #include #include #include "ola/Logging.h" #include "ola/stl/STLUtils.h" #include "ola/web/Json.h" #include "ola/web/JsonPointer.h" namespace ola { namespace web { using std::string; namespace { string LastToken(const JsonPointer &pointer) { return pointer.TokenAt(pointer.TokenCount() - 2); } JsonValue *GetParent(JsonValue *value, const JsonPointer &pointer) { JsonPointer parent_pointer(pointer); parent_pointer.Pop(); return value->LookupElement(parent_pointer); } /** * Most ops have an if-object-then, else-if-array-then clause. This puts all * the grunt work in a single method */ class ObjectOrArrayAction { public: virtual ~ObjectOrArrayAction() {} bool TakeActionOn(JsonValue *value, const JsonPointer &target); // Implement these with the specific actions virtual bool Object(JsonObject *object, const string &key) = 0; virtual bool ArrayIndex(JsonArray *array, uint32_t index) = 0; // Called when the index is '-' virtual bool ArrayLast(JsonArray *array) = 0; }; bool ObjectOrArrayAction::TakeActionOn(JsonValue *value, const JsonPointer &target) { JsonValue *parent = GetParent(value, target); if (!parent) { return false; } const string key = LastToken(target); JsonObject *object = ObjectCast(parent); if (object) { return Object(object, key); } JsonArray *array = ArrayCast(parent); if (array) { if (key == "-") { return ArrayLast(array); } uint32_t index; if (!StringToInt(key, &index)) { return false; } return ArrayIndex(array, index); } return false; } class AddAction : public ObjectOrArrayAction { public: explicit AddAction(const JsonValue *value_to_clone) : m_value(value_to_clone) {} bool Object(JsonObject *object, const string &key) { object->AddValue(key, m_value->Clone()); return true; } bool ArrayIndex(JsonArray *array, uint32_t index) { return array->InsertElementAt(index, m_value->Clone()); } bool ArrayLast(JsonArray *array) { array->AppendValue(m_value->Clone()); return true; } private: const JsonValue *m_value; }; class RemoveAction : public ObjectOrArrayAction { public: bool Object(JsonObject *object, const string &key) { return object->Remove(key); } bool ArrayIndex(JsonArray *array, uint32_t index) { return array->RemoveElementAt(index); } bool ArrayLast(JsonArray *array) { if (array->IsEmpty()) { return false; } array->RemoveElementAt(array->Size() - 1); return true; } }; class ReplaceAction : public ObjectOrArrayAction { public: explicit ReplaceAction(const JsonValue *value) : m_value(value) {} bool Object(JsonObject *object, const string &key) { return object->ReplaceValue(key, m_value->Clone()); } bool ArrayIndex(JsonArray *array, uint32_t index) { return array->ReplaceElementAt(index, m_value->Clone()); } bool ArrayLast(JsonArray *array) { if (array->IsEmpty()) { return false; } array->ReplaceElementAt(array->Size() - 1, m_value->Clone()); return true; } private: const JsonValue *m_value; }; bool AddOp(const JsonPointer &target, JsonValue **root, const JsonValue *value_to_clone) { if (!target.IsValid()) { return false; } if (target.TokenCount() == 1) { // Add also operates as replace as per the spec. // Make a copy before we delete, since the value_to_clone may be within the // root. JsonValue *new_value = value_to_clone ? value_to_clone->Clone() : NULL; if (*root) { delete *root; } *root = new_value; return true; } // If we're not operating on the root, NULLs aren't allowed. if (*root == NULL || value_to_clone == NULL) { return false; } AddAction action(value_to_clone); return action.TakeActionOn(*root, target); } } // namespace bool JsonPatchAddOp::Apply(JsonValue **value) const { return AddOp(m_pointer, value, m_value.get()); } bool JsonPatchRemoveOp::Apply(JsonValue **value) const { if (!m_pointer.IsValid()) { return false; } if (m_pointer.TokenCount() == 1) { delete *value; *value = NULL; return true; } if (*value == NULL) { return false; } RemoveAction action; return action.TakeActionOn(*value, m_pointer); } bool JsonPatchReplaceOp::Apply(JsonValue **value) const { if (!m_pointer.IsValid()) { return false; } if (m_pointer.TokenCount() == 1) { delete *value; *value = m_value.get() ? m_value->Clone() : NULL; return true; } // If we're not operating on the root, NULLs aren't allowed. if (*value == NULL || m_value.get() == NULL) { return false; } ReplaceAction action(m_value.get()); return action.TakeActionOn(*value, m_pointer); } bool JsonPatchMoveOp::Apply(JsonValue **value) const { if (!m_to.IsValid() || !m_from.IsValid()) { return false; } if (m_from == m_to) { return true; } if (m_from.IsPrefixOf(m_to)) { return false; } JsonValue *src_parent = GetParent(*value, m_from); if (!src_parent) { return false; } const string last_token = LastToken(m_from); JsonPointer child_ptr("/" + last_token); JsonValue *source = src_parent->LookupElement(child_ptr); if (!source) { return false; } if (!AddOp(m_to, value, source)) { return false; } if (m_to.IsPrefixOf(m_from)) { // At this point the original has already been destroyed during the Add return true; } RemoveAction action; if (!action.TakeActionOn(src_parent, child_ptr)) { OLA_WARN << "Remove-after-move returned false!"; } return true; } bool JsonPatchCopyOp::Apply(JsonValue **value) const { if (!m_to.IsValid() || !m_from.IsValid()) { return false; } if (m_from == m_to) { return true; } if (*value == NULL) { return false; } JsonValue *src_parent = GetParent(*value, m_from); if (!src_parent) { return false; } const string last_token = LastToken(m_from); JsonPointer child_ptr("/" + last_token); JsonValue *source = src_parent->LookupElement(child_ptr); if (!source) { return false; } return AddOp(m_to, value, source); } bool JsonPatchTestOp::Apply(JsonValue **value) const { if (!m_pointer.IsValid()) { return false; } if (*value == NULL) { return m_pointer.TokenCount() == 1 && m_value.get() == NULL; } JsonValue *target = (*value)->LookupElement(m_pointer); if (!target) { return false; } return *target == *m_value.get(); } JsonPatchSet::~JsonPatchSet() { STLDeleteElements(&m_patch_ops); } void JsonPatchSet::AddOp(JsonPatchOp *op) { m_patch_ops.push_back(op); } bool JsonPatchSet::Apply(JsonValue **value) const { PatchOps::const_iterator iter = m_patch_ops.begin(); for (; iter != m_patch_ops.end(); ++iter) { if (!(*iter)->Apply(value)) { return false; } } return true; } } // namespace web } // namespace ola ola-0.10.5.nojsmin/common/web/JsonSchema.cpp0000644000175000017500000005640513023355232020273 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * JsonSchema.cpp * Json Schema validation. * See http://www.json-schema.org/ * Copyright (C) 2014 Simon Newton */ #include #include #include #include #include #include "ola/Logging.h" #include "common/web/SchemaParser.h" #include "ola/stl/STLUtils.h" #include "ola/web/JsonLexer.h" #include "ola/web/JsonSchema.h" #include "ola/web/JsonTypes.h" namespace ola { namespace web { using std::auto_ptr; using std::set; using std::string; using std::vector; // BaseValidator // ----------------------------------------------------------------------------- BaseValidator::~BaseValidator() { STLDeleteElements(&m_enums); } JsonObject* BaseValidator::GetSchema() const { JsonObject *schema = new JsonObject(); if (!m_schema.empty()) { schema->Add("$schema", m_schema); } if (!m_id.empty()) { schema->Add("id", m_id); } if (!m_title.empty()) { schema->Add("title", m_title); } if (!m_description.empty()) { schema->Add("description", m_description); } const string type = JsonTypeToString(m_type); if (!type.empty()) { schema->Add("type", type); } if (m_default_value.get()) { schema->AddValue("default", m_default_value.get()->Clone()); } if (!m_enums.empty()) { JsonArray *enum_array = schema->AddArray("enum"); vector::const_iterator iter = m_enums.begin(); for (; iter != m_enums.end(); ++iter) { enum_array->AppendValue((*iter)->Clone()); } } ExtendSchema(schema); return schema; } void BaseValidator::SetSchema(const string &schema) { m_schema = schema; } void BaseValidator::SetId(const string &id) { m_id = id; } void BaseValidator::SetTitle(const string &title) { m_title = title; } void BaseValidator::SetDescription(const string &description) { m_description = description; } void BaseValidator::SetDefaultValue(const JsonValue *value) { m_default_value.reset(value); } const JsonValue *BaseValidator::GetDefaultValue() const { return m_default_value.get(); } void BaseValidator::AddEnumValue(const JsonValue *value) { m_enums.push_back(value); } bool BaseValidator::CheckEnums(const JsonValue &value) { if (m_enums.empty()) { return true; } vector::const_iterator iter = m_enums.begin(); for (; iter != m_enums.end(); ++iter) { if (**iter == value) { return true; } } return false; } // ReferenceValidator // ----------------------------------------------------------------------------- ReferenceValidator::ReferenceValidator(const SchemaDefinitions *definitions, const string &schema) : m_definitions(definitions), m_schema(schema), m_validator(NULL) { } bool ReferenceValidator::IsValid() const { return m_validator ? m_validator->IsValid() : false; } void ReferenceValidator::Visit(const JsonString &value) { Validate(value); } void ReferenceValidator::Visit(const JsonBool &value) { Validate(value); } void ReferenceValidator::Visit(const JsonNull &value) { Validate(value); } void ReferenceValidator::Visit(const JsonRawValue &value) { Validate(value); } void ReferenceValidator::Visit(const JsonObject &value) { Validate(value); } void ReferenceValidator::Visit(const JsonArray &value) { Validate(value); } void ReferenceValidator::Visit(const JsonUInt &value) { Validate(value); } void ReferenceValidator::Visit(const JsonUInt64 &value) { Validate(value); } void ReferenceValidator::Visit(const JsonInt &value) { Validate(value); } void ReferenceValidator::Visit(const JsonInt64 &value) { Validate(value); } void ReferenceValidator::Visit(const JsonDouble &value) { Validate(value); } JsonObject* ReferenceValidator::GetSchema() const { JsonObject *schema = new JsonObject(); schema->Add("$ref", m_schema); return schema; } void ReferenceValidator::SetSchema(const std::string&) {} void ReferenceValidator::SetId(const std::string &) {} void ReferenceValidator::SetTitle(const std::string &) {} void ReferenceValidator::SetDescription(const std::string &) {} void ReferenceValidator::SetDefaultValue(const JsonValue *) {} const JsonValue *ReferenceValidator::GetDefaultValue() const { return NULL; } template void ReferenceValidator::Validate(const T &value) { if (!m_validator) { m_validator = m_definitions->Lookup(m_schema); } if (m_validator) { value.Accept(m_validator); } } // StringValidator // ----------------------------------------------------------------------------- void StringValidator::Visit(const JsonString &str) { const std::string& value = str.Value(); size_t str_size = value.size(); if (str_size < m_options.min_length) { m_is_valid = false; return; } if (m_options.max_length >= 0 && str_size > static_cast(m_options.max_length)) { m_is_valid = false; return; } m_is_valid = CheckEnums(str); } void StringValidator::ExtendSchema(JsonObject *schema) const { if (m_options.min_length > 0) { schema->Add("minLength", m_options.min_length); } if (m_options.max_length >= 0) { schema->Add("maxLength", m_options.max_length); } // TODO(simon): Add pattern here? // TODO(simon): Add format here? } // IntegerValidator // ----------------------------------------------------------------------------- IntegerValidator::~IntegerValidator() { STLDeleteElements(&m_constraints); } void IntegerValidator::AddConstraint(NumberConstraint *constraint) { m_constraints.push_back(constraint); } void IntegerValidator::Visit(const JsonUInt &value) { CheckValue(value); } void IntegerValidator::Visit(const JsonInt &value) { CheckValue(value); } void IntegerValidator::Visit(const JsonUInt64 &value) { CheckValue(value); } void IntegerValidator::Visit(const JsonInt64 &value) { CheckValue(value); } void IntegerValidator::Visit(const JsonDouble &value) { BaseValidator::Visit(value); } void IntegerValidator::ExtendSchema(JsonObject *schema) const { vector::const_iterator iter = m_constraints.begin(); for (; iter != m_constraints.end(); ++iter) { (*iter)->ExtendSchema(schema); } } void IntegerValidator::CheckValue(const JsonNumber &value) { vector::const_iterator iter = m_constraints.begin(); for (; iter != m_constraints.end(); ++iter) { if (!(*iter)->IsValid(value)) { m_is_valid = false; return; } } m_is_valid = CheckEnums(value); } void NumberValidator::Visit(const JsonDouble &value) { CheckValue(value); } // ObjectValidator // ----------------------------------------------------------------------------- ObjectValidator::ObjectValidator(const Options &options) : BaseValidator(JSON_OBJECT), m_options(options) { } ObjectValidator::~ObjectValidator() { STLDeleteValues(&m_property_validators); STLDeleteValues(&m_schema_dependencies); } void ObjectValidator::AddValidator(const std::string &property, ValidatorInterface *validator) { STLReplaceAndDelete(&m_property_validators, property, validator); } void ObjectValidator::SetAdditionalValidator(ValidatorInterface *validator) { m_additional_property_validator.reset(validator); } void ObjectValidator::AddSchemaDependency(const string &property, ValidatorInterface *validator) { STLReplaceAndDelete(&m_schema_dependencies, property, validator); } void ObjectValidator::AddPropertyDependency(const string &property, const StringSet &properties) { m_property_dependencies[property] = properties; } void ObjectValidator::Visit(const JsonObject &obj) { m_is_valid = true; if (obj.Size() < m_options.min_properties) { m_is_valid = false; return; } if (m_options.max_properties > 0 && obj.Size() > static_cast(m_options.max_properties)) { m_is_valid = false; return; } m_seen_properties.clear(); obj.VisitProperties(this); StringSet missing_properties; std::set_difference(m_options.required_properties.begin(), m_options.required_properties.end(), m_seen_properties.begin(), m_seen_properties.end(), std::inserter(missing_properties, missing_properties.end())); if (!missing_properties.empty()) { m_is_valid = false; } // Check PropertyDependencies PropertyDependencies::const_iterator prop_iter = m_property_dependencies.begin(); for (; prop_iter != m_property_dependencies.end() && m_is_valid; ++prop_iter) { if (!STLContains(m_seen_properties, prop_iter->first)) { continue; } StringSet::const_iterator iter = prop_iter->second.begin(); for (; iter != prop_iter->second.end(); ++iter) { if (!STLContains(m_seen_properties, *iter)) { m_is_valid = false; break; } } } // Check Schema Dependencies SchemaDependencies::const_iterator schema_iter = m_schema_dependencies.begin(); for (; schema_iter != m_schema_dependencies.end() && m_is_valid; ++schema_iter) { if (STLContains(m_seen_properties, schema_iter->first)) { obj.Accept(schema_iter->second); if (!schema_iter->second->IsValid()) { m_is_valid = false; break; } } } } void ObjectValidator::VisitProperty(const std::string &property, const JsonValue &value) { m_seen_properties.insert(property); // The algorithm is described in section 8.3.3 ValidatorInterface *validator = STLFindOrNull( m_property_validators, property); // patternProperties would be added here if supported if (!validator) { // try the additional validator validator = m_additional_property_validator.get(); } if (validator) { value.Accept(validator); m_is_valid &= validator->IsValid(); } else { // No validator found if (m_options.has_allow_additional_properties && !m_options.allow_additional_properties) { m_is_valid &= false; } } } void ObjectValidator::ExtendSchema(JsonObject *schema) const { if (m_options.min_properties > 0) { schema->Add("minProperties", m_options.min_properties); } if (m_options.max_properties >= 0) { schema->Add("maxProperties", m_options.max_properties); } if (m_options.has_required_properties) { JsonArray *required_properties = schema->AddArray("required"); StringSet::const_iterator iter = m_options.required_properties.begin(); for (; iter != m_options.required_properties.end(); ++iter) { required_properties->Append(*iter); } } if (!m_property_validators.empty()) { JsonObject *properties = schema->AddObject("properties"); PropertyValidators::const_iterator iter = m_property_validators.begin(); for (; iter != m_property_validators.end(); iter++) { JsonObject *child_schema = iter->second->GetSchema(); properties->AddValue(iter->first, child_schema); } } if (m_options.has_allow_additional_properties) { schema->Add("additionalProperties", m_options.allow_additional_properties); } else if (m_additional_property_validator.get()) { schema->AddValue("additionalProperties", m_additional_property_validator->GetSchema()); } if (!(m_property_dependencies.empty() && m_schema_dependencies.empty())) { JsonObject *dependencies = schema->AddObject("dependencies"); PropertyDependencies::const_iterator prop_iter = m_property_dependencies.begin(); for (; prop_iter != m_property_dependencies.end(); ++prop_iter) { JsonArray *properties = dependencies->AddArray(prop_iter->first); StringSet::const_iterator iter = prop_iter->second.begin(); for (; iter != prop_iter->second.end(); ++iter) { properties->Append(*iter); } } SchemaDependencies::const_iterator schema_iter = m_schema_dependencies.begin(); for (; schema_iter != m_schema_dependencies.end(); ++schema_iter) { dependencies->AddValue(schema_iter->first, schema_iter->second->GetSchema()); } } } // ArrayValidator // ----------------------------------------------------------------------------- ArrayValidator::ArrayValidator(Items *items, AdditionalItems *additional_items, const Options &options) : BaseValidator(JSON_ARRAY), m_items(items), m_additional_items(additional_items), m_options(options), m_wildcard_validator(new WildcardValidator()) { } ArrayValidator::~ArrayValidator() {} // items: array or schema (object) // additionalItems : schema (object) or bool // // items = object // items = array, additional = bool // items = array, additional = schema void ArrayValidator::Visit(const JsonArray &array) { if (array.Size() < m_options.min_items) { m_is_valid = false; return; } if (m_options.max_items > 0 && array.Size() > static_cast(m_options.max_items)) { m_is_valid = false; return; } auto_ptr element_validator( ConstructElementValidator()); for (unsigned int i = 0; i < array.Size(); i++) { array.ElementAt(i)->Accept(element_validator.get()); if (!element_validator->IsValid()) { break; } } m_is_valid = element_validator->IsValid(); if (!m_is_valid) { return; } if (m_options.unique_items) { for (unsigned int i = 0; i < array.Size(); i++) { for (unsigned int j = 0; j < i; j++) { if (*(array.ElementAt(i)) == *(array.ElementAt(j))) { m_is_valid = false; return; } } } } } void ArrayValidator::ExtendSchema(JsonObject *schema) const { if (m_options.min_items > 0) { schema->Add("minItems", m_options.min_items); } if (m_options.max_items >= 0) { schema->Add("maxItems", m_options.max_items); } if (m_options.unique_items) { schema->Add("uniqueItems", m_options.unique_items); } if (m_items.get()) { // items exists if (m_items->Validator()) { // items is an object JsonObject *child_schema = m_items->Validator()->GetSchema(); schema->AddValue("items", child_schema); } else { // items is an array const ValidatorList &validators = m_items->Validators(); JsonArray *items = schema->AddArray("items"); ValidatorList::const_iterator iter = validators.begin(); for (; iter != validators.end(); iter++) { JsonObject *child_schema = (*iter)->GetSchema(); items->Append(child_schema); } } } if (m_additional_items.get()) { // additionalItems exists if (m_additional_items->Validator()) { // additionalItems is an object JsonObject *child_schema = m_additional_items->Validator()->GetSchema(); schema->AddValue("additionalItems", child_schema); } else { // additionalItems is a bool schema->Add("additionalItems", m_additional_items->AllowAdditional()); } } } // TODO(simon): do this once at construction, rather than on every visit? ArrayValidator::ArrayElementValidator* ArrayValidator::ConstructElementValidator() const { if (m_items.get()) { if (m_items->Validator()) { // 8.2.3.1, items is an object. ValidatorList empty_validators; return new ArrayElementValidator(empty_validators, m_items->Validator()); } else { // 8.2.3.3, items is an array. const ValidatorList &validators = m_items->Validators(); ValidatorInterface *default_validator = NULL; // Check to see if additionalItems it defined. if (m_additional_items.get()) { if (m_additional_items->Validator()) { // additionalItems is an object default_validator = m_additional_items->Validator(); } else if (m_additional_items->AllowAdditional()) { // additionalItems is a bool, and true default_validator = m_wildcard_validator.get(); } } else { // additionalItems not provided, so it defaults to the empty schema // (wildcard). default_validator = m_wildcard_validator.get(); } return new ArrayElementValidator(validators, default_validator); } } else { // no items, therefore it defaults to the empty (wildcard) schema. ValidatorList empty_validators; return new ArrayElementValidator( empty_validators, m_wildcard_validator.get()); } } // ArrayValidator::ArrayElementValidator // ----------------------------------------------------------------------------- ArrayValidator::ArrayElementValidator::ArrayElementValidator( const ValidatorList &validators, ValidatorInterface *default_validator) : BaseValidator(JSON_UNDEFINED), m_item_validators(validators.begin(), validators.end()), m_default_validator(default_validator) { } void ArrayValidator::ArrayElementValidator::Visit( const JsonString &value) { ValidateItem(value); } void ArrayValidator::ArrayElementValidator::Visit(const JsonBool &value) { ValidateItem(value); } void ArrayValidator::ArrayElementValidator::Visit(const JsonNull &value) { ValidateItem(value); } void ArrayValidator::ArrayElementValidator::Visit(const JsonRawValue &value) { ValidateItem(value); } void ArrayValidator::ArrayElementValidator::Visit(const JsonObject &value) { ValidateItem(value); } void ArrayValidator::ArrayElementValidator::Visit(const JsonArray &value) { ValidateItem(value); } void ArrayValidator::ArrayElementValidator::Visit(const JsonUInt &value) { ValidateItem(value); } void ArrayValidator::ArrayElementValidator::Visit( const JsonUInt64 &value) { ValidateItem(value); } void ArrayValidator::ArrayElementValidator::Visit(const JsonInt &value) { ValidateItem(value); } void ArrayValidator::ArrayElementValidator::Visit(const JsonInt64 &value) { ValidateItem(value); } void ArrayValidator::ArrayElementValidator::Visit( const JsonDouble &value) { ValidateItem(value); } template void ArrayValidator::ArrayElementValidator::ValidateItem(const T &item) { ValidatorInterface *validator = NULL; if (!m_item_validators.empty()) { validator = m_item_validators.front(); m_item_validators.pop_front(); } else if (!m_default_validator) { // additional items aren't allowed m_is_valid = false; return; } else { validator = m_default_validator; } item.Accept(validator); m_is_valid = validator->IsValid(); } // ConjunctionValidator // ----------------------------------------------------------------------------- ConjunctionValidator::ConjunctionValidator(const string &keyword, ValidatorList *validators) : BaseValidator(JSON_UNDEFINED), m_keyword(keyword), m_validators(*validators) { validators->clear(); } ConjunctionValidator::~ConjunctionValidator() { STLDeleteElements(&m_validators); } void ConjunctionValidator::ExtendSchema(JsonObject *schema) const { JsonArray *items = schema->AddArray(m_keyword); ValidatorList::const_iterator iter = m_validators.begin(); for (; iter != m_validators.end(); ++iter) { JsonObject *child_schema = (*iter)->GetSchema(); items->Append(child_schema); } } // AllOfValidator // ----------------------------------------------------------------------------- void AllOfValidator::Validate(const JsonValue &value) { ValidatorList::iterator iter = m_validators.begin(); for (; iter != m_validators.end(); ++iter) { value.Accept(*iter); if (!(*iter)->IsValid()) { m_is_valid = false; return; } } m_is_valid = true; } // AnyOfValidator // ----------------------------------------------------------------------------- void AnyOfValidator::Validate(const JsonValue &value) { ValidatorList::iterator iter = m_validators.begin(); for (; iter != m_validators.end(); ++iter) { value.Accept(*iter); if ((*iter)->IsValid()) { m_is_valid = true; return; } } m_is_valid = false; } // OneOfValidator // ----------------------------------------------------------------------------- void OneOfValidator::Validate(const JsonValue &value) { bool matched = false; ValidatorList::iterator iter = m_validators.begin(); for (; iter != m_validators.end(); ++iter) { value.Accept(*iter); if ((*iter)->IsValid()) { if (matched) { m_is_valid = false; return; } else { matched = true; } } } m_is_valid = matched; } // NotValidator // ----------------------------------------------------------------------------- void NotValidator::Validate(const JsonValue &value) { value.Accept(m_validator.get()); m_is_valid = !m_validator->IsValid(); } void NotValidator::ExtendSchema(JsonObject *schema) const { JsonObject *child_schema = m_validator->GetSchema(); schema->AddValue("not", child_schema); } // SchemaDefinitions // ----------------------------------------------------------------------------- SchemaDefinitions::~SchemaDefinitions() { STLDeleteValues(&m_validators); } void SchemaDefinitions::Add(const string &schema_name, ValidatorInterface *validator) { STLReplaceAndDelete(&m_validators, schema_name, validator); } ValidatorInterface *SchemaDefinitions::Lookup(const string &schema_name) const { return STLFindOrNull(m_validators, schema_name); } void SchemaDefinitions::AddToJsonObject(JsonObject *json) const { SchemaMap::const_iterator iter = m_validators.begin(); for (; iter != m_validators.end(); ++iter) { JsonObject *schema = iter->second->GetSchema(); json->AddValue(iter->first, schema); } } // JsonSchema // ----------------------------------------------------------------------------- JsonSchema::JsonSchema(const std::string &schema_url, ValidatorInterface *root_validator, SchemaDefinitions *schema_defs) : m_schema_uri(schema_url), m_root_validator(root_validator), m_schema_defs(schema_defs) { } string JsonSchema::SchemaURI() const { return m_schema_uri; } bool JsonSchema::IsValid(const JsonValue &value) { value.Accept(m_root_validator.get()); return m_root_validator->IsValid(); } const JsonObject* JsonSchema::AsJson() const { JsonObject *json = m_root_validator->GetSchema(); if (json && m_schema_defs->HasDefinitions()) { JsonObject *definitions = json->AddObject("definitions"); m_schema_defs->AddToJsonObject(definitions); } return json; } JsonSchema* JsonSchema::FromString(const string& schema_string, string *error) { *error = ""; SchemaParser schema_parser; bool ok = JsonLexer::Parse(schema_string, &schema_parser); if (!ok || !schema_parser.IsValidSchema()) { *error = schema_parser.Error(); return NULL; } return new JsonSchema("", schema_parser.ClaimRootValidator(), schema_parser.ClaimSchemaDefs()); } } // namespace web } // namespace ola ola-0.10.5.nojsmin/common/web/PointerTracker.cpp0000644000175000017500000000454113023355232021167 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * PointerTracker.cpp * Maintains a Json pointer from a series of parse events. * Copyright (C) 2014 Simon Newton */ #include #include #include "ola/strings/Format.h" #include "common/web/PointerTracker.h" namespace ola { namespace web { using std::string; using std::vector; void PointerTracker::OpenObject() { IncrementIndex(); Token token(TOKEN_OBJECT); m_tokens.push_back(token); } void PointerTracker::SetProperty(const string &property) { if (m_tokens.empty()) { return; } Token &token = m_tokens.back(); if (token.type != TOKEN_OBJECT) { return; } if (token.property_set) { m_pointer->Pop(); } else { token.property_set = true; } m_pointer->Push(property); } void PointerTracker::CloseObject() { if (m_tokens.empty()) { return; } Token &token = m_tokens.back(); if (token.type == TOKEN_OBJECT) { if (token.property_set) { m_pointer->Pop(); } m_tokens.pop_back(); } } void PointerTracker::OpenArray() { IncrementIndex(); Token token(TOKEN_ARRAY); m_tokens.push_back(token); } void PointerTracker::CloseArray() { if (m_tokens.empty()) { return; } if (m_tokens.back().type == TOKEN_ARRAY) { if (m_tokens.back().index >= 0) { m_pointer->Pop(); } m_tokens.pop_back(); } } void PointerTracker::IncrementIndex() { if (m_tokens.empty()) { return; } Token &token = m_tokens.back(); if (token.type != TOKEN_ARRAY) { return; } if (token.index >= 0) { m_pointer->Pop(); } token.index++; m_pointer->Push(ola::strings::IntToString(token.index)); } } // namespace web } // namespace ola ola-0.10.5.nojsmin/common/web/SchemaParser.cpp0000644000175000017500000001402013023355232020601 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SchemaParser.cpp * A json-schema Parser. * Copyright (C) 2014 Simon Newton */ #include "common/web/SchemaParser.h" #include #include "ola/Logging.h" #include "ola/StringUtils.h" #include "ola/stl/STLUtils.h" #include "ola/web/Json.h" namespace ola { namespace web { using std::string; SchemaParser::SchemaParser() : JsonParserInterface(), m_pointer_tracker(&m_pointer), m_error_logger(&m_pointer) { } SchemaParser::~SchemaParser() {} void SchemaParser::Begin() { m_schema_defs.reset(); m_root_context.reset(); m_root_validator.reset(); STLEmptyStackAndDelete(&m_context_stack); m_error_logger.Reset(); } void SchemaParser::End() {} void SchemaParser::String(const string &value) { if (m_error_logger.HasError()) { return; } if (!m_root_context.get()) { m_error_logger.Error() << "Invalid string for first element: " << value; return; } m_pointer_tracker.IncrementIndex(); if (m_context_stack.top()) { m_context_stack.top()->String(&m_error_logger, value); } else { OLA_INFO << "In null context, skipping value " << value; } } void SchemaParser::Number(uint32_t value) { return HandleNumber(value); } void SchemaParser::Number(int32_t value) { return HandleNumber(value); } void SchemaParser::Number(uint64_t value) { return HandleNumber(value); } void SchemaParser::Number(int64_t value) { return HandleNumber(value); } void SchemaParser::Number(const JsonDouble::DoubleRepresentation &rep) { double d; JsonDouble::AsDouble(rep, &d); return HandleNumber(d); } void SchemaParser::Number(double value) { return HandleNumber(value); } void SchemaParser::Bool(bool value) { if (m_error_logger.HasError()) { return; } if (!m_root_context.get()) { m_error_logger.Error() << "Invalid bool for first element:" << value; return; } m_pointer_tracker.IncrementIndex(); if (m_context_stack.top()) { m_context_stack.top()->Bool(&m_error_logger, value); } else { OLA_INFO << "In null context, skipping value " << value; } } void SchemaParser::Null() { if (m_error_logger.HasError()) { return; } if (!m_root_context.get()) { m_error_logger.Error() << "Invalid null for first element"; return; } m_pointer_tracker.IncrementIndex(); if (m_context_stack.top()) { m_context_stack.top()->Null(&m_error_logger); } else { OLA_INFO << "In null context, skipping null"; } } void SchemaParser::OpenArray() { if (m_error_logger.HasError()) { return; } if (!m_root_context.get()) { m_error_logger.Error() << "Invalid array for first element"; return; } m_pointer_tracker.OpenArray(); if (m_context_stack.top()) { m_context_stack.push( m_context_stack.top()->OpenArray(&m_error_logger)); } else { OLA_INFO << "In null context, skipping OpenArray"; m_context_stack.push(NULL); } } void SchemaParser::CloseArray() { if (m_error_logger.HasError() || !m_root_context.get()) { return; } m_pointer_tracker.CloseArray(); m_context_stack.pop(); if (m_context_stack.top()) { m_context_stack.top()->CloseArray(&m_error_logger); } else { OLA_INFO << "In null context, skipping CloseArray"; } } void SchemaParser::OpenObject() { if (m_error_logger.HasError()) { return; } m_pointer_tracker.OpenObject(); if (!m_root_context.get()) { m_schema_defs.reset(new SchemaDefinitions()); m_root_context.reset(new SchemaParseContext(m_schema_defs.get())); m_context_stack.push(m_root_context.get()); } else { if (m_context_stack.top()) { m_context_stack.push( m_context_stack.top()->OpenObject(&m_error_logger)); } else { OLA_INFO << "In null context, skipping OpenObject"; m_context_stack.push(NULL); } } } void SchemaParser::ObjectKey(const string &key) { if (m_error_logger.HasError()) { return; } m_pointer_tracker.SetProperty(key); if (m_context_stack.top()) { m_context_stack.top()->ObjectKey(&m_error_logger, key); } else { OLA_INFO << "In null context, skipping key " << key; } } void SchemaParser::CloseObject() { if (m_error_logger.HasError()) { return; } m_pointer_tracker.CloseObject(); m_context_stack.pop(); if (m_context_stack.empty()) { // We're at the root m_root_validator.reset(m_root_context->GetValidator(&m_error_logger)); } else { if (m_context_stack.top()) { m_context_stack.top()->CloseObject(&m_error_logger); } } } void SchemaParser::SetError(const string &error) { m_error_logger.Error() << error; } bool SchemaParser::IsValidSchema() { return m_root_validator.get() != NULL; } string SchemaParser::Error() const { return m_error_logger.ErrorString(); } ValidatorInterface* SchemaParser::ClaimRootValidator() { return m_root_validator.release(); } SchemaDefinitions* SchemaParser::ClaimSchemaDefs() { return m_schema_defs.release(); } template void SchemaParser::HandleNumber(T t) { if (m_error_logger.HasError()) { return; } if (!m_root_context.get()) { m_error_logger.Error() << "Invalid number for first element: " << t; return; } m_pointer_tracker.IncrementIndex(); if (m_context_stack.top()) { m_context_stack.top()->Number(&m_error_logger, t); } else { OLA_INFO << "In null context, skipping number " << t; } } } // namespace web } // namespace ola ola-0.10.5.nojsmin/common/web/JsonLexer.cpp0000644000175000017500000002546613134123277020162 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * JsonLexer.cpp * A Json Lexer. * See http://www.json.org/ * Copyright (C) 2014 Simon Newton */ #define __STDC_LIMIT_MACROS // for UINT8_MAX & friends #include "ola/web/JsonLexer.h" #include #include #include #include #include #include "ola/Logging.h" #include "ola/web/Json.h" #include "ola/base/Macro.h" namespace ola { namespace web { using std::auto_ptr; using std::string; static bool ParseTrimmedInput(const char **input, JsonParserInterface *parser); /** * @brief Trim leading whitespace from a string. * @param input A pointer to a pointer with the data. This is updated to point * to the first non-whitespace character. * @returns true if more data remains, false if the string is now empty. * @note This is static within JsonLexer.cpp because we should be using * strings rather than char[]s. The only reason this doesn't use a string is * because I think we'll need a wchar on Windows. */ static bool TrimWhitespace(const char **input) { while (**input != 0 && (**input == ' ' || **input == '\t' || **input == '\r' || **input == '\n')) { (*input)++; } return **input != 0; } /** * @brief Extract a string token from the input. * @param input A pointer to a pointer with the data. This should point to the * first character after the quote (") character. * @param str A string object to store the extracted string. * @param parser the JsonParserInterface to pass tokens to. * @returns true if the string was extracted correctly, false otherwise. */ static bool ParseString(const char **input, string* str, JsonParserInterface *parser) { while (true) { size_t size = strcspn(*input, "\"\\"); char c = (*input)[size]; if (c == 0) { parser->SetError("Unterminated string"); str->clear(); return false; } str->append(*input, size); *input += size + 1; if (c == '"') { return true; } if (c == '\\') { // escape character char append_char = 0; switch (**input) { case '"': case '\\': case '/': append_char = **input; break; case 'b': append_char = '\b'; break; case 'f': append_char = '\f'; break; case 'n': append_char = '\n'; break; case 'r': append_char = '\r'; break; case 't': append_char = '\t'; break; case 'u': // TODO(simonn): handle unicode OLA_INFO << "unicode character found"; break; default: OLA_WARN << "Invalid escape character: \\" << **input; parser->SetError("Invalid string escape sequence"); return false; } str->push_back(append_char); (*input)++; } } return true; } bool ExtractDigits(const char **input, uint64_t *i, unsigned int *leading_zeros = NULL) { *i = 0; bool at_start = true; unsigned int zeros = 0; while (isdigit(**input)) { if (at_start && **input == '0') { zeros++; } else if (at_start) { at_start = false; } *i *= 10; *i += **input - '0'; (*input)++; } if (leading_zeros) { *leading_zeros = zeros; } return true; } /** * Parse a JsonNumber */ static bool ParseNumber(const char **input, JsonParserInterface *parser) { // The number is in the form .e // full and exponent are signed but we track the sign separate from the // value. // Only full is required. uint64_t full = 0; uint64_t fractional = 0; int64_t signed_exponent = 0; uint32_t leading_fractional_zeros = 0; bool has_fractional = false; bool has_exponent = false; bool is_negative = (**input == '-'); if (is_negative) { (*input)++; if (**input == 0) { return false; } } if (**input == '0') { (*input)++; } else if (isdigit(**input)) { ExtractDigits(input, &full); } else { return false; } if (**input == '.') { (*input)++; ExtractDigits(input, &fractional, &leading_fractional_zeros); has_fractional = true; } if (**input == 'e' || **input == 'E') { bool negative_exponent = false; // Handle the exponent (*input)++; switch (**input) { case '-': negative_exponent = true; // fall through OLA_FALLTHROUGH case '+': (*input)++; break; default: {}; } if (**input == 0) { return false; } uint64_t exponent; if (isdigit(**input)) { ExtractDigits(input, &exponent); } else { return false; } signed_exponent = (negative_exponent ? -1 : 1) * exponent; has_exponent = true; } // Now we have all the components, run the correct callback. if (has_fractional || has_exponent) { JsonDouble::DoubleRepresentation double_rep; double_rep.is_negative = is_negative; double_rep.full = full; double_rep.leading_fractional_zeros = leading_fractional_zeros; double_rep.fractional = fractional; double_rep.exponent = signed_exponent; parser->Number(double_rep); return true; } if (is_negative) { int64_t value = -1 * full; if (value < INT32_MIN || value > INT32_MAX) { parser->Number(value); } else { parser->Number(static_cast(value)); } } else { if (full > UINT32_MAX) { parser->Number(full); } else { parser->Number(static_cast(full)); } } return true; } /** * Starts from the first character after the '['. */ static bool ParseArray(const char **input, JsonParserInterface *parser) { if (!TrimWhitespace(input)) { parser->SetError("Unterminated array"); return false; } parser->OpenArray(); if (**input == ']') { (*input)++; parser->CloseArray(); return true; } while (true) { if (!TrimWhitespace(input)) { parser->SetError("Unterminated array"); return false; } bool result = ParseTrimmedInput(input, parser); if (!result) { OLA_INFO << "Invalid input"; return false; } if (!TrimWhitespace(input)) { parser->SetError("Unterminated array"); return false; } switch (**input) { case ']': (*input)++; // move past the ] parser->CloseArray(); return true; case ',': break; default: parser->SetError("Expected either , or ] after an array element"); return false; } (*input)++; // move past the , } } /** * Starts from the first character after the '{'. */ static bool ParseObject(const char **input, JsonParserInterface *parser) { if (!TrimWhitespace(input)) { parser->SetError("Unterminated object"); return false; } parser->OpenObject(); if (**input == '}') { (*input)++; parser->CloseObject(); return true; } while (true) { if (!TrimWhitespace(input)) { parser->SetError("Unterminated object"); return false; } if (**input != '"') { parser->SetError("Expected key for object"); OLA_INFO << "Expected string"; return false; } (*input)++; string key; if (!ParseString(input, &key, parser)) { return false; } parser->ObjectKey(key); if (!TrimWhitespace(input)) { parser->SetError("Missing : after key"); return false; } if (**input != ':') { parser->SetError("Incorrect character after key, should be :"); return false; } (*input)++; if (!TrimWhitespace(input)) { parser->SetError("Unterminated object"); return false; } bool result = ParseTrimmedInput(input, parser); if (!result) { return false; } if (!TrimWhitespace(input)) { parser->SetError("Unterminated object"); return false; } switch (**input) { case '}': (*input)++; // move past the } parser->CloseObject(); return true; case ',': break; default: parser->SetError("Expected either , or } after an object value"); return false; } (*input)++; // move past the , } } static bool ParseTrimmedInput(const char **input, JsonParserInterface *parser) { static const char TRUE_STR[] = "true"; static const char FALSE_STR[] = "false"; static const char NULL_STR[] = "null"; if (**input == '"') { (*input)++; string str; if (ParseString(input, &str, parser)) { parser->String(str); return true; } return false; } else if (strncmp(*input, TRUE_STR, sizeof(TRUE_STR) - 1) == 0) { *input += sizeof(TRUE_STR) - 1; parser->Bool(true); return true; } else if (strncmp(*input, FALSE_STR, sizeof(FALSE_STR) - 1) == 0) { *input += sizeof(FALSE_STR) - 1; parser->Bool(false); return true; } else if (strncmp(*input, NULL_STR, sizeof(NULL_STR) - 1) == 0) { *input += sizeof(NULL_STR) - 1; parser->Null(); return true; } else if (**input == '-' || isdigit(**input)) { return ParseNumber(input, parser); } else if (**input == '[') { (*input)++; return ParseArray(input, parser); } else if (**input == '{') { (*input)++; return ParseObject(input, parser); } parser->SetError("Invalid JSON value"); return false; } bool ParseRaw(const char *input, JsonParserInterface *parser) { if (!TrimWhitespace(&input)) { parser->SetError("No JSON data found"); return false; } parser->Begin(); bool result = ParseTrimmedInput(&input, parser); if (!result) { return false; } parser->End(); return !TrimWhitespace(&input); } bool JsonLexer::Parse(const string &input, JsonParserInterface *parser) { // TODO(simon): Do we need to convert to unicode here? I think this may be // an issue on Windows. Consider mbstowcs. // Copying the input sucks though, so we should use input.c_str() if we can. char* input_data = new char[input.size() + 1]; strncpy(input_data, input.c_str(), input.size() + 1); bool result = ParseRaw(input_data, parser); delete[] input_data; return result; } } // namespace web } // namespace ola ola-0.10.5.nojsmin/common/thread/0000755000175000017500000000000013155164170016222 5ustar wouterwouterola-0.10.5.nojsmin/common/thread/Makefile.mk0000644000175000017500000000231113023355232020260 0ustar wouterwouter# LIBRARIES ################################################## common_libolacommon_la_SOURCES += \ common/thread/ConsumerThread.cpp \ common/thread/ExecutorThread.cpp \ common/thread/Mutex.cpp \ common/thread/PeriodicThread.cpp \ common/thread/SignalThread.cpp \ common/thread/Thread.cpp \ common/thread/ThreadPool.cpp \ common/thread/Utils.cpp # TESTS ################################################## test_programs += common/thread/ExecutorThreadTester \ common/thread/ThreadTester \ common/thread/FutureTester common_thread_ThreadTester_SOURCES = \ common/thread/ThreadPoolTest.cpp \ common/thread/ThreadTest.cpp common_thread_ThreadTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_thread_ThreadTester_LDADD = $(COMMON_TESTING_LIBS) common_thread_FutureTester_SOURCES = common/thread/FutureTest.cpp common_thread_FutureTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_thread_FutureTester_LDADD = $(COMMON_TESTING_LIBS) common_thread_ExecutorThreadTester_SOURCES = \ common/thread/ExecutorThreadTest.cpp common_thread_ExecutorThreadTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_thread_ExecutorThreadTester_LDADD = $(COMMON_TESTING_LIBS) ola-0.10.5.nojsmin/common/thread/PeriodicThread.cpp0000644000175000017500000000405413023355232021612 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * PeriodicThread.cpp * A thread which executes a Callback periodically. * Copyright (C) 2015 Simon Newton */ #include "ola/thread/PeriodicThread.h" #include #include #include namespace ola { namespace thread { PeriodicThread::PeriodicThread(const TimeInterval &delay, PeriodicCallback *callback, const Options &options) : Thread(options), m_delay(delay), m_callback(callback), m_terminate(false) { if (m_callback) { Start(); } } void PeriodicThread::Stop() { { MutexLocker lock(&m_mutex); m_terminate = true; } m_condition.Signal(); Join(NULL); } void *PeriodicThread::Run() { Clock clock; TimeStamp last_run_at; clock.CurrentTime(&last_run_at); if (!m_callback->Run()) { return NULL; } while (true) { { MutexLocker lock(&m_mutex); if (m_terminate) { return NULL; } if (m_condition.TimedWait(&m_mutex, last_run_at + m_delay)) { // Either m_terminate is true, or a spurious wake up if (m_terminate) { return NULL; } continue; } } clock.CurrentTime(&last_run_at); if (!m_callback->Run()) { return NULL; } } return NULL; } } // namespace thread } // namespace ola ola-0.10.5.nojsmin/common/thread/ExecutorThreadTest.cpp0000644000175000017500000000367313023355232022520 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * ExecutorThreadTest.cpp * Test fixture for the ExecutorThread class * Copyright (C) 2015 Simon Newton */ #include #include "ola/thread/ExecutorThread.h" #include "ola/thread/Future.h" #include "ola/testing/TestUtils.h" using ola::NewSingleCallback; using ola::thread::Future; using ola::thread::ExecutorThread; namespace { void SetFuture(Future* f) { f->Set(); } } // namespace class ExecutorThreadTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(ExecutorThreadTest); CPPUNIT_TEST(test); CPPUNIT_TEST_SUITE_END(); public: void test(); }; CPPUNIT_TEST_SUITE_REGISTRATION(ExecutorThreadTest); /* * Check that callbacks are executed correctly. */ void ExecutorThreadTest::test() { Future f1; { ola::thread::Thread::Options options; ExecutorThread thread(options); OLA_ASSERT_TRUE(thread.Start()); Future f2; thread.Execute(NewSingleCallback(SetFuture, &f2)); f2.Get(); OLA_ASSERT_TRUE(thread.Stop()); // Try stop a second time. OLA_ASSERT_FALSE(thread.Stop()); // Confirm that all callbacks are run when the thread is destroyed. thread.Execute(NewSingleCallback(SetFuture, &f1)); } f1.Get(); } ola-0.10.5.nojsmin/common/thread/Utils.cpp0000644000175000017500000000327613023355232020031 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Utils.cpp * Helper functions for threads. * Copyright (C) 2014 Simon Newton */ #include "ola/thread/Utils.h" #include #include #include #include "ola/Logging.h" #include "ola/thread/Thread.h" namespace ola { namespace thread { std::string PolicyToString(int policy) { switch (policy) { case SCHED_FIFO: return "SCHED_FIFO"; case SCHED_RR: return "SCHED_RR"; case SCHED_OTHER: return "SCHED_OTHER"; default: return "unknown"; } } bool SetSchedParam(pthread_t thread, int policy, const struct sched_param ¶m) { int r = pthread_setschedparam(thread, policy, ¶m); if (r != 0) { OLA_FATAL << "Unable to set thread scheduling parameters for thread: " #ifdef _WIN32 << thread.x << ": " << strerror(r); #else << thread << ": " << strerror(r); #endif // _WIN32 return false; } return true; } } // namespace thread } // namespace ola ola-0.10.5.nojsmin/common/thread/Thread.cpp0000644000175000017500000001330513023355232020132 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Thread.cpp * A simple thread class * Copyright (C) 2010 Simon Newton */ #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #include #include #ifdef HAVE_PTHREAD_NP_H #include #endif // HAVE_PTHREAD_NP_H #include #include "ola/Logging.h" #include "ola/thread/Thread.h" #include "ola/thread/Utils.h" namespace { /* * Called by the new thread */ void *StartThread(void *d) { ola::thread::Thread *thread = static_cast(d); return thread->_InternalRun(); } } // namespace namespace ola { namespace thread { using std::string; Thread::Options::Options(const std::string &name) : name(name), inheritsched(PTHREAD_EXPLICIT_SCHED) { // Default the scheduling options to the system-default values. pthread_attr_t attrs; pthread_attr_init(&attrs); struct sched_param param; pthread_attr_getschedpolicy(&attrs, &policy); pthread_attr_getschedparam(&attrs, ¶m); priority = param.sched_priority; pthread_attr_destroy(&attrs); } Thread::Thread(const Options &options) : m_thread_id(), m_running(false), m_options(options) { // Mac has a bug where PTHREAD_INHERIT_SCHED doesn't work. We work around // this by explicitly setting the policy and priority to match the current // thread if PTHREAD_INHERIT_SCHED was requested. if (m_options.inheritsched == PTHREAD_INHERIT_SCHED) { struct sched_param param; pthread_getschedparam(pthread_self(), &m_options.policy, ¶m); m_options.priority = param.sched_priority; m_options.inheritsched = PTHREAD_EXPLICIT_SCHED; } } bool Thread::Start() { MutexLocker locker(&m_mutex); if (m_running) { OLA_WARN << "Attempt to start already running thread " << Name(); return false; } if (FastStart()) { m_condition.Wait(&m_mutex); return true; } return false; } bool Thread::FastStart() { pthread_attr_t attrs; pthread_attr_init(&attrs); if (m_options.inheritsched != PTHREAD_EXPLICIT_SCHED) { OLA_FATAL << "PTHREAD_EXPLICIT_SCHED not set, programming bug for " << Name() << "!"; return false; } // glibc 2.8 and onwards has a bug where PTHREAD_EXPLICIT_SCHED won't be // honored unless the policy and priority are explicitly set. See // man pthread_attr_setinheritsched. // By fetching the default values in Thread::Options(), we avoid this bug. int ret = pthread_attr_setschedpolicy(&attrs, m_options.policy); if (ret) { OLA_WARN << "pthread_attr_setschedpolicy failed for " << Name() << ", policy " << m_options.policy << ": " << strerror(errno); pthread_attr_destroy(&attrs); return false; } struct sched_param param; param.sched_priority = m_options.priority; ret = pthread_attr_setschedparam(&attrs, ¶m); if (ret) { OLA_WARN << "pthread_attr_setschedparam failed for " << Name() << ", priority " << param.sched_priority << ": " << strerror(errno); pthread_attr_destroy(&attrs); return false; } ret = pthread_attr_setinheritsched(&attrs, PTHREAD_EXPLICIT_SCHED); if (ret) { OLA_WARN << "pthread_attr_setinheritsched to PTHREAD_EXPLICIT_SCHED " << "failed for " << Name() << ": " << strerror(errno); pthread_attr_destroy(&attrs); return false; } ret = pthread_create(&m_thread_id, &attrs, StartThread, static_cast(this)); pthread_attr_destroy(&attrs); if (ret) { OLA_WARN << "pthread create failed for " << Name() << ": " << strerror(ret); return false; } return true; } bool Thread::Join(void *ptr) { { MutexLocker locker(&m_mutex); if (!m_running) return false; } int ret = pthread_join(m_thread_id, &ptr); m_running = false; return 0 == ret; } bool Thread::IsRunning() { MutexLocker locker(&m_mutex); return m_running; } void *Thread::_InternalRun() { string truncated_name = m_options.name.substr(0, 15); // There are 4 different variants of pthread_setname_np ! #ifdef HAVE_PTHREAD_SETNAME_NP_2 pthread_setname_np(pthread_self(), truncated_name.c_str()); #endif // HAVE_PTHREAD_SETNAME_NP_2 #if defined(HAVE_PTHREAD_SET_NAME_NP_2) || \ defined(HAVE_PTHREAD_SET_NAME_NP_2_VOID) pthread_set_name_np(pthread_self(), truncated_name.c_str()); #endif // defined(HAVE_PTHREAD_SET_NAME_NP_2) || // defined(HAVE_PTHREAD_SET_NAME_NP_2_VOID) #ifdef HAVE_PTHREAD_SETNAME_NP_1 pthread_setname_np(truncated_name.c_str()); #endif // HAVE_PTHREAD_SETNAME_NP_1 #ifdef HAVE_PTHREAD_SETNAME_NP_3 pthread_setname_np(pthread_self(), truncated_name.c_str(), NULL); #endif // HAVE_PTHREAD_SETNAME_NP_3 int policy; struct sched_param param; pthread_getschedparam(pthread_self(), &policy, ¶m); OLA_INFO << "Thread " << Name() << ", policy " << PolicyToString(policy) << ", priority " << param.sched_priority; { MutexLocker locker(&m_mutex); m_running = true; } m_condition.Signal(); return Run(); } } // namespace thread } // namespace ola ola-0.10.5.nojsmin/common/thread/ThreadPool.cpp0000644000175000017500000000503713023355232020767 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * ThreadPool.cpp * An executor which farms work out to a bunch of threads. * Copyright (C) 2011 Simon Newton */ #include "ola/Logging.h" #include "ola/thread/Thread.h" #include "ola/thread/ThreadPool.h" #include "ola/thread/ConsumerThread.h" namespace ola { namespace thread { /** * Clean up */ ThreadPool::~ThreadPool() { JoinAllThreads(); } /** * Start the threads */ bool ThreadPool::Init() { if (!m_threads.empty()) { OLA_WARN << "Thread pool already started"; return false; } for (unsigned int i = 1 ; i <= m_thread_count; i++) { ConsumerThread *thread = new ConsumerThread( &m_callback_queue, &m_shutdown, &m_mutex, &m_condition_var); if (!thread->Start()) { OLA_WARN << "Failed to start thread " << i << ", aborting ThreadPool::Init()"; JoinAllThreads(); return false; } m_threads.push_back(thread); } return true; } /** * Join all threads */ void ThreadPool::JoinAll() { JoinAllThreads(); } /** * Queue the callback. * Don't call this after JoinAll() otherwise the closure may not run and will * probably leak memory. */ void ThreadPool::Execute(ola::BaseCallback0 *closure) { MutexLocker locker(&m_mutex); if (m_shutdown) { OLA_WARN << "Adding actions to a ThreadPool while it's shutting down, " "this will leak!"; } m_callback_queue.push(closure); m_condition_var.Signal(); } /** * Join all threads. */ void ThreadPool::JoinAllThreads() { if (m_threads.empty()) return; { MutexLocker locker(&m_mutex); m_shutdown = true; m_condition_var.Broadcast(); } while (!m_threads.empty()) { ConsumerThread *thread = m_threads.back(); m_threads.pop_back(); thread->Join(); delete thread; } } } // namespace thread } // namespace ola ola-0.10.5.nojsmin/common/thread/ConsumerThread.cpp0000644000175000017500000000342513023355232021650 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * ConsumerThread.cpp * An thread which consumes Callbacks from a queue and runs them. * Copyright (C) 2011 Simon Newton */ #include "ola/Logging.h" #include "ola/thread/ConsumerThread.h" namespace ola { namespace thread { /** * The run method, this loops, executing actions, until we're told to * terminate. */ void *ConsumerThread::Run() { m_mutex->Lock(); while (true) { EmptyQueue(); // Mutex is held here if (*m_shutdown) { m_mutex->Unlock(); break; } m_condition_var->Wait(m_mutex); } return NULL; } /** * Drain the queue of actions * @pre We hold the Mutex * @post We hold the mutex and the queue is empty. */ void ConsumerThread::EmptyQueue() { while (true) { // we have the lock if (m_callback_queue->empty()) { break; } // action in queue Action action = m_callback_queue->front(); m_callback_queue->pop(); m_mutex->Unlock(); action->Run(); // reacquire the lock m_mutex->Lock(); // coverity[LOCK] } } } // namespace thread } // namespace ola ola-0.10.5.nojsmin/common/thread/ExecutorThread.cpp0000644000175000017500000000410213023355232021644 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * ExecutorThread.cpp * Run callbacks in a separate thread. * Copyright (C) 2015 Simon Newton */ #include "ola/thread/ExecutorThread.h" #include #include #include #include namespace ola { namespace thread { using ola::io::SelectServer; using ola::thread::Future; using ola::thread::Thread; namespace { void SetFuture(Future* f) { f->Set(); } } // namespace ExecutorThread::~ExecutorThread() { RunRemaining(); } void ExecutorThread::Execute(ola::BaseCallback0 *callback) { { MutexLocker locker(&m_mutex); m_callback_queue.push(callback); } m_condition_var.Signal(); } void ExecutorThread::DrainCallbacks() { Future f; Execute(NewSingleCallback(SetFuture, &f)); f.Get(); } bool ExecutorThread::Start() { return m_thread.Start(); } bool ExecutorThread::Stop() { if (!m_thread.IsRunning()) { return false; } { MutexLocker locker(&m_mutex); m_shutdown = true; } m_condition_var.Signal(); bool ok = m_thread.Join(); RunRemaining(); return ok; } void ExecutorThread::RunRemaining() { MutexLocker locker(&m_mutex); while (!m_callback_queue.empty()) { BaseCallback0* cb = m_callback_queue.front(); m_callback_queue.pop(); cb->Run(); } } } // namespace thread } // namespace ola ola-0.10.5.nojsmin/common/thread/FutureTest.cpp0000644000175000017500000000663713023355232021047 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * FutureTest.cpp * Test fixture for the Future class * Copyright (C) 2013 Simon Newton */ #include #include "ola/Logging.h" #include "ola/thread/Future.h" #include "ola/thread/Thread.h" #include "ola/testing/TestUtils.h" using ola::thread::ConditionVariable; using ola::thread::Mutex; using ola::thread::MutexLocker; using ola::thread::Future; class FutureTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(FutureTest); CPPUNIT_TEST(testSingleThreadedFuture); CPPUNIT_TEST(testSingleThreadedVoidFuture); CPPUNIT_TEST(testMultithreadedFuture); CPPUNIT_TEST_SUITE_END(); public: void testSingleThreadedFuture(); void testSingleThreadedVoidFuture(); void testMultithreadedFuture(); }; CPPUNIT_TEST_SUITE_REGISTRATION(FutureTest); class AdderThread: public ola::thread::Thread { public: AdderThread(int i, int j, Future *future) : Thread(), i(i), j(j), future(future) { } ~AdderThread() {} void *Run() { future->Set(i + j); return NULL; } private: const int i, j; Future *future; }; /* * Check that single threaded Future functionality works. */ void FutureTest::testSingleThreadedFuture() { Future f1; OLA_ASSERT_FALSE(f1.IsComplete()); f1.Set(true); OLA_ASSERT_EQ(true, f1.Get()); // now test a copy-constructor Future f2; Future f3(f2); OLA_ASSERT_FALSE(f2.IsComplete()); OLA_ASSERT_FALSE(f3.IsComplete()); f2.Set(true); OLA_ASSERT_EQ(true, f2.Get()); OLA_ASSERT_EQ(true, f3.Get()); // now test an assignment, this is more expensive than the copy-constructor Future f4; Future f5 = f4; OLA_ASSERT_FALSE(f4.IsComplete()); OLA_ASSERT_FALSE(f5.IsComplete()); f5.Set(false); OLA_ASSERT_EQ(false, f4.Get()); OLA_ASSERT_EQ(false, f5.Get()); } /* * Check that single threaded Future functionality works. */ void FutureTest::testSingleThreadedVoidFuture() { Future f1; OLA_ASSERT_FALSE(f1.IsComplete()); f1.Set(); f1.Get(); // now test a copy-constructor Future f2; Future f3(f2); OLA_ASSERT_FALSE(f2.IsComplete()); OLA_ASSERT_FALSE(f3.IsComplete()); f2.Set(); f2.Get(); f3.Get(); // now test an assignment, this is more expensive than the copy-constructor Future f4; Future f5 = f4; OLA_ASSERT_FALSE(f4.IsComplete()); OLA_ASSERT_FALSE(f5.IsComplete()); f5.Set(); f4.Get(); f5.Get(); } /* * Check that Futures work in a multithreaded environment */ void FutureTest::testMultithreadedFuture() { Future f1; AdderThread thread(3, 5, &f1); OLA_ASSERT_FALSE(f1.IsComplete()); thread.Run(); OLA_ASSERT_EQ(8, f1.Get()); } ola-0.10.5.nojsmin/common/thread/ThreadPoolTest.cpp0000644000175000017500000000442213023355232021624 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * ThreadPoolTest.cpp * Test fixture for the ThreadPool class * Copyright (C) 2011 Simon Newton */ #include #include #include #include #include #include "ola/Callback.h" #include "ola/Logging.h" #include "ola/thread/Thread.h" #include "ola/thread/ThreadPool.h" #include "ola/testing/TestUtils.h" using ola::thread::Mutex; using ola::thread::MutexLocker; using ola::thread::ThreadPool; class ThreadPoolTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(ThreadPoolTest); CPPUNIT_TEST(test1By10); CPPUNIT_TEST(test2By10); CPPUNIT_TEST(test10By100); CPPUNIT_TEST_SUITE_END(); public: void test1By10() { RunThreads(1, 10); } void test2By10() { RunThreads(2, 10); } void test10By100() { RunThreads(10, 100); } void setUp() { m_counter = 0; } private: unsigned int m_counter; Mutex m_mutex; void IncrementCounter() { MutexLocker locker(&m_mutex); m_counter++; } void RunThreads(unsigned int threads, unsigned int actions); }; CPPUNIT_TEST_SUITE_REGISTRATION(ThreadPoolTest); /** * Run threads and add actions to the queue */ void ThreadPoolTest::RunThreads(unsigned int threads, unsigned int actions) { ThreadPool pool(threads); OLA_ASSERT_TRUE(pool.Init()); for (unsigned int i = 0; i < actions; i++) pool.Execute( ola::NewSingleCallback(this, &ThreadPoolTest::IncrementCounter)); pool.JoinAll(); OLA_ASSERT_EQ(static_cast(actions), m_counter); } ola-0.10.5.nojsmin/common/thread/SignalThread.cpp0000644000175000017500000001027513023355232021273 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SignalThread.cpp * A thread to handle signals. * Copyright (C) 2013 Simon Newton */ #include #include #include #include #include #include "ola/Callback.h" #include "ola/Logging.h" #include "ola/stl/STLUtils.h" #include "ola/thread/SignalThread.h" namespace ola { namespace thread { #ifdef _WIN32 // Windows doesn't support sigwait and related functions, so we need to use // this workaround. Keep the definition of g_signal_map in sync with // SignalThread::SignalMap. static std::map* g_signal_map = NULL; static void Win32SignalHandler(int signo) { OLA_INFO << "Received signal: " << signo; if (!g_signal_map) { OLA_WARN << "Signal handler called without signal map"; return; } SignalThread::SignalHandler *handler = STLFindOrNull(*g_signal_map, signo); if (handler) { handler->Run(); } } #endif // _WIN32 SignalThread::SignalThread() : Thread(Thread::Options("signal-thread")) {} SignalThread::~SignalThread() { ola::STLDeleteValues(&m_signal_handlers); } /** * @brief Install a signal handler for the given signal. * * This can't be called once the thread has stared. */ bool SignalThread::InstallSignalHandler(int signal, SignalHandler *handler) { if (BlockSignal(signal)) { ola::STLReplaceAndDelete(&m_signal_handlers, signal, handler); return true; } return false; } /** * @brief Entry point into the thread. */ void* SignalThread::Run() { #ifndef _WIN32 sigset_t signals; int signo; #endif // _WIN32 #ifdef _WIN32 if (g_signal_map) { OLA_WARN << "Windows signal map was already set, it will be overwritten."; } g_signal_map = &m_signal_handlers; SignalMap::const_iterator iter = m_signal_handlers.begin(); for (; iter != m_signal_handlers.end(); ++iter) { signal(iter->first, Win32SignalHandler); } #endif // _WIN32 while (true) { #ifndef _WIN32 sigemptyset(&signals); AddSignals(&signals); // Don't try to use sigpending here. It won't work on Mac. if (sigwait(&signals, &signo) != 0) { OLA_INFO << "sigwait error: " << strerror(errno); continue; } OLA_INFO << "Received signal: " << strsignal(signo); SignalHandler *handler = STLFindOrNull(m_signal_handlers, signo); if (handler) { handler->Run(); } #endif // _WIN32 } return NULL; } /** * @brief Add the signals we're interested in to the sigset. */ bool SignalThread::AddSignals(sigset_t *signals) { #ifndef _WIN32 SignalMap::const_iterator iter = m_signal_handlers.begin(); for (; iter != m_signal_handlers.end(); ++iter) { if (sigaddset(signals, iter->first)) { OLA_WARN << "Failed to add " << strsignal(iter->first) << " to the signal set:" << strerror(errno); return false; } } #else (void) signals; #endif // _WIN32 return true; } /** * Block the signal */ bool SignalThread::BlockSignal(int signal) { #ifdef _WIN32 ::signal(signal, SIG_IGN); #else sigset_t signals; if (sigemptyset(&signals)) { OLA_WARN << "Failed to init signal set: " << strerror(errno); return false; } if (sigaddset(&signals, signal)) { OLA_WARN << "Failed to add " << strsignal(signal) << " to the signal set:" << strerror(errno); return false; } if (pthread_sigmask(SIG_BLOCK, &signals, NULL)) { OLA_WARN << "Failed to block signals: " << strerror(errno); return false; } #endif // _WIN32 return true; } } // namespace thread } // namespace ola ola-0.10.5.nojsmin/common/thread/Mutex.cpp0000644000175000017500000000562413023355232020032 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Mutex.cpp * Mutex and ConditionVariable * Copyright (C) 2010 Simon Newton */ #include #include "ola/thread/Mutex.h" namespace ola { namespace thread { /** * Construct a new mutex object */ Mutex::Mutex() { pthread_mutex_init(&m_mutex, NULL); } /** * Clean up */ Mutex::~Mutex() { pthread_mutex_destroy(&m_mutex); } /** * Lock this mutex */ void Mutex::Lock() { pthread_mutex_lock(&m_mutex); } /** * Try and lock this mutex * @return true if we got the lock, false otherwise */ bool Mutex::TryLock() { int i = pthread_mutex_trylock(&m_mutex); return i == 0; } /** * Unlock this mutex */ void Mutex::Unlock() { pthread_mutex_unlock(&m_mutex); } /** * Create a new MutexLocker and lock the mutex. */ MutexLocker::MutexLocker(Mutex *mutex) : m_mutex(mutex), m_requires_unlock(true) { m_mutex->Lock(); } /** * Destroy this MutexLocker and unlock the mutex */ MutexLocker::~MutexLocker() { Release(); } void MutexLocker::Release() { if (m_requires_unlock) { m_mutex->Unlock(); m_requires_unlock = false; } } /** * New ConditionVariable */ ConditionVariable::ConditionVariable() { pthread_cond_init(&m_condition, NULL); } /** * Clean up */ ConditionVariable::~ConditionVariable() { pthread_cond_destroy(&m_condition); } /** * Wait on a condition variable * @param mutex the mutex that is locked */ void ConditionVariable::Wait(Mutex *mutex) { pthread_cond_wait(&m_condition, &mutex->m_mutex); } /** * Timed Wait * @param mutex the mutex that is locked * @param wake_up_time the time to wait up. * @returns true if we received a signal, false if the timeout expired. */ bool ConditionVariable::TimedWait(Mutex *mutex, const TimeStamp &wake_up_time) { struct timespec ts = { wake_up_time.Seconds(), wake_up_time.MicroSeconds() * ONE_THOUSAND }; int i = pthread_cond_timedwait(&m_condition, &mutex->m_mutex, &ts); return i == 0; } /** * Wake up a single listener */ void ConditionVariable::Signal() { pthread_cond_signal(&m_condition); } /** * Wake up all listeners */ void ConditionVariable::Broadcast() { pthread_cond_broadcast(&m_condition); } } // namespace thread } // namespace ola ola-0.10.5.nojsmin/common/thread/ThreadTest.cpp0000644000175000017500000001636113134123277021004 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * ThreadTest.cpp * Test fixture for the Thread class * Copyright (C) 2010 Simon Newton */ #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #include #include #ifndef _WIN32 #include #endif // _WIN32 #include #include "ola/Logging.h" #include "ola/system/Limits.h" #include "ola/testing/TestUtils.h" #include "ola/thread/Thread.h" #include "ola/thread/Utils.h" using ola::thread::ConditionVariable; using ola::thread::Mutex; using ola::thread::MutexLocker; using ola::thread::Thread; // A struct containing the scheduling parameters. struct SchedulingParams { int policy; int priority; }; // Get the current scheduling parameters. SchedulingParams GetCurrentParams() { SchedulingParams our_params; struct sched_param param; pthread_getschedparam(pthread_self(), &our_params.policy, ¶m); our_params.priority = param.sched_priority; return our_params; } // Set the current scheduling parameters. bool SetCurrentParams(const SchedulingParams &new_params) { struct sched_param param; param.sched_priority = new_params.priority; return ola::thread::SetSchedParam(pthread_self(), new_params.policy, param); } // A simple thread that runs, captures the scheduling parameters and exits. class MockThread: public Thread { public: explicit MockThread(const Options &options = Options("MockThread")) : Thread(options), m_thread_ran(false), m_mutex() { } ~MockThread() {} void *Run() { MutexLocker locker(&m_mutex); m_thread_ran = true; m_scheduling_params = GetCurrentParams(); return NULL; } bool HasRan() { MutexLocker locker(&m_mutex); return m_thread_ran; } SchedulingParams GetSchedulingParams() { MutexLocker locker(&m_mutex); return m_scheduling_params; } private: bool m_thread_ran; SchedulingParams m_scheduling_params; Mutex m_mutex; }; bool RunThread(MockThread *thread) { return thread->Start() && thread->Join() && thread->HasRan(); } class ThreadTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(ThreadTest); CPPUNIT_TEST(testThread); CPPUNIT_TEST(testSchedulingOptions); CPPUNIT_TEST(testConditionVariable); CPPUNIT_TEST_SUITE_END(); public: void testThread(); void testConditionVariable(); void testSchedulingOptions(); }; CPPUNIT_TEST_SUITE_REGISTRATION(ThreadTest); /* * Check that basic thread functionality works. */ void ThreadTest::testThread() { MockThread thread; OLA_ASSERT_FALSE(thread.HasRan()); OLA_ASSERT_TRUE(thread.Start()); // starting twice must fail OLA_ASSERT_FALSE(thread.Start()); OLA_ASSERT_TRUE(thread.IsRunning()); OLA_ASSERT_TRUE(thread.Join()); OLA_ASSERT_FALSE(thread.IsRunning()); OLA_ASSERT_TRUE(thread.HasRan()); } /* * Check that the scheduling options behave as expected. */ void ThreadTest::testSchedulingOptions() { #ifndef _WIN32 #if HAVE_DECL_RLIMIT_RTPRIO struct rlimit rlim; OLA_ASSERT_TRUE(ola::system::GetRLimit(RLIMIT_RTPRIO, &rlim)); if (rlim.rlim_cur == 0) { // A value of 0 means the user can't change policies. OLA_INFO << "Skipping testSchedulingOptions since RLIMIT_RTPRIO is 0"; return; } const int max_priority = rlim.rlim_cur - 1; const int other_priority = std::min(1, max_priority - 1); #else const int max_priority = 31; const int other_priority = 15; #endif // HAVE_DECL_RLIMIT_RTPRIO SchedulingParams default_params = GetCurrentParams(); { // Default scheduling options. MockThread thread; OLA_ASSERT_TRUE(RunThread(&thread)); OLA_ASSERT_EQ(default_params.policy, thread.GetSchedulingParams().policy); OLA_ASSERT_EQ(default_params.priority, thread.GetSchedulingParams().priority); } { // A thread that explicitly sets scheduling params. Thread::Options options; options.name = "ExplicitSchedParamsFIFO"; options.policy = SCHED_FIFO; options.priority = max_priority; MockThread thread(options); OLA_ASSERT_TRUE(RunThread(&thread)); OLA_ASSERT_EQ(static_cast(SCHED_FIFO), thread.GetSchedulingParams().policy); OLA_ASSERT_EQ(max_priority, thread.GetSchedulingParams().priority); } // Set the current thread to something other than the default. // This allows us to check inheritance. SchedulingParams override_params; override_params.policy = SCHED_FIFO; override_params.priority = other_priority; OLA_ASSERT_TRUE(SetCurrentParams(override_params)); { // Default scheduling options. MockThread thread; OLA_ASSERT_TRUE(RunThread(&thread)); OLA_ASSERT_EQ(default_params.policy, thread.GetSchedulingParams().policy); OLA_ASSERT_EQ(default_params.priority, thread.GetSchedulingParams().priority); } { // A thread that explicitly sets scheduling params. Thread::Options options; options.name = "ExplicitSchedParamsRR"; options.policy = SCHED_RR; options.priority = max_priority; MockThread thread(options); OLA_ASSERT_TRUE(RunThread(&thread)); OLA_ASSERT_EQ(static_cast(SCHED_RR), thread.GetSchedulingParams().policy); OLA_ASSERT_EQ(max_priority, thread.GetSchedulingParams().priority); } { // A thread that inherits scheduling params. Thread::Options options; options.name = "InheritSchedParams"; options.inheritsched = PTHREAD_INHERIT_SCHED; MockThread thread(options); OLA_ASSERT_TRUE(RunThread(&thread)); OLA_ASSERT_EQ(override_params.policy, thread.GetSchedulingParams().policy); OLA_ASSERT_EQ(override_params.priority, thread.GetSchedulingParams().priority); } #else OLA_WARN << "Scheduling options are not supported on Windows."; #endif // !_WIN32 } class MockConditionThread: public Thread { public: MockConditionThread( Mutex *mutex, ConditionVariable *condition) : m_mutex(mutex), m_condition(condition) {} void *Run() { m_mutex->Lock(); i = EXPECTED; m_mutex->Unlock(); m_condition->Signal(); return NULL; } int i; static const int EXPECTED = 10; private: Mutex *m_mutex; ConditionVariable *m_condition; }; /* * Check that a condition variable works */ void ThreadTest::testConditionVariable() { Mutex mutex; ConditionVariable condition; MockConditionThread thread(&mutex, &condition); thread.Start(); mutex.Lock(); if (thread.i != MockConditionThread::EXPECTED) { condition.Wait(&mutex); } OLA_ASSERT_EQ(10, thread.i); mutex.Unlock(); thread.Join(); } ola-0.10.5.nojsmin/common/io/0000755000175000017500000000000013155164170015362 5ustar wouterwouterola-0.10.5.nojsmin/common/io/IOQueueTest.cpp0000644000175000017500000002161713023355232020244 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * IOQueueTest.cpp * Test fixture for the IOQueue class. * Copyright (C) 2012 Simon Newton */ #include #include #include #include #include "ola/Logging.h" #include "ola/io/IOQueue.h" #include "ola/io/MemoryBlockPool.h" #include "ola/testing/TestUtils.h" using ola::io::IOQueue; using ola::io::IOVec; using ola::io::MemoryBlockPool; using std::auto_ptr; using std::string; class IOQueueTest: public CppUnit::TestFixture { public: CPPUNIT_TEST_SUITE(IOQueueTest); CPPUNIT_TEST(testBasicWrite); CPPUNIT_TEST(testBlockOverflow); CPPUNIT_TEST(testPop); CPPUNIT_TEST(testPeek); CPPUNIT_TEST(testIOVec); CPPUNIT_TEST(testDump); CPPUNIT_TEST(testStringRead); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void tearDown() {} void testBasicWrite(); void testBlockOverflow(); void testPop(); void testPeek(); void testIOVec(); void testDump(); void testStringRead(); private: auto_ptr m_buffer; unsigned int SumLengthOfIOVec(const struct IOVec *iov, int iocnt); }; CPPUNIT_TEST_SUITE_REGISTRATION(IOQueueTest); void IOQueueTest::setUp() { m_buffer.reset(new IOQueue()); } /** * Sum up the length of data in a IOVec */ unsigned int IOQueueTest::SumLengthOfIOVec(const struct IOVec *iov, int iocnt) { unsigned int sum = 0; for (int i = 0; i < iocnt; iov++, i++) sum += iov->iov_len; return sum; } /* * Check that basic appending works. */ void IOQueueTest::testBasicWrite() { OLA_ASSERT_EQ(0u, m_buffer->Size()); uint8_t data1[] = {0, 1, 2, 3, 4}; m_buffer->Write(data1, sizeof(data1)); OLA_ASSERT_EQ(5u, m_buffer->Size()); m_buffer->Pop(1); OLA_ASSERT_EQ(4u, m_buffer->Size()); m_buffer->Pop(4); OLA_ASSERT_EQ(0u, m_buffer->Size()); } /* * Check that overflowing blocks works */ void IOQueueTest::testBlockOverflow() { // block size of 4 MemoryBlockPool pool(4); IOQueue queue(&pool); uint8_t data1[] = {0, 1, 2, 3, 4}; uint8_t data2[] = {5, 6, 7, 8, 9}; uint8_t data3[] = {0xa, 0xb, 0xc, 0xd, 0xe}; queue.Write(data1, sizeof(data1)); OLA_ASSERT_EQ(5u, queue.Size()); queue.Write(data2, sizeof(data2)); OLA_ASSERT_EQ(10u, queue.Size()); queue.Write(data3, sizeof(data3)); OLA_ASSERT_EQ(15u, queue.Size()); queue.Pop(9); OLA_ASSERT_EQ(6u, queue.Size()); // append some more data queue.Write(data1, sizeof(data1)); OLA_ASSERT_EQ(11u, queue.Size()); queue.Write(data2, sizeof(data2)); OLA_ASSERT_EQ(16u, queue.Size()); } /** * Test that Pop behaves */ void IOQueueTest::testPop() { uint8_t data1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; m_buffer->Write(data1, sizeof(data1)); OLA_ASSERT_EQ(9u, m_buffer->Size()); OLA_ASSERT_FALSE(m_buffer->Empty()); m_buffer->Pop(9); OLA_ASSERT_EQ(0u, m_buffer->Size()); OLA_ASSERT_TRUE(m_buffer->Empty()); // try to pop off more data m_buffer->Pop(1); OLA_ASSERT_EQ(0u, m_buffer->Size()); OLA_ASSERT_TRUE(m_buffer->Empty()); // add the data back, then try to pop off more than we have m_buffer->Write(data1, sizeof(data1)); OLA_ASSERT_EQ(9u, m_buffer->Size()); OLA_ASSERT_FALSE(m_buffer->Empty()); m_buffer->Pop(10); OLA_ASSERT_EQ(0u, m_buffer->Size()); OLA_ASSERT_TRUE(m_buffer->Empty()); // one more time m_buffer->Write(data1, sizeof(data1)); OLA_ASSERT_EQ(9u, m_buffer->Size()); // Now try a buffer with smaller blocks MemoryBlockPool pool(4); IOQueue queue(&pool); queue.Write(data1, sizeof(data1)); OLA_ASSERT_EQ(9u, queue.Size()); // pop the same amount as the first block size queue.Pop(4); OLA_ASSERT_EQ(5u, queue.Size()); OLA_ASSERT_FALSE(queue.Empty()); // now pop more than the buffer size queue.Pop(6); OLA_ASSERT_EQ(0u, queue.Size()); OLA_ASSERT_TRUE(queue.Empty()); // test the block boundry uint8_t *output_data = new uint8_t[4]; m_buffer.reset(new IOQueue(&pool)); queue.Write(data1, 4); OLA_ASSERT_EQ(4u, queue.Size()); unsigned int output_size = queue.Peek(output_data, 4); OLA_ASSERT_DATA_EQUALS(data1, 4, output_data, output_size); queue.Pop(4); OLA_ASSERT_TRUE(queue.Empty()); // now add some more data queue.Write(data1 + 4, 4); OLA_ASSERT_EQ(4u, queue.Size()); output_size = queue.Peek(output_data, 4); OLA_ASSERT_DATA_EQUALS(data1 + 4, 4, output_data, output_size); queue.Pop(4); OLA_ASSERT_TRUE(queue.Empty()); delete[] output_data; } /** * Test that Peek behaves */ void IOQueueTest::testPeek() { uint8_t data1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; m_buffer->Write(data1, sizeof(data1)); OLA_ASSERT_EQ(9u, m_buffer->Size()); OLA_ASSERT_FALSE(m_buffer->Empty()); const unsigned int DATA_SIZE = 20; uint8_t *output_data = new uint8_t[DATA_SIZE]; // peek at the first four bytes unsigned int output_size = m_buffer->Peek(output_data, 4); OLA_ASSERT_DATA_EQUALS(data1, 4, output_data, output_size); OLA_ASSERT_EQ(9u, m_buffer->Size()); // peek at the first 9 bytes output_size = m_buffer->Peek(output_data, 9); OLA_ASSERT_DATA_EQUALS(data1, 9, output_data, output_size); OLA_ASSERT_EQ(9u, m_buffer->Size()); // peek at more bytes that exist in the buffer output_size = m_buffer->Peek(output_data, DATA_SIZE); OLA_ASSERT_EQ(9u, output_size); OLA_ASSERT_DATA_EQUALS(data1, sizeof(data1), output_data, output_size); OLA_ASSERT_EQ(9u, m_buffer->Size()); // Now try a buffer with smaller blocks MemoryBlockPool pool(4); IOQueue queue(&pool); queue.Write(data1, sizeof(data1)); OLA_ASSERT_EQ(9u, queue.Size()); // peek at he same amount as the first block size output_size = queue.Peek(output_data, 4); OLA_ASSERT_DATA_EQUALS(data1, 4, output_data, output_size); OLA_ASSERT_EQ(9u, queue.Size()); OLA_ASSERT_FALSE(queue.Empty()); // peek at data from more than one block output_size = queue.Peek(output_data, 6); OLA_ASSERT_DATA_EQUALS(data1, 6, output_data, output_size); OLA_ASSERT_EQ(9u, queue.Size()); OLA_ASSERT_FALSE(queue.Empty()); // peek at data on the two block boundry output_size = queue.Peek(output_data, 8); OLA_ASSERT_DATA_EQUALS(data1, 8, output_data, output_size); OLA_ASSERT_EQ(9u, queue.Size()); OLA_ASSERT_FALSE(queue.Empty()); // peek at all the data output_size = queue.Peek(output_data, 9); OLA_ASSERT_DATA_EQUALS(data1, 9, output_data, output_size); OLA_ASSERT_EQ(9u, queue.Size()); OLA_ASSERT_FALSE(queue.Empty()); // peek at more data than what exists output_size = queue.Peek(output_data, DATA_SIZE); OLA_ASSERT_EQ(9u, output_size); OLA_ASSERT_DATA_EQUALS(data1, 9, output_data, output_size); OLA_ASSERT_EQ(9u, queue.Size()); OLA_ASSERT_FALSE(queue.Empty()); delete[] output_data; } /** * Test getting / setting IOVec work. */ void IOQueueTest::testIOVec() { uint8_t data1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; m_buffer->Write(data1, sizeof(data1)); OLA_ASSERT_EQ(9u, m_buffer->Size()); OLA_ASSERT_FALSE(m_buffer->Empty()); int iocnt; const struct IOVec *vector = m_buffer->AsIOVec(&iocnt); OLA_ASSERT_EQ(9u, SumLengthOfIOVec(vector, iocnt)); OLA_ASSERT_EQ(1, iocnt); m_buffer->FreeIOVec(vector); // try a smaller block size MemoryBlockPool pool(4); IOQueue queue(&pool); m_buffer.reset(new IOQueue(&pool)); queue.Write(data1, sizeof(data1)); OLA_ASSERT_EQ(9u, queue.Size()); vector = queue.AsIOVec(&iocnt); OLA_ASSERT_EQ(3, iocnt); OLA_ASSERT_EQ(9u, SumLengthOfIOVec(vector, iocnt)); queue.FreeIOVec(vector); } /** * Test dumping to a ostream works */ void IOQueueTest::testDump() { MemoryBlockPool pool(4); IOQueue queue(&pool); uint8_t data1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; queue.Write(data1, sizeof(data1)); OLA_ASSERT_EQ(9u, queue.Size()); std::ostringstream str; queue.Dump(&str); OLA_ASSERT_EQ( string("00 01 02 03 04 05 06 07 ........\n" "08 .\n"), str.str()); } /** * Test reading to a string works. */ void IOQueueTest::testStringRead() { MemoryBlockPool pool(4); IOQueue queue(&pool); uint8_t data1[] = {'a', 'b', 'c', 'd', '1', '2', '3', '4', ' '}; queue.Write(data1, sizeof(data1)); OLA_ASSERT_EQ(9u, queue.Size()); string output; OLA_ASSERT_EQ(9u, queue.Read(&output, 9u)); OLA_ASSERT_EQ(string("abcd1234 "), output); } ola-0.10.5.nojsmin/common/io/Makefile.mk0000644000175000017500000000527313023355232017432 0ustar wouterwouter# LIBRARIES ################################################## common_libolacommon_la_SOURCES += \ common/io/Descriptor.cpp \ common/io/ExtendedSerial.cpp \ common/io/EPoller.h \ common/io/IOQueue.cpp \ common/io/IOStack.cpp \ common/io/IOUtils.cpp \ common/io/NonBlockingSender.cpp \ common/io/PollerInterface.cpp \ common/io/PollerInterface.h \ common/io/SelectServer.cpp \ common/io/Serial.cpp \ common/io/StdinHandler.cpp \ common/io/TimeoutManager.cpp \ common/io/TimeoutManager.h if USING_WIN32 common_libolacommon_la_SOURCES += \ common/io/WindowsPoller.cpp \ common/io/WindowsPoller.h else common_libolacommon_la_SOURCES += \ common/io/SelectPoller.cpp \ common/io/SelectPoller.h endif if HAVE_EPOLL common_libolacommon_la_SOURCES += \ common/io/EPoller.h \ common/io/EPoller.cpp endif if HAVE_KQUEUE common_libolacommon_la_SOURCES += \ common/io/KQueuePoller.h \ common/io/KQueuePoller.cpp endif # TESTS ################################################## test_programs += \ common/io/DescriptorTester \ common/io/IOQueueTester \ common/io/IOStackTester \ common/io/MemoryBlockTester \ common/io/SelectServerTester \ common/io/StreamTester \ common/io/TimeoutManagerTester common_io_IOQueueTester_SOURCES = common/io/IOQueueTest.cpp common_io_IOQueueTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_io_IOQueueTester_LDADD = $(COMMON_TESTING_LIBS) common_io_IOStackTester_SOURCES = common/io/IOStackTest.cpp common_io_IOStackTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_io_IOStackTester_LDADD = $(COMMON_TESTING_LIBS) common_io_DescriptorTester_SOURCES = common/io/DescriptorTest.cpp common_io_DescriptorTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_io_DescriptorTester_LDADD = $(COMMON_TESTING_LIBS) common_io_MemoryBlockTester_SOURCES = common/io/MemoryBlockTest.cpp common_io_MemoryBlockTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_io_MemoryBlockTester_LDADD = $(COMMON_TESTING_LIBS) common_io_SelectServerTester_SOURCES = common/io/SelectServerTest.cpp \ common/io/SelectServerThreadTest.cpp common_io_SelectServerTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_io_SelectServerTester_LDADD = $(COMMON_TESTING_LIBS) common_io_TimeoutManagerTester_SOURCES = common/io/TimeoutManagerTest.cpp common_io_TimeoutManagerTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_io_TimeoutManagerTester_LDADD = $(COMMON_TESTING_LIBS) common_io_StreamTester_SOURCES = common/io/InputStreamTest.cpp \ common/io/OutputStreamTest.cpp common_io_StreamTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_io_StreamTester_LDADD = $(COMMON_TESTING_LIBS) ola-0.10.5.nojsmin/common/io/PollerInterface.cpp0000644000175000017500000000324013023355232021136 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * PollerInterface.cpp * A poller provides the select loop. * Copyright (C) 2013 Simon Newton */ #include "common/io/PollerInterface.h" #include namespace ola { namespace io { /** * @brief The number of descriptors registered for read events. */ const char PollerInterface::K_READ_DESCRIPTOR_VAR[] = "ss-read-descriptors"; /** * @brief The number of descriptors registered for write events. */ const char PollerInterface::K_WRITE_DESCRIPTOR_VAR[] = "ss-write-descriptor"; /** * @brief The number of connected descriptors registered for read events. */ const char PollerInterface::K_CONNECTED_DESCRIPTORS_VAR[] = "ss-connected-descriptors"; /** * @brief The time spent in the event loop. */ const char PollerInterface::K_LOOP_TIME[] = "ss-loop-time"; /** * @brief The number of iterations through the event loop. */ const char PollerInterface::K_LOOP_COUNT[] = "ss-loop-count"; } // namespace io } // namespace ola ola-0.10.5.nojsmin/common/io/TimeoutManager.cpp0000644000175000017500000000655113023355232021011 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * TimeoutManager.cpp * Manages timeout events. * Copyright (C) 2013 Simon Newton */ #include #include #include #include "ola/Logging.h" #include "common/io/TimeoutManager.h" namespace ola { namespace io { // Tracks the # of timer functions registered const char TimeoutManager::K_TIMER_VAR[] = "ss-timers"; using ola::Callback0; using ola::ExportMap; using ola::thread::INVALID_TIMEOUT; using ola::thread::timeout_id; TimeoutManager::TimeoutManager(ExportMap *export_map, Clock *clock) : m_export_map(export_map), m_clock(clock) { if (m_export_map) { m_export_map->GetIntegerVar(K_TIMER_VAR); } } TimeoutManager::~TimeoutManager() { m_removed_timeouts.clear(); while (!m_events.empty()) { delete m_events.top(); m_events.pop(); } } timeout_id TimeoutManager::RegisterRepeatingTimeout( const TimeInterval &interval, ola::Callback0 *closure) { if (!closure) return INVALID_TIMEOUT; if (m_export_map) (*m_export_map->GetIntegerVar(K_TIMER_VAR))++; Event *event = new RepeatingEvent(interval, m_clock, closure); m_events.push(event); return event; } timeout_id TimeoutManager::RegisterSingleTimeout( const TimeInterval &interval, ola::SingleUseCallback0 *closure) { if (!closure) return INVALID_TIMEOUT; if (m_export_map) (*m_export_map->GetIntegerVar(K_TIMER_VAR))++; Event *event = new SingleEvent(interval, m_clock, closure); m_events.push(event); return event; } void TimeoutManager::CancelTimeout(timeout_id id) { // TODO(simon): just mark the timeouts as cancelled rather than using a // remove set. if (id == INVALID_TIMEOUT) return; if (!m_removed_timeouts.insert(id).second) OLA_WARN << "timeout " << id << " already in remove set"; } TimeInterval TimeoutManager::ExecuteTimeouts(TimeStamp *now) { Event *e; if (m_events.empty()) return TimeInterval(); for (e = m_events.top(); !m_events.empty() && (e->NextTime() <= *now); e = m_events.top()) { m_events.pop(); // if this was removed, skip it if (m_removed_timeouts.erase(e)) { delete e; if (m_export_map) (*m_export_map->GetIntegerVar(K_TIMER_VAR))--; continue; } if (e->Trigger()) { // true implies we need to run this again e->UpdateTime(*now); m_events.push(e); } else { delete e; if (m_export_map) (*m_export_map->GetIntegerVar(K_TIMER_VAR))--; } m_clock->CurrentTime(now); } if (m_events.empty()) return TimeInterval(); else return m_events.top()->NextTime() - *now; } } // namespace io } // namespace ola ola-0.10.5.nojsmin/common/io/TimeoutManagerTest.cpp0000644000175000017500000001722213023355232021646 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * TimeoutManagerTest.cpp * Test fixture for the TimeoutManager class. * Copyright (C) 2013 Simon Newton */ #include #include #include "common/io/TimeoutManager.h" #include "ola/Callback.h" #include "ola/Clock.h" #include "ola/ExportMap.h" #include "ola/Logging.h" #include "ola/testing/TestUtils.h" using ola::ExportMap; using ola::MockClock; using ola::NewSingleCallback; using ola::NewCallback; using ola::TimeInterval; using ola::TimeStamp; using ola::io::TimeoutManager; using ola::thread::timeout_id; class TimeoutManagerTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(TimeoutManagerTest); CPPUNIT_TEST(testSingleTimeouts); CPPUNIT_TEST(testRepeatingTimeouts); CPPUNIT_TEST(testAbortedRepeatingTimeouts); CPPUNIT_TEST(testPendingEventShutdown); CPPUNIT_TEST_SUITE_END(); public: void testSingleTimeouts(); void testRepeatingTimeouts(); void testAbortedRepeatingTimeouts(); void testPendingEventShutdown(); void HandleEvent(unsigned int event_id) { m_event_counters[event_id]++; } bool HandleRepeatingEvent(unsigned int event_id) { m_event_counters[event_id]++; return true; } // returns false after the second event. bool HandleAbortedEvent(unsigned int event_id) { m_event_counters[event_id]++; return m_event_counters[event_id] < 2; } unsigned int GetEventCounter(unsigned int event_id) { return m_event_counters[event_id]; } private: ExportMap m_map; std::map m_event_counters; }; CPPUNIT_TEST_SUITE_REGISTRATION(TimeoutManagerTest); /* * Check RegisterSingleTimeout works. */ void TimeoutManagerTest::testSingleTimeouts() { MockClock clock; TimeoutManager timeout_manager(&m_map, &clock); OLA_ASSERT_FALSE(timeout_manager.EventsPending()); TimeInterval timeout_interval(1, 0); timeout_id id1 = timeout_manager.RegisterSingleTimeout( timeout_interval, NewSingleCallback(this, &TimeoutManagerTest::HandleEvent, 1u)); OLA_ASSERT_NE(id1, ola::thread::INVALID_TIMEOUT); TimeStamp last_checked_time; clock.AdvanceTime(0, 1); // Small offset to work around timer precision clock.CurrentTime(&last_checked_time); TimeInterval next = timeout_manager.ExecuteTimeouts(&last_checked_time); OLA_ASSERT_EQ(0u, GetEventCounter(1)); OLA_ASSERT_LT(next, timeout_interval); clock.AdvanceTime(0, 500000); clock.CurrentTime(&last_checked_time); next = timeout_manager.ExecuteTimeouts(&last_checked_time); OLA_ASSERT_EQ(0u, GetEventCounter(1)); OLA_ASSERT_LT(next, TimeInterval(0, 500000)); clock.AdvanceTime(0, 500000); clock.CurrentTime(&last_checked_time); next = timeout_manager.ExecuteTimeouts(&last_checked_time); OLA_ASSERT_TRUE(next.IsZero()); OLA_ASSERT_EQ(1u, GetEventCounter(1)); OLA_ASSERT_FALSE(timeout_manager.EventsPending()); // now add another timeout and then remove it timeout_id id2 = timeout_manager.RegisterSingleTimeout( timeout_interval, NewSingleCallback(this, &TimeoutManagerTest::HandleEvent, 2u)); OLA_ASSERT_NE(id2, ola::thread::INVALID_TIMEOUT); OLA_ASSERT_TRUE(timeout_manager.EventsPending()); OLA_ASSERT_EQ(0u, GetEventCounter(2)); timeout_manager.CancelTimeout(id2); clock.AdvanceTime(1, 0); clock.CurrentTime(&last_checked_time); next = timeout_manager.ExecuteTimeouts(&last_checked_time); OLA_ASSERT_FALSE(timeout_manager.EventsPending()); OLA_ASSERT_EQ(0u, GetEventCounter(2)); } /* * Check RegisterRepeatingTimeout works. */ void TimeoutManagerTest::testRepeatingTimeouts() { MockClock clock; TimeoutManager timeout_manager(&m_map, &clock); OLA_ASSERT_FALSE(timeout_manager.EventsPending()); TimeInterval timeout_interval(1, 0); timeout_id id1 = timeout_manager.RegisterRepeatingTimeout( timeout_interval, NewCallback(this, &TimeoutManagerTest::HandleRepeatingEvent, 1u)); OLA_ASSERT_NE(id1, ola::thread::INVALID_TIMEOUT); TimeStamp last_checked_time; clock.AdvanceTime(0, 1); // Small offset to work around timer precision clock.CurrentTime(&last_checked_time); TimeInterval next = timeout_manager.ExecuteTimeouts(&last_checked_time); OLA_ASSERT_EQ(0u, GetEventCounter(1)); OLA_ASSERT_LT(next, timeout_interval); clock.AdvanceTime(0, 500000); clock.CurrentTime(&last_checked_time); next = timeout_manager.ExecuteTimeouts(&last_checked_time); OLA_ASSERT_EQ(0u, GetEventCounter(1)); OLA_ASSERT_LT(next, TimeInterval(0, 500000)); clock.AdvanceTime(0, 500000); clock.CurrentTime(&last_checked_time); next = timeout_manager.ExecuteTimeouts(&last_checked_time); OLA_ASSERT_LTE(next, timeout_interval); OLA_ASSERT_EQ(1u, GetEventCounter(1)); OLA_ASSERT_TRUE(timeout_manager.EventsPending()); // fire the event again clock.AdvanceTime(1, 0); clock.CurrentTime(&last_checked_time); next = timeout_manager.ExecuteTimeouts(&last_checked_time); OLA_ASSERT_LTE(next, timeout_interval); OLA_ASSERT_EQ(2u, GetEventCounter(1)); // cancel the event timeout_manager.CancelTimeout(id1); clock.AdvanceTime(1, 0); clock.CurrentTime(&last_checked_time); next = timeout_manager.ExecuteTimeouts(&last_checked_time); OLA_ASSERT_TRUE(next.IsZero()); OLA_ASSERT_EQ(2u, GetEventCounter(1)); } /* * Check returning false from a repeating timeout cancels the timeout. */ void TimeoutManagerTest::testAbortedRepeatingTimeouts() { MockClock clock; TimeoutManager timeout_manager(&m_map, &clock); OLA_ASSERT_FALSE(timeout_manager.EventsPending()); TimeInterval timeout_interval(1, 0); timeout_id id1 = timeout_manager.RegisterRepeatingTimeout( timeout_interval, NewCallback(this, &TimeoutManagerTest::HandleAbortedEvent, 1u)); OLA_ASSERT_NE(id1, ola::thread::INVALID_TIMEOUT); TimeStamp last_checked_time; clock.AdvanceTime(0, 1); // Small offset to work around timer precision clock.AdvanceTime(1, 0); clock.CurrentTime(&last_checked_time); timeout_manager.ExecuteTimeouts(&last_checked_time); OLA_ASSERT_EQ(1u, GetEventCounter(1)); clock.AdvanceTime(1, 0); clock.CurrentTime(&last_checked_time); timeout_manager.ExecuteTimeouts(&last_checked_time); OLA_ASSERT_EQ(2u, GetEventCounter(1)); OLA_ASSERT_FALSE(timeout_manager.EventsPending()); } /* * Check we don't leak if there are events pending when the manager is * destroyed. */ void TimeoutManagerTest::testPendingEventShutdown() { MockClock clock; TimeoutManager timeout_manager(&m_map, &clock); OLA_ASSERT_FALSE(timeout_manager.EventsPending()); TimeInterval timeout_interval(1, 0); timeout_id id1 = timeout_manager.RegisterSingleTimeout( timeout_interval, NewSingleCallback(this, &TimeoutManagerTest::HandleEvent, 1u)); OLA_ASSERT_NE(id1, ola::thread::INVALID_TIMEOUT); timeout_id id2 = timeout_manager.RegisterRepeatingTimeout( timeout_interval, NewCallback(this, &TimeoutManagerTest::HandleRepeatingEvent, 1u)); OLA_ASSERT_NE(id2, ola::thread::INVALID_TIMEOUT); OLA_ASSERT_TRUE(timeout_manager.EventsPending()); } ola-0.10.5.nojsmin/common/io/SelectServer.cpp0000644000175000017500000002507113023355232020474 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SelectServer.cpp * Implementation of the SelectServer class * Copyright (C) 2005 Simon Newton */ #include "ola/io/SelectServer.h" #ifdef _WIN32 #include #else #include #endif // _WIN32 #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #include #include #include #include #include #ifdef _WIN32 #include "common/io/WindowsPoller.h" #else #include "ola/base/Flags.h" #include "common/io/SelectPoller.h" #endif // _WIN32 #include "ola/io/Descriptor.h" #include "ola/Logging.h" #include "ola/network/Socket.h" #include "ola/stl/STLUtils.h" #ifdef HAVE_EPOLL #include "common/io/EPoller.h" DEFINE_default_bool(use_epoll, true, "Disable the use of epoll(), revert to select()"); #endif // HAVE_EPOLL #ifdef HAVE_KQUEUE #include "common/io/KQueuePoller.h" DEFINE_default_bool(use_kqueue, false, "Use kqueue() rather than select()"); #endif // HAVE_KQUEUE namespace ola { namespace io { using ola::Callback0; using ola::ExportMap; using ola::thread::timeout_id; using std::max; const TimeStamp SelectServer::empty_time; SelectServer::SelectServer(ExportMap *export_map, Clock *clock) : m_export_map(export_map), m_terminate(false), m_is_running(false), m_poll_interval(POLL_INTERVAL_SECOND, POLL_INTERVAL_USECOND), m_clock(clock), m_free_clock(false) { Options options; Init(options); } SelectServer::SelectServer(const Options &options) : m_export_map(options.export_map), m_terminate(false), m_is_running(false), m_poll_interval(POLL_INTERVAL_SECOND, POLL_INTERVAL_USECOND), m_clock(options.clock), m_free_clock(false) { Init(options); } SelectServer::~SelectServer() { DrainCallbacks(); STLDeleteElements(&m_loop_callbacks); if (m_free_clock) { delete m_clock; } } const TimeStamp *SelectServer::WakeUpTime() const { if (m_poller.get()) { return m_poller->WakeUpTime(); } else { return &empty_time; } } void SelectServer::Terminate() { if (m_is_running) { Execute(NewSingleCallback(this, &SelectServer::SetTerminate)); } } void SelectServer::SetDefaultInterval(const TimeInterval &poll_interval) { m_poll_interval = poll_interval; } void SelectServer::Run() { if (m_is_running) { OLA_FATAL << "SelectServer::Run() called recursively"; return; } m_is_running = true; m_terminate = false; while (!m_terminate) { // false indicates an error in CheckForEvents(); if (!CheckForEvents(m_poll_interval)) { break; } } m_is_running = false; } void SelectServer::RunOnce() { RunOnce(TimeInterval(0, 0)); } void SelectServer::RunOnce(const TimeInterval &block_interval) { m_is_running = true; CheckForEvents(block_interval); m_is_running = false; } bool SelectServer::AddReadDescriptor(ReadFileDescriptor *descriptor) { bool added = m_poller->AddReadDescriptor(descriptor); if (added && m_export_map) { (*m_export_map->GetIntegerVar(PollerInterface::K_READ_DESCRIPTOR_VAR))++; } return added; } bool SelectServer::AddReadDescriptor(ConnectedDescriptor *descriptor, bool delete_on_close) { bool added = m_poller->AddReadDescriptor(descriptor, delete_on_close); if (added && m_export_map) { (*m_export_map->GetIntegerVar( PollerInterface::K_CONNECTED_DESCRIPTORS_VAR))++; } return added; } void SelectServer::RemoveReadDescriptor(ReadFileDescriptor *descriptor) { if (!descriptor->ValidReadDescriptor()) { OLA_WARN << "Removing an invalid file descriptor: " << descriptor; return; } bool removed = m_poller->RemoveReadDescriptor(descriptor); if (removed && m_export_map) { (*m_export_map->GetIntegerVar( PollerInterface::K_READ_DESCRIPTOR_VAR))--; } } void SelectServer::RemoveReadDescriptor(ConnectedDescriptor *descriptor) { if (!descriptor->ValidReadDescriptor()) { OLA_WARN << "Removing an invalid file descriptor: " << descriptor; return; } bool removed = m_poller->RemoveReadDescriptor(descriptor); if (removed && m_export_map) { (*m_export_map->GetIntegerVar( PollerInterface::K_CONNECTED_DESCRIPTORS_VAR))--; } } bool SelectServer::AddWriteDescriptor(WriteFileDescriptor *descriptor) { bool added = m_poller->AddWriteDescriptor(descriptor); if (added && m_export_map) { (*m_export_map->GetIntegerVar(PollerInterface::K_WRITE_DESCRIPTOR_VAR))++; } return added; } void SelectServer::RemoveWriteDescriptor(WriteFileDescriptor *descriptor) { if (!descriptor->ValidWriteDescriptor()) { OLA_WARN << "Removing a closed descriptor"; return; } bool removed = m_poller->RemoveWriteDescriptor(descriptor); if (removed && m_export_map) { (*m_export_map->GetIntegerVar(PollerInterface::K_WRITE_DESCRIPTOR_VAR))--; } } timeout_id SelectServer::RegisterRepeatingTimeout( unsigned int ms, ola::Callback0 *callback) { return m_timeout_manager->RegisterRepeatingTimeout( TimeInterval(ms / 1000, ms % 1000 * 1000), callback); } timeout_id SelectServer::RegisterRepeatingTimeout( const TimeInterval &interval, ola::Callback0 *callback) { return m_timeout_manager->RegisterRepeatingTimeout(interval, callback); } timeout_id SelectServer::RegisterSingleTimeout( unsigned int ms, ola::SingleUseCallback0 *callback) { return m_timeout_manager->RegisterSingleTimeout( TimeInterval(ms / 1000, ms % 1000 * 1000), callback); } timeout_id SelectServer::RegisterSingleTimeout( const TimeInterval &interval, ola::SingleUseCallback0 *callback) { return m_timeout_manager->RegisterSingleTimeout(interval, callback); } void SelectServer::RemoveTimeout(timeout_id id) { return m_timeout_manager->CancelTimeout(id); } void SelectServer::RunInLoop(Callback0 *callback) { m_loop_callbacks.insert(callback); } void SelectServer::Execute(ola::BaseCallback0 *callback) { { ola::thread::MutexLocker locker(&m_incoming_mutex); m_incoming_callbacks.push_back(callback); } // kick select(), we do this even if we're in the same thread as select() is // called. If we don't do this there is a race condition because a callback // may be added just prior to select(). Without this kick, select() will // sleep for the poll_interval before executing the callback. uint8_t wake_up = 'a'; m_incoming_descriptor.Send(&wake_up, sizeof(wake_up)); } void SelectServer::DrainCallbacks() { Callbacks callbacks_to_run; while (true) { { ola::thread::MutexLocker locker(&m_incoming_mutex); if (m_incoming_callbacks.empty()) { return; } callbacks_to_run.swap(m_incoming_callbacks); } RunCallbacks(&callbacks_to_run); } } void SelectServer::Init(const Options &options) { if (!m_clock) { m_clock = new Clock; m_free_clock = true; } if (m_export_map) { m_export_map->GetIntegerVar(PollerInterface::K_READ_DESCRIPTOR_VAR); m_export_map->GetIntegerVar(PollerInterface::K_WRITE_DESCRIPTOR_VAR); m_export_map->GetIntegerVar(PollerInterface::K_CONNECTED_DESCRIPTORS_VAR); } m_timeout_manager.reset(new TimeoutManager(m_export_map, m_clock)); #ifdef _WIN32 m_poller.reset(new WindowsPoller(m_export_map, m_clock)); (void) options; #else #ifdef HAVE_EPOLL if (FLAGS_use_epoll && !options.force_select) { m_poller.reset(new EPoller(m_export_map, m_clock)); } if (m_export_map) { m_export_map->GetBoolVar("using-epoll")->Set(FLAGS_use_epoll); } #endif // HAVE_EPOLL #ifdef HAVE_KQUEUE bool using_kqueue = false; if (FLAGS_use_kqueue && !m_poller.get() && !options.force_select) { m_poller.reset(new KQueuePoller(m_export_map, m_clock)); using_kqueue = true; } if (m_export_map) { m_export_map->GetBoolVar("using-kqueue")->Set(using_kqueue); } #endif // HAVE_KQUEUE // Default to the SelectPoller if (!m_poller.get()) { m_poller.reset(new SelectPoller(m_export_map, m_clock)); } #endif // _WIN32 // TODO(simon): this should really be in an Init() method that returns a // bool. if (!m_incoming_descriptor.Init()) { OLA_FATAL << "Failed to init LoopbackDescriptor, Execute() won't work!"; } m_incoming_descriptor.SetOnData( ola::NewCallback(this, &SelectServer::DrainAndExecute)); AddReadDescriptor(&m_incoming_descriptor); } /* * One iteration of the event loop. * @return false on error, true on success. */ bool SelectServer::CheckForEvents(const TimeInterval &poll_interval) { LoopClosureSet::iterator loop_iter; for (loop_iter = m_loop_callbacks.begin(); loop_iter != m_loop_callbacks.end(); ++loop_iter) { (*loop_iter)->Run(); } TimeInterval default_poll_interval = poll_interval; // if we've been told to terminate, make this very short. if (m_terminate) { default_poll_interval = std::min( default_poll_interval, TimeInterval(0, 1000)); } return m_poller->Poll(m_timeout_manager.get(), default_poll_interval); } void SelectServer::DrainAndExecute() { while (m_incoming_descriptor.DataRemaining()) { // try to get everything in one read uint8_t message[100]; unsigned int size; m_incoming_descriptor.Receive(reinterpret_cast(&message), sizeof(message), size); } // We can't hold the mutex while we execute the callback, so instead we swap // out the vector under a lock, release the lock and then run all the // callbacks. Callbacks callbacks_to_run; { thread::MutexLocker lock(&m_incoming_mutex); callbacks_to_run.swap(m_incoming_callbacks); } RunCallbacks(&callbacks_to_run); } void SelectServer::RunCallbacks(Callbacks *callbacks) { Callbacks::iterator iter = callbacks->begin(); for (; iter != callbacks->end(); ++iter) { if (*iter) { (*iter)->Run(); } } callbacks->clear(); } } // namespace io } // namespace ola ola-0.10.5.nojsmin/common/io/IOStackTest.cpp0000644000175000017500000001424513023355232020224 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * IOStackTest.cpp * Test fixture for the IOStack class. * Copyright (C) 2013 Simon Newton */ #include #include #include #include #include "ola/Logging.h" #include "ola/io/IOStack.h" #include "ola/io/IOQueue.h" #include "ola/io/MemoryBlockPool.h" #include "ola/testing/TestUtils.h" using ola::io::IOStack; using ola::io::IOQueue; using ola::io::IOVec; using ola::io::MemoryBlockPool; using std::string; class IOStackTest: public CppUnit::TestFixture { public: CPPUNIT_TEST_SUITE(IOStackTest); CPPUNIT_TEST(testBasicWrite); CPPUNIT_TEST(testBlockOverflow); CPPUNIT_TEST(testIOVec); CPPUNIT_TEST(testAppendToQueue); CPPUNIT_TEST(testBlockReuse); CPPUNIT_TEST_SUITE_END(); public: void testBasicWrite(); void testBlockOverflow(); void testIOVec(); void testAppendToQueue(); void testBlockReuse(); private: unsigned int SumLengthOfIOVec(const struct IOVec *iov, int iocnt); }; CPPUNIT_TEST_SUITE_REGISTRATION(IOStackTest); /** * Sum up the length of data in a IOVec */ unsigned int IOStackTest::SumLengthOfIOVec(const struct IOVec *iov, int iocnt) { unsigned int sum = 0; for (int i = 0; i < iocnt; iov++, i++) sum += iov->iov_len; return sum; } /* * Check that basic prepending works. */ void IOStackTest::testBasicWrite() { IOStack stack; OLA_ASSERT_EQ(0u, stack.Size()); OLA_ASSERT_TRUE(stack.Empty()); uint8_t data1[] = {0, 1}; uint8_t data2[] = {2}; uint8_t data3[] = {3, 4}; stack.Write(data1, sizeof(data1)); OLA_ASSERT_EQ(2u, stack.Size()); stack.Write(data2, sizeof(data2)); OLA_ASSERT_EQ(3u, stack.Size()); stack.Write(data3, sizeof(data3)); OLA_ASSERT_EQ(5u, stack.Size()); std::ostringstream str; stack.Dump(&str); OLA_ASSERT_EQ( string("03 04 02 00 01 .....\n"), str.str()); unsigned int data_size = stack.Size(); uint8_t output[data_size]; OLA_ASSERT_EQ(data_size, stack.Read(output, data_size)); const uint8_t expected_data[] = {3, 4, 2, 0, 1}; OLA_ASSERT_DATA_EQUALS(expected_data, sizeof(expected_data), output, data_size); } /* * Check that overflowing blocks works */ void IOStackTest::testBlockOverflow() { // block size of 4 MemoryBlockPool pool(4); IOStack stack(&pool); uint8_t data1[] = {0, 1, 2, 3, 4}; uint8_t data2[] = {5, 6, 7, 8, 9}; uint8_t data3[] = {0xa, 0xb, 0xc, 0xd, 0xe}; stack.Write(data1, sizeof(data1)); OLA_ASSERT_EQ(5u, stack.Size()); stack.Write(data2, sizeof(data2)); OLA_ASSERT_EQ(10u, stack.Size()); stack.Write(data3, sizeof(data3)); OLA_ASSERT_EQ(15u, stack.Size()); unsigned int data_size = stack.Size(); uint8_t output[data_size]; OLA_ASSERT_EQ(data_size, stack.Read(output, data_size)); const uint8_t expected_data[] = {0xa, 0xb, 0xc, 0xd, 0xe, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4}; OLA_ASSERT_DATA_EQUALS(expected_data, sizeof(expected_data), output, data_size); } /** * Test getting / setting IOVec work. */ void IOStackTest::testIOVec() { MemoryBlockPool pool(4); IOStack stack(&pool); uint8_t data1[] = {5, 6, 7, 8}; uint8_t data2[] = {0, 1, 2, 3, 4}; stack.Write(data1, sizeof(data1)); stack.Write(data2, sizeof(data2)); OLA_ASSERT_EQ(9u, stack.Size()); OLA_ASSERT_FALSE(stack.Empty()); int iocnt; const struct IOVec *vector = stack.AsIOVec(&iocnt); OLA_ASSERT_EQ(9u, SumLengthOfIOVec(vector, iocnt)); OLA_ASSERT_EQ(3, iocnt); stack.FreeIOVec(vector); } /** * Test appending IOStacks to an IOQueue works. */ void IOStackTest::testAppendToQueue() { MemoryBlockPool pool(4); IOStack stack(&pool); uint8_t data1[] = {2, 1, 0}; uint8_t data2[] = {6, 5, 4, 3}; stack.Write(data1, sizeof(data1)); stack.Write(data2, sizeof(data2)); OLA_ASSERT_EQ(7u, stack.Size()); IOQueue queue(&pool); stack.MoveToIOQueue(&queue); OLA_ASSERT_TRUE(stack.Empty()); OLA_ASSERT_EQ(7u, queue.Size()); uint8_t expected_data[] = {6, 5, 4, 3, 2, 1, 0}; uint8_t tmp_data[100]; unsigned int queue_size = queue.Peek(tmp_data, sizeof(tmp_data)); OLA_ASSERT_EQ(7u, queue_size); OLA_ASSERT_DATA_EQUALS(tmp_data, queue_size, expected_data, sizeof(expected_data)); // now add a second stack uint8_t data3[] = {0xb, 0xa}; uint8_t data4[] = {0xf, 0xe, 0xd, 0xc}; stack.Write(data3, sizeof(data3)); stack.Write(data4, sizeof(data4)); OLA_ASSERT_EQ(6u, stack.Size()); stack.MoveToIOQueue(&queue); OLA_ASSERT_TRUE(stack.Empty()); OLA_ASSERT_EQ(13u, queue.Size()); uint8_t expected_data2[] = {6, 5, 4, 3, 2, 1, 0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa}; queue_size = queue.Peek(tmp_data, sizeof(tmp_data)); OLA_ASSERT_EQ(13u, queue_size); OLA_ASSERT_DATA_EQUALS(tmp_data, queue_size, expected_data2, sizeof(expected_data2)); OLA_ASSERT_EQ(4u, pool.BlocksAllocated()); } /** * Confirm we re-use blocks */ void IOStackTest::testBlockReuse() { MemoryBlockPool pool(4); { IOStack stack(&pool); uint8_t data1[] = {6, 5, 3, 3, 2, 1, 0}; stack.Write(data1, sizeof(data1)); OLA_ASSERT_EQ(7u, stack.Size()); } { IOStack stack(&pool); uint8_t data1[] = {0xf, 0xe, 0xd, 0xc, 0xb, 0xa}; stack.Write(data1, sizeof(data1)); OLA_ASSERT_EQ(6u, stack.Size()); } OLA_ASSERT_EQ(2u, pool.BlocksAllocated()); pool.Purge(); OLA_ASSERT_EQ(0u, pool.BlocksAllocated()); } ola-0.10.5.nojsmin/common/io/IOStack.cpp0000644000175000017500000001442013023355232017357 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * IOStack.cpp * A non-contigous memory buffer * Copyright (C) 2012 Simon Newton */ #include #include #include #include #include #include #include #include #include #include #include namespace ola { namespace io { using std::min; using std::string; /** * IOStack. */ IOStack::IOStack() : m_pool(new MemoryBlockPool()), m_delete_pool(true) { } IOStack::IOStack(MemoryBlockPool *block_pool) : m_pool(block_pool), m_delete_pool(false) { } /** * Clean up */ IOStack::~IOStack() { // Return all the blocks to the pool. BlockVector::iterator iter = m_blocks.begin(); for (; iter != m_blocks.end(); ++iter) m_pool->Release(*iter); if (m_delete_pool) delete m_pool; } /** * Return the amount of data in the buffer */ unsigned int IOStack::Size() const { if (m_blocks.empty()) return 0; unsigned int size = 0; BlockVector::const_iterator iter = m_blocks.begin(); for (; iter != m_blocks.end(); ++iter) size += (*iter)->Size(); return size; } /** * Append (length) bytes of data to the front of the buffer. */ void IOStack::Write(const uint8_t *data, unsigned int length) { if (m_blocks.empty()) { PrependBlock(); } unsigned int bytes_written = 0; while (true) { bytes_written += m_blocks.front()->Prepend(data, length - bytes_written); if (bytes_written == length) { return; } PrependBlock(); } } /** * Read up to n bytes into the memory location data and shrink the IOQueue by * the amount read. */ unsigned int IOStack::Read(uint8_t *data, unsigned int length) { unsigned int bytes_read = 0; BlockVector::iterator iter = m_blocks.begin(); while (iter != m_blocks.end() && bytes_read != length) { MemoryBlock *block = *iter; unsigned int bytes_copied = block->Copy(data + bytes_read, length - bytes_read); block->PopFront(bytes_copied); bytes_read += bytes_copied; if (block->Empty()) { m_pool->Release(block); iter = m_blocks.erase(iter); } else { iter++; } } return bytes_read; } /** * Read up to n bytes into the string output. */ unsigned int IOStack::Read(string *output, unsigned int length) { unsigned int bytes_remaining = length; BlockVector::iterator iter = m_blocks.begin(); while (iter != m_blocks.end() && bytes_remaining) { MemoryBlock *block = *iter; unsigned int bytes_to_copy = std::min(block->Size(), bytes_remaining); output->append(reinterpret_cast(block->Data()), bytes_to_copy); bytes_remaining -= bytes_to_copy; if (block->Empty()) { m_pool->Release(block); iter = m_blocks.erase(iter); } else { iter++; } } return length - bytes_remaining; } /** * Return this IOStack as an array of IOVec structures. * Note: The IOVec array points at internal memory structures. This array is * invalidated when any non-const methods are called (Append, Pop etc.) * * Is the IOStack is empty, this will return NULL and set iocnt to 0. * * Use FreeIOVec() to release the IOVec array. */ const struct IOVec *IOStack::AsIOVec(int *iocnt) const { if (m_blocks.empty()) { *iocnt = 0; return NULL; } int max_number_of_blocks = m_blocks.size(); int number_of_blocks = 0; struct IOVec *vector = new struct IOVec[max_number_of_blocks]; struct IOVec *ptr = vector; BlockVector::const_iterator iter = m_blocks.begin(); for (; iter != m_blocks.end(); ++iter, ++ptr, number_of_blocks++) { ptr->iov_base = (*iter)->Data(); ptr->iov_len = (*iter)->Size(); } *iocnt = number_of_blocks; return vector; } /** * Remove bytes from the stack */ void IOStack::Pop(unsigned int bytes_to_remove) { unsigned int bytes_removed = 0; BlockVector::iterator iter = m_blocks.begin(); while (iter != m_blocks.end() && bytes_removed != bytes_to_remove) { MemoryBlock *block = *iter; bytes_removed += block->PopFront(bytes_to_remove - bytes_removed); if (block->Empty()) { m_pool->Release(block); iter = m_blocks.erase(iter); } else { iter++; } } } /** * Append the memory blocks in this stack to the IOQueue. This transfers * ownership of the MemoryBlocks to the queue, so the IOQueue and IOStack * should have the same MemoryBlockPool (or at the very least, the same * implementation). */ void IOStack::MoveToIOQueue(IOQueue *queue) { BlockVector::const_iterator iter = m_blocks.begin(); for (; iter != m_blocks.end(); ++iter) { queue->AppendBlock(*iter); } m_blocks.clear(); } void IOStack::Purge() { m_pool->Purge(); } /** * Dump this IOStack as a human readable string */ void IOStack::Dump(std::ostream *output) { unsigned int length = 0; BlockVector::const_iterator iter = m_blocks.begin(); for (; iter != m_blocks.end(); ++iter) { length += (*iter)->Size(); } // For now just alloc memory for the entire thing uint8_t *tmp = new uint8_t[length]; unsigned int offset = 0; for (iter = m_blocks.begin(); iter != m_blocks.end(); ++iter) { offset += (*iter)->Copy(tmp + offset, length - offset); } ola::FormatData(output, tmp, offset); delete[] tmp; } /** * Append another block. */ void IOStack::PrependBlock() { MemoryBlock *block = m_pool->Allocate(); if (!block) { OLA_FATAL << "Failed to allocate block, we're out of memory!"; } else { block->SeekBack(); // put the block into prepend mode m_blocks.push_front(block); } } } // namespace io } // namespace ola ola-0.10.5.nojsmin/common/io/IOUtils.cpp0000644000175000017500000000307113023355232017412 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * IOUtils.cpp * I/O Helper methods. * Copyright (C) 2013 Simon Newton */ #include "ola/io/IOUtils.h" #include #include #include #include #include #include "ola/Logging.h" namespace ola { namespace io { using std::string; bool Open(const string &path, int oflag, int *fd) { *fd = open(path.c_str(), oflag); if (*fd < 0) { OLA_WARN << "open(" << path << "): " << strerror(errno); return false; } return true; } bool TryOpen(const string &path, int oflag, int *fd) { *fd = open(path.c_str(), oflag); if (*fd < 0) { OLA_INFO << "open(" << path << "): " << strerror(errno); } return *fd >= 0; } bool FileExists(const std::string &file_name) { struct stat file_stat; return 0 == stat(file_name.c_str(), &file_stat); } } // namespace io } // namespace ola ola-0.10.5.nojsmin/common/io/KQueuePoller.h0000644000175000017500000000707313023355232020112 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * KQueuePoller.h * A Poller which uses kqueue / kevent * Copyright (C) 2014 Simon Newton */ #ifndef COMMON_IO_KQUEUEPOLLER_H_ #define COMMON_IO_KQUEUEPOLLER_H_ #include #include #include #include #include #include #include #include #include #include #include "common/io/PollerInterface.h" #include "common/io/TimeoutManager.h" namespace ola { namespace io { class KQueueData; /** * @class KQueuePoller * @brief An implementation of PollerInterface that uses kevent / kqueue. * * kevent is more efficient than select() but only BSD-style systems support * it. */ class KQueuePoller : public PollerInterface { public : /** * @brief Create a new KQueuePoller. * @param export_map the ExportMap to use * @param clock the Clock to use */ KQueuePoller(ExportMap *export_map, Clock *clock); ~KQueuePoller(); bool AddReadDescriptor(class ReadFileDescriptor *descriptor); bool AddReadDescriptor(class ConnectedDescriptor *descriptor, bool delete_on_close); bool RemoveReadDescriptor(class ReadFileDescriptor *descriptor); bool RemoveReadDescriptor(class ConnectedDescriptor *descriptor); bool AddWriteDescriptor(class WriteFileDescriptor *descriptor); bool RemoveWriteDescriptor(class WriteFileDescriptor *descriptor); const TimeStamp *WakeUpTime() const { return &m_wake_up_time; } bool Poll(TimeoutManager *timeout_manager, const TimeInterval &poll_interval); private: enum { CHANGE_SET_SIZE = 10 }; typedef std::map DescriptorMap; typedef std::vector DescriptorList; DescriptorMap m_descriptor_map; // KQueuePoller is re-enterant. Remove may be called while we hold a pointer // to an KQueueData. To avoid deleting data out from underneath // ourselves, we instead move the removed descriptors to this list and then // clean them up outside the callback loop. DescriptorList m_orphaned_descriptors; // A list of pre-allocated descriptors we can use. DescriptorList m_free_descriptors; ExportMap *m_export_map; CounterVariable *m_loop_iterations; CounterVariable *m_loop_time; int m_kqueue_fd; struct kevent m_change_set[CHANGE_SET_SIZE]; unsigned int m_next_change_entry; Clock *m_clock; TimeStamp m_wake_up_time; void CheckDescriptor(struct kevent *event); std::pair LookupOrCreateDescriptor(int fd); bool ApplyChange(int fd, int16_t filter, uint16_t flags, KQueueData *kqueue_data, bool apply_immediately); bool RemoveDescriptor(int fd, int16_t filter); static const int MAX_EVENTS; static const unsigned int MAX_FREE_DESCRIPTORS; DISALLOW_COPY_AND_ASSIGN(KQueuePoller); }; } // namespace io } // namespace ola #endif // COMMON_IO_KQUEUEPOLLER_H_ ola-0.10.5.nojsmin/common/io/InputStreamTest.cpp0000644000175000017500000000442413023355232021200 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * InputStreamTest.cpp * Test fixture for the InputStream classes. * Copyright (C) 2012 Simon Newton */ #include #include "ola/Logging.h" #include "ola/io/MemoryBuffer.h" #include "ola/io/BigEndianStream.h" #include "ola/testing/TestUtils.h" using ola::io::BigEndianInputStream; using ola::io::MemoryBuffer; class InputStreamTest: public CppUnit::TestFixture { public: CPPUNIT_TEST_SUITE(InputStreamTest); CPPUNIT_TEST(testRead); CPPUNIT_TEST_SUITE_END(); public: void testRead(); }; CPPUNIT_TEST_SUITE_REGISTRATION(InputStreamTest); /* * Confirm that reading works. */ void InputStreamTest::testRead() { uint8_t data[] = { 0x80, 0x81, 0x80, 0x00, 0x83, 0x01, 0x87, 0x65, 0x43, 0x21, 0x12, 0x34, 0x56, 0x78, }; MemoryBuffer buffer(data, sizeof(data)); BigEndianInputStream stream(&buffer); int8_t int8; OLA_ASSERT_TRUE(stream >> int8); OLA_ASSERT_EQ(static_cast(-128), int8); uint8_t uint8; OLA_ASSERT_TRUE(stream >> uint8); OLA_ASSERT_EQ(static_cast(129), uint8); int16_t int16; OLA_ASSERT_TRUE(stream >> int16); OLA_ASSERT_EQ(static_cast(-32768), int16); uint16_t uint16; OLA_ASSERT_TRUE(stream >> uint16); OLA_ASSERT_EQ(static_cast(33537), uint16); int32_t int32; OLA_ASSERT_TRUE(stream >> int32); OLA_ASSERT_EQ(static_cast(-2023406815), int32); uint32_t uint32; OLA_ASSERT_TRUE(stream >> uint32); OLA_ASSERT_EQ(static_cast(305419896), uint32); OLA_ASSERT_FALSE(stream >> uint16); } ola-0.10.5.nojsmin/common/io/WindowsPoller.h0000644000175000017500000000575613023355232020353 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * WindowsPoller.h * A Poller for the Windows platform * Copyright (C) 2014 Lukas Erlinghagen */ #ifndef COMMON_IO_WINDOWSPOLLER_H_ #define COMMON_IO_WINDOWSPOLLER_H_ #include #include #include #include #define WIN32_LEAN_AND_MEAN #include #include #include #include #include "common/io/PollerInterface.h" #include "common/io/TimeoutManager.h" namespace ola { namespace io { /** * @class WindowsPoller * @brief An implementation of PollerInterface for Windows. */ class WindowsPoller : public PollerInterface { public : /** * @brief Create a new WindowsPoller. * @param export_map the ExportMap to use * @param clock the Clock to use */ WindowsPoller(ExportMap *export_map, Clock *clock); ~WindowsPoller(); bool AddReadDescriptor(class ReadFileDescriptor *descriptor); bool AddReadDescriptor(class ConnectedDescriptor *descriptor, bool delete_on_close); bool RemoveReadDescriptor(class ReadFileDescriptor *descriptor); bool RemoveReadDescriptor(class ConnectedDescriptor *descriptor); bool AddWriteDescriptor(class WriteFileDescriptor *descriptor); bool RemoveWriteDescriptor(class WriteFileDescriptor *descriptor); const TimeStamp *WakeUpTime() const { return &m_wake_up_time; } bool Poll(TimeoutManager *timeout_manager, const TimeInterval &poll_interval); private: typedef std::map DescriptorMap; typedef std::vector OrphanedDescriptors; ExportMap *m_export_map; CounterVariable *m_loop_iterations; CounterVariable *m_loop_time; Clock *m_clock; TimeStamp m_wake_up_time; DescriptorMap m_descriptor_map; OrphanedDescriptors m_orphaned_descriptors; std::pair LookupOrCreateDescriptor(void* handle); bool RemoveDescriptor(const DescriptorHandle &handle, int flag, bool warn_on_missing); void HandleWakeup(class PollData* data); void FinalCheckIOs(std::vector data); DISALLOW_COPY_AND_ASSIGN(WindowsPoller); }; } // namespace io } // namespace ola #endif // COMMON_IO_WINDOWSPOLLER_H_ ola-0.10.5.nojsmin/common/io/PollerInterface.h0000644000175000017500000001405713023355232020613 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * PollerInterface.h * A poller provides the select loop. * Copyright (C) 2013 Simon Newton */ #ifndef COMMON_IO_POLLERINTERFACE_H_ #define COMMON_IO_POLLERINTERFACE_H_ #include #include #include "common/io/TimeoutManager.h" namespace ola { namespace io { /** * @class PollerInterface * @brief The interface for the Poller classes. * * This forms the basis for the low level event management. The SelectServer * will add / remove descriptors as required and then call Poll() with a * timeout. The Poll() method is responsible for checking for timeouts (via the * TimeoutManager) and then blocking until the descriptors are ready or a * timeout event occurs. This blocking is done with select(), poll(), * epoll() or kevent(), depending on the implementation. * * Once the blocking wait returns. any ready descriptors should the appropriate * method called: ola::io::ReadFileDescriptor::PerformRead(), * ola::io::WriteFileDescriptor::PerformWrite() or the callback set in * ola::io::ConnectedDescriptor::SetOnClose(). Once all * descriptors and any new timeouts have been handled, Poll() returns. * * @warning * It's absolutely critical that implementations of PollerInterface be * reentrant. Calling any of the read / write / close actions may in turn add / * remove descriptors, including the descriptor the method was itself called * on. There are tests in SelectServerTest.cpp to exercise some of these cases * but implementors need to be careful. * * @warning * For example, if Poll() iterates over a set of Descriptors and calls * PerformRead() when appropriate, the RemoveReadDescriptor() method can not * simply call erase on the set, since doing so would invalidate the * iterator held in Poll(). The solution is to either use a data structure that * does not invalidate iterators on erase or use a double-lookup and set the * pointer to NULL to indicate erasure. * * @warning * It's also important to realize that after a RemoveReadDescriptor() or * RemoveWriteDescriptor() is called, neither the FD number nor the pointer to * the Destructor can be used again as a unique identifier. This is because * either may be reused immediately following the call to remove. */ class PollerInterface { public : /** * @brief Destructor */ virtual ~PollerInterface() {} /** * @brief Register a ReadFileDescriptor for read events. * @param descriptor the ReadFileDescriptor to register. The OnData() method * will be called when there is data available for reading. * @returns true if the descriptor was registered, false otherwise. */ virtual bool AddReadDescriptor(ReadFileDescriptor *descriptor) = 0; /** * @brief Register a ConnectedDescriptor for read events. * @param descriptor the ConnectedDescriptor to register. The OnData() method * will be called when there is data available for reading. Additionally, * OnClose() will be called if the other end closes the connection. * @param delete_on_close controls whether the descriptor is deleted when * it's closed. * @returns true if the descriptor was registered, false otherwise. */ virtual bool AddReadDescriptor(ConnectedDescriptor *descriptor, bool delete_on_close) = 0; /** * @brief Unregister a ReadFileDescriptor for read events. * @param descriptor the ReadFileDescriptor to unregister. * @returns true if unregistered successfully, false otherwise. * * @pre descriptor->ReadFileDescriptor() is valid. */ virtual bool RemoveReadDescriptor(ReadFileDescriptor *descriptor) = 0; /** * @brief Unregister a ConnectedDescriptor for read events. * @param descriptor the ConnectedDescriptor to unregister. * @returns true if unregistered successfully, false otherwise. * * @pre descriptor->ReadFileDescriptor() is valid. */ virtual bool RemoveReadDescriptor(ConnectedDescriptor *descriptor) = 0; /** * @brief Register a WriteFileDescriptor to receive ready-to-write events. * @param descriptor the WriteFileDescriptor to register. The PerformWrite() * method will be called when the descriptor is ready for writing. * @returns true if the descriptor was registered, false otherwise. */ virtual bool AddWriteDescriptor(WriteFileDescriptor *descriptor) = 0; /** * @brief Unregister a WriteFileDescriptor for write events. * @param descriptor the WriteFileDescriptor to unregister. * @returns true if unregistered successfully, false otherwise. * * @pre descriptor->WriteFileDescriptor() is valid. */ virtual bool RemoveWriteDescriptor(WriteFileDescriptor *descriptor) = 0; virtual const TimeStamp *WakeUpTime() const = 0; /** * @brief Poll the Descriptors for events and execute any callbacks. * @param timeout_manager the TimeoutManager to use for timer events. * @param poll_interval the maximum time to block for. * @returns false if any errors occured, true if events were handled. */ virtual bool Poll(TimeoutManager *timeout_manager, const TimeInterval &poll_interval) = 0; static const char K_READ_DESCRIPTOR_VAR[]; static const char K_WRITE_DESCRIPTOR_VAR[]; static const char K_CONNECTED_DESCRIPTORS_VAR[]; protected: static const char K_LOOP_TIME[]; static const char K_LOOP_COUNT[]; }; } // namespace io } // namespace ola #endif // COMMON_IO_POLLERINTERFACE_H_ ola-0.10.5.nojsmin/common/io/KQueuePoller.cpp0000644000175000017500000003207313023355232020443 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * KQueuePoller.cpp * A Poller which uses kqueue / kevent * Copyright (C) 2014 Simon Newton */ #include "common/io/KQueuePoller.h" #include #include #include #include #include #include #include #include "ola/Clock.h" #include "ola/Logging.h" #include "ola/base/Macro.h" #include "ola/io/Descriptor.h" #include "ola/stl/STLUtils.h" namespace ola { namespace io { using std::pair; /* * Represents a FD */ class KQueueData { public: KQueueData() : enable_read(false), enable_write(false), delete_connected_on_close(false), connected_close_in_progress(false), read_descriptor(NULL), write_descriptor(NULL), connected_descriptor(NULL) { } void Reset() { enable_read = false; enable_write = false; delete_connected_on_close = false; // True if this is a ConnectedDescriptor and it's in the process of being // closed connected_close_in_progress = false; read_descriptor = NULL; write_descriptor = NULL; connected_descriptor = NULL; } uint8_t enable_read : 1; uint8_t enable_write : 1; uint8_t delete_connected_on_close : 1; uint8_t connected_close_in_progress : 1; ReadFileDescriptor *read_descriptor; WriteFileDescriptor *write_descriptor; ConnectedDescriptor *connected_descriptor; }; /** * @brief The maximum number of events to return in one epoll cycle */ const int KQueuePoller::MAX_EVENTS = 10; /** * @brief The number of pre-allocated KQueueData to have. */ const unsigned int KQueuePoller::MAX_FREE_DESCRIPTORS = 10; KQueuePoller::KQueuePoller(ExportMap *export_map, Clock* clock) : m_export_map(export_map), m_loop_iterations(NULL), m_loop_time(NULL), m_kqueue_fd(INVALID_DESCRIPTOR), m_next_change_entry(0), m_clock(clock) { if (m_export_map) { m_loop_time = m_export_map->GetCounterVar(K_LOOP_TIME); m_loop_iterations = m_export_map->GetCounterVar(K_LOOP_COUNT); } m_kqueue_fd = kqueue(); if (m_kqueue_fd < 0) { OLA_FATAL << "Failed to create new kqueue"; } } KQueuePoller::~KQueuePoller() { if (m_kqueue_fd != INVALID_DESCRIPTOR) { close(m_kqueue_fd); } { DescriptorMap::iterator iter = m_descriptor_map.begin(); for (; iter != m_descriptor_map.end(); ++iter) { if (iter->second->delete_connected_on_close) { delete iter->second->connected_descriptor; } delete iter->second; } } DescriptorList::iterator iter = m_orphaned_descriptors.begin(); for (; iter != m_orphaned_descriptors.end(); ++iter) { if ((*iter)->delete_connected_on_close) { delete (*iter)->connected_descriptor; } delete *iter; } STLDeleteElements(&m_free_descriptors); } bool KQueuePoller::AddReadDescriptor(ReadFileDescriptor *descriptor) { if (m_kqueue_fd == INVALID_DESCRIPTOR) { return false; } if (!descriptor->ValidReadDescriptor()) { OLA_WARN << "AddReadDescriptor called with invalid descriptor"; return false; } pair result = LookupOrCreateDescriptor( descriptor->ReadDescriptor()); KQueueData *kqueue_data = result.first; if (kqueue_data->enable_read) { OLA_WARN << "Descriptor " << descriptor->ReadDescriptor() << " already in read set"; return false; } kqueue_data->enable_read = true; kqueue_data->read_descriptor = descriptor; return ApplyChange(descriptor->ReadDescriptor(), EVFILT_READ, EV_ADD, kqueue_data, false); } bool KQueuePoller::AddReadDescriptor(ConnectedDescriptor *descriptor, bool delete_on_close) { if (m_kqueue_fd == INVALID_DESCRIPTOR) { return false; } if (!descriptor->ValidReadDescriptor()) { OLA_WARN << "AddReadDescriptor called with invalid descriptor"; return false; } pair result = LookupOrCreateDescriptor( descriptor->ReadDescriptor()); KQueueData *kqueue_data = result.first; if (kqueue_data->enable_read) { OLA_WARN << "Descriptor " << descriptor->ReadDescriptor() << " already in read set"; return false; } kqueue_data->enable_read = true; kqueue_data->connected_descriptor = descriptor; kqueue_data->delete_connected_on_close = delete_on_close; return ApplyChange(descriptor->ReadDescriptor(), EVFILT_READ, EV_ADD, kqueue_data, false); } bool KQueuePoller::RemoveReadDescriptor(ReadFileDescriptor *descriptor) { return RemoveDescriptor(descriptor->ReadDescriptor(), EVFILT_READ); } bool KQueuePoller::RemoveReadDescriptor(ConnectedDescriptor *descriptor) { return RemoveDescriptor(descriptor->ReadDescriptor(), EVFILT_READ); } bool KQueuePoller::AddWriteDescriptor(WriteFileDescriptor *descriptor) { if (m_kqueue_fd == INVALID_DESCRIPTOR) { return false; } if (!descriptor->ValidWriteDescriptor()) { OLA_WARN << "AddWriteDescriptor called with invalid descriptor"; return false; } pair result = LookupOrCreateDescriptor( descriptor->WriteDescriptor()); KQueueData *kqueue_data = result.first; if (kqueue_data->enable_write) { OLA_WARN << "Descriptor " << descriptor->WriteDescriptor() << " already in write set"; return false; } kqueue_data->enable_write = true; kqueue_data->write_descriptor = descriptor; return ApplyChange(descriptor->WriteDescriptor(), EVFILT_WRITE, EV_ADD, kqueue_data, false); } bool KQueuePoller::RemoveWriteDescriptor(WriteFileDescriptor *descriptor) { return RemoveDescriptor(descriptor->WriteDescriptor(), EVFILT_WRITE); } bool KQueuePoller::Poll(TimeoutManager *timeout_manager, const TimeInterval &poll_interval) { if (m_kqueue_fd == INVALID_DESCRIPTOR) { return false; } struct kevent events[MAX_EVENTS]; TimeInterval sleep_interval = poll_interval; TimeStamp now; m_clock->CurrentTime(&now); TimeInterval next_event_in = timeout_manager->ExecuteTimeouts(&now); if (!next_event_in.IsZero()) { sleep_interval = std::min(next_event_in, sleep_interval); } // take care of stats accounting if (m_wake_up_time.IsSet()) { TimeInterval loop_time = now - m_wake_up_time; OLA_DEBUG << "ss process time was " << loop_time.ToString(); if (m_loop_time) (*m_loop_time) += loop_time.AsInt(); if (m_loop_iterations) (*m_loop_iterations)++; } struct timespec sleep_time; sleep_time.tv_sec = sleep_interval.Seconds(); sleep_time.tv_nsec = sleep_interval.MicroSeconds() * 1000; int ready = kevent( m_kqueue_fd, reinterpret_cast(m_change_set), m_next_change_entry, events, MAX_EVENTS, &sleep_time); m_next_change_entry = 0; if (ready == 0) { m_clock->CurrentTime(&m_wake_up_time); timeout_manager->ExecuteTimeouts(&m_wake_up_time); return true; } else if (ready == -1) { if (errno == EINTR) return true; OLA_WARN << "kqueue() error, " << strerror(errno); return false; } m_clock->CurrentTime(&m_wake_up_time); for (int i = 0; i < ready; i++) { if (events[i].flags & EV_ERROR) { OLA_WARN << "Error from kqueue on fd: " << events[i].ident << ": " << strerror(events[i].data); } else { CheckDescriptor(&events[i]); } } // Now that we're out of the callback phase, clean up descriptors that were // removed. DescriptorList::iterator iter = m_orphaned_descriptors.begin(); for (; iter != m_orphaned_descriptors.end(); ++iter) { if (m_free_descriptors.size() == MAX_FREE_DESCRIPTORS) { delete *iter; } else { (*iter)->Reset(); m_free_descriptors.push_back(*iter); } } m_orphaned_descriptors.clear(); m_clock->CurrentTime(&m_wake_up_time); timeout_manager->ExecuteTimeouts(&m_wake_up_time); return true; } /* * Check all the registered descriptors: * - Execute the callback for descriptors with data * - Excute OnClose if a remote end closed the connection */ void KQueuePoller::CheckDescriptor(struct kevent *event) { KQueueData *kqueue_data = reinterpret_cast( event->udata); if (event->filter == EVFILT_READ) { if (kqueue_data->read_descriptor) { kqueue_data->read_descriptor->PerformRead(); } else if (kqueue_data->connected_descriptor) { ConnectedDescriptor *connected_descriptor = kqueue_data->connected_descriptor; if (event->data) { connected_descriptor->PerformRead(); } else if (event->flags & EV_EOF) { // The remote end closed the descriptor. // According to man kevent, closing the descriptor removes it from the // list of kevents. We don't want to queue up a EV_DELETE for the FD // because the FD number may be reused in short order. // So instead we set connected_close_in_progress which is a signal to // RemoveDescriptor not to create an EV_DELETE event if // RemoveReadDescriptor() is called. kqueue_data->connected_close_in_progress = true; ConnectedDescriptor::OnCloseCallback *on_close = connected_descriptor->TransferOnClose(); if (on_close) on_close->Run(); // At this point the descriptor may be sitting in the orphan list // if the OnClose handler called into RemoveReadDescriptor() if (kqueue_data->delete_connected_on_close) { delete connected_descriptor; // Remove from m_descriptor_map if it's still there kqueue_data = STLLookupAndRemovePtr(&m_descriptor_map, event->ident); if (kqueue_data) { m_orphaned_descriptors.push_back(kqueue_data); if (m_export_map) { (*m_export_map->GetIntegerVar(K_CONNECTED_DESCRIPTORS_VAR))--; } } } } } } if (event->filter == EVFILT_WRITE) { // kqueue_data->write_descriptor may be null here if this descriptor was // removed between when kevent returned and now. if (kqueue_data->write_descriptor) { kqueue_data->write_descriptor->PerformWrite(); } } } std::pair KQueuePoller::LookupOrCreateDescriptor( int fd) { pair result = m_descriptor_map.insert( DescriptorMap::value_type(fd, NULL)); bool new_descriptor = result.second; if (new_descriptor) { if (m_free_descriptors.empty()) { result.first->second = new KQueueData(); } else { result.first->second = m_free_descriptors.back(); m_free_descriptors.pop_back(); } } return std::make_pair(result.first->second, new_descriptor); } bool KQueuePoller::ApplyChange(int fd, int16_t filter, uint16_t flags, KQueueData *descriptor, bool apply_immediately) { #ifdef __NetBSD__ EV_SET(&m_change_set[m_next_change_entry++], fd, filter, flags, 0, 0, reinterpret_cast(descriptor)); #else EV_SET(&m_change_set[m_next_change_entry++], fd, filter, flags, 0, 0, descriptor); #endif // __NetBSD__ if (m_next_change_entry == CHANGE_SET_SIZE || apply_immediately) { int r = kevent(m_kqueue_fd, m_change_set, m_next_change_entry, NULL, 0, NULL); if (r < 0) { OLA_WARN << "Failed to apply kqueue changes: " << strerror(errno); } m_next_change_entry = 0; } return true; } bool KQueuePoller::RemoveDescriptor(int fd, int16_t filter) { if (fd == INVALID_DESCRIPTOR) { OLA_WARN << "Attempt to remove an invalid file descriptor"; return false; } KQueueData *kqueue_data = STLFindOrNull(m_descriptor_map, fd); if (!kqueue_data) { OLA_WARN << "Couldn't find KQueueData for fd " << fd; return false; } bool remove_from_kevent = true; if (filter == EVFILT_READ) { kqueue_data->enable_read = false; kqueue_data->read_descriptor = NULL; if (kqueue_data->connected_descriptor) { remove_from_kevent = !kqueue_data->connected_close_in_progress; kqueue_data->connected_descriptor = NULL; } } else if (filter == EVFILT_WRITE) { kqueue_data->enable_write = false; kqueue_data->write_descriptor = NULL; } else { OLA_WARN << "Unknown kqueue filter: " << filter; } if (remove_from_kevent) { ApplyChange(fd, filter, EV_DELETE, NULL, true); } if (!kqueue_data->enable_read && !kqueue_data->enable_write) { m_orphaned_descriptors.push_back( STLLookupAndRemovePtr(&m_descriptor_map, fd)); } return true; } } // namespace io } // namespace ola ola-0.10.5.nojsmin/common/io/Serial.cpp0000644000175000017500000001533713023355232017311 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Serial.cpp * Serial I/O Helper methods. * Copyright (C) 2014 Peter Newman */ #include #include #include #include #include #ifdef _WIN32 #include #include #else #include #endif // _WIN32 #include #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #include #include #include #include "ola/Logging.h" #include "ola/base/Array.h" #include "ola/file/Util.h" #include "ola/io/IOUtils.h" #include "ola/io/Serial.h" #include "ola/StringUtils.h" namespace ola { namespace io { using std::vector; using std::string; namespace { string GetLockFile(const string &path) { const string base_name = ola::file::FilenameFromPath(path); return ola::file::JoinPaths(UUCP_LOCK_DIR, "LCK.." + base_name); } bool GetPidFromFile(const string &lock_file, pid_t *pid) { int fd = open(lock_file.c_str(), O_RDONLY); if (fd < 0) { if (errno == ENOENT) { // If it doesn't exist we're ok, any other error should be treated as if // a lock exists. *pid = 0; return true; } OLA_INFO << "Failed to open " << lock_file << ": " << strerror(errno); return false; } char buffer[100]; int r = read(fd, buffer, arraysize(buffer)); close(fd); if (r < 0) { OLA_INFO << "Failed to read PID from " << lock_file << ": " << strerror(errno); return false; } if (!StringToInt(string(buffer, r), pid)) { OLA_DEBUG << "Failed to convert contents of " << lock_file; return false; } return true; } bool ProcessExists(pid_t pid) { #ifdef _WIN32 // TODO(Peter): Implement this (void) pid; OLA_WARN << "Not implemented yet"; return false; #else errno = 0; if (0 == kill(pid, 0)) { return true; } return errno != ESRCH; #endif // _WIN32 } bool RemoveLockFile(const string &lock_file) { if (unlink(lock_file.c_str())) { OLA_WARN << "Failed to remove UUCP lock file: " << lock_file; return false; } return true; } } // namespace bool UIntToSpeedT(uint32_t value, speed_t *output) { switch (value) { case BAUD_RATE_9600: *output = B9600; return true; case BAUD_RATE_19200: *output = B19200; return true; case BAUD_RATE_38400: *output = B38400; return true; case BAUD_RATE_57600: *output = B57600; return true; case BAUD_RATE_115200: *output = B115200; return true; case BAUD_RATE_230400: *output = B230400; return true; } return false; } bool AcquireUUCPLockAndOpen(const std::string &path, int oflag, int *fd) { // This is rather tricky since there is no real convention for LCK files. // If it was only a single process doing the locking we could use fnctl as // described in 55.6 of the Linux Programing Interface book. // First, check if the path exists, there's no point trying to open it if not if (!FileExists(path)) { OLA_INFO << "Device " << path << " doesn't exist, so there's no point " "trying to acquire a lock"; return false; } // Second, clean up a stale lockfile. const string lock_file = GetLockFile(path); OLA_DEBUG << "Checking for " << lock_file; pid_t locked_pid; if (!GetPidFromFile(lock_file, &locked_pid)) { OLA_INFO << "Failed to get PID from " << lock_file; return false; } if (locked_pid) { // This will return false even if we have the lock, this is what we want // since different plugins may try to open the same serial port - see issue // #888. if (ProcessExists(locked_pid)) { OLA_INFO << "Device " << path << " locked by PID " << locked_pid << " and process exists, failed to acquire lock"; return false; } // There is a race between the read & the unlink here. I'm not convinced it // can be solved. if (!RemoveLockFile(lock_file)) { OLA_INFO << "Device " << path << " was locked by PID " << locked_pid << " which is no longer active, however failed to remove stale " << "lock file"; return false; } } pid_t our_pid = getpid(); // Now try to open the file in O_EXCL mode. If we fail, someone else already // took the lock. int lock_fd = open(lock_file.c_str(), O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR #ifndef _WIN32 | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH #endif // !_WIN32 ); // NOLINT(whitespace/parens) if (lock_fd < 0) { OLA_INFO << "Failed to open " << lock_file << " in exclusive mode: " << strerror(errno); return false; } OLA_INFO << "Acquired " << lock_file; // write our pid to the file std::stringstream str; str << std::setw(10) << our_pid << std::endl; const string pid_file_contents = str.str(); size_t r = write(lock_fd, pid_file_contents.c_str(), pid_file_contents.size()); close(lock_fd); if (r != pid_file_contents.size()) { OLA_WARN << "Failed to write complete LCK file: " << lock_file; RemoveLockFile(lock_file); return false; } // Now try to open the serial device. if (!TryOpen(path, oflag, fd)) { OLA_DEBUG << "Failed to open device " << path << " despite having the " << "lock file"; RemoveLockFile(lock_file); return false; } #if HAVE_SYS_IOCTL_H // As a final safety mechanism, use ioctl(TIOCEXCL) if available to prevent // further opens. if (ioctl(*fd, TIOCEXCL) == -1) { OLA_WARN << "TIOCEXCL " << path << " failed: " << strerror(errno); close(*fd); RemoveLockFile(lock_file); return false; } #endif // HAVE_SYS_IOCTL_H return true; } void ReleaseUUCPLock(const std::string &path) { const string lock_file = GetLockFile(path); pid_t locked_pid; if (!GetPidFromFile(lock_file, &locked_pid)) { return; } pid_t our_pid = getpid(); if (our_pid == locked_pid) { if (RemoveLockFile(lock_file)) { OLA_INFO << "Released " << lock_file; } } } } // namespace io } // namespace ola ola-0.10.5.nojsmin/common/io/Descriptor.cpp0000644000175000017500000004420613023355232020205 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Descriptor.cpp * Implementation of the Descriptor classes * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include #include #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #ifdef _WIN32 #include #include #else #include #include #include #endif // _WIN32 #include #include #include "ola/Logging.h" #include "ola/base/Macro.h" #include "ola/io/Descriptor.h" namespace ola { namespace io { #ifndef _WIN32 // Check binary compatibility between IOVec and iovec STATIC_ASSERT(sizeof(struct iovec) == sizeof(struct IOVec)); #endif // _WIN32 #ifdef _WIN32 // DescriptorHandle // ------------------------------------------------ DescriptorHandle::DescriptorHandle(): m_type(GENERIC_DESCRIPTOR), m_event(NULL), m_async_data(NULL), m_async_data_size(NULL) { m_handle.m_fd = -1; } DescriptorHandle::~DescriptorHandle() { } void* ToHandle(const DescriptorHandle &handle) { return handle.m_handle.m_handle; } bool DescriptorHandle::AllocAsyncBuffer() { if (m_async_data || m_async_data_size) { OLA_WARN << "Async data already allocated"; return false; } try { m_async_data = new uint8_t[ASYNC_DATA_BUFFER_SIZE]; m_async_data_size = new uint32_t; *m_async_data_size = 0; } catch (std::exception& ex) { OLA_WARN << ex.what(); } return (m_async_data && m_async_data_size); } void DescriptorHandle::FreeAsyncBuffer() { if (m_async_data) { delete[] m_async_data; m_async_data = NULL; } if (m_async_data_size) { delete m_async_data_size; m_async_data_size = NULL; } } bool DescriptorHandle::IsValid() const { return (m_handle.m_fd != -1); } bool operator!=(const DescriptorHandle &lhs, const DescriptorHandle &rhs) { return !(lhs == rhs); } bool operator==(const DescriptorHandle &lhs, const DescriptorHandle &rhs) { return ((lhs.m_handle.m_fd == rhs.m_handle.m_fd) && (lhs.m_type == rhs.m_type)); } bool operator<(const DescriptorHandle &lhs, const DescriptorHandle &rhs) { return (lhs.m_handle.m_fd < rhs.m_handle.m_fd); } std::ostream& operator<<(std::ostream &stream, const DescriptorHandle &data) { stream << data.m_handle.m_fd; return stream; } #endif // _WIN32 int ToFD(const DescriptorHandle &handle) { #ifdef _WIN32 switch (handle.m_type) { case SOCKET_DESCRIPTOR: return handle.m_handle.m_fd; default: return -1; } #else return handle; #endif // _WIN32 } /** * Helper function to create a anonymous pipe * @param handle_pair a 2 element array which is updated with the handles * @return true if successful, false otherwise. */ bool CreatePipe(DescriptorHandle handle_pair[2]) { #ifdef _WIN32 HANDLE read_handle = NULL; HANDLE write_handle = NULL; static unsigned int pipe_name_counter = 0; std::ostringstream pipe_name; pipe_name << "\\\\.\\Pipe\\OpenLightingArchitecture."; pipe_name.setf(std::ios::hex, std::ios::basefield); pipe_name.setf(std::ios::showbase); pipe_name.width(8); pipe_name << GetCurrentProcessId() << "."; pipe_name.width(8); pipe_name << pipe_name_counter++; SECURITY_ATTRIBUTES security_attributes; // Set the bInheritHandle flag so pipe handles are inherited. security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES); security_attributes.bInheritHandle = TRUE; security_attributes.lpSecurityDescriptor = NULL; read_handle = CreateNamedPipeA( pipe_name.str().c_str(), PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_WAIT, 1, 4096, 4096, 0, &security_attributes); if (read_handle == INVALID_HANDLE_VALUE) { OLA_WARN << "Could not create read end of pipe: %d" << GetLastError(); return false; } write_handle = CreateFileA( pipe_name.str().c_str(), GENERIC_WRITE, 0, &security_attributes, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); if (write_handle == INVALID_HANDLE_VALUE) { OLA_WARN << "Could not create write end of pipe: %d" << GetLastError(); CloseHandle(read_handle); return false; } handle_pair[0].m_handle.m_handle = read_handle; handle_pair[0].m_type = PIPE_DESCRIPTOR; handle_pair[1].m_handle.m_handle = write_handle; handle_pair[1].m_type = PIPE_DESCRIPTOR; if (!handle_pair[0].AllocAsyncBuffer() || !handle_pair[1].AllocAsyncBuffer()) return false; #else if (pipe(handle_pair) < 0) { OLA_WARN << "pipe() failed, " << strerror(errno); return false; } #endif // _WIN32 return true; } // BidirectionalFileDescriptor // ------------------------------------------------ void BidirectionalFileDescriptor::PerformRead() { if (m_on_read) m_on_read->Run(); else OLA_FATAL << "FileDescriptor " << ReadDescriptor() << " is ready but no handler attached, this is bad!"; } void BidirectionalFileDescriptor::PerformWrite() { if (m_on_write) m_on_write->Run(); else OLA_FATAL << "FileDescriptor " << WriteDescriptor() << " is ready but no write handler attached, this is bad!"; } // UnmanagedFileDescriptor // ------------------------------------------------ UnmanagedFileDescriptor::UnmanagedFileDescriptor(int fd) : BidirectionalFileDescriptor() { #ifdef _WIN32 m_handle.m_handle.m_fd = fd; m_handle.m_type = GENERIC_DESCRIPTOR; #else m_handle = fd; #endif // _WIN32 } // ConnectedDescriptor // ------------------------------------------------ bool ConnectedDescriptor::SetNonBlocking(DescriptorHandle fd) { if (fd == INVALID_DESCRIPTOR) return false; #ifdef _WIN32 bool success = true; if (fd.m_type == SOCKET_DESCRIPTOR) { u_long mode = 1; success = (ioctlsocket(ToFD(fd), FIONBIO, &mode) != SOCKET_ERROR); } #else int val = fcntl(fd, F_GETFL, 0); bool success = fcntl(fd, F_SETFL, val | O_NONBLOCK) == 0; #endif // _WIN32 if (!success) { OLA_WARN << "failed to set " << fd << " non-blocking: " << strerror(errno); return false; } return true; } bool ConnectedDescriptor::SetNoSigPipe(DescriptorHandle fd) { if (!IsSocket()) return true; #if HAVE_DECL_SO_NOSIGPIPE int sig_pipe_flag = 1; int ok = setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &sig_pipe_flag, sizeof(sig_pipe_flag)); if (ok == -1) { OLA_INFO << "Failed to disable SIGPIPE on " << fd << ": " << strerror(errno); return false; } #else (void) fd; #endif // HAVE_DECL_SO_NOSIGPIPE return true; } int ConnectedDescriptor::DataRemaining() const { if (!ValidReadDescriptor()) return 0; int unread = 0; #ifdef _WIN32 bool failed = false; if (ReadDescriptor().m_type == PIPE_DESCRIPTOR) { return ReadDescriptor().m_async_data_size ? *ReadDescriptor().m_async_data_size : 0; } else if (ReadDescriptor().m_type == SOCKET_DESCRIPTOR) { u_long unrd; failed = ioctlsocket(ToFD(ReadDescriptor()), FIONREAD, &unrd) < 0; unread = unrd; } else { OLA_WARN << "DataRemaining() called on unsupported descriptor type"; failed = true; } #else bool failed = ioctl(ReadDescriptor(), FIONREAD, &unread) < 0; #endif // _WIN32 if (failed) { OLA_WARN << "ioctl error for " << ReadDescriptor() << ", " << strerror(errno); return 0; } return unread; } ssize_t ConnectedDescriptor::Send(const uint8_t *buffer, unsigned int size) { if (!ValidWriteDescriptor()) return 0; ssize_t bytes_sent; #ifdef _WIN32 if (WriteDescriptor().m_type == PIPE_DESCRIPTOR) { DWORD bytes_written = 0; if (!WriteFile(ToHandle(WriteDescriptor()), buffer, size, &bytes_written, NULL)) { OLA_WARN << "WriteFile() failed with " << GetLastError(); bytes_sent = -1; } else { bytes_sent = bytes_written; } } else if (WriteDescriptor().m_type == SOCKET_DESCRIPTOR) { bytes_sent = send(ToFD(WriteDescriptor()), reinterpret_cast(buffer), size, 0); } else { OLA_WARN << "Send() called on unsupported descriptor type"; return 0; } #else // BSD Sockets #if HAVE_DECL_MSG_NOSIGNAL if (IsSocket()) { bytes_sent = send(WriteDescriptor(), buffer, size, MSG_NOSIGNAL); } else { #endif // HAVE_DECL_MSG_NOSIGNAL bytes_sent = write(WriteDescriptor(), buffer, size); #if HAVE_DECL_MSG_NOSIGNAL } #endif // HAVE_DECL_MSG_NOSIGNAL #endif // _WIN32 if (bytes_sent < 0 || static_cast(bytes_sent) != size) { OLA_INFO << "Failed to send on " << WriteDescriptor() << ": " << strerror(errno); } return bytes_sent; } ssize_t ConnectedDescriptor::Send(IOQueue *ioqueue) { if (!ValidWriteDescriptor()) return 0; int iocnt; const struct IOVec *iov = ioqueue->AsIOVec(&iocnt); ssize_t bytes_sent = 0; #ifdef _WIN32 /* There is no scatter/gather functionality for generic descriptors on * Windows, so this is implemented as a write loop. Derived classes should * re-implement Send() using scatter/gather I/O where available. */ int bytes_written = 0; for (int io = 0; io < iocnt; ++io) { bytes_written = Send(reinterpret_cast(iov[io].iov_base), iov[io].iov_len); if (bytes_written == 0) { OLA_INFO << "Failed to send on " << WriteDescriptor() << ": " << strerror(errno); bytes_sent = -1; break; } bytes_sent += bytes_written; } #else #if HAVE_DECL_MSG_NOSIGNAL if (IsSocket()) { struct msghdr message; memset(&message, 0, sizeof(message)); message.msg_name = NULL; message.msg_namelen = 0; message.msg_iov = reinterpret_cast(const_cast(iov)); message.msg_iovlen = iocnt; bytes_sent = sendmsg(WriteDescriptor(), &message, MSG_NOSIGNAL); } else { #else { #endif // HAVE_DECL_MSG_NOSIGNAL bytes_sent = writev(WriteDescriptor(), reinterpret_cast(iov), iocnt); } #endif // _WIN32 ioqueue->FreeIOVec(iov); if (bytes_sent < 0) { OLA_INFO << "Failed to send on " << WriteDescriptor() << ": " << strerror(errno); } else { ioqueue->Pop(bytes_sent); } return bytes_sent; } int ConnectedDescriptor::Receive( uint8_t *buffer, unsigned int size, unsigned int &data_read) { // NOLINT(runtime/references) int ret; uint8_t *data = buffer; data_read = 0; if (!ValidReadDescriptor()) return -1; while (data_read < size) { #ifdef _WIN32 if (ReadDescriptor().m_type == PIPE_DESCRIPTOR) { if (!ReadDescriptor().m_async_data_size) { OLA_WARN << "No async data buffer for descriptor " << ReadDescriptor(); return -1; } // Check if data was read by the async ReadFile() call DWORD async_data_size = *ReadDescriptor().m_async_data_size; if (async_data_size > 0) { DWORD size_to_copy = std::min(static_cast(size), async_data_size); memcpy(buffer, ReadDescriptor().m_async_data, size_to_copy); data_read = size_to_copy; if (async_data_size > size) { memmove(ReadDescriptor().m_async_data, &(ReadDescriptor().m_async_data[size_to_copy]), async_data_size - size_to_copy); } *ReadDescriptor().m_async_data_size -= size_to_copy; } return 0; } else if (ReadDescriptor().m_type == SOCKET_DESCRIPTOR) { ret = recv(ToFD(ReadDescriptor()), reinterpret_cast(data), size - data_read, 0); if (ret < 0) { if (WSAGetLastError() == WSAEWOULDBLOCK) { return 0; } else if (WSAGetLastError() != WSAEINTR) { OLA_WARN << "read failed, " << WSAGetLastError(); return -1; } } else if (ret == 0) { return 0; } data_read += ret; data += data_read; } else { OLA_WARN << "Descriptor type not implemented for reading: " << ReadDescriptor().m_type; return -1; } } #else if ((ret = read(ReadDescriptor(), data, size - data_read)) < 0) { if (errno == EAGAIN) return 0; if (errno != EINTR) { OLA_WARN << "read failed, " << strerror(errno); return -1; } } else if (ret == 0) { return 0; } data_read += ret; data += data_read; } #endif // _WIN32 return 0; } bool ConnectedDescriptor::IsClosed() const { return DataRemaining() == 0; } // LoopbackDescriptor // ------------------------------------------------ LoopbackDescriptor::LoopbackDescriptor() { m_handle_pair[0] = INVALID_DESCRIPTOR; m_handle_pair[1] = INVALID_DESCRIPTOR; } bool LoopbackDescriptor::Init() { if (m_handle_pair[0] != INVALID_DESCRIPTOR || m_handle_pair[1] != INVALID_DESCRIPTOR) return false; if (!CreatePipe(m_handle_pair)) return false; SetReadNonBlocking(); SetNoSigPipe(WriteDescriptor()); return true; } bool LoopbackDescriptor::Close() { if (m_handle_pair[0] != INVALID_DESCRIPTOR) { #ifdef _WIN32 CloseHandle(ToHandle(m_handle_pair[0])); #else close(m_handle_pair[0]); #endif // _WIN32 } if (m_handle_pair[1] != INVALID_DESCRIPTOR) { #ifdef _WIN32 CloseHandle(ToHandle(m_handle_pair[1])); #else close(m_handle_pair[1]); #endif // _WIN32 } m_handle_pair[0] = INVALID_DESCRIPTOR; m_handle_pair[1] = INVALID_DESCRIPTOR; return true; } bool LoopbackDescriptor::CloseClient() { if (m_handle_pair[1] != INVALID_DESCRIPTOR) { #ifdef _WIN32 CloseHandle(ToHandle(m_handle_pair[1])); #else close(m_handle_pair[1]); #endif // _WIN32 } m_handle_pair[1] = INVALID_DESCRIPTOR; return true; } // PipeDescriptor // ------------------------------------------------ PipeDescriptor::PipeDescriptor(): m_other_end(NULL) { m_in_pair[0] = m_in_pair[1] = INVALID_DESCRIPTOR; m_out_pair[0] = m_out_pair[1] = INVALID_DESCRIPTOR; } bool PipeDescriptor::Init() { if (m_in_pair[0] != INVALID_DESCRIPTOR || m_out_pair[1] != INVALID_DESCRIPTOR) return false; if (!CreatePipe(m_in_pair)) { return false; } if (!CreatePipe(m_out_pair)) { #ifdef _WIN32 CloseHandle(ToHandle(m_in_pair[0])); CloseHandle(ToHandle(m_in_pair[1])); #else close(m_in_pair[0]); close(m_in_pair[1]); #endif // _WIN32 m_in_pair[0] = m_in_pair[1] = INVALID_DESCRIPTOR; return false; } SetReadNonBlocking(); SetNoSigPipe(WriteDescriptor()); return true; } PipeDescriptor *PipeDescriptor::OppositeEnd() { if (m_in_pair[0] == INVALID_DESCRIPTOR || m_out_pair[1] == INVALID_DESCRIPTOR) return NULL; if (!m_other_end) { m_other_end = new PipeDescriptor(m_out_pair, m_in_pair, this); m_other_end->SetReadNonBlocking(); } return m_other_end; } bool PipeDescriptor::Close() { if (m_in_pair[0] != INVALID_DESCRIPTOR) { #ifdef _WIN32 CloseHandle(ToHandle(m_in_pair[0])); #else close(m_in_pair[0]); #endif // _WIN32 } if (m_out_pair[1] != INVALID_DESCRIPTOR) { #ifdef _WIN32 CloseHandle(ToHandle(m_out_pair[1])); #else close(m_out_pair[1]); #endif // _WIN32 } m_in_pair[0] = INVALID_DESCRIPTOR; m_out_pair[1] = INVALID_DESCRIPTOR; return true; } bool PipeDescriptor::CloseClient() { if (m_out_pair[1] != INVALID_DESCRIPTOR) { #ifdef _WIN32 CloseHandle(ToHandle(m_out_pair[1])); #else close(m_out_pair[1]); #endif // _WIN32 } m_out_pair[1] = INVALID_DESCRIPTOR; return true; } PipeDescriptor::PipeDescriptor(DescriptorHandle in_pair[2], DescriptorHandle out_pair[2], PipeDescriptor *other_end) { m_in_pair[0] = in_pair[0]; m_in_pair[1] = in_pair[1]; m_out_pair[0] = out_pair[0]; m_out_pair[1] = out_pair[1]; m_other_end = other_end; } // UnixSocket // ------------------------------------------------ bool UnixSocket::Init() { #ifdef _WIN32 return false; #else int pair[2]; if ((m_handle != INVALID_DESCRIPTOR) || m_other_end) return false; if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair)) { OLA_WARN << "socketpair() failed, " << strerror(errno); return false; } m_handle = pair[0]; SetReadNonBlocking(); SetNoSigPipe(WriteDescriptor()); m_other_end = new UnixSocket(pair[1], this); m_other_end->SetReadNonBlocking(); return true; #endif // _WIN32 } UnixSocket *UnixSocket::OppositeEnd() { return m_other_end; } /* * Close this UnixSocket */ bool UnixSocket::Close() { #ifdef _WIN32 return true; #else if (m_handle != INVALID_DESCRIPTOR) { close(m_handle); } m_handle = INVALID_DESCRIPTOR; return true; #endif // _WIN32 } bool UnixSocket::CloseClient() { #ifndef _WIN32 if (m_handle != INVALID_DESCRIPTOR) shutdown(m_handle, SHUT_WR); #endif // !_WIN32 m_handle = INVALID_DESCRIPTOR; return true; } UnixSocket::UnixSocket(int socket, UnixSocket *other_end) { #ifdef _WIN32 m_handle.m_handle.m_fd = socket; #else m_handle = socket; #endif // _WIN32 m_other_end = other_end; } // DeviceDescriptor // ------------------------------------------------ DeviceDescriptor::DeviceDescriptor(int fd) { #ifdef _WIN32 m_handle.m_handle.m_fd = fd; m_handle.m_type = GENERIC_DESCRIPTOR; #else m_handle = fd; #endif // _WIN32 } bool DeviceDescriptor::Close() { if (m_handle == INVALID_DESCRIPTOR) return true; #ifdef _WIN32 int ret = close(m_handle.m_handle.m_fd); #else int ret = close(m_handle); #endif // _WIN32 m_handle = INVALID_DESCRIPTOR; return ret == 0; } } // namespace io } // namespace ola ola-0.10.5.nojsmin/common/io/SelectServerTest.cpp0000644000175000017500000005126313023355232021336 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SelectServerTest.cpp * Test fixture for the SelectServer. * Copyright (C) 2005 Simon Newton * * This tries to test many of the tricky reentrancy cases of a SelectServer. * Because the add / remove descriptor methods can be called from within * callbacks, it's important that the SelectServer remain reentrant. This in * turn means implementations of PollerInterface also need to be reentrant. */ #ifdef _WIN32 #include #endif // _WIN32 #include #include #include #include "common/io/PollerInterface.h" #include "ola/Callback.h" #include "ola/Clock.h" #include "ola/ExportMap.h" #include "ola/Logging.h" #include "ola/base/Array.h" #include "ola/io/SelectServer.h" #include "ola/network/Socket.h" #include "ola/testing/TestUtils.h" using ola::ExportMap; using ola::IntegerVariable; using ola::NewCallback; using ola::NewSingleCallback; using ola::TimeStamp; using ola::io::ConnectedDescriptor; using ola::io::LoopbackDescriptor; using ola::io::PollerInterface; using ola::io::SelectServer; using ola::io::UnixSocket; using ola::io::WriteFileDescriptor; using ola::network::UDPSocket; using std::auto_ptr; using std::set; /* * For some of the tests we need precise control over the timing. * So we mock a clock out here. */ class CustomMockClock: public ola::Clock { public: explicit CustomMockClock(TimeStamp *timestamp) : m_timestamp(timestamp) { } void CurrentTime(TimeStamp *timestamp) const { *timestamp = *m_timestamp; } private: TimeStamp *m_timestamp; }; class SelectServerTest: public CppUnit::TestFixture { typedef set Descriptors; CPPUNIT_TEST_SUITE(SelectServerTest); CPPUNIT_TEST(testAddInvalidDescriptor); CPPUNIT_TEST(testDoubleAddAndRemove); CPPUNIT_TEST(testAddRemoveReadDescriptor); CPPUNIT_TEST(testRemoteEndClose); CPPUNIT_TEST(testRemoteEndCloseWithDelete); CPPUNIT_TEST(testRemoteEndCloseWithRemoveAndDelete); CPPUNIT_TEST(testRemoveWriteWhenOtherReadable); CPPUNIT_TEST(testRemoveWriteWhenReadable); CPPUNIT_TEST(testRemoveOthersWhenReadable); CPPUNIT_TEST(testRemoveOthersWhenWriteable); #ifndef _WIN32 CPPUNIT_TEST(testReadWriteInteraction); #endif // !_WIN32 CPPUNIT_TEST(testShutdownWithActiveDescriptors); CPPUNIT_TEST(testTimeout); CPPUNIT_TEST(testOffByOneTimeout); CPPUNIT_TEST(testLoopCallbacks); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void tearDown(); void testAddInvalidDescriptor(); void testDoubleAddAndRemove(); void testAddRemoveReadDescriptor(); void testRemoteEndClose(); void testRemoteEndCloseWithDelete(); void testRemoteEndCloseWithRemoveAndDelete(); void testRemoveWriteWhenOtherReadable(); void testRemoveWriteWhenReadable(); void testRemoveOthersWhenReadable(); void testRemoveOthersWhenWriteable(); void testReadWriteInteraction(); void testShutdownWithActiveDescriptors(); void testTimeout(); void testOffByOneTimeout(); void testLoopCallbacks(); void FatalTimeout() { OLA_FAIL("Fatal Timeout"); } void Terminate() { OLA_DEBUG << "Terminate called"; if (m_ss) { m_ss->Terminate(); } } void SingleIncrementTimeout() { OLA_DEBUG << "Single increment timeout called"; m_timeout_counter++; OLA_DEBUG << "Timeout counter is now " << m_timeout_counter; } void ReentrantTimeout(SelectServer *ss) { OLA_DEBUG << "Re-entrant timeout called, adding two single increment " "timeouts"; ss->RegisterSingleTimeout( 0, ola::NewSingleCallback(this, &SelectServerTest::SingleIncrementTimeout)); ss->RegisterSingleTimeout( 5, ola::NewSingleCallback(this, &SelectServerTest::SingleIncrementTimeout)); } void NullHandler() {} bool IncrementTimeout() { if (m_ss && m_ss->IsRunning()) m_timeout_counter++; return true; } void ReadDataAndRemove(ConnectedDescriptor *descriptor) { uint8_t data[10]; unsigned int size; descriptor->Receive(data, arraysize(data), size); if (m_ss) { m_ss->RemoveReadDescriptor(descriptor); m_ss->RemoveWriteDescriptor(descriptor); m_ss->Terminate(); delete descriptor; } } void RemoveAndDeleteDescriptors(Descriptors read_descriptors, Descriptors write_descriptors, Descriptors delete_descriptors) { Descriptors::iterator iter; for (iter = read_descriptors.begin(); iter != read_descriptors.end(); ++iter) { m_ss->RemoveReadDescriptor(*iter); } for (iter = write_descriptors.begin(); iter != write_descriptors.end(); ++iter) { m_ss->RemoveWriteDescriptor(*iter); } for (iter = delete_descriptors.begin(); iter != delete_descriptors.end(); ++iter) { delete *iter; } m_ss->Terminate(); } void IncrementLoopCounter() { m_loop_counter++; } private: unsigned int m_timeout_counter; unsigned int m_loop_counter; ExportMap m_map; IntegerVariable *connected_read_descriptor_count; IntegerVariable *read_descriptor_count; IntegerVariable *write_descriptor_count; SelectServer *m_ss; }; CPPUNIT_TEST_SUITE_REGISTRATION(SelectServerTest); void SelectServerTest::setUp() { connected_read_descriptor_count = m_map.GetIntegerVar( PollerInterface::K_CONNECTED_DESCRIPTORS_VAR); read_descriptor_count = m_map.GetIntegerVar( PollerInterface::K_READ_DESCRIPTOR_VAR); write_descriptor_count = m_map.GetIntegerVar( PollerInterface::K_WRITE_DESCRIPTOR_VAR); m_ss = new SelectServer(&m_map); m_timeout_counter = 0; m_loop_counter = 0; #if _WIN32 WSADATA wsa_data; int result = WSAStartup(MAKEWORD(2, 0), &wsa_data); OLA_ASSERT_EQ(result, 0); #endif // _WIN32 } void SelectServerTest::tearDown() { delete m_ss; #ifdef _WIN32 WSACleanup(); #endif // _WIN32 } /* * Confirm we can't add invalid descriptors to the SelectServer */ void SelectServerTest::testAddInvalidDescriptor() { OLA_ASSERT_EQ(1, connected_read_descriptor_count->Get()); // internal socket OLA_ASSERT_EQ(0, read_descriptor_count->Get()); OLA_ASSERT_EQ(0, write_descriptor_count->Get()); // Adding and removing a uninitialized socket should fail LoopbackDescriptor bad_socket; OLA_ASSERT_FALSE(m_ss->AddReadDescriptor(&bad_socket)); OLA_ASSERT_FALSE(m_ss->AddWriteDescriptor(&bad_socket)); m_ss->RemoveReadDescriptor(&bad_socket); m_ss->RemoveWriteDescriptor(&bad_socket); OLA_ASSERT_EQ(1, connected_read_descriptor_count->Get()); OLA_ASSERT_EQ(0, read_descriptor_count->Get()); OLA_ASSERT_EQ(0, write_descriptor_count->Get()); } /* * Confirm we can't add the same descriptor twice. */ void SelectServerTest::testDoubleAddAndRemove() { OLA_ASSERT_EQ(1, connected_read_descriptor_count->Get()); // internal socket OLA_ASSERT_EQ(0, read_descriptor_count->Get()); OLA_ASSERT_EQ(0, write_descriptor_count->Get()); LoopbackDescriptor loopback; loopback.Init(); OLA_ASSERT_TRUE(m_ss->AddReadDescriptor(&loopback)); OLA_ASSERT_EQ(2, connected_read_descriptor_count->Get()); OLA_ASSERT_EQ(0, read_descriptor_count->Get()); OLA_ASSERT_EQ(0, write_descriptor_count->Get()); OLA_ASSERT_TRUE(m_ss->AddWriteDescriptor(&loopback)); OLA_ASSERT_EQ(2, connected_read_descriptor_count->Get()); OLA_ASSERT_EQ(0, read_descriptor_count->Get()); OLA_ASSERT_EQ(1, write_descriptor_count->Get()); m_ss->RemoveReadDescriptor(&loopback); OLA_ASSERT_EQ(1, connected_read_descriptor_count->Get()); OLA_ASSERT_EQ(0, read_descriptor_count->Get()); OLA_ASSERT_EQ(1, write_descriptor_count->Get()); m_ss->RemoveWriteDescriptor(&loopback); OLA_ASSERT_EQ(1, connected_read_descriptor_count->Get()); OLA_ASSERT_EQ(0, read_descriptor_count->Get()); OLA_ASSERT_EQ(0, write_descriptor_count->Get()); // Trying to remove a second time shouldn't crash m_ss->RemoveReadDescriptor(&loopback); m_ss->RemoveWriteDescriptor(&loopback); } /* * Check AddReadDescriptor/RemoveReadDescriptor works correctly and that the * export map is updated. */ void SelectServerTest::testAddRemoveReadDescriptor() { OLA_ASSERT_EQ(1, connected_read_descriptor_count->Get()); OLA_ASSERT_EQ(0, read_descriptor_count->Get()); OLA_ASSERT_EQ(0, write_descriptor_count->Get()); LoopbackDescriptor loopback; loopback.Init(); OLA_ASSERT_TRUE(m_ss->AddReadDescriptor(&loopback)); OLA_ASSERT_EQ(2, connected_read_descriptor_count->Get()); OLA_ASSERT_EQ(0, read_descriptor_count->Get()); OLA_ASSERT_EQ(0, write_descriptor_count->Get()); // Add a udp socket UDPSocket udp_socket; OLA_ASSERT_TRUE(udp_socket.Init()); OLA_ASSERT_TRUE(m_ss->AddReadDescriptor(&udp_socket)); OLA_ASSERT_EQ(2, connected_read_descriptor_count->Get()); OLA_ASSERT_EQ(1, read_descriptor_count->Get()); OLA_ASSERT_EQ(0, write_descriptor_count->Get()); // Check remove works m_ss->RemoveReadDescriptor(&loopback); OLA_ASSERT_EQ(1, connected_read_descriptor_count->Get()); OLA_ASSERT_EQ(1, read_descriptor_count->Get()); OLA_ASSERT_EQ(0, write_descriptor_count->Get()); m_ss->RemoveReadDescriptor(&udp_socket); OLA_ASSERT_EQ(1, connected_read_descriptor_count->Get()); OLA_ASSERT_EQ(0, read_descriptor_count->Get()); OLA_ASSERT_EQ(0, write_descriptor_count->Get()); } /* * Confirm we correctly detect the remote end closing the connection. */ void SelectServerTest::testRemoteEndClose() { Descriptors read_set, write_set, delete_set; LoopbackDescriptor loopback; loopback.Init(); read_set.insert(&loopback); loopback.SetOnClose(NewSingleCallback( this, &SelectServerTest::RemoveAndDeleteDescriptors, read_set, write_set, delete_set)); OLA_ASSERT_TRUE(m_ss->AddReadDescriptor(&loopback)); OLA_ASSERT_EQ(2, connected_read_descriptor_count->Get()); OLA_ASSERT_EQ(0, read_descriptor_count->Get()); // now the Write end closes loopback.CloseClient(); m_ss->Run(); OLA_ASSERT_EQ(1, connected_read_descriptor_count->Get()); OLA_ASSERT_EQ(0, read_descriptor_count->Get()); } /* * Confirm we correctly detect the remote end closing the connection. * This uses the delete_on_close option. */ void SelectServerTest::testRemoteEndCloseWithDelete() { // Ownership is transferred to the SelectServer. LoopbackDescriptor *loopback = new LoopbackDescriptor(); loopback->Init(); loopback->SetOnClose(NewSingleCallback( this, &SelectServerTest::Terminate)); OLA_ASSERT_TRUE(m_ss->AddReadDescriptor(loopback, true)); OLA_ASSERT_EQ(2, connected_read_descriptor_count->Get()); OLA_ASSERT_EQ(0, read_descriptor_count->Get()); // Now the Write end closes loopback->CloseClient(); m_ss->Run(); OLA_ASSERT_EQ(1, connected_read_descriptor_count->Get()); OLA_ASSERT_EQ(0, read_descriptor_count->Get()); } /* * Check the delete_on_close feature handles the case where the descriptor * being closed is removed from the on_close handler. */ void SelectServerTest::testRemoteEndCloseWithRemoveAndDelete() { Descriptors read_set, write_set, delete_set; LoopbackDescriptor *loopback = new LoopbackDescriptor(); loopback->Init(); read_set.insert(loopback); loopback->SetOnClose(NewSingleCallback( this, &SelectServerTest::RemoveAndDeleteDescriptors, read_set, write_set, delete_set)); // Ownership is transferred. OLA_ASSERT_TRUE(m_ss->AddReadDescriptor(loopback, true)); OLA_ASSERT_EQ(2, connected_read_descriptor_count->Get()); OLA_ASSERT_EQ(0, read_descriptor_count->Get()); // Close the write end of the descriptor. loopback->CloseClient(); m_ss->Run(); OLA_ASSERT_EQ(1, connected_read_descriptor_count->Get()); OLA_ASSERT_EQ(0, read_descriptor_count->Get()); } /* * Check that RemoveWriteDescriptor is reentrant. * We use the Execute() method to close a write descriptor during the same * cycle in which it becomes writeable. See * https://github.com/OpenLightingProject/ola/pull/429 for details. */ void SelectServerTest::testRemoveWriteWhenOtherReadable() { Descriptors read_set, write_set, delete_set; LoopbackDescriptor *loopback = new LoopbackDescriptor(); loopback->Init(); loopback->SetOnWritable(NewCallback(this, &SelectServerTest::NullHandler)); write_set.insert(loopback); delete_set.insert(loopback); OLA_ASSERT_TRUE(m_ss->AddWriteDescriptor(loopback)); OLA_ASSERT_EQ(1, write_descriptor_count->Get()); OLA_ASSERT_EQ(0, read_descriptor_count->Get()); m_ss->Execute(NewSingleCallback( this, &SelectServerTest::RemoveAndDeleteDescriptors, read_set, write_set, delete_set)); m_ss->Run(); OLA_ASSERT_EQ(0, write_descriptor_count->Get()); OLA_ASSERT_EQ(1, connected_read_descriptor_count->Get()); OLA_ASSERT_EQ(0, read_descriptor_count->Get()); } /* * Check that RemoveWriteDescriptor is reentrant. * Similar to the case above, but this removes & deletes the descriptor from * within the OnRead callback of the same descriptor. */ void SelectServerTest::testRemoveWriteWhenReadable() { // Ownership is transferred to the SelectServer. LoopbackDescriptor *loopback = new LoopbackDescriptor(); loopback->Init(); loopback->SetOnData(NewCallback( this, &SelectServerTest::ReadDataAndRemove, static_cast(loopback))); loopback->SetOnWritable(NewCallback(this, &SelectServerTest::NullHandler)); OLA_ASSERT_TRUE(m_ss->AddReadDescriptor(loopback)); OLA_ASSERT_TRUE(m_ss->AddWriteDescriptor(loopback)); OLA_ASSERT_EQ(2, connected_read_descriptor_count->Get()); OLA_ASSERT_EQ(1, write_descriptor_count->Get()); OLA_ASSERT_EQ(0, read_descriptor_count->Get()); // Send some data to make this descriptor readable. uint8_t data[] = {'a'}; loopback->Send(data, arraysize(data)); m_ss->Run(); OLA_ASSERT_EQ(0, write_descriptor_count->Get()); OLA_ASSERT_EQ(1, connected_read_descriptor_count->Get()); OLA_ASSERT_EQ(0, read_descriptor_count->Get()); } /* * Check that we don't invalid iterators by removing descriptors during an * on_read callback. */ void SelectServerTest::testRemoveOthersWhenReadable() { Descriptors read_set, write_set, delete_set; LoopbackDescriptor loopback1, loopback2, loopback3; loopback1.Init(); loopback2.Init(); loopback3.Init(); OLA_ASSERT_TRUE(m_ss->AddReadDescriptor(&loopback1)); OLA_ASSERT_TRUE(m_ss->AddReadDescriptor(&loopback2)); OLA_ASSERT_TRUE(m_ss->AddReadDescriptor(&loopback3)); read_set.insert(&loopback1); read_set.insert(&loopback2); read_set.insert(&loopback3); loopback2.SetOnClose(NewSingleCallback( this, &SelectServerTest::RemoveAndDeleteDescriptors, read_set, write_set, delete_set)); OLA_ASSERT_EQ(0, write_descriptor_count->Get()); OLA_ASSERT_EQ(4, connected_read_descriptor_count->Get()); loopback2.CloseClient(); m_ss->Run(); OLA_ASSERT_EQ(0, write_descriptor_count->Get()); OLA_ASSERT_EQ(1, connected_read_descriptor_count->Get()); OLA_ASSERT_EQ(0, read_descriptor_count->Get()); } /* * Check that we don't invalid iterators by removing descriptors during an * on_Write callback. */ void SelectServerTest::testRemoveOthersWhenWriteable() { Descriptors read_set, write_set, delete_set; LoopbackDescriptor loopback1, loopback2, loopback3; loopback1.Init(); loopback2.Init(); loopback3.Init(); OLA_ASSERT_TRUE(m_ss->AddWriteDescriptor(&loopback1)); OLA_ASSERT_TRUE(m_ss->AddWriteDescriptor(&loopback2)); OLA_ASSERT_TRUE(m_ss->AddWriteDescriptor(&loopback3)); write_set.insert(&loopback1); write_set.insert(&loopback2); write_set.insert(&loopback3); loopback1.SetOnWritable(NewCallback( this, &SelectServerTest::NullHandler)); loopback2.SetOnWritable(NewCallback( this, &SelectServerTest::RemoveAndDeleteDescriptors, read_set, write_set, delete_set)); loopback3.SetOnWritable(NewCallback( this, &SelectServerTest::NullHandler)); OLA_ASSERT_EQ(3, write_descriptor_count->Get()); OLA_ASSERT_EQ(1, connected_read_descriptor_count->Get()); m_ss->Run(); OLA_ASSERT_EQ(0, write_descriptor_count->Get()); OLA_ASSERT_EQ(1, connected_read_descriptor_count->Get()); OLA_ASSERT_EQ(0, read_descriptor_count->Get()); } /* * Test the interaction between read and write descriptor. */ void SelectServerTest::testReadWriteInteraction() { UnixSocket socket; socket.Init(); socket.SetOnClose(NewSingleCallback(this, &SelectServerTest::Terminate)); OLA_ASSERT_TRUE(m_ss->AddReadDescriptor(&socket)); OLA_ASSERT_TRUE(m_ss->AddWriteDescriptor(&socket)); m_ss->RemoveWriteDescriptor(&socket); // now the Write end closes auto_ptr other_end(socket.OppositeEnd()); other_end->CloseClient(); m_ss->RegisterSingleTimeout( 100, ola::NewSingleCallback(this, &SelectServerTest::FatalTimeout)); m_ss->Run(); m_ss->RemoveReadDescriptor(&socket); OLA_ASSERT_EQ(1, connected_read_descriptor_count->Get()); OLA_ASSERT_EQ(0, read_descriptor_count->Get()); } /* * Confirm we don't leak memory when the SelectServer is destroyed without all * the descriptors being removed. */ void SelectServerTest::testShutdownWithActiveDescriptors() { LoopbackDescriptor loopback; loopback.Init(); OLA_ASSERT_TRUE(m_ss->AddReadDescriptor(&loopback)); OLA_ASSERT_TRUE(m_ss->AddWriteDescriptor(&loopback)); } /* * Timeout tests */ void SelectServerTest::testTimeout() { // Check a single timeout m_ss->RegisterSingleTimeout( 10, ola::NewSingleCallback(this, &SelectServerTest::SingleIncrementTimeout)); m_ss->RegisterSingleTimeout( 20, ola::NewSingleCallback(this, &SelectServerTest::Terminate)); m_ss->Run(); OLA_ASSERT_EQ(1u, m_timeout_counter); // Now check a timeout that adds another timeout OLA_DEBUG << "Checking re-entrant timeouts"; m_timeout_counter = 0; OLA_DEBUG << "Timeout counter is now " << m_timeout_counter; m_ss->RegisterSingleTimeout( 10, ola::NewSingleCallback(this, &SelectServerTest::ReentrantTimeout, m_ss)); // The terminate timeout is 40ms to allow the check to pass on Win XP. See // https://github.com/OpenLightingProject/ola/pull/626 for more info m_ss->RegisterSingleTimeout( 40, ola::NewSingleCallback(this, &SelectServerTest::Terminate)); OLA_DEBUG << "Timeout counter is now " << m_timeout_counter; m_ss->Run(); OLA_DEBUG << "Timeout counter is now " << m_timeout_counter; OLA_ASSERT_EQ(2u, m_timeout_counter); // Check repeating timeouts // Some systems (VMs in particular) can't do 10ms resolution so we go for // larger numbers here. m_timeout_counter = 0; m_ss->RegisterRepeatingTimeout( 100, ola::NewCallback(this, &SelectServerTest::IncrementTimeout)); m_ss->RegisterSingleTimeout( 980, ola::NewSingleCallback(this, &SelectServerTest::Terminate)); m_ss->Run(); // This seems to go as low as 7 std::ostringstream str; str << "Timeout counter was " << m_timeout_counter; OLA_ASSERT_TRUE_MSG(m_timeout_counter >= 5 && m_timeout_counter <= 9, str.str()); // Confirm timeouts are removed correctly ola::thread::timeout_id timeout1 = m_ss->RegisterSingleTimeout( 10, ola::NewSingleCallback(this, &SelectServerTest::FatalTimeout)); m_ss->RegisterSingleTimeout( 20, ola::NewSingleCallback(this, &SelectServerTest::Terminate)); m_ss->RemoveTimeout(timeout1); m_ss->Run(); } /* * Test that timeouts aren't skipped. */ void SelectServerTest::testOffByOneTimeout() { TimeStamp now; ola::Clock actual_clock; actual_clock.CurrentTime(&now); CustomMockClock clock(&now); SelectServer ss(NULL, &clock); ss.RegisterSingleTimeout( 10, ola::NewSingleCallback(this, &SelectServerTest::SingleIncrementTimeout)); now += ola::TimeInterval(0, 10000); ss.m_timeout_manager->ExecuteTimeouts(&now); OLA_ASSERT_EQ(m_timeout_counter, 1u); } /* * Check that the loop closures are called. */ void SelectServerTest::testLoopCallbacks() { m_ss->SetDefaultInterval(ola::TimeInterval(0, 100000)); // poll every 100ms m_ss->RunInLoop( ola::NewCallback(this, &SelectServerTest::IncrementLoopCounter)); m_ss->RegisterSingleTimeout( 500, ola::NewSingleCallback(this, &SelectServerTest::Terminate)); m_ss->Run(); // we should have at least 5 calls to IncrementLoopCounter OLA_ASSERT_TRUE(m_loop_counter >= 5); } ola-0.10.5.nojsmin/common/io/SelectPoller.h0000644000175000017500000000564413023355232020134 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SelectPoller.h * A Poller which uses select() * Copyright (C) 2013 Simon Newton */ #ifndef COMMON_IO_SELECTPOLLER_H_ #define COMMON_IO_SELECTPOLLER_H_ #include #include #include #include #include #include #include "common/io/PollerInterface.h" #include "common/io/TimeoutManager.h" namespace ola { namespace io { /** * @class SelectPoller * @brief An implementation of PollerInterface that uses select(). * */ class SelectPoller : public PollerInterface { public : /** * @brief Create a new SelectPoller. * @param export_map the ExportMap to use * @param clock the Clock to use */ SelectPoller(ExportMap *export_map, Clock *clock); ~SelectPoller(); bool AddReadDescriptor(class ReadFileDescriptor *descriptor); bool AddReadDescriptor(class ConnectedDescriptor *descriptor, bool delete_on_close); bool RemoveReadDescriptor(class ReadFileDescriptor *descriptor); bool RemoveReadDescriptor(class ConnectedDescriptor *descriptor); bool AddWriteDescriptor(class WriteFileDescriptor *descriptor); bool RemoveWriteDescriptor(class WriteFileDescriptor *descriptor); const TimeStamp *WakeUpTime() const { return &m_wake_up_time; } bool Poll(TimeoutManager *timeout_manager, const TimeInterval &poll_interval); private: typedef struct { ConnectedDescriptor *descriptor; bool delete_on_close; } connected_descriptor_t; typedef std::map ReadDescriptorMap; typedef std::map WriteDescriptorMap; typedef std::map ConnectedDescriptorMap; ExportMap *m_export_map; CounterVariable *m_loop_iterations; CounterVariable *m_loop_time; Clock *m_clock; TimeStamp m_wake_up_time; ReadDescriptorMap m_read_descriptors; WriteDescriptorMap m_write_descriptors; ConnectedDescriptorMap m_connected_read_descriptors; void CheckDescriptors(fd_set *r_set, fd_set *w_set); bool AddDescriptorsToSet(fd_set *r_set, fd_set *w_set, int *max_sd); DISALLOW_COPY_AND_ASSIGN(SelectPoller); }; } // namespace io } // namespace ola #endif // COMMON_IO_SELECTPOLLER_H_ ola-0.10.5.nojsmin/common/io/EPoller.cpp0000644000175000017500000003163213023355232017430 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * EPoller.cpp * A Poller which uses epoll() * Copyright (C) 2013 Simon Newton */ #include "common/io/EPoller.h" #include #include #include #include #include #include #include #include "ola/Clock.h" #include "ola/Logging.h" #include "ola/base/Macro.h" #include "ola/io/Descriptor.h" #include "ola/stl/STLUtils.h" namespace ola { namespace io { using std::pair; /* * Represents a FD */ class EPollData { public: EPollData() : events(0), read_descriptor(NULL), write_descriptor(NULL), connected_descriptor(NULL), delete_connected_on_close(false) { } void Reset() { events = 0; read_descriptor = NULL; write_descriptor = NULL; connected_descriptor = NULL; delete_connected_on_close = false; } uint32_t events; ReadFileDescriptor *read_descriptor; WriteFileDescriptor *write_descriptor; ConnectedDescriptor *connected_descriptor; bool delete_connected_on_close; }; namespace { /* * Add the fd to the epoll_fd. * descriptor is the user data to associated with the event */ bool AddEvent(int epoll_fd, int fd, EPollData *descriptor) { epoll_event event; event.events = descriptor->events; event.data.ptr = descriptor; OLA_DEBUG << "EPOLL_CTL_ADD " << fd << ", events " << std::hex << event.events << ", descriptor: " << descriptor; int r = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &event); if (r) { OLA_WARN << "EPOLL_CTL_ADD " << fd << " failed: " << strerror(errno); return false; } return true; } /* * Update the fd in the epoll event set * descriptor is the user data to associated with the event */ bool UpdateEvent(int epoll_fd, int fd, EPollData *descriptor) { epoll_event event; event.events = descriptor->events; event.data.ptr = descriptor; OLA_DEBUG << "EPOLL_CTL_MOD " << fd << ", events " << std::hex << event.events << ", descriptor: " << descriptor; int r = epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fd, &event); if (r) { OLA_WARN << "EPOLL_CTL_MOD " << fd << " failed: " << strerror(errno); return false; } return true; } /* * Remove the fd from the epoll fd */ bool RemoveEvent(int epoll_fd, int fd) { epoll_event event; OLA_DEBUG << "EPOLL_CTL_DEL " << fd; int r = epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, &event); if (r) { OLA_WARN << "EPOLL_CTL_DEL " << fd << " failed: " << strerror(errno); return false; } return true; } } // namespace /** * @brief The maximum number of events to return in one epoll cycle */ const int EPoller::MAX_EVENTS = 10; /** * @brief the EPOLL flags used for read descriptors. */ const int EPoller::READ_FLAGS = EPOLLIN | EPOLLRDHUP; /** * @brief The number of pre-allocated EPollData to have. */ const unsigned int EPoller::MAX_FREE_DESCRIPTORS = 10; EPoller::EPoller(ExportMap *export_map, Clock* clock) : m_export_map(export_map), m_loop_iterations(NULL), m_loop_time(NULL), m_epoll_fd(INVALID_DESCRIPTOR), m_clock(clock) { if (m_export_map) { m_loop_time = m_export_map->GetCounterVar(K_LOOP_TIME); m_loop_iterations = m_export_map->GetCounterVar(K_LOOP_COUNT); } m_epoll_fd = epoll_create1(EPOLL_CLOEXEC); if (m_epoll_fd < 0) { OLA_FATAL << "Failed to create new epoll instance"; } } EPoller::~EPoller() { if (m_epoll_fd != INVALID_DESCRIPTOR) { close(m_epoll_fd); } { DescriptorMap::iterator iter = m_descriptor_map.begin(); for (; iter != m_descriptor_map.end(); ++iter) { if (iter->second->delete_connected_on_close) { delete iter->second->connected_descriptor; } delete iter->second; } } DescriptorList::iterator iter = m_orphaned_descriptors.begin(); for (; iter != m_orphaned_descriptors.end(); ++iter) { if ((*iter)->delete_connected_on_close) { delete (*iter)->connected_descriptor; } delete *iter; } STLDeleteElements(&m_free_descriptors); } bool EPoller::AddReadDescriptor(ReadFileDescriptor *descriptor) { if (m_epoll_fd == INVALID_DESCRIPTOR) { return false; } if (!descriptor->ValidReadDescriptor()) { OLA_WARN << "AddReadDescriptor called with invalid descriptor"; return false; } pair result = LookupOrCreateDescriptor( descriptor->ReadDescriptor()); if (result.first->events & READ_FLAGS) { OLA_WARN << "Descriptor " << descriptor->ReadDescriptor() << " already in read set"; return false; } result.first->events |= READ_FLAGS; result.first->read_descriptor = descriptor; if (result.second) { return AddEvent(m_epoll_fd, descriptor->ReadDescriptor(), result.first); } else { return UpdateEvent(m_epoll_fd, descriptor->ReadDescriptor(), result.first); } } bool EPoller::AddReadDescriptor(ConnectedDescriptor *descriptor, bool delete_on_close) { if (m_epoll_fd == INVALID_DESCRIPTOR) { return false; } if (!descriptor->ValidReadDescriptor()) { OLA_WARN << "AddReadDescriptor called with invalid descriptor"; return false; } pair result = LookupOrCreateDescriptor( descriptor->ReadDescriptor()); if (result.first->events & READ_FLAGS) { OLA_WARN << "Descriptor " << descriptor->ReadDescriptor() << " already in read set"; return false; } result.first->events |= READ_FLAGS; result.first->connected_descriptor = descriptor; result.first->delete_connected_on_close = delete_on_close; if (result.second) { return AddEvent(m_epoll_fd, descriptor->ReadDescriptor(), result.first); } else { return UpdateEvent(m_epoll_fd, descriptor->ReadDescriptor(), result.first); } } bool EPoller::RemoveReadDescriptor(ReadFileDescriptor *descriptor) { return RemoveDescriptor(descriptor->ReadDescriptor(), READ_FLAGS, true); } bool EPoller::RemoveReadDescriptor(ConnectedDescriptor *descriptor) { return RemoveDescriptor(descriptor->ReadDescriptor(), READ_FLAGS, true); } bool EPoller::AddWriteDescriptor(WriteFileDescriptor *descriptor) { if (m_epoll_fd == INVALID_DESCRIPTOR) { return false; } if (!descriptor->ValidWriteDescriptor()) { OLA_WARN << "AddWriteDescriptor called with invalid descriptor"; return false; } pair result = LookupOrCreateDescriptor( descriptor->WriteDescriptor()); if (result.first->events & EPOLLOUT) { OLA_WARN << "Descriptor " << descriptor->WriteDescriptor() << " already in write set"; return false; } result.first->events |= EPOLLOUT; result.first->write_descriptor = descriptor; if (result.second) { return AddEvent(m_epoll_fd, descriptor->WriteDescriptor(), result.first); } else { return UpdateEvent(m_epoll_fd, descriptor->WriteDescriptor(), result.first); } } bool EPoller::RemoveWriteDescriptor(WriteFileDescriptor *descriptor) { return RemoveDescriptor(descriptor->WriteDescriptor(), EPOLLOUT, true); } bool EPoller::Poll(TimeoutManager *timeout_manager, const TimeInterval &poll_interval) { if (m_epoll_fd == INVALID_DESCRIPTOR) { return false; } epoll_event events[MAX_EVENTS]; TimeInterval sleep_interval = poll_interval; TimeStamp now; m_clock->CurrentTime(&now); TimeInterval next_event_in = timeout_manager->ExecuteTimeouts(&now); if (!next_event_in.IsZero()) { sleep_interval = std::min(next_event_in, sleep_interval); } // take care of stats accounting if (m_wake_up_time.IsSet()) { TimeInterval loop_time = now - m_wake_up_time; OLA_DEBUG << "ss process time was " << loop_time.ToString(); if (m_loop_time) (*m_loop_time) += loop_time.AsInt(); if (m_loop_iterations) (*m_loop_iterations)++; } int ms_to_sleep = sleep_interval.InMilliSeconds(); int ready = epoll_wait(m_epoll_fd, reinterpret_cast(&events), MAX_EVENTS, ms_to_sleep ? ms_to_sleep : 1); if (ready == 0) { m_clock->CurrentTime(&m_wake_up_time); timeout_manager->ExecuteTimeouts(&m_wake_up_time); return true; } else if (ready == -1) { if (errno == EINTR) return true; OLA_WARN << "epoll() error, " << strerror(errno); return false; } m_clock->CurrentTime(&m_wake_up_time); for (int i = 0; i < ready; i++) { EPollData *descriptor = reinterpret_cast( events[i].data.ptr); CheckDescriptor(&events[i], descriptor); } // Now that we're out of the callback phase, clean up descriptors that were // removed. DescriptorList::iterator iter = m_orphaned_descriptors.begin(); for (; iter != m_orphaned_descriptors.end(); ++iter) { if (m_free_descriptors.size() == MAX_FREE_DESCRIPTORS) { delete *iter; } else { (*iter)->Reset(); m_free_descriptors.push_back(*iter); } } m_orphaned_descriptors.clear(); m_clock->CurrentTime(&m_wake_up_time); timeout_manager->ExecuteTimeouts(&m_wake_up_time); return true; } /* * Check all the registered descriptors: * - Execute the callback for descriptors with data * - Excute OnClose if a remote end closed the connection */ void EPoller::CheckDescriptor(struct epoll_event *event, EPollData *epoll_data) { if (event->events & (EPOLLHUP | EPOLLRDHUP)) { if (epoll_data->read_descriptor) { epoll_data->read_descriptor->PerformRead(); } else if (epoll_data->write_descriptor) { epoll_data->write_descriptor->PerformWrite(); } else if (epoll_data->connected_descriptor) { ConnectedDescriptor::OnCloseCallback *on_close = epoll_data->connected_descriptor->TransferOnClose(); if (on_close) on_close->Run(); // At this point the descriptor may be sitting in the orphan list if the // OnClose handler called into RemoveReadDescriptor() if (epoll_data->delete_connected_on_close && epoll_data->connected_descriptor) { bool removed = RemoveDescriptor( epoll_data->connected_descriptor->ReadDescriptor(), READ_FLAGS, false); if (removed && m_export_map) { (*m_export_map->GetIntegerVar(K_CONNECTED_DESCRIPTORS_VAR))--; } delete epoll_data->connected_descriptor; epoll_data->connected_descriptor = NULL; } } else { OLA_FATAL << "HUP event for " << epoll_data << " but no write or connected descriptor found!"; } event->events = 0; } if (event->events & EPOLLIN) { if (epoll_data->read_descriptor) { epoll_data->read_descriptor->PerformRead(); } else if (epoll_data->connected_descriptor) { epoll_data->connected_descriptor->PerformRead(); } } if (event->events & EPOLLOUT) { // epoll_data->write_descriptor may be null here if this descriptor was // removed between when kevent returned and now. if (epoll_data->write_descriptor) { epoll_data->write_descriptor->PerformWrite(); } } } std::pair EPoller::LookupOrCreateDescriptor(int fd) { pair result = m_descriptor_map.insert( DescriptorMap::value_type(fd, NULL)); bool new_descriptor = result.second; if (new_descriptor) { if (m_free_descriptors.empty()) { result.first->second = new EPollData(); } else { result.first->second = m_free_descriptors.back(); m_free_descriptors.pop_back(); } } return std::make_pair(result.first->second, new_descriptor); } bool EPoller::RemoveDescriptor(int fd, int event, bool warn_on_missing) { if (fd == INVALID_DESCRIPTOR) { OLA_WARN << "Attempt to remove an invalid file descriptor"; return false; } EPollData *epoll_data = STLFindOrNull(m_descriptor_map, fd); if (!epoll_data) { if (warn_on_missing) { OLA_WARN << "Couldn't find EPollData for " << fd; } return false; } epoll_data->events &= (~event); if (event & EPOLLOUT) { epoll_data->write_descriptor = NULL; } else if (event & EPOLLIN) { epoll_data->read_descriptor = NULL; epoll_data->connected_descriptor = NULL; } if (epoll_data->events == 0) { RemoveEvent(m_epoll_fd, fd); m_orphaned_descriptors.push_back( STLLookupAndRemovePtr(&m_descriptor_map, fd)); } else { return UpdateEvent(m_epoll_fd, fd, epoll_data); } return true; } } // namespace io } // namespace ola ola-0.10.5.nojsmin/common/io/NonBlockingSender.cpp0000644000175000017500000000534413023355232021433 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * NonBlockingSender.cpp * Copyright (C) 2013 Simon Newton */ #include "ola/Callback.h" #include "ola/io/IOQueue.h" #include "ola/io/IOStack.h" #include "ola/io/NonBlockingSender.h" namespace ola { namespace io { const unsigned int NonBlockingSender::DEFAULT_MAX_BUFFER_SIZE = 1024; NonBlockingSender::NonBlockingSender(ola::io::ConnectedDescriptor *descriptor, ola::io::SelectServerInterface *ss, ola::io::MemoryBlockPool *memory_pool, unsigned int max_buffer_size) : m_descriptor(descriptor), m_ss(ss), m_output_buffer(memory_pool), m_associated(false), m_max_buffer_size(max_buffer_size) { m_descriptor->SetOnWritable( ola::NewCallback(this, &NonBlockingSender::PerformWrite)); } NonBlockingSender::~NonBlockingSender() { if (m_associated) { m_ss->RemoveWriteDescriptor(m_descriptor); } m_descriptor->SetOnWritable(NULL); } bool NonBlockingSender::LimitReached() const { return m_output_buffer.Size() >= m_max_buffer_size; } bool NonBlockingSender::SendMessage(ola::io::IOStack *stack) { if (LimitReached()) { return false; } stack->MoveToIOQueue(&m_output_buffer); AssociateIfRequired(); return true; } bool NonBlockingSender::SendMessage(IOQueue *queue) { if (LimitReached()) { return false; } m_output_buffer.AppendMove(queue); AssociateIfRequired(); return true; } /* * Called when the descriptor is writeable, this does the actual write() call. */ void NonBlockingSender::PerformWrite() { m_descriptor->Send(&m_output_buffer); if (m_output_buffer.Empty() && m_associated) { m_ss->RemoveWriteDescriptor(m_descriptor); m_associated = false; } } /* * Associate our descriptor with the SelectServer if we have data to send. */ void NonBlockingSender::AssociateIfRequired() { if (m_output_buffer.Empty()) { return; } m_ss->AddWriteDescriptor(m_descriptor); m_associated = true; } } // namespace io } // namespace ola ola-0.10.5.nojsmin/common/io/WindowsPoller.cpp0000644000175000017500000006026213023355232020677 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * WindowsPoller.cpp * A Poller for the Windows platform * Copyright (C) 2014 Lukas Erlinghagen */ #include "common/io/WindowsPoller.h" #include #include #define WIN32_LEAN_AND_MEAN #define VC_EXTRALEAN #include #include #include #include #include #include #include "ola/Clock.h" #include "ola/Logging.h" #include "ola/base/Macro.h" #include "ola/io/Descriptor.h" #include "ola/stl/STLUtils.h" using std::map; using std::pair; using std::vector; namespace ola { namespace io { ////////////////////////////////////////////////////////////////////////////// static const int FLAG_READ = 1; static const int FLAG_WRITE = 2; class WindowsPollerDescriptor { public: WindowsPollerDescriptor() : read_descriptor(NULL), write_descriptor(NULL), connected_descriptor(NULL), delete_connected_on_close(false), type(GENERIC_DESCRIPTOR), flags(0) { } ReadFileDescriptor *read_descriptor; WriteFileDescriptor *write_descriptor; ConnectedDescriptor *connected_descriptor; bool delete_connected_on_close; DescriptorType type; int flags; }; ////////////////////////////////////////////////////////////////////////////// class EventHolder { public: EventHolder() : event(CreateEvent(NULL, FALSE, FALSE, NULL)) { } ~EventHolder() { CloseHandle(event); } operator HANDLE() { return event; } private: HANDLE event; }; ////////////////////////////////////////////////////////////////////////////// WindowsPoller::WindowsPoller(ExportMap *export_map, Clock *clock) : m_export_map(export_map), m_loop_iterations(NULL), m_loop_time(NULL), m_clock(clock) { if (m_export_map) { m_loop_time = m_export_map->GetCounterVar(K_LOOP_TIME); m_loop_iterations = m_export_map->GetCounterVar(K_LOOP_COUNT); } } WindowsPoller::~WindowsPoller() { { DescriptorMap::iterator iter = m_descriptor_map.begin(); for (; iter != m_descriptor_map.end(); ++iter) { if (iter->second->delete_connected_on_close) { delete iter->second->connected_descriptor; } delete iter->second; } } OrphanedDescriptors::iterator iter = m_orphaned_descriptors.begin(); for (; iter != m_orphaned_descriptors.end(); ++iter) { if ((*iter)->delete_connected_on_close) { delete (*iter)->connected_descriptor; } delete *iter; } } bool WindowsPoller::AddReadDescriptor(ReadFileDescriptor *descriptor) { if (!descriptor->ValidReadDescriptor()) { OLA_WARN << "AddReadDescriptor called with invalid descriptor"; return false; } pair result = LookupOrCreateDescriptor( ToHandle(descriptor->ReadDescriptor())); if (result.first->flags & FLAG_READ) { OLA_WARN << "Descriptor " << descriptor->ReadDescriptor() << " already in read set"; return false; } result.first->flags |= FLAG_READ; result.first->read_descriptor = descriptor; result.first->type = descriptor->ReadDescriptor().m_type; return result.second ? true : false; } bool WindowsPoller::AddReadDescriptor(ConnectedDescriptor *descriptor, bool delete_on_close) { if (!descriptor->ValidReadDescriptor()) { OLA_WARN << "AddReadDescriptor called with invalid descriptor"; return false; } pair result = LookupOrCreateDescriptor( ToHandle(descriptor->ReadDescriptor())); if (result.first->flags & FLAG_READ) { OLA_WARN << "Descriptor " << descriptor->ReadDescriptor() << " already in read set"; return false; } result.first->flags |= FLAG_READ; result.first->connected_descriptor = descriptor; result.first->type = descriptor->ReadDescriptor().m_type; result.first->delete_connected_on_close = delete_on_close; return (result.second)? true : false; } bool WindowsPoller::RemoveReadDescriptor(ReadFileDescriptor *descriptor) { return RemoveDescriptor(descriptor->ReadDescriptor(), FLAG_READ, true); } bool WindowsPoller::RemoveReadDescriptor(ConnectedDescriptor *descriptor) { return RemoveDescriptor(descriptor->ReadDescriptor(), FLAG_READ, true); } bool WindowsPoller::AddWriteDescriptor(WriteFileDescriptor *descriptor) { if (!descriptor->ValidWriteDescriptor()) { OLA_WARN << "AddWriteDescriptor called with invalid descriptor"; return false; } if ((descriptor->WriteDescriptor().m_type != SOCKET_DESCRIPTOR) && (descriptor->WriteDescriptor().m_type != PIPE_DESCRIPTOR)) { OLA_WARN << "Cannot add descriptor " << descriptor << " for writing."; return false; } pair result = LookupOrCreateDescriptor( ToHandle(descriptor->WriteDescriptor())); if (result.first->flags & FLAG_WRITE) { OLA_WARN << "Descriptor " << descriptor->WriteDescriptor() << " already in write set"; return false; } result.first->flags |= FLAG_WRITE; result.first->write_descriptor = descriptor; result.first->type = descriptor->WriteDescriptor().m_type; return (result.second)? true : false; } bool WindowsPoller::RemoveWriteDescriptor(WriteFileDescriptor *descriptor) { return RemoveDescriptor(descriptor->WriteDescriptor(), FLAG_WRITE, true); } ////////////////////////////////////////////////////////////////////////////// class PollData { public: PollData(HANDLE event, HANDLE handle, bool read) : event(event), handle(handle), buffer(NULL), size(0), overlapped(NULL), read(read) { } ~PollData() { if (buffer) { delete[] buffer; buffer = NULL; } if (overlapped) { delete overlapped; overlapped = NULL; } } bool AllocBuffer(DWORD size) { if (buffer) { OLA_WARN << "Buffer already allocated"; return false; } buffer = new char[size]; this->size = size; return true; } bool CreateOverlapped() { if (overlapped) { OLA_WARN << "Overlapped already allocated"; return false; } overlapped = new OVERLAPPED; memset(overlapped, 0, sizeof(*overlapped)); overlapped->hEvent = event; return true; } HANDLE event; HANDLE handle; char* buffer; DWORD size; OVERLAPPED* overlapped; bool read; }; void CancelIOs(vector* data) { vector::iterator iter = data->begin(); for (; iter != data->end(); ++iter) { PollData* poll_data = *iter; if (poll_data->overlapped) { CancelIo(poll_data->handle); } } } bool WindowsPoller::Poll(TimeoutManager *timeout_manager, const TimeInterval &poll_interval) { TimeInterval sleep_interval = poll_interval; TimeStamp now; m_clock->CurrentTime(&now); TimeInterval next_event_in = timeout_manager->ExecuteTimeouts(&now); if (!next_event_in.IsZero()) { sleep_interval = std::min(next_event_in, sleep_interval); } // take care of stats accounting if (m_wake_up_time.IsSet()) { TimeInterval loop_time = now - m_wake_up_time; OLA_DEBUG << "ss process time was " << loop_time.ToString(); if (m_loop_time) (*m_loop_time) += loop_time.AsInt(); if (m_loop_iterations) (*m_loop_iterations)++; } int ms_to_sleep = sleep_interval.InMilliSeconds(); // Prepare events vector events; vector data; vector event_holders; DescriptorMap::iterator next, iter = m_descriptor_map.begin(); bool success = true; // We're not using a for loop here since we might call RemoveDescriptor(), // thereby invalidating the 'iter' iterator. while (iter != m_descriptor_map.end()) { next = iter; ++next; WindowsPollerDescriptor* descriptor = iter->second; PollData* poll_data = NULL; DWORD result = 0; DescriptorHandle descriptor_handle; EventHolder* event_holder; switch (descriptor->type) { case PIPE_DESCRIPTOR: if (descriptor->connected_descriptor) { descriptor_handle = descriptor->connected_descriptor->ReadDescriptor(); event_holder = new EventHolder(); poll_data = new PollData(*event_holder, ToHandle(descriptor_handle), true); poll_data->AllocBuffer(ASYNC_DATA_BUFFER_SIZE); poll_data->CreateOverlapped(); success = ReadFile(poll_data->handle, poll_data->buffer, poll_data->size, &(poll_data->size), poll_data->overlapped); result = GetLastError(); if (success || result == ERROR_IO_PENDING) { data.push_back(poll_data); events.push_back(poll_data->event); event_holders.push_back(event_holder); } else if (!success && (result != ERROR_IO_PENDING)) { if (result == ERROR_BROKEN_PIPE) { OLA_DEBUG << "Broken pipe: " << ToHandle(descriptor_handle); // Pipe was closed, so close the descriptor ConnectedDescriptor::OnCloseCallback *on_close = descriptor->connected_descriptor->TransferOnClose(); if (on_close) on_close->Run(); if (descriptor->connected_descriptor) { if (descriptor->delete_connected_on_close) { if (RemoveReadDescriptor(descriptor->connected_descriptor) && m_export_map) { (*m_export_map->GetIntegerVar( K_CONNECTED_DESCRIPTORS_VAR))--; } delete descriptor->connected_descriptor; descriptor->connected_descriptor = NULL; } } delete poll_data; delete event_holder; } else { OLA_WARN << "ReadFile failed with " << result << " for " << ToHandle(descriptor_handle); delete poll_data; delete event_holder; } } } if (descriptor->write_descriptor) { descriptor_handle = descriptor->write_descriptor->WriteDescriptor(); event_holder = new EventHolder(); poll_data = new PollData(*event_holder, ToHandle(descriptor_handle), false); poll_data->AllocBuffer(1); poll_data->CreateOverlapped(); success = WriteFile(poll_data->handle, poll_data->buffer, poll_data->size, &(poll_data->size), poll_data->overlapped); result = GetLastError(); if (success || (result == ERROR_IO_PENDING)) { data.push_back(poll_data); events.push_back(poll_data->event); event_holders.push_back(event_holder); } else if (result == ERROR_BROKEN_PIPE) { OLA_DEBUG << "Broken pipe: " << ToHandle(descriptor_handle); // Pipe was closed, so close the descriptor descriptor->write_descriptor = NULL; delete poll_data; delete event_holder; } else { OLA_WARN << "WriteFile failed with " << result << " for " << ToHandle(descriptor_handle); delete poll_data; delete event_holder; } } break; case SOCKET_DESCRIPTOR: if (descriptor->connected_descriptor || descriptor->read_descriptor) { // select() for readable events if (descriptor->connected_descriptor) { descriptor_handle = descriptor->connected_descriptor->ReadDescriptor(); } else { descriptor_handle = descriptor->read_descriptor->ReadDescriptor(); } event_holder = new EventHolder(); poll_data = new PollData(*event_holder, ToHandle(descriptor_handle), true); if (WSAEventSelect(ToFD(descriptor_handle), *event_holder, FD_READ | FD_CLOSE | FD_ACCEPT) != 0) { OLA_WARN << "WSAEventSelect failed with " << WSAGetLastError(); delete poll_data; delete event_holder; } else { data.push_back(poll_data); events.push_back(poll_data->event); event_holders.push_back(event_holder); } } if (descriptor->write_descriptor) { // select() for writeable events descriptor_handle = descriptor->write_descriptor->WriteDescriptor(); event_holder = new EventHolder(); poll_data = new PollData(*event_holder, ToHandle(descriptor_handle), false); if (WSAEventSelect(ToFD(descriptor_handle), *event_holder, FD_WRITE | FD_CLOSE | FD_CONNECT) != 0) { OLA_WARN << "WSAEventSelect failed with " << WSAGetLastError(); delete poll_data; delete event_holder; } else { data.push_back(poll_data); events.push_back(poll_data->event); event_holders.push_back(event_holder); } } break; default: OLA_WARN << "Descriptor type not implemented: " << descriptor->type; break; } iter = next; } bool return_value = true; // Wait for events or timeout if (events.size() > 0) { DWORD result = WaitForMultipleObjectsEx(events.size(), events.data(), FALSE, ms_to_sleep, TRUE); CancelIOs(&data); if (result == WAIT_TIMEOUT) { m_clock->CurrentTime(&m_wake_up_time); timeout_manager->ExecuteTimeouts(&m_wake_up_time); // We can't return here since any of the cancelled IO calls still might // have succeeded. } else if (result == WAIT_FAILED) { OLA_WARN << "WaitForMultipleObjectsEx failed with " << GetLastError(); return_value = false; // We can't return here since any of the cancelled IO calls still might // have succeeded. } else if ((result >= WAIT_OBJECT_0) && (result < (WAIT_OBJECT_0 + events.size()))) { do { DWORD index = result - WAIT_OBJECT_0; PollData* poll_data = data[index]; HandleWakeup(poll_data); events.erase(events.begin() + index); data.erase(data.begin() + index); event_holders.erase(event_holders.begin() + index); result = WaitForMultipleObjectsEx(events.size(), events.data(), FALSE, 0, TRUE); } while ((result >= WAIT_OBJECT_0) && (result < (WAIT_OBJECT_0 + events.size()))); } else { OLA_WARN << "Unhandled return value from WaitForMultipleObjectsEx: " << result; } } else { Sleep(ms_to_sleep); CancelIOs(&data); } m_clock->CurrentTime(&m_wake_up_time); timeout_manager->ExecuteTimeouts(&m_wake_up_time); FinalCheckIOs(data); // Loop through all descriptors again and look for any with pending data DescriptorMap::iterator map_iter = m_descriptor_map.begin(); for (; map_iter != m_descriptor_map.end(); ++map_iter) { WindowsPollerDescriptor* descriptor = map_iter->second; if (!descriptor->connected_descriptor) { continue; } if (descriptor->type != PIPE_DESCRIPTOR) { continue; } DescriptorHandle handle = descriptor->connected_descriptor->ReadDescriptor(); if (*handle.m_async_data_size > 0) { descriptor->connected_descriptor->PerformRead(); } } STLDeleteElements(&m_orphaned_descriptors); STLDeleteElements(&data); STLDeleteElements(&event_holders); m_clock->CurrentTime(&m_wake_up_time); timeout_manager->ExecuteTimeouts(&m_wake_up_time); return return_value; } ////////////////////////////////////////////////////////////////////////////// std::pair WindowsPoller::LookupOrCreateDescriptor(void* handle) { pair result = m_descriptor_map.insert( DescriptorMap::value_type(handle, NULL)); bool new_descriptor = result.second; if (new_descriptor) { result.first->second = new WindowsPollerDescriptor(); OLA_DEBUG << "Created WindowsPollerDescriptor " << result.first->second << " for handle " << handle; } return std::make_pair(result.first->second, new_descriptor); } bool WindowsPoller::RemoveDescriptor(const DescriptorHandle &handle, int flag, bool warn_on_missing) { if (!handle.IsValid()) { OLA_WARN << "Attempt to remove an invalid file descriptor"; return false; } WindowsPollerDescriptor *descriptor = STLFindOrNull(m_descriptor_map, ToHandle(handle)); if (!descriptor) { if (warn_on_missing) { OLA_WARN << "Couldn't find WindowsPollerDescriptor for " << handle; } return false; } if (flag & FLAG_READ) { descriptor->connected_descriptor = NULL; descriptor->read_descriptor = NULL; } else if (flag & FLAG_WRITE) { descriptor->write_descriptor = NULL; } descriptor->flags &= ~flag; if (descriptor->flags == 0) { m_orphaned_descriptors.push_back( STLLookupAndRemovePtr(&m_descriptor_map, ToHandle(handle))); } return true; } void WindowsPoller::HandleWakeup(PollData* data) { DescriptorMap::iterator iter = m_descriptor_map.find(data->handle); if (iter == m_descriptor_map.end()) { OLA_WARN << "Descriptor not found for handle " << data->handle; return; } WindowsPollerDescriptor* descriptor = iter->second; switch (descriptor->type) { case PIPE_DESCRIPTOR: { if (!data->overlapped) { OLA_WARN << "No overlapped entry for pipe descriptor"; return; } if (data->read && descriptor->connected_descriptor) { if (!descriptor->connected_descriptor->ValidReadDescriptor()) { RemoveDescriptor(descriptor->connected_descriptor->ReadDescriptor(), FLAG_READ, false); return; } DescriptorHandle handle = descriptor->connected_descriptor->ReadDescriptor(); DWORD bytes_transferred = 0; if (!GetOverlappedResult(data->handle, data->overlapped, &bytes_transferred, TRUE)) { if (GetLastError() != ERROR_OPERATION_ABORTED) { OLA_WARN << "GetOverlappedResult failed with " << GetLastError(); return; } } uint32_t to_copy = std::min(static_cast(bytes_transferred), (ASYNC_DATA_BUFFER_SIZE - *handle.m_async_data_size)); if (to_copy < bytes_transferred) { OLA_WARN << "Pipe descriptor has lost data"; } memcpy(&(handle.m_async_data[*handle.m_async_data_size]), data->buffer, to_copy); *handle.m_async_data_size += to_copy; if (*handle.m_async_data_size > 0) { descriptor->connected_descriptor->PerformRead(); } } else if (!data->read && descriptor->write_descriptor) { OLA_WARN << "Write wakeup"; if (!descriptor->write_descriptor->ValidWriteDescriptor()) { RemoveDescriptor(descriptor->write_descriptor->WriteDescriptor(), FLAG_WRITE, false); return; } descriptor->write_descriptor->PerformWrite(); } else { OLA_WARN << "Overlapped wakeup with data mismatch"; } } break; case SOCKET_DESCRIPTOR: { WSANETWORKEVENTS events; if (WSAEnumNetworkEvents(reinterpret_cast(data->handle), data->event, & events) != 0) { OLA_WARN << "WSAEnumNetworkEvents failed with " << WSAGetLastError(); } else { if (events.lNetworkEvents & (FD_READ | FD_ACCEPT)) { if (descriptor->connected_descriptor) { descriptor->connected_descriptor->PerformRead(); } else if (descriptor->read_descriptor) { descriptor->read_descriptor->PerformRead(); } else { OLA_WARN << "No read descriptor for socket with read event"; } } if (events.lNetworkEvents & (FD_WRITE | FD_CONNECT)) { if (descriptor->write_descriptor) { descriptor->write_descriptor->PerformWrite(); } else { OLA_WARN << "No write descriptor for socket with write event"; } } if (events.lNetworkEvents & FD_CLOSE) { if (descriptor->connected_descriptor) { ConnectedDescriptor::OnCloseCallback *on_close = descriptor->connected_descriptor->TransferOnClose(); if (on_close) on_close->Run(); if (descriptor->delete_connected_on_close) { if (RemoveReadDescriptor(descriptor->connected_descriptor) && m_export_map) { (*m_export_map->GetIntegerVar(K_CONNECTED_DESCRIPTORS_VAR))--; } delete descriptor->connected_descriptor; descriptor->connected_descriptor = NULL; } } else { OLA_WARN << "Close event for " << descriptor << " but no connected descriptor found"; } } } } break; default: OLA_WARN << "Unhandled descriptor type"; break; } } void WindowsPoller::FinalCheckIOs(vector data) { vector::iterator iter = data.begin(); for (; iter != data.end(); ++iter) { PollData* poll_data = *iter; if (!poll_data->overlapped) { // No overlapped input for this descriptor, skip it continue; } DWORD bytes_transferred = 0; if (!GetOverlappedResult(poll_data->handle, poll_data->overlapped, &bytes_transferred, TRUE)) { if (GetLastError() != ERROR_OPERATION_ABORTED) { OLA_WARN << "GetOverlappedResult failed with " << GetLastError(); return; } } if (bytes_transferred > 0) { DescriptorMap::iterator iter = m_descriptor_map.find(poll_data->handle); if (iter == m_descriptor_map.end()) { OLA_WARN << "Descriptor not found for handle " << poll_data->handle; return; } WindowsPollerDescriptor* descriptor = iter->second; DescriptorHandle handle = descriptor->connected_descriptor->ReadDescriptor(); uint32_t to_copy = std::min(static_cast(bytes_transferred), (ASYNC_DATA_BUFFER_SIZE - *handle.m_async_data_size)); if (to_copy < bytes_transferred) { OLA_WARN << "Pipe descriptor has lost data"; } memcpy(&(handle.m_async_data[*handle.m_async_data_size]), poll_data->buffer, to_copy); *handle.m_async_data_size += to_copy; descriptor->connected_descriptor->PerformRead(); } } } } // namespace io } // namespace ola ola-0.10.5.nojsmin/common/io/DescriptorTest.cpp0000644000175000017500000002221513023355232021041 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * DescriptorTest.cpp * Test fixture for the Descriptor classes * Copyright (C) 2005 Simon Newton */ #include #include #include #include #ifdef _WIN32 #include #endif // _WIN32 #include "ola/Callback.h" #include "ola/Logging.h" #include "ola/io/Descriptor.h" #include "ola/io/SelectServer.h" #include "ola/testing/TestUtils.h" using std::string; using ola::io::ConnectedDescriptor; using ola::io::LoopbackDescriptor; using ola::io::PipeDescriptor; #ifndef _WIN32 using ola::io::UnixSocket; #endif // !_WIN32 using ola::io::SelectServer; static const unsigned char test_cstring[] = "Foo"; // used to set a timeout which aborts the tests static const int ABORT_TIMEOUT_IN_MS = 1000; class DescriptorTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(DescriptorTest); CPPUNIT_TEST(testLoopbackDescriptor); CPPUNIT_TEST(testPipeDescriptorClientClose); CPPUNIT_TEST(testPipeDescriptorServerClose); #ifndef _WIN32 CPPUNIT_TEST(testUnixSocketClientClose); CPPUNIT_TEST(testUnixSocketServerClose); #endif // !_WIN32 CPPUNIT_TEST_SUITE_END(); public: void setUp(); void tearDown(); void testLoopbackDescriptor(); void testPipeDescriptorClientClose(); void testPipeDescriptorServerClose(); #ifndef _WIN32 void testUnixSocketClientClose(); void testUnixSocketServerClose(); #endif // !_WIN32 // timing out indicates something went wrong void Timeout() { OLA_ASSERT_TRUE(false); m_timeout_closure = NULL; } // Socket data actions void ReceiveAndClose(ConnectedDescriptor *socket); void ReceiveAndTerminate(ConnectedDescriptor *socket); void Receive(ConnectedDescriptor *socket); void ReceiveAndSend(ConnectedDescriptor *socket); void ReceiveSendAndClose(ConnectedDescriptor *socket); // Socket close actions void TerminateOnClose() { m_ss->Terminate(); } private: SelectServer *m_ss; ola::SingleUseCallback0 *m_timeout_closure; void SocketClientClose(ConnectedDescriptor *socket, ConnectedDescriptor *socket2); void SocketServerClose(ConnectedDescriptor *socket, ConnectedDescriptor *socket2); }; CPPUNIT_TEST_SUITE_REGISTRATION(DescriptorTest); /* * Setup the select server */ void DescriptorTest::setUp() { m_ss = new SelectServer(); m_timeout_closure = ola::NewSingleCallback(this, &DescriptorTest::Timeout); OLA_ASSERT_TRUE(m_ss->RegisterSingleTimeout(ABORT_TIMEOUT_IN_MS, m_timeout_closure)); #if _WIN32 WSADATA wsa_data; int result = WSAStartup(MAKEWORD(2, 0), &wsa_data); OLA_ASSERT_EQ(result, 0); #endif // _WIN32 } /* * Cleanup the select server */ void DescriptorTest::tearDown() { delete m_ss; #ifdef _WIN32 WSACleanup(); #endif // _WIN32 } /* * Test a loopback socket works correctly */ void DescriptorTest::testLoopbackDescriptor() { LoopbackDescriptor socket; OLA_ASSERT_TRUE(socket.Init()); OLA_ASSERT_FALSE(socket.Init()); socket.SetOnData(ola::NewCallback(this, &DescriptorTest::ReceiveAndTerminate, static_cast(&socket))); OLA_ASSERT_TRUE(m_ss->AddReadDescriptor(&socket)); ssize_t bytes_sent = socket.Send( static_cast(test_cstring), sizeof(test_cstring)); OLA_ASSERT_EQ(static_cast(sizeof(test_cstring)), bytes_sent); m_ss->Run(); m_ss->RemoveReadDescriptor(&socket); } /* * Test a pipe socket works correctly. * The client sends some data and expects the same data to be returned. The * client then closes the connection. */ void DescriptorTest::testPipeDescriptorClientClose() { PipeDescriptor socket; OLA_ASSERT_TRUE(socket.Init()); OLA_ASSERT_FALSE(socket.Init()); SocketClientClose(&socket, socket.OppositeEnd()); } /* * Test a pipe socket works correctly. * The client sends some data. The server echos the data and closes the * connection. */ void DescriptorTest::testPipeDescriptorServerClose() { PipeDescriptor socket; OLA_ASSERT_TRUE(socket.Init()); OLA_ASSERT_FALSE(socket.Init()); SocketServerClose(&socket, socket.OppositeEnd()); } #ifndef _WIN32 /* * Test a unix socket works correctly. * The client sends some data and expects the same data to be returned. The * client then closes the connection. */ void DescriptorTest::testUnixSocketClientClose() { UnixSocket socket; OLA_ASSERT_TRUE(socket.Init()); OLA_ASSERT_FALSE(socket.Init()); SocketClientClose(&socket, socket.OppositeEnd()); } /* * Test a unix socket works correctly. * The client sends some data. The server echos the data and closes the * connection. */ void DescriptorTest::testUnixSocketServerClose() { UnixSocket socket; OLA_ASSERT_TRUE(socket.Init()); OLA_ASSERT_FALSE(socket.Init()); SocketServerClose(&socket, socket.OppositeEnd()); } #endif // !_WIN32 /* * Receive some data and close the socket */ void DescriptorTest::ReceiveAndClose(ConnectedDescriptor *socket) { Receive(socket); m_ss->RemoveReadDescriptor(socket); socket->Close(); } /* * Receive some data and terminate */ void DescriptorTest::ReceiveAndTerminate(ConnectedDescriptor *socket) { Receive(socket); m_ss->Terminate(); } /* * Receive some data and check it's what we expected. */ void DescriptorTest::Receive(ConnectedDescriptor *socket) { // try to read more than what we sent to test non-blocking uint8_t buffer[sizeof(test_cstring) + 10]; unsigned int data_read; OLA_ASSERT_FALSE(socket->Receive(buffer, sizeof(buffer), data_read)); OLA_ASSERT_EQ(static_cast(sizeof(test_cstring)), data_read); OLA_ASSERT_FALSE(memcmp(test_cstring, buffer, data_read)); } /* * Receive some data and send it back */ void DescriptorTest::ReceiveAndSend(ConnectedDescriptor *socket) { uint8_t buffer[sizeof(test_cstring) + 10]; unsigned int data_read; OLA_ASSERT_EQ(0, socket->Receive(buffer, sizeof(buffer), data_read)); OLA_ASSERT_EQ(static_cast(sizeof(test_cstring)), data_read); ssize_t bytes_sent = socket->Send(buffer, data_read); OLA_ASSERT_EQ(static_cast(sizeof(test_cstring)), bytes_sent); } /* * Receive some data, send the same data and close */ void DescriptorTest::ReceiveSendAndClose(ConnectedDescriptor *socket) { ReceiveAndSend(socket); m_ss->RemoveReadDescriptor(socket); socket->Close(); } /** * Generic method to test client initiated close */ void DescriptorTest::SocketClientClose(ConnectedDescriptor *socket, ConnectedDescriptor *socket2) { OLA_ASSERT_TRUE(socket); socket->SetOnData( ola::NewCallback(this, &DescriptorTest::ReceiveAndClose, static_cast(socket))); OLA_ASSERT_TRUE(m_ss->AddReadDescriptor(socket)); OLA_ASSERT_TRUE(socket2); socket2->SetOnData( ola::NewCallback(this, &DescriptorTest::ReceiveAndSend, static_cast(socket2))); socket2->SetOnClose( ola::NewSingleCallback(this, &DescriptorTest::TerminateOnClose)); OLA_ASSERT_TRUE(m_ss->AddReadDescriptor(socket2)); ssize_t bytes_sent = socket->Send( static_cast(test_cstring), sizeof(test_cstring)); OLA_ASSERT_EQ(static_cast(sizeof(test_cstring)), bytes_sent); m_ss->Run(); m_ss->RemoveReadDescriptor(socket); m_ss->RemoveReadDescriptor(socket2); delete socket2; } /** * Generic method to test server initiated close */ void DescriptorTest::SocketServerClose(ConnectedDescriptor *socket, ConnectedDescriptor *socket2) { OLA_ASSERT_TRUE(socket); socket->SetOnData(ola::NewCallback( this, &DescriptorTest::Receive, static_cast(socket))); socket->SetOnClose( ola::NewSingleCallback(this, &DescriptorTest::TerminateOnClose)); OLA_ASSERT_TRUE(m_ss->AddReadDescriptor(socket)); OLA_ASSERT_TRUE(socket2); socket2->SetOnData(ola::NewCallback( this, &DescriptorTest::ReceiveSendAndClose, static_cast(socket2))); OLA_ASSERT_TRUE(m_ss->AddReadDescriptor(socket2)); ssize_t bytes_sent = socket->Send( static_cast(test_cstring), sizeof(test_cstring)); OLA_ASSERT_EQ(static_cast(sizeof(test_cstring)), bytes_sent); m_ss->Run(); m_ss->RemoveReadDescriptor(socket); m_ss->RemoveReadDescriptor(socket2); delete socket2; } ola-0.10.5.nojsmin/common/io/TimeoutManager.h0000644000175000017500000001243413023355232020453 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * TimeoutManager.h * Manages timeout events. * Copyright (C) 2013 Simon Newton */ #ifndef COMMON_IO_TIMEOUTMANAGER_H_ #define COMMON_IO_TIMEOUTMANAGER_H_ #include #include #include #include "ola/Callback.h" #include "ola/Clock.h" #include "ola/ExportMap.h" #include "ola/base/Macro.h" #include "ola/thread/SchedulerInterface.h" namespace ola { namespace io { /** * @class TimeoutManager * @brief Manages timer events. * * The TimeoutManager allows Callbacks to trigger at some point in the future. * Callbacks can be invoked once, or periodically. */ class TimeoutManager { public : /** * @brief Create a new TimeoutManager. * @param export_map an ExportMap to update * @param clock the Clock to use. */ TimeoutManager(ola::ExportMap *export_map, Clock *clock); ~TimeoutManager(); /** * @brief Register a repeating timeout. * Returning false from the Callback will cancel this timer. * @param interval the delay before the closure will be run. * @param closure the closure to invoke when the event triggers. Ownership is * given up to the select server - make sure nothing else uses this Callback. * @returns the identifier for this timeout, this can be used to remove it * later. */ ola::thread::timeout_id RegisterRepeatingTimeout( const ola::TimeInterval &interval, ola::Callback0 *closure); /** * @brief Register a single use timeout function. * @param interval the delay between function calls * @param closure the Callback to invoke when the event triggers * @returns the identifier for this timeout, this can be used to remove it * later. */ ola::thread::timeout_id RegisterSingleTimeout( const ola::TimeInterval &interval, ola::SingleUseCallback0 *closure); /** * @brief Cancel a timeout. * @param id the id of the timeout */ void CancelTimeout(ola::thread::timeout_id id); /** * @brief Check if there are any events in the queue. * Events remain in the queue even if they have been cancelled. * @returns true if there are events pending, false otherwise. */ bool EventsPending() const { return !m_events.empty(); } /** * @brief Execute any expired timeouts. * @param[in,out] now the current time, set to the last time events were * checked. * @returns the time until the next event. */ TimeInterval ExecuteTimeouts(TimeStamp *now); static const char K_TIMER_VAR[]; private : class Event { public: explicit Event(const TimeInterval &interval, const Clock *clock) : m_interval(interval) { TimeStamp now; clock->CurrentTime(&now); m_next = now + m_interval; } virtual ~Event() {} virtual bool Trigger() = 0; void UpdateTime(const TimeStamp &now) { m_next = now + m_interval; } TimeStamp NextTime() const { return m_next; } private: TimeInterval m_interval; TimeStamp m_next; }; // An event that only happens once class SingleEvent: public Event { public: SingleEvent(const TimeInterval &interval, const Clock *clock, ola::BaseCallback0 *closure): Event(interval, clock), m_closure(closure) { } virtual ~SingleEvent() { if (m_closure) delete m_closure; } bool Trigger() { if (m_closure) { m_closure->Run(); // it's deleted itself at this point m_closure = NULL; } return false; } private: ola::BaseCallback0 *m_closure; }; /* * An event that occurs more than once. The closure can return false to * indicate that it should not be called again. */ class RepeatingEvent: public Event { public: RepeatingEvent(const TimeInterval &interval, const Clock *clock, ola::BaseCallback0 *closure): Event(interval, clock), m_closure(closure) { } ~RepeatingEvent() { delete m_closure; } bool Trigger() { if (!m_closure) return false; return m_closure->Run(); } private: ola::BaseCallback0 *m_closure; }; struct ltevent { bool operator()(Event *e1, Event *e2) const { return e1->NextTime() > e2->NextTime(); } }; typedef std::priority_queue, ltevent> event_queue_t; ola::ExportMap *m_export_map; Clock *m_clock; event_queue_t m_events; std::set m_removed_timeouts; DISALLOW_COPY_AND_ASSIGN(TimeoutManager); }; } // namespace io } // namespace ola #endif // COMMON_IO_TIMEOUTMANAGER_H_ ola-0.10.5.nojsmin/common/io/IOQueue.cpp0000644000175000017500000001454013023355232017401 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * IOQueue.cpp * A non-contigous memory buffer * Copyright (C) 2012 Simon Newton */ #include #include #include #include #include #include #include #include #include #include namespace ola { namespace io { using std::min; using std::string; /** * @brief IOQueue. */ IOQueue::IOQueue() : m_pool(new MemoryBlockPool()), m_delete_pool(true) { } IOQueue::IOQueue(MemoryBlockPool *block_pool) : m_pool(block_pool), m_delete_pool(false) { } /** * Clean up */ IOQueue::~IOQueue() { Clear(); if (m_delete_pool) delete m_pool; } /** * Return the amount of data in the buffer */ unsigned int IOQueue::Size() const { if (m_blocks.empty()) return 0; unsigned int size = 0; BlockVector::const_iterator iter = m_blocks.begin(); for (; iter != m_blocks.end(); ++iter) size += (*iter)->Size(); return size; } /** * Append (length) bytes of data to the buffer */ void IOQueue::Write(const uint8_t *data, unsigned int length) { unsigned int bytes_written = 0; if (m_blocks.empty()) { AppendBlock(); } while (true) { bytes_written += m_blocks.back()->Append(data + bytes_written, length - bytes_written); if (bytes_written == length) { return; } AppendBlock(); } } /** * Read up to n bytes into the memory location data and shrink the IOQueue by * the amount read. */ unsigned int IOQueue::Read(uint8_t *data, unsigned int n) { unsigned int bytes_read = 0; BlockVector::iterator iter = m_blocks.begin(); while (iter != m_blocks.end() && bytes_read != n) { MemoryBlock *block = *iter; unsigned int bytes_copied = block->Copy(data + bytes_read, n - bytes_read); block->PopFront(bytes_copied); bytes_read += bytes_copied; if (block->Empty()) { m_pool->Release(block); iter = m_blocks.erase(iter); } else { iter++; } } return bytes_read; } /** * Read up to n bytes into the string output. */ unsigned int IOQueue::Read(string *output, unsigned int n) { unsigned int bytes_remaining = n; BlockVector::iterator iter = m_blocks.begin(); while (iter != m_blocks.end() && bytes_remaining) { MemoryBlock *block = *iter; unsigned int bytes_to_copy = std::min(block->Size(), bytes_remaining); output->append(reinterpret_cast(block->Data()), bytes_to_copy); bytes_remaining -= bytes_to_copy; if (block->Empty()) { m_pool->Release(block); iter = m_blocks.erase(iter); } else { iter++; } } return n - bytes_remaining; } /** * Copy the first n bytes into the region pointed to by data */ unsigned int IOQueue::Peek(uint8_t *data, unsigned int n) const { unsigned int bytes_read = 0; BlockVector::const_iterator iter = m_blocks.begin(); while (iter != m_blocks.end() && bytes_read != n) { bytes_read += (*iter)->Copy(data + bytes_read, n - bytes_read); iter++; } return bytes_read; } /** * Remove the first n bytes from the buffer */ void IOQueue::Pop(unsigned int n) { unsigned int bytes_popped = 0; BlockVector::iterator iter = m_blocks.begin(); while (iter != m_blocks.end() && bytes_popped != n) { MemoryBlock *block = *iter; bytes_popped += block->PopFront(n - bytes_popped); if (block->Empty()) { m_pool->Release(block); iter = m_blocks.erase(iter); } else { iter++; } } } /** * Return this IOQueue as an array of IOVec structures. * Note: The IOVec array points at internal memory structures. This array is * invalidated when any non-const methods are called (Append, Pop etc.) * * Is the IOQueue is empty, this will return NULL and set iocnt to 0. * * Use FreeIOVec() to release the IOVec array. */ const struct IOVec *IOQueue::AsIOVec(int *iocnt) const { if (m_blocks.empty()) { *iocnt = 0; return NULL; } int max_number_of_blocks = m_blocks.size(); int number_of_blocks = 0; struct IOVec *vector = new struct IOVec[max_number_of_blocks]; struct IOVec *ptr = vector; BlockVector::const_iterator iter = m_blocks.begin(); for (; iter != m_blocks.end(); ++iter, ++ptr, number_of_blocks++) { ptr->iov_base = (*iter)->Data(); ptr->iov_len = (*iter)->Size(); } *iocnt = number_of_blocks; return vector; } /** * Append an MemoryBlock to this queue. This may leave a hole in the last block * before this method was called, but that's unavoidable without copying (which * we don't want to do). */ void IOQueue::AppendBlock(class MemoryBlock *block) { m_blocks.push_back(block); } void IOQueue::AppendMove(IOQueue *other) { BlockVector::const_iterator iter = other->m_blocks.begin(); for (; iter != other->m_blocks.end(); ++iter) { m_blocks.push_back(*iter); } other->m_blocks.clear(); } /** * Remove all data from the IOQueue. */ void IOQueue::Clear() { BlockVector::iterator iter = m_blocks.begin(); for (; iter != m_blocks.end(); ++iter) m_pool->Release(*iter); m_blocks.clear(); } void IOQueue::Purge() { m_pool->Purge(); } /** * Dump this IOQueue as a human readable string */ void IOQueue::Dump(std::ostream *output) { // For now just alloc memory for the entire thing unsigned int length = Size(); uint8_t *tmp = new uint8_t[length]; length = Peek(tmp, length); ola::FormatData(output, tmp, length); delete[] tmp; } /** * Append another block. */ void IOQueue::AppendBlock() { MemoryBlock *block = m_pool->Allocate(); if (!block) { OLA_FATAL << "Failed to allocate block, we're out of memory!"; } m_blocks.push_back(block); } } // namespace io } // namespace ola ola-0.10.5.nojsmin/common/io/OutputStreamTest.cpp0000644000175000017500000000543713023355232021406 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * OutputStreamTest.cpp * Test fixture for the OutputStream class. * Copyright (C) 2012 Simon Newton */ #include #include #include #include #include "ola/Logging.h" #include "ola/io/BigEndianStream.h" #include "ola/io/IOQueue.h" #include "ola/network/NetworkUtils.h" #include "ola/testing/TestUtils.h" using ola::io::IOQueue; using ola::io::BigEndianOutputStream; using ola::network::HostToNetwork; using std::auto_ptr; using std::string; class OutputStreamTest: public CppUnit::TestFixture { public: CPPUNIT_TEST_SUITE(OutputStreamTest); CPPUNIT_TEST(testBasicWrite); CPPUNIT_TEST(testWritePrimatives); CPPUNIT_TEST_SUITE_END(); public: void testBasicWrite(); void testWritePrimatives(); private: IOQueue m_buffer; unsigned int SumLengthOfIOVec(const struct IOVec *iov, int iocnt); }; CPPUNIT_TEST_SUITE_REGISTRATION(OutputStreamTest); /* * Check that basic appending works. */ void OutputStreamTest::testBasicWrite() { BigEndianOutputStream stream(&m_buffer); OLA_ASSERT_EQ(0u, m_buffer.Size()); uint8_t data1[] = {0, 1, 2, 3, 4}; stream.Write(data1, sizeof(data1)); OLA_ASSERT_EQ(5u, m_buffer.Size()); m_buffer.Pop(1); OLA_ASSERT_EQ(4u, m_buffer.Size()); m_buffer.Pop(4); OLA_ASSERT_EQ(0u, m_buffer.Size()); } /* * Check that the << operators work */ void OutputStreamTest::testWritePrimatives() { BigEndianOutputStream stream(&m_buffer); OLA_ASSERT_EQ(0u, m_buffer.Size()); stream << 4; OLA_ASSERT_EQ(4u, m_buffer.Size()); stream << (1u << 31); OLA_ASSERT_EQ(8u, m_buffer.Size()); stream << static_cast(10) << static_cast(2400); OLA_ASSERT_EQ(11u, m_buffer.Size()); // confirm this matches what we expect const unsigned int DATA_SIZE = 20; uint8_t *output_data = new uint8_t[DATA_SIZE]; uint8_t data1[] = {0, 0, 0, 4, 0x80, 0, 0, 0, 0xa, 0x9, 0x60}; unsigned int output_size = m_buffer.Peek(output_data, m_buffer.Size()); OLA_ASSERT_DATA_EQUALS(data1, sizeof(data1), output_data, output_size); delete[] output_data; } ola-0.10.5.nojsmin/common/io/SelectServerThreadTest.cpp0000644000175000017500000000602313023355232022460 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SelectServerThreadTest.cpp * Test fixture for the SelectServer class that ensures Execute works * correctly. * Copyright (C) 2011 Simon Newton */ #include #include "ola/testing/TestUtils.h" #include "ola/Callback.h" #include "ola/Logging.h" #include "ola/thread/Thread.h" #include "ola/io/SelectServer.h" #include "ola/network/Socket.h" using ola::io::SelectServer; using ola::network::UDPSocket; using ola::thread::ThreadId; class TestThread: public ola::thread::Thread { public: TestThread(SelectServer *ss, ThreadId ss_thread_id) : m_ss(ss), m_ss_thread_id(ss_thread_id), m_callback_executed(false) { } void *Run() { m_ss->Execute( ola::NewSingleCallback(this, &TestThread::TestCallback)); return NULL; } void TestCallback() { OLA_ASSERT_TRUE( pthread_equal(m_ss_thread_id, ola::thread::Thread::Self())); m_callback_executed = true; m_ss->Terminate(); } bool CallbackRun() const { return m_callback_executed; } private: SelectServer *m_ss; ThreadId m_ss_thread_id; bool m_callback_executed; }; class SelectServerThreadTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(SelectServerThreadTest); CPPUNIT_TEST(testSameThreadCallback); CPPUNIT_TEST(testDifferentThreadCallback); CPPUNIT_TEST_SUITE_END(); public: void testSameThreadCallback(); void testDifferentThreadCallback(); private: SelectServer m_ss; }; CPPUNIT_TEST_SUITE_REGISTRATION(SelectServerThreadTest); /** * Check that a callback from the SelectServer thread executes. */ void SelectServerThreadTest::testSameThreadCallback() { TestThread test_thread(&m_ss, ola::thread::Thread::Self()); m_ss.Execute( ola::NewSingleCallback(&test_thread, &TestThread::TestCallback)); OLA_ASSERT_FALSE(test_thread.CallbackRun()); m_ss.Run(); OLA_ASSERT_TRUE(test_thread.CallbackRun()); } /* * Check that a callback from a different thread is executed in the * SelectServer thread. */ void SelectServerThreadTest::testDifferentThreadCallback() { TestThread test_thread(&m_ss, ola::thread::Thread::Self()); test_thread.Start(); OLA_ASSERT_FALSE(test_thread.CallbackRun()); m_ss.Run(); test_thread.Join(); OLA_ASSERT_TRUE(test_thread.CallbackRun()); } ola-0.10.5.nojsmin/common/io/ExtendedSerial.cpp0000644000175000017500000000500213023355232020756 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * ExtendedSerial.cpp * The DMX through a UART plugin for ola * Copyright (C) 2011 Rui Barreiros * Copyright (C) 2014 Richard Ash */ #include "ola/io/ExtendedSerial.h" #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #include #include #ifdef HAVE_STROPTS_H // this provides ioctl() definition without conflicting with asm/termios.h #include #endif // HAVE_STROPTS_H #ifdef HAVE_ASM_TERMIOS_H // use this not standard termios for custom baud rates // // On mips architectures, sets some cpp macros which cause // (included by , used by ) to not define // ERANGE, EDOM, or EILSEQ, causing a spectacular compile failure there. // // Explicitly include now to avoid the issue. #include #include #endif // HAVE_ASM_TERMIOS_H #include namespace ola { namespace io { bool LinuxHelper::SetDmxBaud(int fd) { #if defined(HAVE_STROPTS_H) && defined(HAVE_TERMIOS2) static const int rate = 250000; struct termios2 tio; // linux-specific terminal stuff if (ioctl(fd, TCGETS2, &tio) < 0) { return false; } tio.c_cflag &= ~CBAUD; tio.c_cflag |= BOTHER; tio.c_ispeed = rate; tio.c_ospeed = rate; // set custom speed directly if (ioctl(fd, TCSETS2, &tio) < 0) { return false; } if (LogLevel() >= OLA_LOG_INFO) { if (ioctl(fd, TCGETS2, &tio) < 0) { OLA_INFO << "Error getting altered settings from port"; } else { OLA_INFO << "Port speeds for " << fd << " are " << tio.c_ispeed << " in and " << tio.c_ospeed << " out"; } } return true; #else return false; (void) fd; #endif // defined(HAVE_STROPTS_H) && defined(HAVE_TERMIOS2) } } // namespace io } // namespace ola ola-0.10.5.nojsmin/common/io/SelectPoller.cpp0000644000175000017500000003154613023355232020467 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SelectPoller.cpp * A Poller which uses select() * Copyright (C) 2013 Simon Newton */ #ifdef _WIN32 // Pull in fd_set and related definitions. #include #endif // _WIN32 #include "common/io/SelectPoller.h" #include #include #include #include #include #include #include #include "ola/Clock.h" #include "ola/Logging.h" #include "ola/base/Macro.h" #include "ola/io/Descriptor.h" #include "ola/stl/STLUtils.h" namespace ola { namespace io { using std::pair; using std::map; using std::string; /** * @brief Insert a descriptor into one of the descriptor maps. * @param descriptor_map the descriptor_map to insert into. * @param fd the FD to use as the key * @param value the value to associate with the key * @param type the name of the map, used for logging if the fd already exists * in the map. * @returns true if the descriptor was inserted, false if it was already in the * map. * * There are three possibilities: * - The fd does not already exist in the map * - The fd exists and the value is NULL. * - The fd exists and is not NULL. */ template bool InsertIntoDescriptorMap(map *descriptor_map, int fd, T *value, const string &type) { typedef map MapType; pair p = descriptor_map->insert( typename MapType::value_type(fd, value)); if (!p.second) { // already in map if (p.first->second == NULL) { p.first->second = value; } else { OLA_WARN << "FD " << fd << " was already in the " << type << " descriptor map: " << p.first->second << " : " << value; return false; } } return true; } /** * @brief Remove a FD from a descriptor map by setting the value to NULL. * @returns true if the FD was removed from the map, false if it didn't exist * in the map. */ template bool RemoveFromDescriptorMap(map *descriptor_map, int fd) { T **ptr = STLFind(descriptor_map, fd); if (ptr) { *ptr = NULL; return true; } return false; } SelectPoller::SelectPoller(ExportMap *export_map, Clock* clock) : m_export_map(export_map), m_loop_iterations(NULL), m_loop_time(NULL), m_clock(clock) { if (m_export_map) { m_loop_time = m_export_map->GetCounterVar(K_LOOP_TIME); m_loop_iterations = m_export_map->GetCounterVar(K_LOOP_COUNT); } } SelectPoller::~SelectPoller() { ConnectedDescriptorMap::iterator iter = m_connected_read_descriptors.begin(); for (; iter != m_connected_read_descriptors.end(); ++iter) { if (iter->second) { if (iter->second->delete_on_close) { delete iter->second->descriptor; } delete iter->second; } } m_read_descriptors.clear(); m_connected_read_descriptors.clear(); m_write_descriptors.clear(); } bool SelectPoller::AddReadDescriptor(class ReadFileDescriptor *descriptor) { if (!descriptor->ValidReadDescriptor()) { OLA_WARN << "AddReadDescriptor called with invalid descriptor"; return false; } return InsertIntoDescriptorMap(&m_read_descriptors, descriptor->ReadDescriptor(), descriptor, "read"); } bool SelectPoller::AddReadDescriptor(class ConnectedDescriptor *descriptor, bool delete_on_close) { if (!descriptor->ValidReadDescriptor()) { OLA_WARN << "AddReadDescriptor called with invalid descriptor"; return false; } connected_descriptor_t *cd = new connected_descriptor_t(); cd->descriptor = descriptor; cd->delete_on_close = delete_on_close; bool ok = InsertIntoDescriptorMap(&m_connected_read_descriptors, descriptor->ReadDescriptor(), cd, "connected"); if (!ok) { delete cd; } return ok; } bool SelectPoller::RemoveReadDescriptor(class ReadFileDescriptor *descriptor) { if (!descriptor->ValidReadDescriptor()) { OLA_WARN << "Removing an invalid ReadDescriptor"; return false; } return RemoveFromDescriptorMap(&m_read_descriptors, descriptor->ReadDescriptor()); } bool SelectPoller::RemoveReadDescriptor(class ConnectedDescriptor *descriptor) { if (!descriptor->ValidReadDescriptor()) { OLA_WARN << "Removing an invalid ConnectedDescriptor"; return false; } connected_descriptor_t **ptr = STLFind( &m_connected_read_descriptors, descriptor->ReadDescriptor()); if (ptr && *ptr) { delete *ptr; *ptr = NULL; return true; } return false; } bool SelectPoller::AddWriteDescriptor(class WriteFileDescriptor *descriptor) { if (!descriptor->ValidWriteDescriptor()) { OLA_WARN << "AddWriteDescriptor called with invalid descriptor"; return false; } return InsertIntoDescriptorMap(&m_write_descriptors, descriptor->WriteDescriptor(), descriptor, "write"); } bool SelectPoller::RemoveWriteDescriptor( class WriteFileDescriptor *descriptor) { if (!descriptor->ValidWriteDescriptor()) { OLA_WARN << "Removing an invalid WriteDescriptor"; return false; } return RemoveFromDescriptorMap(&m_write_descriptors, descriptor->WriteDescriptor()); } bool SelectPoller::Poll(TimeoutManager *timeout_manager, const TimeInterval &poll_interval) { int maxsd; fd_set r_fds, w_fds; TimeStamp now; TimeInterval sleep_interval = poll_interval; struct timeval tv; maxsd = 0; FD_ZERO(&r_fds); FD_ZERO(&w_fds); m_clock->CurrentTime(&now); TimeInterval next_event_in = timeout_manager->ExecuteTimeouts(&now); if (!next_event_in.IsZero()) { sleep_interval = std::min(next_event_in, sleep_interval); } // Adding descriptors should be the last thing we do, they may have changed // due to timeouts above. bool closed_descriptors = AddDescriptorsToSet(&r_fds, &w_fds, &maxsd); // If there are closed descriptors, set the timeout to something // very small (1ms). This ensures we at least make a pass through the // descriptors. if (closed_descriptors) { sleep_interval = std::min(sleep_interval, TimeInterval(0, 1000)); } // take care of stats accounting if (m_wake_up_time.IsSet()) { TimeInterval loop_time = now - m_wake_up_time; OLA_DEBUG << "ss process time was " << loop_time.ToString(); if (m_loop_time) (*m_loop_time) += loop_time.AsInt(); if (m_loop_iterations) (*m_loop_iterations)++; } sleep_interval.AsTimeval(&tv); switch (select(maxsd + 1, &r_fds, &w_fds, NULL, &tv)) { case 0: // timeout m_clock->CurrentTime(&m_wake_up_time); timeout_manager->ExecuteTimeouts(&m_wake_up_time); if (closed_descriptors) { // there were closed descriptors before the select() we need to deal // with them. FD_ZERO(&r_fds); FD_ZERO(&w_fds); CheckDescriptors(&r_fds, &w_fds); } return true; case -1: if (errno == EINTR) return true; OLA_WARN << "select() error, " << strerror(errno); return false; default: m_clock->CurrentTime(&m_wake_up_time); CheckDescriptors(&r_fds, &w_fds); m_clock->CurrentTime(&m_wake_up_time); timeout_manager->ExecuteTimeouts(&m_wake_up_time); } return true; } /* * Add all the descriptors to the FD_SET. * @returns true if there are descriptors that have been closed. * * This also takes care of removing any entries from the maps where the value * is NULL. This is safe because we don't execute any callbacks from within * this method. */ bool SelectPoller::AddDescriptorsToSet(fd_set *r_set, fd_set *w_set, int *max_sd) { bool closed_descriptors = false; ReadDescriptorMap::iterator iter = m_read_descriptors.begin(); while (iter != m_read_descriptors.end()) { ReadDescriptorMap::iterator this_iter = iter; iter++; ReadFileDescriptor *descriptor = this_iter->second; if (!descriptor) { // This one was removed. m_read_descriptors.erase(this_iter); continue; } if (descriptor->ValidReadDescriptor()) { *max_sd = std::max(*max_sd, descriptor->ReadDescriptor()); FD_SET(descriptor->ReadDescriptor(), r_set); } else { // The descriptor was probably closed without removing it from the select // server if (m_export_map) { (*m_export_map->GetIntegerVar(K_READ_DESCRIPTOR_VAR))--; } m_read_descriptors.erase(this_iter); OLA_WARN << "Removed a inactive descriptor from the select server"; } } ConnectedDescriptorMap::iterator con_iter = m_connected_read_descriptors.begin(); while (con_iter != m_connected_read_descriptors.end()) { ConnectedDescriptorMap::iterator this_iter = con_iter; con_iter++; if (!this_iter->second) { // This one was removed. m_connected_read_descriptors.erase(this_iter); continue; } if (this_iter->second->descriptor->ValidReadDescriptor()) { *max_sd = std::max( *max_sd, this_iter->second->descriptor->ReadDescriptor()); FD_SET(this_iter->second->descriptor->ReadDescriptor(), r_set); } else { closed_descriptors = true; } } WriteDescriptorMap::iterator write_iter = m_write_descriptors.begin(); while (write_iter != m_write_descriptors.end()) { WriteDescriptorMap::iterator this_iter = write_iter; write_iter++; WriteFileDescriptor *descriptor = this_iter->second; if (!descriptor) { // This one was removed. m_write_descriptors.erase(this_iter); continue; } if (descriptor->ValidWriteDescriptor()) { *max_sd = std::max(*max_sd, descriptor->WriteDescriptor()); FD_SET(descriptor->WriteDescriptor(), w_set); } else { // The descriptor was probably closed without removing it from the select // server if (m_export_map) { (*m_export_map->GetIntegerVar(K_WRITE_DESCRIPTOR_VAR))--; } m_write_descriptors.erase(this_iter); OLA_WARN << "Removed a disconnected descriptor from the select server"; } } return closed_descriptors; } /* * Check all the registered descriptors: * - Execute the callback for descriptors with data * - Excute OnClose if a remote end closed the connection */ void SelectPoller::CheckDescriptors(fd_set *r_set, fd_set *w_set) { // Remember the add / remove methods above may be called during // PerformRead(), PerformWrite() or the on close handler. Our iterators are // safe because we only ever call erase from within AddDescriptorsToSet(), // which isn't called from any of the Add / Remove methods. ReadDescriptorMap::iterator iter = m_read_descriptors.begin(); for (; iter != m_read_descriptors.end(); ++iter) { if (iter->second && FD_ISSET(iter->second->ReadDescriptor(), r_set)) { iter->second->PerformRead(); } } ConnectedDescriptorMap::iterator con_iter = m_connected_read_descriptors.begin(); for (; con_iter != m_connected_read_descriptors.end(); ++con_iter) { if (!con_iter->second) { continue; } connected_descriptor_t *cd = con_iter->second; ConnectedDescriptor *descriptor = cd->descriptor; bool closed = false; if (!descriptor->ValidReadDescriptor()) { closed = true; } else if (FD_ISSET(descriptor->ReadDescriptor(), r_set)) { if (descriptor->IsClosed()) { closed = true; } else { descriptor->PerformRead(); } } if (closed) { ConnectedDescriptor::OnCloseCallback *on_close = descriptor->TransferOnClose(); bool delete_on_close = cd->delete_on_close; delete con_iter->second; con_iter->second = NULL; if (m_export_map) { (*m_export_map->GetIntegerVar(K_CONNECTED_DESCRIPTORS_VAR))--; } if (on_close) on_close->Run(); if (delete_on_close) delete descriptor; } } // Check the write sockets. These may have changed since the start of the // method due to running callbacks. WriteDescriptorMap::iterator write_iter = m_write_descriptors.begin(); for (; write_iter != m_write_descriptors.end(); write_iter++) { if (write_iter->second && FD_ISSET(write_iter->second->WriteDescriptor(), w_set)) { write_iter->second->PerformWrite(); } } } } // namespace io } // namespace ola ola-0.10.5.nojsmin/common/io/EPoller.h0000644000175000017500000000650713023355232017100 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * EPoller.h * A Poller which uses epoll() * Copyright (C) 2013 Simon Newton */ #ifndef COMMON_IO_EPOLLER_H_ #define COMMON_IO_EPOLLER_H_ #include #include #include #include #include #include #include #include #include #include #include "common/io/PollerInterface.h" #include "common/io/TimeoutManager.h" namespace ola { namespace io { class EPollData; /** * @class EPoller * @brief An implementation of PollerInterface that uses epoll(). * * epoll() is more efficient than select() but only newer Linux systems support * it. */ class EPoller : public PollerInterface { public : /** * @brief Create a new EPoller. * @param export_map the ExportMap to use * @param clock the Clock to use */ EPoller(ExportMap *export_map, Clock *clock); ~EPoller(); bool AddReadDescriptor(class ReadFileDescriptor *descriptor); bool AddReadDescriptor(class ConnectedDescriptor *descriptor, bool delete_on_close); bool RemoveReadDescriptor(class ReadFileDescriptor *descriptor); bool RemoveReadDescriptor(class ConnectedDescriptor *descriptor); bool AddWriteDescriptor(class WriteFileDescriptor *descriptor); bool RemoveWriteDescriptor(class WriteFileDescriptor *descriptor); const TimeStamp *WakeUpTime() const { return &m_wake_up_time; } bool Poll(TimeoutManager *timeout_manager, const TimeInterval &poll_interval); private: typedef std::map DescriptorMap; typedef std::vector DescriptorList; DescriptorMap m_descriptor_map; // EPoller is re-enterant. Remove may be called while we hold a pointer to an // EPollData. To avoid deleting data out from underneath ourselves, we // instead move the removed descriptors to this list and then clean them up // outside the callback loop. DescriptorList m_orphaned_descriptors; // A list of pre-allocated descriptors we can use. DescriptorList m_free_descriptors; ExportMap *m_export_map; CounterVariable *m_loop_iterations; CounterVariable *m_loop_time; int m_epoll_fd; Clock *m_clock; TimeStamp m_wake_up_time; std::pair LookupOrCreateDescriptor(int fd); bool RemoveDescriptor(int fd, int event, bool warn_on_missing); void CheckDescriptor(struct epoll_event *event, EPollData *descriptor); static const int MAX_EVENTS; static const int READ_FLAGS; static const unsigned int MAX_FREE_DESCRIPTORS; DISALLOW_COPY_AND_ASSIGN(EPoller); }; } // namespace io } // namespace ola #endif // COMMON_IO_EPOLLER_H_ ola-0.10.5.nojsmin/common/io/MemoryBlockTest.cpp0000644000175000017500000000752613023355232021156 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * MemoryBlockTest.cpp * Test fixture for the IOQueue class. * Copyright (C) 2012 Simon Newton */ #include #include #include #include "ola/Logging.h" #include "ola/base/Array.h" #include "ola/io/MemoryBlock.h" #include "ola/testing/TestUtils.h" using ola::io::MemoryBlock; class MemoryBlockTest: public CppUnit::TestFixture { public: CPPUNIT_TEST_SUITE(MemoryBlockTest); CPPUNIT_TEST(testAppend); CPPUNIT_TEST(testPrepend); CPPUNIT_TEST_SUITE_END(); public: void testAppend(); void testPrepend(); }; CPPUNIT_TEST_SUITE_REGISTRATION(MemoryBlockTest); /* * Check that basic appending works. */ void MemoryBlockTest::testAppend() { unsigned int size = 100; uint8_t *data = new uint8_t[size]; MemoryBlock block(data, size); OLA_ASSERT_EQ(0u, block.Size()); OLA_ASSERT_EQ(size, block.Capacity()); OLA_ASSERT_EQ(size, block.Remaining()); OLA_ASSERT_TRUE(block.Empty()); OLA_ASSERT_EQ(data, block.Data()); // append 4 bytes const uint8_t data1[] = {1, 2, 3, 4}; block.Append(data1, arraysize(data1)); OLA_ASSERT_EQ(static_cast(arraysize(data1)), block.Size()); OLA_ASSERT_EQ(size - static_cast(arraysize(data1)), block.Remaining()); OLA_ASSERT_FALSE(block.Empty()); OLA_ASSERT_DATA_EQUALS(data1, arraysize(data1), block.Data(), block.Size()); // pop 1 byte OLA_ASSERT_EQ(1u, block.PopFront(1)); OLA_ASSERT_EQ(3u, block.Size()); // popping doesn't change the location of the data in the memory block. OLA_ASSERT_EQ(96u, block.Remaining()); OLA_ASSERT_FALSE(block.Empty()); OLA_ASSERT_DATA_EQUALS(data1 + 1, arraysize(data1) - 1, block.Data(), block.Size()); // try to pop more data than exists OLA_ASSERT_EQ(3u, block.PopFront(5)); OLA_ASSERT_EQ(0u, block.Size()); // now that all data is removed, the block should reset OLA_ASSERT_EQ(100u, block.Remaining()); OLA_ASSERT_TRUE(block.Empty()); } /* * Check that basic prepending works. */ void MemoryBlockTest::testPrepend() { unsigned int size = 100; uint8_t *data = new uint8_t[size]; MemoryBlock block(data, size); // by default the insertion point is at the begining const uint8_t data1[] = {1, 2, 3, 4}; OLA_ASSERT_EQ(0u, block.Prepend(data1, arraysize(data1))); // seek block.SeekBack(); OLA_ASSERT_EQ(4u, block.Prepend(data1, arraysize(data1))); OLA_ASSERT_EQ(4u, block.Size()); OLA_ASSERT_EQ(0u, block.Remaining()); OLA_ASSERT_FALSE(block.Empty()); OLA_ASSERT_DATA_EQUALS(data1, arraysize(data1), block.Data(), block.Size()); // pop OLA_ASSERT_EQ(1u, block.PopFront(1)); OLA_ASSERT_EQ(3u, block.Size()); // popping doesn't change the location of the data in the memory block. OLA_ASSERT_EQ(0u, block.Remaining()); OLA_ASSERT_FALSE(block.Empty()); OLA_ASSERT_DATA_EQUALS(data1 + 1, arraysize(data1) - 1, block.Data(), block.Size()); // try to pop more data than exists OLA_ASSERT_EQ(3u, block.PopFront(5)); OLA_ASSERT_EQ(0u, block.Size()); // now that all data is removed, the block should reset OLA_ASSERT_EQ(100u, block.Remaining()); } ola-0.10.5.nojsmin/common/io/StdinHandler.cpp0000644000175000017500000000410013023355232020433 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * StdinHandler.cpp * Enables reading input from stdin one character at a time. Useful if you want * to create a simple interactive interface for programs. * Copyright (C) 2012 Simon Newton */ #ifndef _WIN32 #include #endif // _WIN32 #include #include #include namespace ola { namespace io { StdinHandler::StdinHandler(SelectServerInterface *ss, InputCallback *callback) #ifdef _WIN32 : m_stdin_descriptor(0), #else : m_stdin_descriptor(STDIN_FILENO), #endif // _WIN32 m_ss(ss), m_callback(callback) { m_stdin_descriptor.SetOnData( ola::NewCallback(this, &StdinHandler::HandleData)); // turn off buffering #ifdef _WIN32 setbuf(stdin, NULL); #else tcgetattr(STDIN_FILENO, &m_old_tc); termios new_tc = m_old_tc; new_tc.c_lflag &= static_cast(~ICANON & ~ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &new_tc); #endif // _WIN32 // Add to the SelectServer m_ss->AddReadDescriptor(&m_stdin_descriptor); } StdinHandler::~StdinHandler() { m_ss->RemoveReadDescriptor(&m_stdin_descriptor); #ifndef _WIN32 tcsetattr(STDIN_FILENO, TCSANOW, &m_old_tc); #endif // !_WIN32 } void StdinHandler::HandleData() { int c = getchar(); if (m_callback.get()) { m_callback->Run(c); } } } // namespace io } // namespace ola ola-0.10.5.nojsmin/common/rdm/0000755000175000017500000000000013155164170015535 5ustar wouterwouterola-0.10.5.nojsmin/common/rdm/SubDeviceDispatcher.cpp0000644000175000017500000001134313023355232022116 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SubDeviceDispatcher.cpp * Handles dispatching RDM requests to the correct sub device. * Copyright (C) 2013 Simon Newton */ #include #include #include #include #include "ola/Logging.h" #include "ola/rdm/SubDeviceDispatcher.h" #include "ola/stl/STLUtils.h" namespace ola { namespace rdm { using std::string; using std::vector; /** * Add or remove a sub device. Ownership of the device is not transferred. */ void SubDeviceDispatcher::AddSubDevice(uint16_t sub_device_number, RDMControllerInterface *device) { if (sub_device_number != ROOT_RDM_DEVICE) { STLReplace(&m_subdevices, sub_device_number, device); } else { OLA_WARN << "SubDeviceDispatcher does not accept Root Devices"; } } /* * Handle an RDM Request */ void SubDeviceDispatcher::SendRDMRequest(RDMRequest *request, RDMCallback *callback) { if (request->SubDevice() == ALL_RDM_SUBDEVICES) { FanOutToSubDevices(request, callback); } else { RDMControllerInterface *sub_device = STLFindOrNull( m_subdevices, request->SubDevice()); if (sub_device) { sub_device->SendRDMRequest(request, callback); } else { NackIfNotBroadcast(request, callback, NR_SUB_DEVICE_OUT_OF_RANGE); } } } /** * Handle commands sent to the SUB_DEVICE_ALL_CALL target. */ void SubDeviceDispatcher::FanOutToSubDevices( const RDMRequest *request, RDMCallback *callback) { // GETs to the all subdevices don't make any sense. // Section 9.2.2 if (request->CommandClass() == RDMCommand::GET_COMMAND) { NackIfNotBroadcast(request, callback, NR_SUB_DEVICE_OUT_OF_RANGE); return; } // Fan out to all sub devices but don't include the root device if (m_subdevices.empty()) { RunRDMCallback(callback, RDM_WAS_BROADCAST); } else { SubDeviceMap::iterator iter = m_subdevices.begin(); FanOutTracker *tracker = new FanOutTracker(m_subdevices.size(), callback); for (; iter != m_subdevices.end(); ++iter) { iter->second->SendRDMRequest( request->Duplicate(), NewSingleCallback(this, &SubDeviceDispatcher::HandleSubDeviceResponse, tracker)); } } } /** * Respond with a NACK, or RDM_WAS_BROADCAST. * Takes ownership of the request object. */ void SubDeviceDispatcher::NackIfNotBroadcast( const RDMRequest *request_ptr, RDMCallback *callback, rdm_nack_reason nack_reason) { std::auto_ptr request(request_ptr); if (request->DestinationUID().IsBroadcast()) { RunRDMCallback(callback, RDM_WAS_BROADCAST); } else { RDMReply reply(RDM_COMPLETED_OK, NackWithReason(request.get(), nack_reason)); callback->Run(&reply); } } /** * Called when a subdevice returns during a ALL_RDM_SUBDEVICES call. */ void SubDeviceDispatcher::HandleSubDeviceResponse(FanOutTracker *tracker, RDMReply *reply) { if (tracker->NumResponses() == 0) { tracker->SetResponse(reply->StatusCode(), reply->Response()->Duplicate()); } if (tracker->IncrementAndCheckIfComplete()) { // now it's not really clear what we're supposed to return here. // We do the least crazy thing, which is to return the root device response. tracker->RunCallback(); delete tracker; } } SubDeviceDispatcher::FanOutTracker::FanOutTracker( uint16_t number_of_subdevices, RDMCallback *callback) : m_number_of_subdevices(number_of_subdevices), m_responses_so_far(0), m_callback(callback), m_status_code(RDM_COMPLETED_OK), m_response(NULL) { } void SubDeviceDispatcher::FanOutTracker::SetResponse( RDMStatusCode code, RDMResponse *response) { m_status_code = code; m_response = response; } void SubDeviceDispatcher::FanOutTracker::RunCallback() { if (m_callback) { RDMReply reply(m_status_code, m_response); m_callback->Run(&reply); } m_callback = NULL; } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/QueueingRDMControllerTest.cpp0000644000175000017500000006112713023355232023274 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * QueueingRDMControllerTest.cpp * Test fixture for the UID classes * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include #include "ola/Logging.h" #include "ola/base/Array.h" #include "ola/Callback.h" #include "ola/rdm/UID.h" #include "ola/rdm/UIDSet.h" #include "ola/rdm/RDMControllerInterface.h" #include "ola/rdm/QueueingRDMController.h" #include "ola/testing/TestUtils.h" using ola::NewSingleCallback; using ola::rdm::ACK_OVERFLOW; using ola::rdm::RDMCallback; using ola::rdm::RDMDiscoveryCallback; using ola::rdm::RDMFrame; using ola::rdm::RDMFrames; using ola::rdm::RDMGetResponse; using ola::rdm::RDMReply; using ola::rdm::RDMRequest; using ola::rdm::RDMResponse; using ola::rdm::RDM_ACK; using ola::rdm::UID; using ola::rdm::UIDSet; using std::auto_ptr; using std::string; using std::vector; RDMRequest *NewGetRequest(const UID &source, const UID &destination) { return new ola::rdm::RDMGetRequest(source, destination, 0, // transaction # 1, // port id 10, // sub device 296, // param id NULL, // data 0); // data length } RDMResponse *NewGetResponse(const UID &source, const UID &destination) { return new RDMGetResponse(source, destination, 0, // transaction # RDM_ACK, 0, // message count 10, // sub device 296, // param id NULL, // data 0); // data length } class QueueingRDMControllerTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(QueueingRDMControllerTest); CPPUNIT_TEST(testSendAndReceive); CPPUNIT_TEST(testDelayedSendAndReceive); CPPUNIT_TEST(testAckOverflows); CPPUNIT_TEST(testPauseAndResume); CPPUNIT_TEST(testQueueOverflow); CPPUNIT_TEST(testDiscovery); CPPUNIT_TEST(testMultipleDiscovery); CPPUNIT_TEST(testReentrantDiscovery); CPPUNIT_TEST(testRequestAndDiscovery); CPPUNIT_TEST_SUITE_END(); public: QueueingRDMControllerTest() : m_source(1, 2), m_destination(3, 4), m_discovery_complete_count(0) { } void testSendAndReceive(); void testDelayedSendAndReceive(); void testAckOverflows(); void testPauseAndResume(); void testQueueOverflow(); void testDiscovery(); void testMultipleDiscovery(); void testReentrantDiscovery(); void testRequestAndDiscovery(); void VerifyResponse(RDMReply *expected_reply, RDMReply *reply) { OLA_ASSERT_EQ(*expected_reply, *reply); } void VerifyDiscoveryComplete(UIDSet *expected_uids, const UIDSet &uids) { OLA_ASSERT_EQ(*expected_uids, uids); m_discovery_complete_count++; } void ReentrantDiscovery( ola::rdm::DiscoverableQueueingRDMController *controller, UIDSet *expected_uids, const UIDSet &uids); private: UID m_source; UID m_destination; int m_discovery_complete_count; static const uint8_t MOCK_FRAME_DATA[]; static const uint8_t MOCK_FRAME_DATA2[]; }; const uint8_t QueueingRDMControllerTest::MOCK_FRAME_DATA[] = { 1, 2, 3, 4 }; const uint8_t QueueingRDMControllerTest::MOCK_FRAME_DATA2[] = { 5, 6, 7, 8 }; CPPUNIT_TEST_SUITE_REGISTRATION(QueueingRDMControllerTest); /** * The MockRDMController, used to verify the behaviour */ class MockRDMController: public ola::rdm::DiscoverableRDMControllerInterface { public: MockRDMController() : m_rdm_callback(NULL), m_discovery_callback(NULL) { } void SendRDMRequest(RDMRequest *request, RDMCallback *on_complete); void ExpectCallAndCapture(RDMRequest *request); /* * Takes ownership of reply. */ void ExpectCallAndReplyWith(RDMRequest *request, RDMReply *reply); void AddExpectedDiscoveryCall(bool full, const UIDSet *uids); void RunFullDiscovery(RDMDiscoveryCallback *callback); void RunIncrementalDiscovery(RDMDiscoveryCallback *callback); void RunRDMCallback(RDMReply *reply); void RunDiscoveryCallback(const UIDSet &uids); void Verify(); private: typedef struct { RDMRequest *request; RDMReply *reply; bool run_callback; } expected_call; typedef struct { bool full; const UIDSet *uids; } expected_discovery_call; std::queue m_expected_calls; std::queue m_expected_discover_calls; RDMCallback *m_rdm_callback; RDMDiscoveryCallback *m_discovery_callback; }; void MockRDMController::SendRDMRequest(RDMRequest *request, RDMCallback *on_complete) { OLA_ASSERT_TRUE(m_expected_calls.size()); expected_call call = m_expected_calls.front(); m_expected_calls.pop(); OLA_ASSERT_TRUE(*call.request == *request); delete request; if (call.run_callback) { on_complete->Run(call.reply); delete call.reply; } else { OLA_ASSERT_FALSE(m_rdm_callback); m_rdm_callback = on_complete; } } void MockRDMController::RunFullDiscovery(RDMDiscoveryCallback *callback) { OLA_ASSERT_TRUE(m_expected_discover_calls.size()); expected_discovery_call call = m_expected_discover_calls.front(); m_expected_discover_calls.pop(); OLA_ASSERT_TRUE(call.full); if (call.uids) { callback->Run(*call.uids); } else { OLA_ASSERT_FALSE(m_discovery_callback); m_discovery_callback = callback; } } void MockRDMController::RunIncrementalDiscovery( RDMDiscoveryCallback *callback) { OLA_ASSERT_TRUE(m_expected_discover_calls.size()); expected_discovery_call call = m_expected_discover_calls.front(); m_expected_discover_calls.pop(); OLA_ASSERT_FALSE(call.full); if (call.uids) { callback->Run(*call.uids); } else { OLA_ASSERT_FALSE(m_discovery_callback); m_discovery_callback = callback; } } void MockRDMController::ExpectCallAndCapture(RDMRequest *request) { expected_call call = { request, NULL, false, }; m_expected_calls.push(call); } void MockRDMController::ExpectCallAndReplyWith(RDMRequest *request, RDMReply *reply) { expected_call call = { request, reply, true, }; m_expected_calls.push(call); } void MockRDMController::AddExpectedDiscoveryCall(bool full, const UIDSet *uids) { expected_discovery_call call = { full, uids, }; m_expected_discover_calls.push(call); } /** * Run the current RDM callback */ void MockRDMController::RunRDMCallback(RDMReply *reply) { OLA_ASSERT_TRUE(m_rdm_callback); RDMCallback *callback = m_rdm_callback; m_rdm_callback = NULL; callback->Run(reply); } /** * Run the current discovery callback */ void MockRDMController::RunDiscoveryCallback(const UIDSet &uids) { OLA_ASSERT_TRUE(m_discovery_callback); RDMDiscoveryCallback *callback = m_discovery_callback; m_discovery_callback = NULL; callback->Run(uids); } /** * Verify no expected calls remain */ void MockRDMController::Verify() { OLA_ASSERT_EQ(static_cast(0), m_expected_calls.size()); OLA_ASSERT_EQ(static_cast(0), m_expected_discover_calls.size()); } void QueueingRDMControllerTest::ReentrantDiscovery( ola::rdm::DiscoverableQueueingRDMController *controller, UIDSet *expected_uids, const UIDSet &uids) { OLA_ASSERT_EQ(*expected_uids, uids); m_discovery_complete_count++; controller->RunFullDiscovery( NewSingleCallback( this, &QueueingRDMControllerTest::VerifyDiscoveryComplete, expected_uids)); } /* * Check that sending RDM commands work. * This runs the RDMCallback immediately. */ void QueueingRDMControllerTest::testSendAndReceive() { MockRDMController mock_controller; ola::rdm::QueueingRDMController controller(&mock_controller, 10); // Some mock frame data. RDMFrame frame(MOCK_FRAME_DATA, arraysize(MOCK_FRAME_DATA)); RDMFrames frames; frames.push_back(frame); // test a simple request/response RDMRequest *get_request = NewGetRequest(m_source, m_destination); RDMReply *expected_reply = new RDMReply( ola::rdm::RDM_COMPLETED_OK, NewGetResponse(m_destination, m_source), frames); mock_controller.ExpectCallAndReplyWith(get_request, expected_reply); controller.SendRDMRequest( get_request, ola::NewSingleCallback( this, &QueueingRDMControllerTest::VerifyResponse, expected_reply)); // check a response where we return ok, but pass a null pointer get_request = NewGetRequest(m_source, m_destination); expected_reply = new RDMReply(ola::rdm::RDM_COMPLETED_OK, NULL, frames); mock_controller.ExpectCallAndReplyWith(get_request, expected_reply); controller.SendRDMRequest( get_request, ola::NewSingleCallback( this, &QueueingRDMControllerTest::VerifyResponse, expected_reply)); // check a failed command get_request = NewGetRequest(m_source, m_destination); expected_reply = new RDMReply(ola::rdm::RDM_FAILED_TO_SEND); mock_controller.ExpectCallAndReplyWith(get_request, expected_reply); controller.SendRDMRequest( get_request, ola::NewSingleCallback( this, &QueueingRDMControllerTest::VerifyResponse, expected_reply)); mock_controller.Verify(); } /* * Check that sending RDM commands work. * This all defer the running of the RDMCallback. */ void QueueingRDMControllerTest::testDelayedSendAndReceive() { MockRDMController mock_controller; ola::rdm::QueueingRDMController controller(&mock_controller, 10); // Some mock frame data. RDMFrame frame(MOCK_FRAME_DATA, arraysize(MOCK_FRAME_DATA)); RDMFrames frames; frames.push_back(frame); // test a simple request/response RDMRequest *get_request = NewGetRequest(m_source, m_destination); mock_controller.ExpectCallAndCapture(get_request); RDMReply expected_reply( ola::rdm::RDM_COMPLETED_OK, NewGetResponse(m_destination, m_source), frames); controller.SendRDMRequest( get_request, ola::NewSingleCallback( this, &QueueingRDMControllerTest::VerifyResponse, &expected_reply)); // now run the callback mock_controller.RunRDMCallback(&expected_reply); mock_controller.Verify(); } /* * Check that overflow sequences work. */ void QueueingRDMControllerTest::testAckOverflows() { MockRDMController mock_controller; ola::rdm::QueueingRDMController controller(&mock_controller, 10); // Some mock frame data. RDMFrame frame1(MOCK_FRAME_DATA, arraysize(MOCK_FRAME_DATA)); RDMFrame frame2(MOCK_FRAME_DATA2, arraysize(MOCK_FRAME_DATA2)); // test an ack overflow sequence RDMRequest *get_request = NewGetRequest(m_source, m_destination); uint8_t data[] = {0xaa, 0xbb}; RDMGetResponse *response1 = new RDMGetResponse( m_destination, m_source, 0, // transaction # ACK_OVERFLOW, // response type 0, // message count 10, // sub device 296, // param id data, // data 1); // data length RDMGetResponse *response2 = new RDMGetResponse( m_destination, m_source, 0, // transaction # RDM_ACK, // response type 0, // message count 10, // sub device 296, // param id data + 1, // data 1); // data length RDMGetResponse *expected_response = new RDMGetResponse( m_destination, m_source, 0, // transaction # RDM_ACK, // response type 0, // message count 10, // sub device 296, // param id data, // data 2); // data length RDMFrames frames1; frames1.push_back(frame1); RDMFrames frames2; frames2.push_back(frame2); mock_controller.ExpectCallAndReplyWith( get_request, new RDMReply(ola::rdm::RDM_COMPLETED_OK, response1, frames1)); mock_controller.ExpectCallAndReplyWith( get_request, new RDMReply(ola::rdm::RDM_COMPLETED_OK, response2, frames2)); RDMFrames expected_frames; expected_frames.push_back(frame1); expected_frames.push_back(frame2); RDMReply expected_reply( ola::rdm::RDM_COMPLETED_OK, expected_response, expected_frames); controller.SendRDMRequest( get_request, ola::NewSingleCallback( this, &QueueingRDMControllerTest::VerifyResponse, &expected_reply)); // now check an broken transaction. We first ACK, the return a timeout get_request = NewGetRequest(m_source, m_destination); RDMReply timeout_reply(ola::rdm::RDM_TIMEOUT); response1 = new RDMGetResponse( m_destination, m_source, 0, // transaction # ACK_OVERFLOW, // response type 0, // message count 10, // sub device 296, // param id data, // data 1); // data length mock_controller.ExpectCallAndReplyWith( get_request, new RDMReply(ola::rdm::RDM_COMPLETED_OK, response1)); mock_controller.ExpectCallAndReplyWith( get_request, new RDMReply(ola::rdm::RDM_TIMEOUT)); controller.SendRDMRequest( get_request, ola::NewSingleCallback( this, &QueueingRDMControllerTest::VerifyResponse, &timeout_reply)); // now test the case where the responses can't be combined get_request = NewGetRequest(m_source, m_destination); response1 = new RDMGetResponse( m_destination, m_source, 0, // transaction # ACK_OVERFLOW, // response type 0, // message count 10, // sub device 296, // param id data, // data 1); // data length response2 = new RDMGetResponse( m_source, m_source, 0, // transaction # RDM_ACK, // response type 0, // message count 10, // sub device 296, // param id data + 1, // data 1); // data length mock_controller.ExpectCallAndReplyWith( get_request, new RDMReply(ola::rdm::RDM_COMPLETED_OK, response1)); mock_controller.ExpectCallAndReplyWith( get_request, new RDMReply(ola::rdm::RDM_COMPLETED_OK, response2)); RDMReply invalid_reply(ola::rdm::RDM_INVALID_RESPONSE); controller.SendRDMRequest( get_request, ola::NewSingleCallback( this, &QueueingRDMControllerTest::VerifyResponse, &invalid_reply)); mock_controller.Verify(); } /* * Verify that pausing works. */ void QueueingRDMControllerTest::testPauseAndResume() { MockRDMController mock_controller; ola::rdm::QueueingRDMController controller(&mock_controller, 10); controller.Pause(); // queue up two requests RDMRequest *get_request1 = NewGetRequest(m_source, m_destination); RDMRequest *get_request2 = NewGetRequest(m_source, m_destination); RDMReply *expected_reply1 = new RDMReply( ola::rdm::RDM_COMPLETED_OK, NewGetResponse(m_destination, m_source)); RDMReply *expected_reply2 = new RDMReply( ola::rdm::RDM_FAILED_TO_SEND); // queue up two requests controller.SendRDMRequest( get_request1, ola::NewSingleCallback( this, &QueueingRDMControllerTest::VerifyResponse, expected_reply1)); controller.SendRDMRequest( get_request2, ola::NewSingleCallback( this, &QueueingRDMControllerTest::VerifyResponse, expected_reply2)); // now resume mock_controller.ExpectCallAndReplyWith(get_request1, expected_reply1); mock_controller.ExpectCallAndReplyWith(get_request2, expected_reply2); controller.Resume(); } /* * Verify that overflowing the queue behaves */ void QueueingRDMControllerTest::testQueueOverflow() { MockRDMController mock_controller; auto_ptr controller( new ola::rdm::QueueingRDMController(&mock_controller, 1)); controller->Pause(); RDMRequest *get_request = NewGetRequest(m_source, m_destination); RDMReply failed_to_send_reply(ola::rdm::RDM_FAILED_TO_SEND); controller->SendRDMRequest( get_request, ola::NewSingleCallback( this, &QueueingRDMControllerTest::VerifyResponse, &failed_to_send_reply)); // this one should overflow the queue get_request = NewGetRequest(m_source, m_destination); controller->SendRDMRequest( get_request, ola::NewSingleCallback( this, &QueueingRDMControllerTest::VerifyResponse, &failed_to_send_reply)); // now because we're paused the first should fail as well when the control // goes out of scope } /* * Verify discovery works */ void QueueingRDMControllerTest::testDiscovery() { MockRDMController mock_controller; auto_ptr controller( new ola::rdm::DiscoverableQueueingRDMController(&mock_controller, 1)); UIDSet uids, uids2; UID uid1(2, 3); UID uid2(10, 11); UID uid3(20, 22); UID uid4(65, 45); uids.AddUID(uid1); uids.AddUID(uid2); uids2.AddUID(uid3); uids2.AddUID(uid4); // trigger discovery, in this case the callback runs immediately. mock_controller.AddExpectedDiscoveryCall(true, &uids); controller->RunFullDiscovery( NewSingleCallback( this, &QueueingRDMControllerTest::VerifyDiscoveryComplete, &uids)); OLA_ASSERT_TRUE(m_discovery_complete_count); m_discovery_complete_count = 0; mock_controller.Verify(); // now test incremental discovery // trigger discovery, in this case the callback runs immediately. mock_controller.AddExpectedDiscoveryCall(false, &uids); controller->RunIncrementalDiscovery( NewSingleCallback( this, &QueueingRDMControllerTest::VerifyDiscoveryComplete, &uids)); OLA_ASSERT_TRUE(m_discovery_complete_count); m_discovery_complete_count = 0; mock_controller.Verify(); // now check the deferred case mock_controller.AddExpectedDiscoveryCall(true, NULL); controller->RunFullDiscovery( NewSingleCallback( this, &QueueingRDMControllerTest::VerifyDiscoveryComplete, &uids2)); mock_controller.Verify(); OLA_ASSERT_FALSE(m_discovery_complete_count); // now run the callback mock_controller.RunDiscoveryCallback(uids2); OLA_ASSERT_TRUE(m_discovery_complete_count); m_discovery_complete_count = 0; mock_controller.Verify(); // now try an incremental that deferrs the callback mock_controller.AddExpectedDiscoveryCall(false, NULL); controller->RunIncrementalDiscovery( NewSingleCallback( this, &QueueingRDMControllerTest::VerifyDiscoveryComplete, &uids2)); mock_controller.Verify(); OLA_ASSERT_FALSE(m_discovery_complete_count); // now run the callback mock_controller.RunDiscoveryCallback(uids2); OLA_ASSERT_TRUE(m_discovery_complete_count); m_discovery_complete_count = 0; mock_controller.Verify(); } /* * Check that attempting a discovery while another is running fails. */ void QueueingRDMControllerTest::testMultipleDiscovery() { MockRDMController mock_controller; auto_ptr controller( new ola::rdm::DiscoverableQueueingRDMController(&mock_controller, 1)); UIDSet uids, uids2; UID uid1(2, 3); UID uid2(10, 11); UID uid3(20, 22); UID uid4(65, 45); uids.AddUID(uid1); uids.AddUID(uid2); uids2.AddUID(uid3); uids2.AddUID(uid4); // trigger discovery, this doesn't run the callback immediately mock_controller.AddExpectedDiscoveryCall(true, NULL); controller->RunFullDiscovery( NewSingleCallback( this, &QueueingRDMControllerTest::VerifyDiscoveryComplete, &uids)); mock_controller.Verify(); OLA_ASSERT_FALSE(m_discovery_complete_count); // trigger discovery again, this should queue the discovery request controller->RunIncrementalDiscovery( NewSingleCallback( this, &QueueingRDMControllerTest::VerifyDiscoveryComplete, &uids2)); mock_controller.Verify(); // and again controller->RunIncrementalDiscovery( NewSingleCallback( this, &QueueingRDMControllerTest::VerifyDiscoveryComplete, &uids2)); mock_controller.Verify(); // return from the first one, this will trigger the second discovery call mock_controller.AddExpectedDiscoveryCall(false, NULL); mock_controller.RunDiscoveryCallback(uids); OLA_ASSERT_TRUE(m_discovery_complete_count); m_discovery_complete_count = 0; mock_controller.Verify(); // now return from the second one, which should complete the 2nd and 3rd // requests mock_controller.RunDiscoveryCallback(uids2); OLA_ASSERT_EQ(2, m_discovery_complete_count); m_discovery_complete_count = 0; mock_controller.Verify(); } /* * Verify reentrant discovery works */ void QueueingRDMControllerTest::testReentrantDiscovery() { MockRDMController mock_controller; auto_ptr controller( new ola::rdm::DiscoverableQueueingRDMController(&mock_controller, 1)); UIDSet uids; UID uid1(2, 3); UID uid2(10, 11); uids.AddUID(uid1); uids.AddUID(uid2); // trigger discovery, the ReentrantDiscovery starts a new discovery from // within the callback of the first. mock_controller.AddExpectedDiscoveryCall(true, NULL); controller->RunFullDiscovery( NewSingleCallback( this, &QueueingRDMControllerTest::ReentrantDiscovery, controller.get(), &uids)); mock_controller.Verify(); // this will finish the first discovery attempt, and start the second mock_controller.AddExpectedDiscoveryCall(true, NULL); mock_controller.RunDiscoveryCallback(uids); OLA_ASSERT_TRUE(m_discovery_complete_count); m_discovery_complete_count = 0; mock_controller.Verify(); // now unblock the second mock_controller.RunDiscoveryCallback(uids); OLA_ASSERT_TRUE(m_discovery_complete_count); m_discovery_complete_count = 0; mock_controller.Verify(); } /* * Check that interleaving requests and discovery commands work. */ void QueueingRDMControllerTest::testRequestAndDiscovery() { MockRDMController mock_controller; auto_ptr controller( new ola::rdm::DiscoverableQueueingRDMController(&mock_controller, 1)); UIDSet uids; UID uid1(2, 3); UID uid2(10, 11); uids.AddUID(uid1); uids.AddUID(uid2); // Send a request, but don't run the RDM request callback RDMRequest *get_request = NewGetRequest(m_source, m_destination); mock_controller.ExpectCallAndCapture(get_request); RDMReply expected_reply( ola::rdm::RDM_COMPLETED_OK, NewGetResponse(m_destination, m_source)); controller->SendRDMRequest( get_request, ola::NewSingleCallback( this, &QueueingRDMControllerTest::VerifyResponse, &expected_reply)); // now queue up a discovery request controller->RunFullDiscovery( NewSingleCallback( this, &QueueingRDMControllerTest::VerifyDiscoveryComplete, &uids)); mock_controller.Verify(); OLA_ASSERT_FALSE(m_discovery_complete_count); // now run the RDM callback, this should unblock the discovery process mock_controller.AddExpectedDiscoveryCall(true, NULL); mock_controller.RunRDMCallback(&expected_reply); mock_controller.Verify(); // now queue another RDM request RDMRequest *get_request2 = NewGetRequest(m_source, m_destination); RDMReply *expected_reply2 = new RDMReply( ola::rdm::RDM_COMPLETED_OK, NewGetResponse(m_destination, m_source)); mock_controller.ExpectCallAndReplyWith(get_request2, expected_reply2); // discovery is still running so this won't send the request just yet. controller->SendRDMRequest( get_request2, ola::NewSingleCallback( this, &QueueingRDMControllerTest::VerifyResponse, expected_reply2)); // now finish the discovery mock_controller.RunDiscoveryCallback(uids); OLA_ASSERT_TRUE(m_discovery_complete_count); mock_controller.Verify(); } ola-0.10.5.nojsmin/common/rdm/RDMCommand.cpp0000644000175000017500000006365313023355232020172 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * RDMCommand.cpp * The RDMCommand class * Copyright (C) 2010 Simon Newton */ /** * @addtogroup rdm_command * @{ * @file RDMCommand.cpp * @} */ #include #include #include "ola/Logging.h" #include "ola/network/NetworkUtils.h" #include "ola/rdm/RDMCommand.h" #include "ola/rdm/UID.h" #include "ola/strings/Format.h" #include "ola/util/Utils.h" namespace ola { namespace rdm { using std::string; using ola::strings::ToHex; using ola::utils::JoinUInt8; using ola::utils::SplitUInt16; // Internal Helper Functions namespace { /** * @brief Guess the CommandClass of an RDM message. * @param data a pointer to the RDM message (excluding the start code) * @param length length of the RDM data * @returns A RDMCommandClass value, which is set to INVALID_COMMAND if we * couldn't determine the message type. * * This doesn't perform any data checking (that's left to the Inflate* methods). */ RDMCommand::RDMCommandClass GuessMessageType(const uint8_t *data, unsigned int length) { static const unsigned int COMMAND_CLASS_OFFSET = 19; if (!data || length < COMMAND_CLASS_OFFSET + 1) { return RDMCommand::INVALID_COMMAND; } switch (data[COMMAND_CLASS_OFFSET]) { case RDMCommand::GET_COMMAND: case RDMCommand::GET_COMMAND_RESPONSE: case RDMCommand::SET_COMMAND: case RDMCommand::SET_COMMAND_RESPONSE: case RDMCommand::DISCOVER_COMMAND: case RDMCommand::DISCOVER_COMMAND_RESPONSE: return static_cast( data[COMMAND_CLASS_OFFSET]); default: return RDMCommand::INVALID_COMMAND; } } } // namespace /** * @addtogroup rdm_command * @{ */ RDMCommand::RDMCommand(const UID &source, const UID &destination, uint8_t transaction_number, uint8_t port_id, uint8_t message_count, uint16_t sub_device, uint16_t param_id, const uint8_t *data, unsigned int length): m_port_id(port_id), m_source(source), m_destination(destination), m_transaction_number(transaction_number), m_message_count(message_count), m_sub_device(sub_device), m_param_id(param_id), m_data(NULL), m_data_length(length) { SetParamData(data, length); } RDMCommand::~RDMCommand() { if (m_data) { delete[] m_data; } } string RDMCommand::ToString() const { std::ostringstream str; str << m_source << " -> " << m_destination << ", Trans # " << static_cast(m_transaction_number) << ", Port ID " << static_cast(m_port_id) << ", Msg Cnt " << static_cast(m_message_count) << ", SubDevice " << m_sub_device << ", Cmd Class " << CommandClass() << ", Param ID " << m_param_id << ", Data Len " << m_data_length; str << ", Data "; for (unsigned int i = 0 ; i < m_data_length; i++) { str << std::hex << std::setw(2) << static_cast(m_data[i]) << " "; } return str.str(); } bool RDMCommand::operator==(const RDMCommand &other) const { if (SourceUID() == other.SourceUID() && DestinationUID() == other.DestinationUID() && TransactionNumber() == other.TransactionNumber() && MessageCount() == other.MessageCount() && SubDevice() == other.SubDevice() && CommandClass() == other.CommandClass() && ParamId() == other.ParamId() && ParamDataSize() == other.ParamDataSize()) { return 0 == memcmp(ParamData(), other.ParamData(), ParamDataSize()); } return false; } RDMCommand *RDMCommand::Inflate(const uint8_t *data, unsigned int length) { RDMCommandClass command_class = GuessMessageType(data, length); RDMStatusCode status_code = RDM_COMPLETED_OK; switch (command_class) { case RDMCommand::GET_COMMAND: case RDMCommand::SET_COMMAND: return RDMRequest::InflateFromData(data, length); case RDMCommand::GET_COMMAND_RESPONSE: case RDMCommand::SET_COMMAND_RESPONSE: return RDMResponse::InflateFromData(data, length, &status_code); case RDMCommand::DISCOVER_COMMAND: return RDMDiscoveryRequest::InflateFromData(data, length); case RDMCommand::DISCOVER_COMMAND_RESPONSE: return RDMDiscoveryResponse::InflateFromData(data, length); case RDMCommand::INVALID_COMMAND: return NULL; } return NULL; } uint8_t RDMCommand::MessageLength() const { // The size of packet including start code, excluding checksum return sizeof(RDMCommandHeader) + m_data_length + 1; } /** * Set the parameter data */ void RDMCommand::SetParamData(const uint8_t *data, unsigned int length) { m_data_length = length; if (m_data_length > 0 && data != NULL) { if (m_data) delete[] m_data; m_data = new uint8_t[m_data_length]; memcpy(m_data, data, m_data_length); } } /* * Convert a block of RDM data to an RDMCommand object. * The data must not include the RDM start code. * @param data the raw RDM data, starting from the sub-start-code * @param length the length of the data * @param command_header the RDMCommandHeader struct to copy the data to * @return a RDMStatusCode */ RDMStatusCode RDMCommand::VerifyData(const uint8_t *data, size_t length, RDMCommandHeader *command_header) { if (length < sizeof(RDMCommandHeader)) { OLA_WARN << "RDM message is too small, needs to be at least " << sizeof(RDMCommandHeader) << ", was " << length; return RDM_PACKET_TOO_SHORT; } if (!data) { OLA_WARN << "RDM data was null"; return RDM_INVALID_RESPONSE; } memcpy(reinterpret_cast(command_header), data, sizeof(*command_header)); if (command_header->sub_start_code != SUB_START_CODE) { OLA_WARN << "Sub start code mis match, was 0x" << std::hex << static_cast(command_header->sub_start_code) << ", required 0x" << static_cast(SUB_START_CODE); return RDM_WRONG_SUB_START_CODE; } unsigned int message_length = command_header->message_length; if (length < message_length + 1) { OLA_WARN << "RDM message is too small, needs to be " << message_length + 1 << ", was " << length; return RDM_PACKET_LENGTH_MISMATCH; } uint16_t checksum = CalculateChecksum(data, message_length - 1); uint16_t actual_checksum = (data[message_length - 1] << 8) + data[message_length]; if (actual_checksum != checksum) { OLA_WARN << "RDM checksum mismatch, was " << actual_checksum << " but was supposed to be " << checksum; return RDM_CHECKSUM_INCORRECT; } // check param length is valid here unsigned int block_size = length - sizeof(RDMCommandHeader) - 2; if (command_header->param_data_length > block_size) { OLA_WARN << "Param length " << static_cast(command_header->param_data_length) << " exceeds remaining RDM message size of " << block_size; return RDM_PARAM_LENGTH_MISMATCH; } return RDM_COMPLETED_OK; } /* * Calculate the checksum of this packet */ uint16_t RDMCommand::CalculateChecksum(const uint8_t *data, unsigned int packet_length) { unsigned int checksum_value = START_CODE; for (unsigned int i = 0; i < packet_length; i++) checksum_value += data[i]; return static_cast(checksum_value); } /* * Convert the Command Class int to an enum */ RDMCommand::RDMCommandClass RDMCommand::ConvertCommandClass( uint8_t command_class) { switch (command_class) { case DISCOVER_COMMAND: return DISCOVER_COMMAND; case DISCOVER_COMMAND_RESPONSE: return DISCOVER_COMMAND_RESPONSE; case GET_COMMAND: return GET_COMMAND; case GET_COMMAND_RESPONSE: return GET_COMMAND_RESPONSE; case SET_COMMAND: return SET_COMMAND; case SET_COMMAND_RESPONSE: return SET_COMMAND_RESPONSE; default: return INVALID_COMMAND; } } RDMRequest::RDMRequest(const UID &source, const UID &destination, uint8_t transaction_number, uint8_t port_id, uint16_t sub_device, RDMCommandClass command_class, uint16_t param_id, const uint8_t *data, unsigned int length, const OverrideOptions &options) : RDMCommand(source, destination, transaction_number, port_id, options.message_count, sub_device, param_id, data, length), m_override_options(options), m_command_class(command_class) { } bool RDMRequest::IsDUB() const { return (CommandClass() == ola::rdm::RDMCommand::DISCOVER_COMMAND && ParamId() == ola::rdm::PID_DISC_UNIQUE_BRANCH); } uint8_t RDMRequest::SubStartCode() const { return m_override_options.sub_start_code; } uint8_t RDMRequest::MessageLength() const { if (m_override_options.has_message_length) { return m_override_options.message_length; } else { return RDMCommand::MessageLength(); } } uint16_t RDMRequest::Checksum(uint16_t checksum) const { return m_override_options.has_checksum ? m_override_options.checksum : checksum; } RDMRequest* RDMRequest::InflateFromData(const uint8_t *data, unsigned int length) { RDMCommandHeader command_message; RDMStatusCode status_code = VerifyData(data, length, &command_message); if (status_code != RDM_COMPLETED_OK) { return NULL; } uint16_t sub_device = JoinUInt8(command_message.sub_device[0], command_message.sub_device[1]); uint16_t param_id = JoinUInt8(command_message.param_id[0], command_message.param_id[1]); RDMCommandClass command_class = ConvertCommandClass( command_message.command_class); OverrideOptions options; options.sub_start_code = command_message.sub_start_code; options.message_length = command_message.message_length; options.message_count = command_message.message_count; switch (command_class) { case DISCOVER_COMMAND: return new RDMDiscoveryRequest( UID(command_message.source_uid), UID(command_message.destination_uid), command_message.transaction_number, // transaction # command_message.port_id, // port id sub_device, param_id, data + sizeof(RDMCommandHeader), command_message.param_data_length, // data length options); case GET_COMMAND: return new RDMGetRequest( UID(command_message.source_uid), UID(command_message.destination_uid), command_message.transaction_number, // transaction # command_message.port_id, // port id sub_device, param_id, data + sizeof(RDMCommandHeader), command_message.param_data_length, // data length options); case SET_COMMAND: return new RDMSetRequest( UID(command_message.source_uid), UID(command_message.destination_uid), command_message.transaction_number, // transaction # command_message.port_id, // port id sub_device, param_id, data + sizeof(RDMCommandHeader), command_message.param_data_length, // data length options); default: OLA_WARN << "Expected a RDM request command but got " << command_class; return NULL; } } RDMResponse* RDMResponse::InflateFromData(const uint8_t *data, size_t length, RDMStatusCode *status_code, const RDMRequest *request) { RDMCommandHeader command_message; *status_code = VerifyData(data, length, &command_message); if (*status_code != RDM_COMPLETED_OK) { return NULL; } UID source_uid(command_message.source_uid); UID destination_uid(command_message.destination_uid); uint16_t sub_device = ((command_message.sub_device[0] << 8) + command_message.sub_device[1]); RDMCommandClass command_class = ConvertCommandClass( command_message.command_class); if (request) { // check dest uid if (request->SourceUID() != destination_uid) { OLA_WARN << "The destination UID in the response doesn't match, got " << destination_uid << ", expected " << request->SourceUID(); *status_code = RDM_DEST_UID_MISMATCH; return NULL; } // check src uid if (request->DestinationUID() != source_uid) { OLA_WARN << "The source UID in the response doesn't match, got " << source_uid << ", expected " << request->DestinationUID(); *status_code = RDM_SRC_UID_MISMATCH; return NULL; } // check transaction # if (command_message.transaction_number != request->TransactionNumber()) { OLA_WARN << "Transaction numbers don't match, got " << static_cast(command_message.transaction_number) << ", expected " << static_cast(request->TransactionNumber()); *status_code = RDM_TRANSACTION_MISMATCH; return NULL; } // check subdevice, but ignore if request was for all sub devices or // QUEUED_MESSAGE if (sub_device != request->SubDevice() && request->SubDevice() != ALL_RDM_SUBDEVICES && request->ParamId() != PID_QUEUED_MESSAGE) { OLA_WARN << "Sub device didn't match, got " << sub_device << ", expected " << request->SubDevice(); *status_code = RDM_SUB_DEVICE_MISMATCH; return NULL; } // check command class if (request->CommandClass() == GET_COMMAND && command_class != GET_COMMAND_RESPONSE && request->ParamId() != PID_QUEUED_MESSAGE) { OLA_WARN << "Expected GET_COMMAND_RESPONSE, got " << ToHex(command_class); *status_code = RDM_COMMAND_CLASS_MISMATCH; return NULL; } if (request->CommandClass() == SET_COMMAND && command_class != SET_COMMAND_RESPONSE) { OLA_WARN << "Expected SET_COMMAND_RESPONSE, got " << ToHex(command_class); *status_code = RDM_COMMAND_CLASS_MISMATCH; return NULL; } if (request->CommandClass() == DISCOVER_COMMAND && command_class != DISCOVER_COMMAND_RESPONSE) { OLA_WARN << "Expected DISCOVER_COMMAND_RESPONSE, got " << ToHex(command_class); *status_code = RDM_COMMAND_CLASS_MISMATCH; return NULL; } } // check response type if (command_message.port_id > ACK_OVERFLOW) { OLA_WARN << "Response type isn't valid, got " << static_cast(command_message.port_id); *status_code = RDM_INVALID_RESPONSE_TYPE; return NULL; } uint16_t param_id = JoinUInt8(command_message.param_id[0], command_message.param_id[1]); uint8_t return_transaction_number = command_message.transaction_number; switch (command_class) { case DISCOVER_COMMAND_RESPONSE: *status_code = RDM_COMPLETED_OK; return new RDMDiscoveryResponse( source_uid, destination_uid, return_transaction_number, // transaction # command_message.port_id, // port id command_message.message_count, // message count sub_device, param_id, data + sizeof(RDMCommandHeader), command_message.param_data_length); // data length case GET_COMMAND_RESPONSE: *status_code = RDM_COMPLETED_OK; return new RDMGetResponse( source_uid, destination_uid, return_transaction_number, // transaction # command_message.port_id, // port id command_message.message_count, // message count sub_device, param_id, data + sizeof(RDMCommandHeader), command_message.param_data_length); // data length case SET_COMMAND_RESPONSE: *status_code = RDM_COMPLETED_OK; return new RDMSetResponse( source_uid, destination_uid, return_transaction_number, // transaction # command_message.port_id, // port id command_message.message_count, // message count sub_device, param_id, data + sizeof(RDMCommandHeader), command_message.param_data_length); // data length default: OLA_WARN << "Command class isn't valid, got " << ToHex(command_class); *status_code = RDM_INVALID_COMMAND_CLASS; return NULL; } } RDMResponse* RDMResponse::CombineResponses(const RDMResponse *response1, const RDMResponse *response2) { unsigned int combined_length = response1->ParamDataSize() + response2->ParamDataSize(); // do some sort of checking if (combined_length > MAX_OVERFLOW_SIZE) { OLA_WARN << "ACK_OVERFLOW buffer size hit! Limit is " << MAX_OVERFLOW_SIZE << ", request size is " << combined_length; return NULL; } else if (response1->SourceUID() != response2->SourceUID()) { OLA_WARN << "Source UIDs don't match"; return NULL; } uint8_t *combined_data = new uint8_t[combined_length]; memcpy(combined_data, response1->ParamData(), response1->ParamDataSize()); memcpy(combined_data + response1->ParamDataSize(), response2->ParamData(), response2->ParamDataSize()); RDMResponse *response = NULL; if (response1->CommandClass() == GET_COMMAND_RESPONSE && response2->CommandClass() == GET_COMMAND_RESPONSE) { response = new RDMGetResponse( response1->SourceUID(), response1->DestinationUID(), response1->TransactionNumber(), RDM_ACK, response2->MessageCount(), response1->SubDevice(), response1->ParamId(), combined_data, combined_length); } else if (response1->CommandClass() == SET_COMMAND_RESPONSE && response2->CommandClass() == SET_COMMAND_RESPONSE) { response = new RDMSetResponse( response1->SourceUID(), response1->DestinationUID(), response1->TransactionNumber(), RDM_ACK, response2->MessageCount(), response1->SubDevice(), response1->ParamId(), combined_data, combined_length); } else { OLA_WARN << "Expected a RDM request command but got " << std::hex << response1->CommandClass(); } delete[] combined_data; return response; } // Helper functions follow RDMResponse *NackWithReason(const RDMRequest *request, rdm_nack_reason reason_enum, uint8_t outstanding_messages) { uint16_t reason = ola::network::HostToNetwork( static_cast(reason_enum)); return GetResponseFromData(request, reinterpret_cast(&reason), sizeof(reason), RDM_NACK_REASON, outstanding_messages); } RDMResponse *GetResponseFromData(const RDMRequest *request, const uint8_t *data, unsigned int length, rdm_response_type type, uint8_t outstanding_messages) { // We can reuse GetResponseWithPid return GetResponseWithPid(request, request->ParamId(), data, length, type, outstanding_messages); } RDMResponse *GetResponseWithPid(const RDMRequest *request, uint16_t pid, const uint8_t *data, unsigned int length, uint8_t type, uint8_t outstanding_messages) { switch (request->CommandClass()) { case RDMCommand::GET_COMMAND: // coverity[SWAPPED_ARGUMENTS] return new RDMGetResponse( request->DestinationUID(), request->SourceUID(), request->TransactionNumber(), type, outstanding_messages, request->SubDevice(), pid, data, length); case RDMCommand::SET_COMMAND: // coverity[SWAPPED_ARGUMENTS] return new RDMSetResponse( request->DestinationUID(), request->SourceUID(), request->TransactionNumber(), type, outstanding_messages, request->SubDevice(), pid, data, length); case RDMCommand::DISCOVER_COMMAND: // coverity[SWAPPED_ARGUMENTS] return new RDMDiscoveryResponse( request->DestinationUID(), request->SourceUID(), request->TransactionNumber(), type, outstanding_messages, request->SubDevice(), pid, data, length); default: return NULL; } } /** * @brief Inflate a discovery request. */ RDMDiscoveryRequest* RDMDiscoveryRequest::InflateFromData( const uint8_t *data, unsigned int length) { RDMCommandHeader command_message; RDMStatusCode code = VerifyData(data, length, &command_message); if (code != RDM_COMPLETED_OK) { return NULL; } uint16_t sub_device = JoinUInt8(command_message.sub_device[0], command_message.sub_device[1]); uint16_t param_id = JoinUInt8(command_message.param_id[0], command_message.param_id[1]); RDMCommandClass command_class = ConvertCommandClass( command_message.command_class); OverrideOptions options; options.sub_start_code = command_message.sub_start_code; options.message_length = command_message.message_length; options.message_count = command_message.message_count; if (command_class == DISCOVER_COMMAND) { return new RDMDiscoveryRequest( UID(command_message.source_uid), UID(command_message.destination_uid), command_message.transaction_number, // transaction # command_message.port_id, // port id sub_device, param_id, data + sizeof(RDMCommandHeader), command_message.param_data_length, // data length options); } else { OLA_WARN << "Expected a RDM discovery request but got " << command_class; return NULL; } } /* * Create a new DUB request object. */ RDMDiscoveryRequest *NewDiscoveryUniqueBranchRequest( const UID &source, const UID &lower, const UID &upper, uint8_t transaction_number, uint8_t port_id) { uint8_t param_data[UID::UID_SIZE * 2]; unsigned int length = sizeof(param_data); lower.Pack(param_data, length); upper.Pack(param_data + UID::UID_SIZE, length - UID::UID_SIZE); return new RDMDiscoveryRequest(source, UID::AllDevices(), transaction_number, port_id, ROOT_RDM_DEVICE, PID_DISC_UNIQUE_BRANCH, param_data, length); } /* * Create a new Mute Request Object. */ RDMDiscoveryRequest *NewMuteRequest(const UID &source, const UID &destination, uint8_t transaction_number, uint8_t port_id) { return new RDMDiscoveryRequest(source, destination, transaction_number, port_id, ROOT_RDM_DEVICE, PID_DISC_MUTE, NULL, 0); } /** * Create a new UnMute request object. */ RDMDiscoveryRequest *NewUnMuteRequest(const UID &source, const UID &destination, uint8_t transaction_number, uint8_t port_id) { return new RDMDiscoveryRequest(source, destination, transaction_number, port_id, ROOT_RDM_DEVICE, PID_DISC_UN_MUTE, NULL, 0); } /** * Inflate a discovery response. */ RDMDiscoveryResponse* RDMDiscoveryResponse::InflateFromData( const uint8_t *data, unsigned int length) { RDMCommandHeader command_message; RDMStatusCode code = VerifyData(data, length, &command_message); if (code != RDM_COMPLETED_OK) return NULL; uint16_t sub_device = ((command_message.sub_device[0] << 8) + command_message.sub_device[1]); uint16_t param_id = ((command_message.param_id[0] << 8) + command_message.param_id[1]); RDMCommandClass command_class = ConvertCommandClass( command_message.command_class); if (command_class == DISCOVER_COMMAND_RESPONSE) { return new RDMDiscoveryResponse( UID(command_message.source_uid), UID(command_message.destination_uid), command_message.transaction_number, // transaction # command_message.port_id, // port id command_message.message_count, // message count sub_device, param_id, data + sizeof(RDMCommandHeader), command_message.param_data_length); // data length } else { OLA_WARN << "Expected a RDM discovery response but got " << command_class; return NULL; } } /**@}*/ } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/RDMCommandSerializerTest.cpp0000644000175000017500000003473013023355232023056 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * RDMCommandSerializerTest.cpp * Test fixture for the RDMCommandSerializer. * Copyright (C) 2010 Simon Newton */ #include #include #include #include #include "common/rdm/TestHelper.h" #include "ola/Logging.h" #include "ola/base/Array.h" #include "ola/io/ByteString.h" #include "ola/io/IOStack.h" #include "ola/network/NetworkUtils.h" #include "ola/rdm/RDMCommand.h" #include "ola/rdm/RDMCommandSerializer.h" #include "ola/rdm/RDMPacket.h" #include "ola/rdm/UID.h" #include "ola/testing/TestUtils.h" #include "ola/util/Utils.h" using ola::io::IOStack; using ola::io::ByteString; using ola::rdm::RDMCommand; using ola::rdm::RDMCommandSerializer; using ola::rdm::RDMDiscoveryRequest; using ola::rdm::RDMGetRequest; using ola::rdm::RDMRequest; using ola::rdm::RDMSetRequest; using ola::rdm::UID; using std::auto_ptr; void UpdateChecksum(uint8_t *expected, unsigned int expected_length) { unsigned int checksum = ola::rdm::START_CODE; for (unsigned int i = 0 ; i < expected_length - 2; i++) checksum += expected[i]; ola::utils::SplitUInt16(checksum, &expected[expected_length - 2], &expected[expected_length - 1]); } class RDMCommandSerializerTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(RDMCommandSerializerTest); CPPUNIT_TEST(testGetRequest); CPPUNIT_TEST(testRequestOverrides); CPPUNIT_TEST(testPackWithStartCode); CPPUNIT_TEST(testDUB); CPPUNIT_TEST(testMuteRequest); CPPUNIT_TEST(testUnMuteRequest); CPPUNIT_TEST(testPackAndInflate); CPPUNIT_TEST(testIOStack); CPPUNIT_TEST_SUITE_END(); public: RDMCommandSerializerTest() : m_source(1, 2), m_destination(3, 4) { } void setUp(); void testGetRequest(); void testRequestOverrides(); void testPackWithStartCode(); void testDUB(); void testMuteRequest(); void testUnMuteRequest(); void testPackAndInflate(); void testIOStack(); private: UID m_source; UID m_destination; static uint8_t EXPECTED_GET_BUFFER[]; static uint8_t EXPECTED_SET_BUFFER[]; static uint8_t EXPECTED_DISCOVERY_REQUEST[]; static uint8_t EXPECTED_MUTE_REQUEST[]; static uint8_t EXPECTED_UNMUTE_REQUEST[]; static uint8_t MUTE_RESPONSE[]; }; CPPUNIT_TEST_SUITE_REGISTRATION(RDMCommandSerializerTest); uint8_t RDMCommandSerializerTest::EXPECTED_GET_BUFFER[] = { 1, 24, // sub code & length 0, 3, 0, 0, 0, 4, // dst uid 0, 1, 0, 0, 0, 2, // src uid 0, 1, 0, 0, 10, // transaction, port id, msg count & sub device 0x20, 1, 40, 0, // command, param id, param data length 0, 0 // checksum, filled in below }; uint8_t RDMCommandSerializerTest::EXPECTED_SET_BUFFER[] = { 1, 28, // sub code & length 0, 3, 0, 0, 0, 4, // dst uid 0, 1, 0, 0, 0, 2, // src uid 0, 1, 0, 0, 10, // transaction, port id, msg count & sub device 0x30, 1, 40, 4, // command, param id, param data length 0xa5, 0xa5, 0xa5, 0xa5, // param data 0, 0 // checksum, filled in below }; uint8_t RDMCommandSerializerTest::EXPECTED_DISCOVERY_REQUEST[] = { 1, 36, // sub code & length 255, 255, 255, 255, 255, 255, // dst uid 0, 1, 0, 0, 0, 2, // src uid 1, 1, 0, 0, 0, // transaction, port id, msg count & sub device 0x10, 0, 1, 12, // command, param id, param data length 1, 2, 0, 0, 3, 4, // lower uid 5, 6, 0, 0, 7, 8, // upper uid 0, 0 // checksum, filled in below }; uint8_t RDMCommandSerializerTest::EXPECTED_MUTE_REQUEST[] = { 1, 24, // sub code & length 0, 3, 0, 0, 0, 4, // dst uid 0, 1, 0, 0, 0, 2, // src uid 1, 1, 0, 0, 0, // transaction, port id, msg count & sub device 0x10, 0, 2, 0, // command, param id, param data length 0, 0 // checksum, filled in below }; uint8_t RDMCommandSerializerTest::EXPECTED_UNMUTE_REQUEST[] = { 1, 24, // sub code & length 0, 3, 0, 0, 0, 4, // dst uid 0, 1, 0, 0, 0, 2, // src uid 1, 1, 0, 0, 0, // transaction, port id, msg count & sub device 0x10, 0, 3, 0, // command, param id, param data length 0, 0 // checksum, filled in below }; /* * Fill in the checksums */ void RDMCommandSerializerTest::setUp() { UpdateChecksum(EXPECTED_GET_BUFFER, arraysize(EXPECTED_GET_BUFFER)); UpdateChecksum(EXPECTED_SET_BUFFER, arraysize(EXPECTED_SET_BUFFER)); UpdateChecksum(EXPECTED_DISCOVERY_REQUEST, arraysize(EXPECTED_DISCOVERY_REQUEST)); UpdateChecksum(EXPECTED_MUTE_REQUEST, arraysize(EXPECTED_MUTE_REQUEST)); UpdateChecksum(EXPECTED_UNMUTE_REQUEST, arraysize(EXPECTED_UNMUTE_REQUEST)); } void RDMCommandSerializerTest::testGetRequest() { RDMGetRequest request(m_source, m_destination, 0, // transaction # 1, // port id 10, // sub device 296, // param id NULL, // data 0); // data length unsigned int length = RDMCommandSerializer::RequiredSize(request); uint8_t *data = new uint8_t[length]; OLA_ASSERT_TRUE(RDMCommandSerializer::Pack(request, data, &length)); OLA_ASSERT_DATA_EQUALS(EXPECTED_GET_BUFFER, arraysize(EXPECTED_GET_BUFFER), data, length); ByteString output; OLA_ASSERT_TRUE(RDMCommandSerializer::Pack(request, &output)); OLA_ASSERT_DATA_EQUALS(EXPECTED_GET_BUFFER, arraysize(EXPECTED_GET_BUFFER), output.data(), output.length()); delete[] data; } void RDMCommandSerializerTest::testRequestOverrides() { RDMRequest::OverrideOptions options; options.SetMessageLength(10); options.SetChecksum(999); options.sub_start_code = 5; options.message_count = 9; RDMGetRequest request(m_source, m_destination, 0, // transaction # 1, // port id 10, // sub device 296, // param id NULL, // data 0, // data length options); const uint8_t expected_data[] = { 5, 10, // sub code & length 0, 3, 0, 0, 0, 4, // dst uid 0, 1, 0, 0, 0, 2, // src uid 0, 1, 9, 0, 10, // transaction, port id, msg count & sub device 0x20, 1, 40, 0, // command, param id, param data length 0x3, 0xe7 // checksum, }; unsigned int length = RDMCommandSerializer::RequiredSize(request); uint8_t *data = new uint8_t[length]; OLA_ASSERT_TRUE(RDMCommandSerializer::Pack(request, data, &length)); OLA_ASSERT_DATA_EQUALS(expected_data, arraysize(expected_data), data, length); delete[] data; ByteString output; OLA_ASSERT_TRUE(RDMCommandSerializer::Pack(request, &output)); OLA_ASSERT_DATA_EQUALS(expected_data, arraysize(expected_data), output.data(), output.length()); } void RDMCommandSerializerTest::testPackWithStartCode() { RDMGetRequest request(m_source, m_destination, 0, // transaction # 1, // port id 10, // sub device 296, // param id NULL, // data 0); // data length const uint8_t expected_data[] = { 0xcc, 1, 24, // start code, sub code & length 0, 3, 0, 0, 0, 4, // dst uid 0, 1, 0, 0, 0, 2, // src uid 0, 1, 0, 0, 10, // transaction, port id, msg count & sub device 0x20, 1, 40, 0, // command, param id, param data length 0x1, 0x43 // checksum, }; ByteString output; OLA_ASSERT_TRUE(RDMCommandSerializer::PackWithStartCode(request, &output)); OLA_ASSERT_DATA_EQUALS(expected_data, arraysize(expected_data), output.data(), output.length()); } void RDMCommandSerializerTest::testDUB() { UID lower(0x0102, 0x0304); UID upper(0x0506, 0x0708); auto_ptr request( NewDiscoveryUniqueBranchRequest(m_source, lower, upper, 1)); OLA_ASSERT_EQ(RDMCommand::DISCOVER_COMMAND, request->CommandClass()); OLA_ASSERT_TRUE(request->IsDUB()); // test pack unsigned int length = RDMCommandSerializer::RequiredSize(*request); OLA_ASSERT_EQ(37u, length); uint8_t *data = new uint8_t[length]; OLA_ASSERT_TRUE(RDMCommandSerializer::Pack(*request, data, &length)); OLA_ASSERT_DATA_EQUALS(EXPECTED_DISCOVERY_REQUEST, arraysize(EXPECTED_DISCOVERY_REQUEST), data, length); ByteString output; OLA_ASSERT_TRUE(RDMCommandSerializer::Pack(*request.get(), &output)); OLA_ASSERT_DATA_EQUALS(EXPECTED_DISCOVERY_REQUEST, arraysize(EXPECTED_DISCOVERY_REQUEST), output.data(), output.length()); delete[] data; } void RDMCommandSerializerTest::testMuteRequest() { auto_ptr request( NewMuteRequest(m_source, m_destination, 1)); OLA_ASSERT_EQ(RDMCommand::DISCOVER_COMMAND, request->CommandClass()); // test pack unsigned int length = RDMCommandSerializer::RequiredSize(*request); OLA_ASSERT_EQ(25u, length); uint8_t *data = new uint8_t[length]; OLA_ASSERT_TRUE(RDMCommandSerializer::Pack(*request, data, &length)); OLA_ASSERT_DATA_EQUALS(EXPECTED_MUTE_REQUEST, arraysize(EXPECTED_MUTE_REQUEST), data, length); ByteString output; OLA_ASSERT_TRUE(RDMCommandSerializer::Pack(*request.get(), &output)); OLA_ASSERT_DATA_EQUALS(EXPECTED_MUTE_REQUEST, arraysize(EXPECTED_MUTE_REQUEST), output.data(), output.length()); delete[] data; } void RDMCommandSerializerTest::testUnMuteRequest() { auto_ptr request( NewUnMuteRequest(m_source, m_destination, 1)); OLA_ASSERT_EQ(RDMCommand::DISCOVER_COMMAND, request->CommandClass()); // test pack unsigned int length = RDMCommandSerializer::RequiredSize(*request); OLA_ASSERT_EQ(25u, length); uint8_t *data = new uint8_t[length]; OLA_ASSERT_TRUE(RDMCommandSerializer::Pack(*request, data, &length)); OLA_ASSERT_DATA_EQUALS(EXPECTED_UNMUTE_REQUEST, arraysize(EXPECTED_UNMUTE_REQUEST), data, length); ByteString output; OLA_ASSERT_TRUE(RDMCommandSerializer::Pack(*request.get(), &output)); OLA_ASSERT_DATA_EQUALS(EXPECTED_UNMUTE_REQUEST, arraysize(EXPECTED_UNMUTE_REQUEST), output.data(), output.length()); delete[] data; } void RDMCommandSerializerTest::testPackAndInflate() { RDMGetRequest get_command(m_source, m_destination, 99, // transaction # 1, // port id 10, // sub device 296, // param id NULL, // data 0); // data length unsigned int length = RDMCommandSerializer::RequiredSize(get_command); uint8_t *data = new uint8_t[length]; OLA_ASSERT_TRUE(RDMCommandSerializer::Pack(get_command, data, &length)); auto_ptr command(RDMRequest::InflateFromData(data, length)); OLA_ASSERT_NOT_NULL(command.get()); OLA_ASSERT_EQ(m_source, command->SourceUID()); OLA_ASSERT_EQ(m_destination, command->DestinationUID()); OLA_ASSERT_EQ((uint8_t) 99, command->TransactionNumber()); OLA_ASSERT_EQ((uint8_t) 1, command->PortId()); OLA_ASSERT_EQ((uint8_t) 0, command->MessageCount()); OLA_ASSERT_EQ((uint16_t) 10, command->SubDevice()); OLA_ASSERT_EQ(RDMCommand::GET_COMMAND, command->CommandClass()); OLA_ASSERT_EQ((uint16_t) 296, command->ParamId()); OLA_ASSERT_EQ(static_cast(NULL), command->ParamData()); OLA_ASSERT_EQ(0u, command->ParamDataSize()); OLA_ASSERT_EQ(25u, RDMCommandSerializer::RequiredSize(*command)); delete[] data; } /* * Test writing to an IOStack works. */ void RDMCommandSerializerTest::testIOStack() { UID source(1, 2); UID destination(3, 4); RDMGetRequest command(source, destination, 0, // transaction # 1, // port id 10, // sub device 296, // param id NULL, // data 0); // data length IOStack stack; OLA_ASSERT_TRUE(RDMCommandSerializer::Write(command, &stack)); unsigned int raw_command_size = stack.Size(); OLA_ASSERT_EQ(raw_command_size, RDMCommandSerializer::RequiredSize(command)); uint8_t raw_command[raw_command_size]; OLA_ASSERT_EQ(raw_command_size, stack.Read(raw_command, raw_command_size)); OLA_ASSERT_EQ(0u, stack.Size()); OLA_ASSERT_DATA_EQUALS(EXPECTED_GET_BUFFER, arraysize(EXPECTED_GET_BUFFER), raw_command, raw_command_size); // now try a command with data uint32_t data_value = 0xa5a5a5a5; RDMSetRequest command2(source, destination, 0, // transaction # 1, // port id 10, // sub device 296, // param id reinterpret_cast(&data_value), // data sizeof(data_value)); // data length OLA_ASSERT_EQ(29u, RDMCommandSerializer::RequiredSize(command2)); OLA_ASSERT_TRUE(RDMCommandSerializer::Write(command2, &stack)); raw_command_size = stack.Size(); OLA_ASSERT_EQ(raw_command_size, RDMCommandSerializer::RequiredSize(command2)); uint8_t raw_command2[raw_command_size]; OLA_ASSERT_EQ(raw_command_size, stack.Read(raw_command2, raw_command_size)); OLA_ASSERT_EQ(0u, stack.Size()); OLA_ASSERT_DATA_EQUALS(EXPECTED_SET_BUFFER, arraysize(EXPECTED_SET_BUFFER), raw_command2, raw_command_size); } ola-0.10.5.nojsmin/common/rdm/MessageSerializerTest.cpp0000644000175000017500000002542113023355232022516 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * MessageSerializerTest.cpp * Test fixture for the MessageSerializer classes * Copyright (C) 2011 Simon Newton */ #include #include #include #include #include #include "ola/Logging.h" #include "ola/messaging/Descriptor.h" #include "ola/messaging/Message.h" #include "ola/rdm/StringMessageBuilder.h" #include "ola/rdm/MessageSerializer.h" #include "ola/testing/TestUtils.h" using ola::messaging::BoolFieldDescriptor; using ola::messaging::Descriptor; using ola::messaging::FieldDescriptor; using ola::messaging::FieldDescriptorGroup; using ola::messaging::Int16FieldDescriptor; using ola::messaging::Int32FieldDescriptor; using ola::messaging::Int8FieldDescriptor; using ola::messaging::IPV4FieldDescriptor; using ola::messaging::MACFieldDescriptor; using ola::messaging::Message; using ola::messaging::StringFieldDescriptor; using ola::messaging::UInt16FieldDescriptor; using ola::messaging::UInt32FieldDescriptor; using ola::messaging::UInt8FieldDescriptor; using ola::messaging::UIDFieldDescriptor; using ola::rdm::StringMessageBuilder; using ola::rdm::MessageSerializer; using std::auto_ptr; using std::string; using std::vector; class MessageSerializerTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(MessageSerializerTest); CPPUNIT_TEST(testSimple); CPPUNIT_TEST(testString); CPPUNIT_TEST(testUID); CPPUNIT_TEST(testLittleEndian); CPPUNIT_TEST(testWithGroups); CPPUNIT_TEST(testWithNestedGroups); CPPUNIT_TEST_SUITE_END(); public: void testSimple(); void testString(); void testUID(); void testLittleEndian(); void testWithGroups(); void testWithNestedGroups(); private: const Message *BuildMessage(const Descriptor &descriptor, const vector &inputs); }; CPPUNIT_TEST_SUITE_REGISTRATION(MessageSerializerTest); /** * Build a message from a given set of inputs and return the string * representation of the message. */ const Message *MessageSerializerTest::BuildMessage( const Descriptor &descriptor, const vector &inputs) { StringMessageBuilder builder; const Message *message = builder.GetMessage(inputs, &descriptor); if (!message) OLA_WARN << "Error with field: " << builder.GetError(); return message; } /** * Check the MessageSerializer works. */ void MessageSerializerTest::testSimple() { // build the descriptor vector fields; fields.push_back(new BoolFieldDescriptor("bool1")); fields.push_back(new UInt8FieldDescriptor("uint8")); fields.push_back(new Int8FieldDescriptor("int8")); fields.push_back(new UInt16FieldDescriptor("uint16")); fields.push_back(new Int16FieldDescriptor("int16")); fields.push_back(new UInt32FieldDescriptor("uint32")); fields.push_back(new Int32FieldDescriptor("int32")); fields.push_back(new IPV4FieldDescriptor("ip")); fields.push_back(new MACFieldDescriptor("mac")); fields.push_back(new StringFieldDescriptor("string", 0, 32)); Descriptor descriptor("Test Descriptor", fields); // now setup the inputs vector inputs; inputs.push_back("true"); inputs.push_back("1"); inputs.push_back("-3"); inputs.push_back("300"); inputs.push_back("-400"); inputs.push_back("66000"); inputs.push_back("-66000"); inputs.push_back("10.0.0.1"); inputs.push_back("01:23:45:67:89:ab"); inputs.push_back("foo"); auto_ptr message(BuildMessage(descriptor, inputs)); // verify OLA_ASSERT_NOT_NULL(message.get()); MessageSerializer serializer; unsigned int packed_length; const uint8_t *data = serializer.SerializeMessage(message.get(), &packed_length); OLA_ASSERT_NOT_NULL(data); OLA_ASSERT_EQ(28u, packed_length); uint8_t expected[] = { 1, 1, 253, 1, 44, 254, 112, 0, 1, 1, 208, 255, 254, 254, 48, 10, 0, 0, 1, 1, 35, 69, 103, 137, 171, 'f', 'o', 'o'}; OLA_ASSERT_DATA_EQUALS(expected, sizeof(expected), data, packed_length); } /** * Check that strings do the right thing */ void MessageSerializerTest::testString() { vector fields; fields.push_back(new StringFieldDescriptor("string", 10, 10)); fields.push_back(new StringFieldDescriptor("string", 0, 32)); Descriptor descriptor("Test Descriptor", fields); // now setup the inputs vector inputs; inputs.push_back("foo bar"); // this is shorter than the min size inputs.push_back("long long foo bar baz"); auto_ptr message(BuildMessage(descriptor, inputs)); // verify OLA_ASSERT_NOT_NULL(message.get()); MessageSerializer serializer; unsigned int packed_length; const uint8_t *data = serializer.SerializeMessage(message.get(), &packed_length); OLA_ASSERT_NOT_NULL(data); OLA_ASSERT_EQ(31u, packed_length); uint8_t expected[] = "foo bar\0\0\0long long foo bar baz"; OLA_ASSERT_DATA_EQUALS(expected, sizeof(expected) - 1, // ignore the trailing \0 data, packed_length); } /** * Check that UIDs work. */ void MessageSerializerTest::testUID() { vector fields; fields.push_back(new UIDFieldDescriptor("Address")); Descriptor descriptor("Test Descriptor", fields); // now setup the inputs vector inputs; inputs.push_back("7a70:00000001"); auto_ptr message(BuildMessage(descriptor, inputs)); // verify OLA_ASSERT_NOT_NULL(message.get()); MessageSerializer serializer; unsigned int packed_length; const uint8_t *data = serializer.SerializeMessage(message.get(), &packed_length); OLA_ASSERT_NOT_NULL(data); OLA_ASSERT_EQ(6u, packed_length); uint8_t expected[] = {0x7a, 0x70, 0, 0, 0, 1}; OLA_ASSERT_DATA_EQUALS(expected, sizeof(expected), data, packed_length); } /** * Check the MessageSerializer works with little endian fields. */ void MessageSerializerTest::testLittleEndian() { // build the descriptor vector fields; fields.push_back(new UInt8FieldDescriptor("uint8", true)); fields.push_back(new Int8FieldDescriptor("int8", true)); fields.push_back(new UInt16FieldDescriptor("uint16", true)); fields.push_back(new Int16FieldDescriptor("int16", true)); fields.push_back(new UInt32FieldDescriptor("uint32", true)); fields.push_back(new Int32FieldDescriptor("int32", true)); Descriptor descriptor("Test Descriptor", fields); // now setup the inputs vector inputs; inputs.push_back("1"); inputs.push_back("-3"); inputs.push_back("300"); inputs.push_back("-400"); inputs.push_back("66000"); inputs.push_back("-66000"); auto_ptr message(BuildMessage(descriptor, inputs)); // verify OLA_ASSERT_NOT_NULL(message.get()); MessageSerializer serializer; unsigned int packed_length; const uint8_t *data = serializer.SerializeMessage(message.get(), &packed_length); OLA_ASSERT_NOT_NULL(data); OLA_ASSERT_EQ(14u, packed_length); uint8_t expected[] = { 1, 253, 44, 1, 112, 254, 208, 1, 1, 0, 48, 254, 254, 255}; OLA_ASSERT_DATA_EQUALS(expected, sizeof(expected), data, packed_length); } /** * Check the MessageSerializer works with variable sized groups. */ void MessageSerializerTest::testWithGroups() { // build the descriptor vector group_fields; group_fields.push_back(new BoolFieldDescriptor("bool")); group_fields.push_back(new UInt8FieldDescriptor("uint8")); vector fields; fields.push_back(new FieldDescriptorGroup("group", group_fields, 0, 3)); Descriptor descriptor("Test Descriptor", fields); // now setup the inputs vector inputs; inputs.push_back("true"); inputs.push_back("10"); auto_ptr message(BuildMessage(descriptor, inputs)); // verify OLA_ASSERT_NOT_NULL(message.get()); MessageSerializer serializer; unsigned int packed_length; const uint8_t *data = serializer.SerializeMessage(message.get(), &packed_length); OLA_ASSERT_NOT_NULL(data); OLA_ASSERT_EQ(2u, packed_length); uint8_t expected[] = {1, 10}; OLA_ASSERT_DATA_EQUALS(expected, sizeof(expected), data, packed_length); // now do multiple groups vector inputs2; inputs2.push_back("true"); inputs2.push_back("10"); inputs2.push_back("true"); inputs2.push_back("42"); inputs2.push_back("false"); inputs2.push_back("240"); auto_ptr message2(BuildMessage(descriptor, inputs2)); data = serializer.SerializeMessage(message2.get(), &packed_length); OLA_ASSERT_NOT_NULL(data); OLA_ASSERT_EQ(6u, packed_length); uint8_t expected2[] = {1, 10, 1, 42, 0, 240}; OLA_ASSERT_DATA_EQUALS(expected2, sizeof(expected2), data, packed_length); } /** * test MessageSerializer with nested fixed groups */ void MessageSerializerTest::testWithNestedGroups() { vector fields, group_fields, group_fields2; group_fields.push_back(new BoolFieldDescriptor("bool")); group_fields2.push_back(new Int16FieldDescriptor("int16")); group_fields2.push_back(new FieldDescriptorGroup("bar", group_fields, 2, 2)); const FieldDescriptorGroup *nested_group = new FieldDescriptorGroup( "", group_fields2, 0, 4); fields.push_back(nested_group); Descriptor descriptor("Test Descriptor", fields); vector inputs; inputs.push_back("1"); inputs.push_back("true"); inputs.push_back("true"); inputs.push_back("2"); inputs.push_back("true"); inputs.push_back("false"); auto_ptr message(BuildMessage(descriptor, inputs)); OLA_ASSERT_NOT_NULL(message.get()); MessageSerializer serializer; unsigned int packed_length; const uint8_t *data = serializer.SerializeMessage(message.get(), &packed_length); OLA_ASSERT_NOT_NULL(data); OLA_ASSERT_EQ(8u, packed_length); uint8_t expected[] = {0, 1, 1, 1, 0, 2, 1, 0}; OLA_ASSERT_DATA_EQUALS(expected, sizeof(expected), data, packed_length); } ola-0.10.5.nojsmin/common/rdm/Makefile.mk0000644000175000017500000001375013134123277017611 0ustar wouterwouterbuilt_sources += \ common/rdm/Pids.pb.cc \ common/rdm/Pids.pb.h # LIBRARIES ################################################## common_libolacommon_la_SOURCES += \ common/rdm/AckTimerResponder.cpp \ common/rdm/AdvancedDimmerResponder.cpp \ common/rdm/CommandPrinter.cpp \ common/rdm/DescriptorConsistencyChecker.cpp \ common/rdm/DescriptorConsistencyChecker.h \ common/rdm/DimmerResponder.cpp \ common/rdm/DimmerRootDevice.cpp \ common/rdm/DimmerSubDevice.cpp \ common/rdm/DiscoveryAgent.cpp \ common/rdm/DiscoveryAgentTestHelper.h \ common/rdm/DummyResponder.cpp \ common/rdm/FakeNetworkManager.cpp \ common/rdm/FakeNetworkManager.h \ common/rdm/GroupSizeCalculator.cpp \ common/rdm/GroupSizeCalculator.h \ common/rdm/MessageDeserializer.cpp \ common/rdm/MessageSerializer.cpp \ common/rdm/MovingLightResponder.cpp \ common/rdm/NetworkManager.cpp \ common/rdm/NetworkManager.h \ common/rdm/NetworkResponder.cpp \ common/rdm/OpenLightingEnums.cpp \ common/rdm/PidStore.cpp \ common/rdm/PidStoreHelper.cpp \ common/rdm/PidStoreLoader.cpp \ common/rdm/PidStoreLoader.h \ common/rdm/QueueingRDMController.cpp \ common/rdm/RDMAPI.cpp \ common/rdm/RDMCommand.cpp \ common/rdm/RDMCommandSerializer.cpp \ common/rdm/RDMFrame.cpp \ common/rdm/RDMHelper.cpp \ common/rdm/RDMReply.cpp \ common/rdm/ResponderHelper.cpp \ common/rdm/ResponderLoadSensor.cpp \ common/rdm/ResponderPersonality.cpp \ common/rdm/ResponderSettings.cpp \ common/rdm/ResponderSlotData.cpp \ common/rdm/SensorResponder.cpp \ common/rdm/StringMessageBuilder.cpp \ common/rdm/SubDeviceDispatcher.cpp \ common/rdm/UID.cpp \ common/rdm/VariableFieldSizeCalculator.cpp \ common/rdm/VariableFieldSizeCalculator.h nodist_common_libolacommon_la_SOURCES += common/rdm/Pids.pb.cc common_libolacommon_la_CXXFLAGS += -DPID_DATA_DIR=\"${piddatadir}\" common_libolacommon_la_LIBADD += $(libprotobuf_LIBS) EXTRA_DIST += common/rdm/Pids.proto common/rdm/Pids.pb.cc common/rdm/Pids.pb.h: common/rdm/Makefile.mk common/rdm/Pids.proto $(PROTOC) --cpp_out common/rdm --proto_path $(srcdir)/common/rdm $(srcdir)/common/rdm/Pids.proto # TESTS_DATA ################################################## EXTRA_DIST += \ common/rdm/testdata/duplicate_manufacturer.proto \ common/rdm/testdata/duplicate_pid_name.proto \ common/rdm/testdata/duplicate_pid_value.proto \ common/rdm/testdata/inconsistent_pid.proto \ common/rdm/testdata/invalid_esta_pid.proto \ common/rdm/testdata/pids/overrides.proto \ common/rdm/testdata/pids/pids1.proto \ common/rdm/testdata/pids/pids2.proto \ common/rdm/testdata/test_pids.proto # TESTS ################################################## test_programs += \ common/rdm/DiscoveryAgentTester \ common/rdm/PidStoreTester \ common/rdm/QueueingRDMControllerTester \ common/rdm/RDMAPITester \ common/rdm/RDMCommandSerializerTester \ common/rdm/RDMCommandTester \ common/rdm/RDMFrameTester \ common/rdm/RDMHelperTester \ common/rdm/RDMMessageTester \ common/rdm/RDMReplyTester \ common/rdm/UIDAllocatorTester \ common/rdm/UIDTester common_rdm_DiscoveryAgentTester_SOURCES = common/rdm/DiscoveryAgentTest.cpp common_rdm_DiscoveryAgentTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_rdm_DiscoveryAgentTester_LDADD = $(COMMON_TESTING_LIBS) common_rdm_PidStoreTester_SOURCES = \ common/rdm/DescriptorConsistencyCheckerTest.cpp \ common/rdm/PidStoreTest.cpp common_rdm_PidStoreTester_CXXFLAGS = $(COMMON_TESTING_PROTOBUF_FLAGS) common_rdm_PidStoreTester_LDADD = $(COMMON_TESTING_LIBS) common_rdm_RDMHelperTester_SOURCES = common/rdm/RDMHelperTest.cpp common_rdm_RDMHelperTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_rdm_RDMHelperTester_LDADD = $(COMMON_TESTING_LIBS) common_rdm_RDMMessageTester_SOURCES = \ common/rdm/GroupSizeCalculatorTest.cpp \ common/rdm/MessageSerializerTest.cpp \ common/rdm/MessageDeserializerTest.cpp \ common/rdm/RDMMessageInterationTest.cpp \ common/rdm/StringMessageBuilderTest.cpp \ common/rdm/VariableFieldSizeCalculatorTest.cpp common_rdm_RDMMessageTester_CXXFLAGS = $(COMMON_TESTING_PROTOBUF_FLAGS) common_rdm_RDMMessageTester_LDADD = $(COMMON_TESTING_LIBS) common_rdm_RDMAPITester_SOURCES = \ common/rdm/RDMAPITest.cpp common_rdm_RDMAPITester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_rdm_RDMAPITester_LDADD = $(COMMON_TESTING_LIBS) common_rdm_RDMCommandTester_SOURCES = \ common/rdm/RDMCommandTest.cpp \ common/rdm/TestHelper.h common_rdm_RDMCommandTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_rdm_RDMCommandTester_LDADD = $(COMMON_TESTING_LIBS) common_rdm_RDMFrameTester_SOURCES = \ common/rdm/RDMFrameTest.cpp \ common/rdm/TestHelper.h common_rdm_RDMFrameTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_rdm_RDMFrameTester_LDADD = $(COMMON_TESTING_LIBS) common_rdm_RDMReplyTester_SOURCES = \ common/rdm/RDMReplyTest.cpp \ common/rdm/TestHelper.h common_rdm_RDMReplyTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_rdm_RDMReplyTester_LDADD = $(COMMON_TESTING_LIBS) common_rdm_RDMCommandSerializerTester_SOURCES = \ common/rdm/RDMCommandSerializerTest.cpp \ common/rdm/TestHelper.h common_rdm_RDMCommandSerializerTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_rdm_RDMCommandSerializerTester_LDADD = $(COMMON_TESTING_LIBS) common_rdm_QueueingRDMControllerTester_SOURCES = \ common/rdm/QueueingRDMControllerTest.cpp \ common/rdm/TestHelper.h common_rdm_QueueingRDMControllerTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_rdm_QueueingRDMControllerTester_LDADD = $(COMMON_TESTING_LIBS) common_rdm_UIDAllocatorTester_SOURCES = \ common/rdm/UIDAllocatorTest.cpp common_rdm_UIDAllocatorTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_rdm_UIDAllocatorTester_LDADD = $(COMMON_TESTING_LIBS) common_rdm_UIDTester_SOURCES = \ common/rdm/UIDTest.cpp common_rdm_UIDTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_rdm_UIDTester_LDADD = $(COMMON_TESTING_LIBS) ola-0.10.5.nojsmin/common/rdm/DescriptorConsistencyCheckerTest.cpp0000644000175000017500000002344713023355232024733 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * DescriptorConsistencyCheckerTest.cpp * Test fixture for the DescriptorConsistencyChecker class. * Copyright (C) 2011 Simon Newton */ #include #include #include "ola/Logging.h" #include "ola/messaging/Descriptor.h" #include "common/rdm/DescriptorConsistencyChecker.h" #include "ola/testing/TestUtils.h" using ola::messaging::Descriptor; using ola::messaging::FieldDescriptor; using ola::rdm::DescriptorConsistencyChecker; using std::vector; class DescriptorConsistencyCheckerTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(DescriptorConsistencyCheckerTest); CPPUNIT_TEST(testOkDescriptors); CPPUNIT_TEST(testDuplicateStrings); CPPUNIT_TEST(testGroups); CPPUNIT_TEST(testNestedGroups); CPPUNIT_TEST_SUITE_END(); public: void testOkDescriptors(); void testDuplicateStrings(); void testGroups(); void testNestedGroups(); }; CPPUNIT_TEST_SUITE_REGISTRATION(DescriptorConsistencyCheckerTest); /* * Test the simple Descriptor cases */ void DescriptorConsistencyCheckerTest::testOkDescriptors() { DescriptorConsistencyChecker checker; // test the empty descriptor vector fields; const Descriptor empty_descriptor("Empty", fields); OLA_ASSERT_TRUE(checker.CheckConsistency(&empty_descriptor)); // now a simple multi-field descriptor vector fields2; fields2.push_back(new ola::messaging::UInt8FieldDescriptor("uint8")); fields2.push_back(new ola::messaging::BoolFieldDescriptor("bool")); const Descriptor simple_descriptor("Simple", fields2); OLA_ASSERT_TRUE(checker.CheckConsistency(&simple_descriptor)); // now a multi-field descriptor with a variable string vector fields3; fields3.push_back(new ola::messaging::UInt8FieldDescriptor("uint8")); fields3.push_back( new ola::messaging::StringFieldDescriptor("string1", 0, 32)); const Descriptor simple_string_descriptor("Simple", fields3); OLA_ASSERT_TRUE(checker.CheckConsistency(&simple_string_descriptor)); } /* * Verify that the check fails if the descriptor contains mutiple, variable * length strings. Also check that it passes if there are multiple, fixed * length strings. */ void DescriptorConsistencyCheckerTest::testDuplicateStrings() { DescriptorConsistencyChecker checker; // test fixed length strings vector fields; fields.push_back(new ola::messaging::StringFieldDescriptor("string1", 4, 4)); fields.push_back(new ola::messaging::StringFieldDescriptor("string2", 4, 4)); const Descriptor fixed_length_descriptor("Fixed", fields); OLA_ASSERT_TRUE(checker.CheckConsistency(&fixed_length_descriptor)); // variable length strings vector fields2; fields2.push_back( new ola::messaging::StringFieldDescriptor("string1", 4, 32)); fields2.push_back( new ola::messaging::StringFieldDescriptor("string2", 4, 32)); const Descriptor variable_length_descriptor("Variable", fields2); OLA_ASSERT_FALSE(checker.CheckConsistency(&variable_length_descriptor)); // test one fixed and one variable vector fields3; fields3.push_back( new ola::messaging::StringFieldDescriptor("string1", 4, 4)); fields3.push_back( new ola::messaging::StringFieldDescriptor("string2", 4, 32)); const Descriptor combination_descriptor("Variable", fields3); OLA_ASSERT_TRUE(checker.CheckConsistency(&combination_descriptor)); } /** * Verify that groups produce the correct results */ void DescriptorConsistencyCheckerTest::testGroups() { DescriptorConsistencyChecker checker; // test a single, fixed sized group vector fields, group_fields; group_fields.push_back(new ola::messaging::UInt8FieldDescriptor("uint8")); fields.push_back( new ola::messaging::FieldDescriptorGroup("group", group_fields, 2, 2)); const Descriptor fixed_length_descriptor("SingleFixed", fields); OLA_ASSERT_TRUE(checker.CheckConsistency(&fixed_length_descriptor)); // test multiple, fixed size groups vector fields2, group_fields2, group_fields3; group_fields2.push_back(new ola::messaging::UInt8FieldDescriptor("uint8")); group_fields3.push_back(new ola::messaging::UInt8FieldDescriptor("uint8")); fields2.push_back( new ola::messaging::FieldDescriptorGroup("group1", group_fields2, 2, 2)); fields2.push_back( new ola::messaging::FieldDescriptorGroup("group2", group_fields3, 2, 2)); const Descriptor multiple_fixed_descriptor("MuiltpleFixed", fields2); OLA_ASSERT_TRUE(checker.CheckConsistency(&multiple_fixed_descriptor)); // test a fixed size group, and a variable-sized group vector fields3, group_fields4, group_fields5; group_fields4.push_back(new ola::messaging::UInt8FieldDescriptor("uint8")); group_fields5.push_back(new ola::messaging::UInt8FieldDescriptor("uint8")); fields3.push_back( new ola::messaging::FieldDescriptorGroup("group1", group_fields4, 2, 2)); fields3.push_back( new ola::messaging::FieldDescriptorGroup("group2", group_fields5, 2, 8)); const Descriptor fixed_and_variable_descriptor("Fixed", fields3); OLA_ASSERT_TRUE(checker.CheckConsistency(&fixed_and_variable_descriptor)); // test a variable sized group vector fields4, group_fields6; group_fields6.push_back(new ola::messaging::UInt8FieldDescriptor("uint8")); fields4.push_back( new ola::messaging::FieldDescriptorGroup("group1", group_fields6, 2, 8)); const Descriptor variable_descriptor("Variable", fields4); OLA_ASSERT_TRUE(checker.CheckConsistency(&variable_descriptor)); // test a multiple variable sized groups vector fields5, group_fields7, group_fields8; group_fields7.push_back(new ola::messaging::UInt8FieldDescriptor("uint8")); group_fields8.push_back(new ola::messaging::UInt8FieldDescriptor("uint8")); fields5.push_back( new ola::messaging::FieldDescriptorGroup("group1", group_fields7, 2, 8)); fields5.push_back( new ola::messaging::FieldDescriptorGroup("group1", group_fields8, 2, 8)); const Descriptor multiple_variable_descriptor("Variable", fields5); OLA_ASSERT_FALSE(checker.CheckConsistency(&multiple_variable_descriptor)); } /** * Verify that nested groups produce the correct results. */ void DescriptorConsistencyCheckerTest::testNestedGroups() { DescriptorConsistencyChecker checker; // nested, fixed sized groups vector fields, group_fields1, group_fields2; group_fields1.push_back(new ola::messaging::UInt8FieldDescriptor("uint8")); group_fields1.push_back(new ola::messaging::UInt8FieldDescriptor("uint8")); group_fields2.push_back(new ola::messaging::BoolFieldDescriptor("bool")); group_fields2.push_back( new ola::messaging::FieldDescriptorGroup("", group_fields1, 2, 2)); fields.push_back( new ola::messaging::FieldDescriptorGroup("", group_fields2, 2, 2)); const Descriptor nested_fixed_descriptor("", fields); OLA_ASSERT_TRUE(checker.CheckConsistency(&nested_fixed_descriptor)); // nested, both variable vector fields2, group_fields3, group_fields4; group_fields3.push_back(new ola::messaging::UInt8FieldDescriptor("uint8")); group_fields3.push_back(new ola::messaging::UInt8FieldDescriptor("uint8")); group_fields4.push_back(new ola::messaging::BoolFieldDescriptor("bool")); group_fields4.push_back( new ola::messaging::FieldDescriptorGroup("", group_fields3, 2, 4)); fields2.push_back( new ola::messaging::FieldDescriptorGroup("", group_fields4, 2, 4)); const Descriptor nested_variable_descriptor("", fields2); OLA_ASSERT_FALSE(checker.CheckConsistency(&nested_variable_descriptor)); // variable, containing a fixed size group vector fields3, group_fields5, group_fields6; group_fields5.push_back(new ola::messaging::UInt8FieldDescriptor("uint8")); group_fields5.push_back(new ola::messaging::UInt8FieldDescriptor("uint8")); group_fields6.push_back(new ola::messaging::BoolFieldDescriptor("bool")); group_fields6.push_back( new ola::messaging::FieldDescriptorGroup("", group_fields5, 2, 2)); fields3.push_back( new ola::messaging::FieldDescriptorGroup("", group_fields6, 2, 4)); const Descriptor variable_fixed_descriptor("", fields3); OLA_ASSERT_TRUE(checker.CheckConsistency(&variable_fixed_descriptor)); // fixed, containing a variable sized group vector fields4, group_fields7, group_fields8; group_fields7.push_back(new ola::messaging::UInt8FieldDescriptor("uint8")); group_fields7.push_back(new ola::messaging::UInt8FieldDescriptor("uint8")); group_fields8.push_back(new ola::messaging::BoolFieldDescriptor("bool")); group_fields8.push_back( new ola::messaging::FieldDescriptorGroup("", group_fields7, 2, 4)); fields4.push_back( new ola::messaging::FieldDescriptorGroup("", group_fields8, 2, 2)); const Descriptor fixed_variable_descriptor("", fields4); OLA_ASSERT_FALSE(checker.CheckConsistency(&fixed_variable_descriptor)); } ola-0.10.5.nojsmin/common/rdm/StringMessageBuilderTest.cpp0000644000175000017500000002762313023355232023170 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * StringMessageBuilderTest.cpp * Test fixture for the StringMessageBuilder classes * Copyright (C) 2011 Simon Newton */ #include #include #include #include #include #include "ola/testing/TestUtils.h" #include "ola/Logging.h" #include "ola/messaging/Descriptor.h" #include "ola/messaging/Message.h" #include "ola/messaging/MessagePrinter.h" #include "ola/rdm/StringMessageBuilder.h" using ola::messaging::BoolFieldDescriptor; using ola::messaging::Descriptor; using ola::messaging::FieldDescriptor; using ola::messaging::FieldDescriptorGroup; using ola::messaging::IPV4FieldDescriptor; using ola::messaging::Int16FieldDescriptor; using ola::messaging::Int32FieldDescriptor; using ola::messaging::Int8FieldDescriptor; using ola::messaging::MACFieldDescriptor; using ola::messaging::Message; using ola::messaging::StringFieldDescriptor; using ola::messaging::UInt16FieldDescriptor; using ola::messaging::UInt32FieldDescriptor; using ola::messaging::UInt8FieldDescriptor; using ola::rdm::StringMessageBuilder; using std::auto_ptr; using std::string; using std::vector; class StringBuilderTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(StringBuilderTest); CPPUNIT_TEST(testSimpleBuilder); CPPUNIT_TEST(testBuilderWithLabels); CPPUNIT_TEST(testBuilderWithGroups); CPPUNIT_TEST(testBuilderWithNestedGroups); CPPUNIT_TEST(testBuilderWithVariableNestedGroups); CPPUNIT_TEST(testBoolFailure); CPPUNIT_TEST(testUIntFailure); CPPUNIT_TEST(testIntFailure); CPPUNIT_TEST(testStringFailure); CPPUNIT_TEST_SUITE_END(); public: void testSimpleBuilder(); void testBuilderWithLabels(); void testBuilderWithGroups(); void testBuilderWithNestedGroups(); void testBuilderWithVariableNestedGroups(); void testBoolFailure(); void testUIntFailure(); void testIntFailure(); void testStringFailure(); private: ola::messaging::GenericMessagePrinter m_printer; const Message *BuildMessage(const Descriptor &descriptor, const vector &inputs); }; CPPUNIT_TEST_SUITE_REGISTRATION(StringBuilderTest); /** * Build a message from a given set of inputs and return the string * representation of the message. */ const Message *StringBuilderTest::BuildMessage( const Descriptor &descriptor, const vector &inputs) { StringMessageBuilder builder; const Message *message = builder.GetMessage(inputs, &descriptor); if (!message) OLA_WARN << "Error with field: " << builder.GetError(); return message; } /** * Check the StringBuilder works. */ void StringBuilderTest::testSimpleBuilder() { // build the descriptor vector fields; fields.push_back(new BoolFieldDescriptor("bool1")); fields.push_back(new BoolFieldDescriptor("bool2")); fields.push_back(new BoolFieldDescriptor("bool3")); fields.push_back(new BoolFieldDescriptor("bool4")); fields.push_back(new BoolFieldDescriptor("bool5")); fields.push_back(new BoolFieldDescriptor("bool6")); fields.push_back(new IPV4FieldDescriptor("ip1")); fields.push_back(new MACFieldDescriptor("mac1")); fields.push_back(new UInt8FieldDescriptor("uint8")); fields.push_back(new UInt16FieldDescriptor("uint16")); fields.push_back(new UInt32FieldDescriptor("uint32")); fields.push_back(new Int8FieldDescriptor("int8")); fields.push_back(new Int16FieldDescriptor("int16")); fields.push_back(new Int32FieldDescriptor("int32")); fields.push_back(new StringFieldDescriptor("string", 0, 32)); fields.push_back(new UInt16FieldDescriptor("hex uint16")); Descriptor descriptor("Test Descriptor", fields); // now setup the inputs vector inputs; inputs.push_back("true"); inputs.push_back("false"); inputs.push_back("1"); inputs.push_back("0"); inputs.push_back("TRUE"); inputs.push_back("FALSE"); inputs.push_back("10.0.0.1"); inputs.push_back("01:23:45:67:89:ab"); inputs.push_back("255"); inputs.push_back("300"); inputs.push_back("66000"); inputs.push_back("-128"); inputs.push_back("-300"); inputs.push_back("-66000"); inputs.push_back("foo"); inputs.push_back("0x400"); auto_ptr message(BuildMessage(descriptor, inputs)); // verify OLA_ASSERT_TRUE(message.get()); OLA_ASSERT_EQ(static_cast(fields.size()), message->FieldCount()); string expected = ( "bool1: true\nbool2: false\nbool3: true\nbool4: false\nbool5: true\n" "bool6: false\nip1: 10.0.0.1\nmac1: 01:23:45:67:89:ab\nuint8: 255\n" "uint16: 300\nuint32: 66000\nint8: -128\nint16: -300\nint32: -66000\n" "string: foo\nhex uint16: 1024\n"); OLA_ASSERT_EQ(expected, m_printer.AsString(message.get())); } /** * Check the builder accepts labels */ void StringBuilderTest::testBuilderWithLabels() { // build the descriptor UInt8FieldDescriptor::IntervalVector intervals; UInt8FieldDescriptor::LabeledValues labels; labels["dozen"] = 12; labels["bakers_dozen"] = 13; vector fields; fields.push_back(new UInt8FieldDescriptor("uint8", intervals, labels)); Descriptor descriptor("Test Descriptor", fields); // now setup the inputs vector inputs; inputs.push_back("dozen"); auto_ptr message(BuildMessage(descriptor, inputs)); // verify OLA_ASSERT_NOT_NULL(message.get()); OLA_ASSERT_EQ(static_cast(fields.size()), message->FieldCount()); string expected = "uint8: dozen\n"; OLA_ASSERT_EQ(expected, m_printer.AsString(message.get())); } /** * Check the StringBuilder works with variable sized groups. */ void StringBuilderTest::testBuilderWithGroups() { // build the descriptor vector group_fields; group_fields.push_back(new BoolFieldDescriptor("bool")); group_fields.push_back(new UInt8FieldDescriptor("uint8")); vector fields; fields.push_back(new FieldDescriptorGroup("group", group_fields, 0, 3)); Descriptor descriptor("Test Descriptor", fields); // now setup the inputs vector inputs; inputs.push_back("true"); inputs.push_back("10"); auto_ptr message(BuildMessage(descriptor, inputs)); // verify OLA_ASSERT_TRUE(message.get()); OLA_ASSERT_EQ(1u, message->FieldCount()); string expected = ( "group {\n bool: true\n uint8: 10\n}\n"); OLA_ASSERT_EQ(expected, m_printer.AsString(message.get())); // now do multiple groups vector inputs2; inputs2.push_back("true"); inputs2.push_back("10"); inputs2.push_back("true"); inputs2.push_back("42"); inputs2.push_back("false"); inputs2.push_back("240"); auto_ptr message2(BuildMessage(descriptor, inputs2)); // verify OLA_ASSERT_NOT_NULL(message2.get()); OLA_ASSERT_EQ(3u, message2->FieldCount()); string expected2 = ( "group {\n bool: true\n uint8: 10\n}\n" "group {\n bool: true\n uint8: 42\n}\n" "group {\n bool: false\n uint8: 240\n}\n"); OLA_ASSERT_EQ(expected2, m_printer.AsString(message2.get())); // now provide too many inputs inputs2.clear(); inputs2.push_back("true"); inputs2.push_back("10"); inputs2.push_back("true"); inputs2.push_back("42"); inputs2.push_back("false"); inputs2.push_back("240"); inputs2.push_back("false"); inputs2.push_back("53"); OLA_ASSERT_NULL(BuildMessage(descriptor, inputs2)); } /** * test StringBuilder with nested fixed groups */ void StringBuilderTest::testBuilderWithNestedGroups() { vector fields, group_fields, group_fields2; group_fields.push_back(new BoolFieldDescriptor("bool")); group_fields2.push_back(new Int16FieldDescriptor("int16")); group_fields2.push_back(new FieldDescriptorGroup("bar", group_fields, 2, 2)); const FieldDescriptorGroup *nested_group = new FieldDescriptorGroup( "", group_fields2, 0, 4); fields.push_back(nested_group); Descriptor descriptor("Test Descriptor", fields); vector inputs; inputs.push_back("1"); inputs.push_back("true"); inputs.push_back("true"); auto_ptr message(BuildMessage(descriptor, inputs)); // verify OLA_ASSERT_NOT_NULL(message.get()); OLA_ASSERT_EQ(1u, message->FieldCount()); string expected = ( " {\n int16: 1\n bar {\n bool: true\n }\n" " bar {\n bool: true\n }\n}\n"); OLA_ASSERT_EQ(expected, m_printer.AsString(message.get())); } /** * test StringBuilder with nested varible groups. */ void StringBuilderTest::testBuilderWithVariableNestedGroups() { vector fields, group_fields, group_fields2; group_fields.push_back(new BoolFieldDescriptor("bool")); group_fields.push_back(new UInt8FieldDescriptor("uint8")); group_fields2.push_back(new Int16FieldDescriptor("int16")); group_fields2.push_back(new FieldDescriptorGroup("", group_fields, 0, 2)); const FieldDescriptorGroup *nested_variable_group = new FieldDescriptorGroup( "", group_fields2, 0, 4); fields.push_back(new Int16FieldDescriptor("int16")); fields.push_back(nested_variable_group); Descriptor descriptor("Test Descriptor", fields); vector inputs; OLA_ASSERT_NULL(BuildMessage(descriptor, inputs)); } /** * Test that the bool parsing fails with bad data. */ void StringBuilderTest::testBoolFailure() { vector fields; fields.push_back(new BoolFieldDescriptor("bool1")); Descriptor descriptor("Test Descriptor", fields); // bad string input vector inputs; inputs.push_back("foo"); OLA_ASSERT_FALSE(BuildMessage(descriptor, inputs)); // bad int input vector inputs2; inputs2.push_back("2"); OLA_ASSERT_FALSE(BuildMessage(descriptor, inputs2)); } /** * Test that the int parsing fails with bad data. */ void StringBuilderTest::testUIntFailure() { vector fields; fields.push_back(new UInt8FieldDescriptor("uint8")); Descriptor descriptor("Test Descriptor", fields); // bad uint8 input vector inputs; inputs.push_back("a"); OLA_ASSERT_FALSE(BuildMessage(descriptor, inputs)); vector inputs2; inputs2.push_back("-1"); OLA_ASSERT_FALSE(BuildMessage(descriptor, inputs2)); vector inputs3; inputs3.push_back("256"); OLA_ASSERT_FALSE(BuildMessage(descriptor, inputs3)); } /** * Test that the int parsing fails with bad data. */ void StringBuilderTest::testIntFailure() { vector fields; fields.push_back(new Int8FieldDescriptor("int8")); Descriptor descriptor("Test Descriptor", fields); // bad uint8 input vector inputs; inputs.push_back("a"); OLA_ASSERT_FALSE(BuildMessage(descriptor, inputs)); vector inputs2; inputs2.push_back("-129"); OLA_ASSERT_FALSE(BuildMessage(descriptor, inputs2)); vector inputs3; inputs3.push_back("128"); OLA_ASSERT_FALSE(BuildMessage(descriptor, inputs3)); } /** * Test that the int parsing fails with bad data. */ void StringBuilderTest::testStringFailure() { vector fields; fields.push_back(new StringFieldDescriptor("string", 0, 10)); Descriptor descriptor("Test Descriptor", fields); // bad string input vector inputs; inputs.push_back("this is a very long string"); OLA_ASSERT_FALSE(BuildMessage(descriptor, inputs)); } ola-0.10.5.nojsmin/common/rdm/PidStore.cpp0000644000175000017500000001451313023355232017771 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * PidStore.cpp * The PidStore and Pid classes. * Copyright (C) 2011 Simon Newton */ #include #include #include "common/rdm/PidStoreLoader.h" #include "ola/StringUtils.h" #include "ola/rdm/PidStore.h" #include "ola/rdm/RDMEnums.h" #include "ola/stl/STLUtils.h" namespace ola { namespace rdm { using std::string; using std::vector; RootPidStore::~RootPidStore() { m_esta_store.reset(); STLDeleteValues(&m_manufacturer_store); } const PidStore *RootPidStore::ManufacturerStore(uint16_t esta_id) const { ManufacturerMap::const_iterator iter = m_manufacturer_store.find(esta_id); if (iter == m_manufacturer_store.end()) return NULL; return iter->second; } const PidDescriptor *RootPidStore::GetDescriptor( const string &pid_name) const { string canonical_pid_name = pid_name; ola::ToUpper(&canonical_pid_name); return InternalESTANameLookup(canonical_pid_name); } const PidDescriptor *RootPidStore::GetDescriptor( const string &pid_name, uint16_t manufacturer_id) const { string canonical_pid_name = pid_name; ola::ToUpper(&canonical_pid_name); const PidDescriptor *descriptor = InternalESTANameLookup(canonical_pid_name); if (descriptor) return descriptor; // now try the specific manufacturer store const PidStore *store = ManufacturerStore(manufacturer_id); if (store) return store->LookupPID(canonical_pid_name); return NULL; } const PidDescriptor *RootPidStore::GetDescriptor(uint16_t pid_value) const { if (m_esta_store.get()) { const PidDescriptor *descriptor = m_esta_store->LookupPID(pid_value); if (descriptor) return descriptor; } return NULL; } const PidDescriptor *RootPidStore::GetDescriptor( uint16_t pid_value, uint16_t manufacturer_id) const { const PidDescriptor *descriptor = GetDescriptor(pid_value); if (descriptor) return descriptor; // now try the specific manufacturer store const PidStore *store = ManufacturerStore(manufacturer_id); if (store) { const PidDescriptor *descriptor = store->LookupPID(pid_value); if (descriptor) return descriptor; } return NULL; } const PidDescriptor *RootPidStore::InternalESTANameLookup( const string &canonical_pid_name) const { if (m_esta_store.get()) { const PidDescriptor *descriptor = m_esta_store->LookupPID( canonical_pid_name); if (descriptor) return descriptor; } return NULL; } const RootPidStore *RootPidStore::LoadFromFile(const string &file, bool validate) { PidStoreLoader loader; return loader.LoadFromFile(file, validate); } const RootPidStore *RootPidStore::LoadFromDirectory( const string &directory, bool validate) { PidStoreLoader loader; string data_source = directory; if (directory.empty()) { data_source = DataLocation(); } return loader.LoadFromDirectory(data_source, validate); } const string RootPidStore::DataLocation() { // Provided at compile time. return PID_DATA_DIR; } PidStore::PidStore(const vector &pids) { vector::const_iterator iter = pids.begin(); for (; iter != pids.end(); ++iter) { m_pid_by_value[(*iter)->Value()] = *iter; m_pid_by_name[(*iter)->Name()] = *iter; } } PidStore::~PidStore() { STLDeleteValues(&m_pid_by_value); m_pid_by_name.clear(); } void PidStore::AllPids(vector *pids) const { pids->reserve(pids->size() + m_pid_by_value.size()); PidMap::const_iterator iter = m_pid_by_value.begin(); for (; iter != m_pid_by_value.end(); ++iter) { pids->push_back(iter->second); } } /** * Clean up */ PidDescriptor::~PidDescriptor() { delete m_get_request; delete m_get_response; delete m_set_request; delete m_set_response; } /** * Lookup a PID by value. * @param pid_value the 16 bit pid value. */ const PidDescriptor *PidStore::LookupPID(uint16_t pid_value) const { PidMap::const_iterator iter = m_pid_by_value.find(pid_value); if (iter == m_pid_by_value.end()) return NULL; else return iter->second; } /** * Lookup a PID by name * @param pid_name the name of the pid. */ const PidDescriptor *PidStore::LookupPID(const string &pid_name) const { PidNameMap::const_iterator iter = m_pid_by_name.find(pid_name); if (iter == m_pid_by_name.end()) return NULL; else return iter->second; } /** * Check if a GET request to this subdevice is valid * @param sub_device the sub device for this request. * @returns true if the request is valid, false otherwise. */ bool PidDescriptor::IsGetValid(uint16_t sub_device) const { return m_get_request && RequestValid(sub_device, m_get_subdevice_range); } /** * Check if a SET request to this subdevice is valid * @param sub_device the sub device for this request. * @returns true if the request is valid, false otherwise. */ bool PidDescriptor::IsSetValid(uint16_t sub_device) const { return m_set_request && RequestValid(sub_device, m_set_subdevice_range); } /** * Returns is a request is valid */ bool PidDescriptor::RequestValid(uint16_t sub_device, const sub_device_validator &validator) const { switch (validator) { case ROOT_DEVICE: // 0 only return sub_device == 0; case ANY_SUB_DEVICE: // 0 - 512 of ALL_RDM_SUBDEVICES return (sub_device <= MAX_SUBDEVICE_NUMBER || sub_device == ALL_RDM_SUBDEVICES); case NON_BROADCAST_SUB_DEVICE: // 0 - 512 return sub_device <= MAX_SUBDEVICE_NUMBER; case SPECIFIC_SUB_DEVICE: // 1 - 512 return sub_device > 0 && sub_device <= MAX_SUBDEVICE_NUMBER; default: return false; } } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/MessageSerializer.cpp0000644000175000017500000001214613023355232021656 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * MessageSerializer.cpp * Prints the test representation of a Message. * Copyright (C) 2011 Simon Newton */ #include #include #include #include #include namespace ola { namespace rdm { MessageSerializer::MessageSerializer(unsigned int initial_size) : m_data(NULL), m_offset(0), m_buffer_size(0), m_initial_buffer_size(initial_size) { } MessageSerializer::~MessageSerializer() { if (m_data) { delete[] m_data; } } /** * Serialize a message and return a pointer to the message in memory */ const uint8_t *MessageSerializer::SerializeMessage( const ola::messaging::Message *message, unsigned int *length) { if (!m_data) { m_buffer_size = m_initial_buffer_size; m_data = new uint8_t[m_buffer_size]; } m_offset = 0; message->Accept(this); *length = m_offset; return m_data; } void MessageSerializer::Visit( const ola::messaging::BoolMessageField *message) { CheckForFreeSpace(message->GetDescriptor()->MaxSize()); m_data[m_offset++] = message->Value(); } void MessageSerializer::Visit( const ola::messaging::IPV4MessageField *message) { CheckForFreeSpace(message->GetDescriptor()->MaxSize()); uint32_t data = message->Value().AsInt(); memcpy(m_data + m_offset, reinterpret_cast(&data), sizeof(data)); m_offset += sizeof(data); } void MessageSerializer::Visit( const ola::messaging::MACMessageField *message) { unsigned int size = message->GetDescriptor()->MaxSize(); CheckForFreeSpace(size); message->Value().Pack(m_data + m_offset, size); m_offset += size; } void MessageSerializer::Visit( const ola::messaging::UIDMessageField *message) { unsigned int size = message->GetDescriptor()->MaxSize(); CheckForFreeSpace(size); message->Value().Pack(m_data + m_offset, size); m_offset += size; } void MessageSerializer::Visit( const ola::messaging::StringMessageField *message) { unsigned int size = std::min( static_cast(message->Value().size()), message->GetDescriptor()->MaxSize()); unsigned int used_size = std::max( size, message->GetDescriptor()->MinSize()); CheckForFreeSpace(size); memcpy(m_data + m_offset, message->Value().c_str(), size); memset(m_data + m_offset + size, 0, used_size - size); m_offset += used_size; } void MessageSerializer::Visit( const ola::messaging::BasicMessageField *message) { IntVisit(message); } void MessageSerializer::Visit( const ola::messaging::BasicMessageField *message) { IntVisit(message); } void MessageSerializer::Visit( const ola::messaging::BasicMessageField *message) { IntVisit(message); } void MessageSerializer::Visit( const ola::messaging::BasicMessageField *message) { IntVisit(message); } void MessageSerializer::Visit( const ola::messaging::BasicMessageField *message) { IntVisit(message); } void MessageSerializer::Visit( const ola::messaging::BasicMessageField *message) { IntVisit(message); } void MessageSerializer::Visit( const ola::messaging::GroupMessageField *message) { (void) message; } void MessageSerializer::PostVisit( const ola::messaging::GroupMessageField *message) { (void) message; } /** * Check that there is at least required_size bytes of space left, if not * expand the memory so the new data can fit. */ void MessageSerializer::CheckForFreeSpace(unsigned int required_size) { if (m_buffer_size - m_offset > required_size) { return; } uint8_t *old_buffer = m_data; m_data = new uint8_t[2 * m_buffer_size]; memcpy(m_data, old_buffer, m_offset); delete[] old_buffer; } /** * Serialize an integer value, converting to little endian if needed */ template void MessageSerializer::IntVisit( const ola::messaging::BasicMessageField *message) { CheckForFreeSpace(sizeof(int_type)); int_type value; if (message->GetDescriptor()->IsLittleEndian()) { value = ola::network::HostToLittleEndian( static_cast(message->Value())); } else { value = ola::network::HostToNetwork( static_cast(message->Value())); } uint8_t *ptr = reinterpret_cast(&value); memcpy(m_data + m_offset, ptr, sizeof(int_type)); m_offset += sizeof(int_type); } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/RDMHelper.cpp0000644000175000017500000010131013023355232020012 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * RDMHelper.cpp * Various misc RDM functions. * Copyright (C) 2010 Simon Newton * * At some point we may want to localize this file. */ #include #include #include #include "ola/rdm/RDMHelper.h" #include "ola/StringUtils.h" namespace ola { namespace rdm { using std::ostringstream; using std::string; using std::vector; /** * Convert a RDMStatusCode to a string */ string StatusCodeToString(RDMStatusCode status) { switch (status) { case RDM_COMPLETED_OK: return "Completed Ok"; case RDM_WAS_BROADCAST: return "Request was broadcast"; case RDM_FAILED_TO_SEND: return "Failed to send request"; case RDM_TIMEOUT: return "Response Timeout"; case RDM_INVALID_RESPONSE: return "Invalid Response"; case RDM_UNKNOWN_UID: return "The RDM device could not be found"; case RDM_CHECKSUM_INCORRECT: return "Incorrect checksum"; case RDM_TRANSACTION_MISMATCH: return "Transaction number mismatch"; case RDM_SUB_DEVICE_MISMATCH: return "Sub device mismatch"; case RDM_SRC_UID_MISMATCH: return "Source UID in response doesn't match"; case RDM_DEST_UID_MISMATCH: return "Destination UID in response doesn't match"; case RDM_WRONG_SUB_START_CODE: return "Incorrect sub start code"; case RDM_PACKET_TOO_SHORT: return "RDM response was smaller than the minimum size"; case RDM_PACKET_LENGTH_MISMATCH: return "The length field of packet didn't match length received"; case RDM_PARAM_LENGTH_MISMATCH: return "The parameter length exceeds the remaining packet size"; case RDM_INVALID_COMMAND_CLASS: return "The command class was not one of GET_RESPONSE or SET_RESPONSE"; case RDM_COMMAND_CLASS_MISMATCH: return "The command class didn't match the request"; case RDM_INVALID_RESPONSE_TYPE: return "The response type was not ACK, ACK_OVERFLOW, ACK_TIMER or NACK"; case RDM_PLUGIN_DISCOVERY_NOT_SUPPORTED: return "The output plugin does not support DISCOVERY commands"; case RDM_DUB_RESPONSE: return "DUB response"; default: return "Unknown"; } } /** * Convert a uint8_t representing a data type to a human-readable string. * @param type the data type value */ string DataTypeToString(uint8_t type) { switch (type) { case DS_NOT_DEFINED: return "Not defined"; case DS_BIT_FIELD: return "Bit field"; case DS_ASCII: return "ASCII"; case DS_UNSIGNED_BYTE: return "uint8"; case DS_SIGNED_BYTE: return "int8"; case DS_UNSIGNED_WORD: return "uint16"; case DS_SIGNED_WORD: return "int16"; case DS_UNSIGNED_DWORD: return "uint32"; case DS_SIGNED_DWORD: return "int32"; default: ostringstream str; str << "Unknown, was " << static_cast(type); return str.str(); } } /** * Convert a uint8_t representing a lamp mode to a human-readable string. * @param lamp_mode the lamp mode value */ string LampModeToString(uint8_t lamp_mode) { switch (lamp_mode) { case LAMP_ON_MODE_OFF: return "Off"; case LAMP_ON_MODE_DMX: return "DMX"; case LAMP_ON_MODE_ON: return "On"; case LAMP_ON_MODE_ON_AFTER_CAL: return "On after calibration"; default: ostringstream str; str << "Unknown, was " << static_cast(lamp_mode); return str.str(); } } /** * Convert a uint8_t representing a lamp state to a human-readable string. * @param lamp_state the lamp state value */ string LampStateToString(uint8_t lamp_state) { switch (lamp_state) { case LAMP_OFF: return "Off"; case LAMP_ON: return "On"; case LAMP_STRIKE: return "Strike"; case LAMP_STANDBY: return "Standby"; case LAMP_NOT_PRESENT: return "Lamp not present"; case LAMP_ERROR: return "Error"; default: ostringstream str; str << "Unknown, was " << static_cast(lamp_state); return str.str(); } } /** * Convert a uint16_t representing a nack reason to a human-readable string. * @param reason the nack reason value */ string NackReasonToString(uint16_t reason) { switch (reason) { case NR_UNKNOWN_PID: return "Unknown PID"; case NR_FORMAT_ERROR: return "Format error"; case NR_HARDWARE_FAULT: return "Hardware fault"; case NR_PROXY_REJECT: return "Proxy reject"; case NR_WRITE_PROTECT: return "Write protect"; case NR_UNSUPPORTED_COMMAND_CLASS: return "Unsupported command class"; case NR_DATA_OUT_OF_RANGE: return "Data out of range"; case NR_BUFFER_FULL: return "Buffer full"; case NR_PACKET_SIZE_UNSUPPORTED: return "Packet size unsupported"; case NR_SUB_DEVICE_OUT_OF_RANGE: return "Sub device out of range"; case NR_PROXY_BUFFER_FULL: return "Proxy buffer full"; case NR_ACTION_NOT_SUPPORTED: return "Action not supported"; case NR_ENDPOINT_NUMBER_INVALID: return "Invalid endpoint"; default: ostringstream str; str << "Unknown, was " << reason; return str.str(); } } /** * Convert a uint8_t representing a power state to a human-readable string. * @param power_state the power state value */ string PowerStateToString(uint8_t power_state) { switch (power_state) { case POWER_STATE_FULL_OFF: return "Full Off"; case POWER_STATE_SHUTDOWN: return "Shutdown"; case POWER_STATE_STANDBY: return "Standby"; case POWER_STATE_NORMAL: return "Normal"; default: ostringstream str; str << "Unknown, was " << static_cast(power_state); return str.str(); } } /** * Safely convert a uint8_t to a rdm_power_state */ bool UIntToPowerState(uint8_t state, rdm_power_state *power_state) { switch (state) { case POWER_STATE_FULL_OFF: *power_state = POWER_STATE_FULL_OFF; return true; case POWER_STATE_SHUTDOWN: *power_state = POWER_STATE_SHUTDOWN; return true; case POWER_STATE_STANDBY: *power_state = POWER_STATE_STANDBY; return true; case POWER_STATE_NORMAL: *power_state = POWER_STATE_NORMAL; return true; default: return false; } } /** * Convert a uint8 representing a prefix to a human-readable string. * @param prefix the prefix value */ string PrefixToString(uint8_t prefix) { switch (prefix) { case PREFIX_NONE: return ""; case PREFIX_DECI: return "Deci"; case PREFIX_CENTI: return "Centi"; case PREFIX_MILLI: return "Milli"; case PREFIX_MICRO: return "Micro"; case PREFIX_NANO: return "Nano"; case PREFIX_PICO: return "Pico"; case PREFIX_FEMPTO: return "Fempto"; case PREFIX_ATTO: return "Atto"; case PREFIX_ZEPTO: return "Zepto"; case PREFIX_YOCTO: return "Yocto"; case PREFIX_DECA: return "Deca"; case PREFIX_HECTO: return "Hecto"; case PREFIX_KILO: return "Kilo"; case PREFIX_MEGA: return "Mega"; case PREFIX_GIGA: return "Giga"; case PREFIX_TERRA: return "Terra"; case PREFIX_PETA: return "Peta"; case PREFIX_EXA: return "Exa"; case PREFIX_ZETTA: return "Zetta"; case PREFIX_YOTTA: return "Yotta"; default: ostringstream str; str << "Unknown, was " << static_cast(prefix); return str.str(); } } /** * Convert a uint16_t representing a product category to a human-readable * string. * @param category the product category value */ string ProductCategoryToString(uint16_t category) { switch (category) { case PRODUCT_CATEGORY_NOT_DECLARED: return "Not declared"; case PRODUCT_CATEGORY_FIXTURE: return "Fixture"; case PRODUCT_CATEGORY_FIXTURE_FIXED: return "Fixed fixture"; case PRODUCT_CATEGORY_FIXTURE_MOVING_YOKE: return "Moving yoke fixture"; case PRODUCT_CATEGORY_FIXTURE_MOVING_MIRROR: return "Moving mirror fixture"; case PRODUCT_CATEGORY_FIXTURE_OTHER: return "Fixture other"; case PRODUCT_CATEGORY_FIXTURE_ACCESSORY: return "Fixture accessory"; case PRODUCT_CATEGORY_FIXTURE_ACCESSORY_COLOR: return "Fixture accessory color"; case PRODUCT_CATEGORY_FIXTURE_ACCESSORY_YOKE: return "Fixture accessory yoke"; case PRODUCT_CATEGORY_FIXTURE_ACCESSORY_MIRROR: return "Fixture accessory mirror"; case PRODUCT_CATEGORY_FIXTURE_ACCESSORY_EFFECT: return "Fixture accessory effect"; case PRODUCT_CATEGORY_FIXTURE_ACCESSORY_BEAM: return "Fixture accessory beam"; case PRODUCT_CATEGORY_FIXTURE_ACCESSORY_OTHER: return "Fixture accessory other"; case PRODUCT_CATEGORY_PROJECTOR: return "Projector"; case PRODUCT_CATEGORY_PROJECTOR_FIXED: return "Projector fixed"; case PRODUCT_CATEGORY_PROJECTOR_MOVING_YOKE: return "Projector moving yoke"; case PRODUCT_CATEGORY_PROJECTOR_MOVING_MIRROR: return "Projector moving mirror"; case PRODUCT_CATEGORY_PROJECTOR_OTHER: return "Projector other"; case PRODUCT_CATEGORY_ATMOSPHERIC: return "Atmospheric"; case PRODUCT_CATEGORY_ATMOSPHERIC_EFFECT: return "Atmospheric effect"; case PRODUCT_CATEGORY_ATMOSPHERIC_PYRO: return "Atmospheric pyro"; case PRODUCT_CATEGORY_ATMOSPHERIC_OTHER: return "Atmospheric other"; case PRODUCT_CATEGORY_DIMMER: return "Dimmer"; case PRODUCT_CATEGORY_DIMMER_AC_INCANDESCENT: return "Dimmer AC incandescent"; case PRODUCT_CATEGORY_DIMMER_AC_FLUORESCENT: return "Dimmer AC fluorescent"; case PRODUCT_CATEGORY_DIMMER_AC_COLDCATHODE: return "Dimmer AC cold cathode"; case PRODUCT_CATEGORY_DIMMER_AC_NONDIM: return "Dimmer AC no dim"; case PRODUCT_CATEGORY_DIMMER_AC_ELV: return "Dimmer AC ELV"; case PRODUCT_CATEGORY_DIMMER_AC_OTHER: return "Dimmer AC other"; case PRODUCT_CATEGORY_DIMMER_DC_LEVEL: return "Dimmer DC level"; case PRODUCT_CATEGORY_DIMMER_DC_PWM: return "Dimmer DC PWM"; case PRODUCT_CATEGORY_DIMMER_CS_LED: return "Dimmer DC LED"; case PRODUCT_CATEGORY_DIMMER_OTHER: return "Dimmer other"; case PRODUCT_CATEGORY_POWER: return "Power"; case PRODUCT_CATEGORY_POWER_CONTROL: return "Power control"; case PRODUCT_CATEGORY_POWER_SOURCE: return "Power source"; case PRODUCT_CATEGORY_POWER_OTHER: return "Power other"; case PRODUCT_CATEGORY_SCENIC: return "Scenic"; case PRODUCT_CATEGORY_SCENIC_DRIVE: return "Scenic drive"; case PRODUCT_CATEGORY_SCENIC_OTHER: return "Scenic other"; case PRODUCT_CATEGORY_DATA: return "Data"; case PRODUCT_CATEGORY_DATA_DISTRIBUTION: return "Data distribution"; case PRODUCT_CATEGORY_DATA_CONVERSION: return "Data conversion"; case PRODUCT_CATEGORY_DATA_OTHER: return "Data other"; case PRODUCT_CATEGORY_AV: return "A/V"; case PRODUCT_CATEGORY_AV_AUDIO: return "A/V audio"; case PRODUCT_CATEGORY_AV_VIDEO: return "A/V video"; case PRODUCT_CATEGORY_AV_OTHER: return "AV other"; case PRODUCT_CATEGORY_MONITOR: return "Monitor"; case PRODUCT_CATEGORY_MONITOR_ACLINEPOWER: return "AC line power monitor"; case PRODUCT_CATEGORY_MONITOR_DCPOWER: return "DC power monitor"; case PRODUCT_CATEGORY_MONITOR_ENVIRONMENTAL: return "Environmental monitor"; case PRODUCT_CATEGORY_MONITOR_OTHER: return "Other monitor"; case PRODUCT_CATEGORY_CONTROL: return "Control"; case PRODUCT_CATEGORY_CONTROL_CONTROLLER: return "Controller"; case PRODUCT_CATEGORY_CONTROL_BACKUPDEVICE: return "Backup device"; case PRODUCT_CATEGORY_CONTROL_OTHER: return "Other control"; case PRODUCT_CATEGORY_TEST: return "Test"; case PRODUCT_CATEGORY_TEST_EQUIPMENT: return "Test equipment"; case PRODUCT_CATEGORY_TEST_EQUIPMENT_OTHER: return "Test equipment other"; case PRODUCT_CATEGORY_OTHER: return "Other"; default: ostringstream str; str << "Unknown, was " << static_cast(category); return str.str(); } } /** * Convert a uint16_t representing a product detail to a human-readable string. * @param detail the product detail value. */ string ProductDetailToString(uint16_t detail) { switch (detail) { case PRODUCT_DETAIL_NOT_DECLARED: return "Not declared"; case PRODUCT_DETAIL_ARC: return "Arc Lamp"; case PRODUCT_DETAIL_METAL_HALIDE: return "Metal Halide Lamp"; case PRODUCT_DETAIL_INCANDESCENT: return "Incandescent Lamp"; case PRODUCT_DETAIL_LED: return "LED"; case PRODUCT_DETAIL_FLUORESCENT: return "Fluorescent"; case PRODUCT_DETAIL_COLDCATHODE: return "Cold Cathode"; case PRODUCT_DETAIL_ELECTROLUMINESCENT: return "Electro-luminescent"; case PRODUCT_DETAIL_LASER: return "Laser"; case PRODUCT_DETAIL_FLASHTUBE: return "Flash Tube"; case PRODUCT_DETAIL_COLORSCROLLER: return "Color Scroller"; case PRODUCT_DETAIL_COLORWHEEL: return "Color Wheel"; case PRODUCT_DETAIL_COLORCHANGE: return "Color Changer (Semaphore or other type)"; case PRODUCT_DETAIL_IRIS_DOUSER: return "Iris"; case PRODUCT_DETAIL_DIMMING_SHUTTER: return "Dimming Shuttle"; case PRODUCT_DETAIL_PROFILE_SHUTTER: return "Profile Shuttle"; case PRODUCT_DETAIL_BARNDOOR_SHUTTER: return "Barndoor Shuttle"; case PRODUCT_DETAIL_EFFECTS_DISC: return "Effects Disc"; case PRODUCT_DETAIL_GOBO_ROTATOR: return "Gobo Rotator"; case PRODUCT_DETAIL_VIDEO: return "Video"; case PRODUCT_DETAIL_SLIDE: return "Slide"; case PRODUCT_DETAIL_FILM: return "Film"; case PRODUCT_DETAIL_OILWHEEL: return "Oil Wheel"; case PRODUCT_DETAIL_LCDGATE: return "LCD Gate"; case PRODUCT_DETAIL_FOGGER_GLYCOL: return "Fogger, Glycol"; case PRODUCT_DETAIL_FOGGER_MINERALOIL: return "Fogger, Mineral Oil"; case PRODUCT_DETAIL_FOGGER_WATER: return "Fogger, Water"; case PRODUCT_DETAIL_CO2: return "Dry Ice/ Carbon Dioxide Device"; case PRODUCT_DETAIL_LN2: return "Nitrogen based"; case PRODUCT_DETAIL_BUBBLE: return "Bubble or Foam Machine"; case PRODUCT_DETAIL_FLAME_PROPANE: return "Propane Flame"; case PRODUCT_DETAIL_FLAME_OTHER: return "Other Flame"; case PRODUCT_DETAIL_OLEFACTORY_STIMULATOR: return "Scents"; case PRODUCT_DETAIL_SNOW: return "Snow Machine"; case PRODUCT_DETAIL_WATER_JET: return "Water Jet"; case PRODUCT_DETAIL_WIND: return "Wind Machine"; case PRODUCT_DETAIL_CONFETTI: return "Confetti Machine"; case PRODUCT_DETAIL_HAZARD: return "Hazard (Any form of pyrotechnic control or device.)"; case PRODUCT_DETAIL_PHASE_CONTROL: return "Phase Control"; case PRODUCT_DETAIL_REVERSE_PHASE_CONTROL: return "Phase Angle"; case PRODUCT_DETAIL_SINE: return "Sine"; case PRODUCT_DETAIL_PWM: return "PWM"; case PRODUCT_DETAIL_DC: return "DC"; case PRODUCT_DETAIL_HFBALLAST: return "HF Ballast"; case PRODUCT_DETAIL_HFHV_NEONBALLAST: return "HFHV Neon/Argon"; case PRODUCT_DETAIL_HFHV_EL: return "HFHV Electroluminscent"; case PRODUCT_DETAIL_MHR_BALLAST: return "Metal Halide Ballast"; case PRODUCT_DETAIL_BITANGLE_MODULATION: return "Bit Angle Modulation"; case PRODUCT_DETAIL_FREQUENCY_MODULATION: return "Frequency Modulation"; case PRODUCT_DETAIL_HIGHFREQUENCY_12V: return "High Frequency 12V"; case PRODUCT_DETAIL_RELAY_MECHANICAL: return "Mechanical Relay"; case PRODUCT_DETAIL_RELAY_ELECTRONIC: return "Electronic Relay"; case PRODUCT_DETAIL_SWITCH_ELECTRONIC: return "Electronic Switch"; case PRODUCT_DETAIL_CONTACTOR: return "Contactor"; case PRODUCT_DETAIL_MIRRORBALL_ROTATOR: return "Mirror Ball Rotator"; case PRODUCT_DETAIL_OTHER_ROTATOR: return "Other Rotator"; case PRODUCT_DETAIL_KABUKI_DROP: return "Kabuki Drop"; case PRODUCT_DETAIL_CURTAIN: return "Curtain"; case PRODUCT_DETAIL_LINESET: return "Line Set"; case PRODUCT_DETAIL_MOTOR_CONTROL: return "Motor Control"; case PRODUCT_DETAIL_DAMPER_CONTROL: return "Damper Control"; case PRODUCT_DETAIL_SPLITTER: return "Splitter"; case PRODUCT_DETAIL_ETHERNET_NODE: return "Ethernet Node"; case PRODUCT_DETAIL_MERGE: return "DMX512 Merger"; case PRODUCT_DETAIL_DATAPATCH: return "Data Patch"; case PRODUCT_DETAIL_WIRELESS_LINK: return "Wireless link"; case PRODUCT_DETAIL_PROTOCOL_CONVERTOR: return "Protocol Convertor"; case PRODUCT_DETAIL_ANALOG_DEMULTIPLEX: return "DMX512 to DC Voltage"; case PRODUCT_DETAIL_ANALOG_MULTIPLEX: return "DC Voltage to DMX512"; case PRODUCT_DETAIL_SWITCH_PANEL: return "Switch Panel"; case PRODUCT_DETAIL_ROUTER: return "Router"; case PRODUCT_DETAIL_FADER: return "Fader, Single Channel"; case PRODUCT_DETAIL_MIXER: return "Mixer, Multi Channel"; case PRODUCT_DETAIL_CHANGEOVER_MANUAL: return "Manual Changeover"; case PRODUCT_DETAIL_CHANGEOVER_AUTO: return "Auto Changeover"; case PRODUCT_DETAIL_TEST: return "Test Device"; case PRODUCT_DETAIL_GFI_RCD: return "GFI / RCD Device"; case PRODUCT_DETAIL_BATTERY: return "Battery"; case PRODUCT_DETAIL_CONTROLLABLE_BREAKER: return "Controllable Breaker"; case PRODUCT_DETAIL_OTHER: return "Other Device"; default: ostringstream str; str << "Unknown, was " << detail; return str.str(); } } /** * Convert a uint8_t representing a reset device to a human-readable string. * @param reset_device the reset device value */ string ResetDeviceToString(uint8_t reset_device) { switch (reset_device) { case RESET_WARM: return "Warm"; case RESET_COLD: return "Cold"; default: ostringstream str; str << "Unknown, was " << static_cast(reset_device); return str.str(); } } /** * Safely convert a uint8_t to a rdm_reset_device_mode */ bool UIntToResetDevice(uint8_t state, rdm_reset_device_mode *reset_device) { switch (state) { case RESET_WARM: *reset_device = RESET_WARM; return true; case RESET_COLD: *reset_device = RESET_COLD; return true; default: return false; } } /** * Convert a uint8_t representing a sensor type to a human-readable string. * @param type the sensor type value */ string SensorTypeToString(uint8_t type) { switch (type) { case SENSOR_TEMPERATURE: return "Temperature"; case SENSOR_VOLTAGE: return "Voltage"; case SENSOR_CURRENT: return "Current"; case SENSOR_FREQUENCY: return "Frequency"; case SENSOR_RESISTANCE: return "Resistance"; case SENSOR_POWER: return "Power"; case SENSOR_MASS: return "Mass"; case SENSOR_LENGTH: return "Length"; case SENSOR_AREA: return "Area"; case SENSOR_VOLUME: return "Volume"; case SENSOR_DENSITY: return "Density"; case SENSOR_VELOCITY: return "Velocity"; case SENSOR_ACCELERATION: return "Acceleration"; case SENSOR_FORCE: return "Force"; case SENSOR_ENERGY: return "Energy"; case SENSOR_PRESSURE: return "Pressure"; case SENSOR_TIME: return "Time"; case SENSOR_ANGLE: return "Angle"; case SENSOR_POSITION_X: return "Position X"; case SENSOR_POSITION_Y: return "Position Y"; case SENSOR_POSITION_Z: return "Position Z"; case SENSOR_ANGULAR_VELOCITY: return "Angular velocity"; case SENSOR_LUMINOUS_INTENSITY: return "Luminous intensity"; case SENSOR_LUMINOUS_FLUX: return "Luminous flux"; case SENSOR_ILLUMINANCE: return "Illuminance"; case SENSOR_CHROMINANCE_RED: return "Chrominance red"; case SENSOR_CHROMINANCE_GREEN: return "Chrominance green"; case SENSOR_CHROMINANCE_BLUE: return "Chrominance blue"; case SENSOR_CONTACTS: return "Contacts"; case SENSOR_MEMORY: return "Memory"; case SENSOR_ITEMS: return "Items"; case SENSOR_HUMIDITY: return "Humidity"; case SENSOR_COUNTER_16BIT: return "16 bit counter"; case SENSOR_OTHER: return "Other"; default: ostringstream str; str << "Unknown, was " << static_cast(type); return str.str(); } } /** * Convert a uint8_t representing a sensor's recording support to a * human-readable string. * @param supports_recording the sensor recording support bitmask */ string SensorSupportsRecordingToString(uint8_t supports_recording) { vector recording_support; if (supports_recording & SENSOR_RECORDED_VALUE) { recording_support.push_back("Recorded Value"); } if (supports_recording & SENSOR_RECORDED_RANGE_VALUES) { recording_support.push_back("Lowest/Highest Detected Values"); } return StringJoin(", ", recording_support); } /** * Convert a uint16_t representing a slot type to a human-readable string. * @param slot_type the type of the slot. * @param slot_label the label for the slot. */ string SlotInfoToString(uint8_t slot_type, uint16_t slot_label) { if (slot_type == ST_PRIMARY) { switch (slot_label) { case SD_INTENSITY: return "Primary, intensity"; case SD_INTENSITY_MASTER: return "Primary, intensity master"; case SD_PAN: return "Primary, pan"; case SD_TILT: return "Primary, tilt"; case SD_COLOR_WHEEL: return "Primary, color wheel"; case SD_COLOR_SUB_CYAN: return "Primary, subtractive cyan"; case SD_COLOR_SUB_YELLOW: return "Primary, subtractive yellow"; case SD_COLOR_SUB_MAGENTA: return "Primary, subtractive magenta"; case SD_COLOR_ADD_RED: return "Primary, additive red"; case SD_COLOR_ADD_GREEN: return "Primary, additive green"; case SD_COLOR_ADD_BLUE: return "Primary, additive blue"; case SD_COLOR_CORRECTION: return "Primary, color correction"; case SD_COLOR_SCROLL: return "Primary, scroll"; case SD_COLOR_SEMAPHORE: return "Primary, color semaphone"; case SD_COLOR_ADD_AMBER: return "Primary, additive amber"; case SD_COLOR_ADD_WHITE: return "Primary, additive white"; case SD_COLOR_ADD_WARM_WHITE: return "Primary, additive warm white"; case SD_COLOR_ADD_COOL_WHITE: return "Primary, additive cool white"; case SD_COLOR_SUB_UV: return "Primary, subtractive UV"; case SD_COLOR_HUE: return "Primary, hue"; case SD_COLOR_SATURATION: return "Primary, saturation"; case SD_STATIC_GOBO_WHEEL: return "Primary, static gobo wheel"; case SD_ROTO_GOBO_WHEEL: return "Primary, gobo wheel"; case SD_PRISM_WHEEL: return "Primary, prism wheel"; case SD_EFFECTS_WHEEL: return "Primary, effects wheel"; case SD_BEAM_SIZE_IRIS: return "Primary, iris size"; case SD_EDGE: return "Primary, edge"; case SD_FROST: return "Primary, frost"; case SD_STROBE: return "Primary, strobe"; case SD_ZOOM: return "Primary, zoom"; case SD_FRAMING_SHUTTER: return "Primary, framing shutter"; case SD_SHUTTER_ROTATE: return "Primary, shuttle rotate"; case SD_DOUSER: return "Primary, douser"; case SD_BARN_DOOR: return "Primary, barn door"; case SD_LAMP_CONTROL: return "Primary, lamp control"; case SD_FIXTURE_CONTROL: return "Primary, fixture control"; case SD_FIXTURE_SPEED: return "Primary, fixture speed"; case SD_MACRO: return "Primary, macro"; case SD_POWER_CONTROL: return "Primary, relay or power control"; case SD_FAN_CONTROL: return "Primary, fan control"; case SD_HEATER_CONTROL: return "Primary, heater control"; case SD_FOUNTAIN_CONTROL: return "Primary, fountain water pump control"; case SD_UNDEFINED: return "Primary, undefined"; default: ostringstream str; str << "Primary, unknown, was " << slot_label; return str.str(); } } else { ostringstream str; str << "Secondary, "; switch (slot_type) { case ST_SEC_FINE: str << "fine control for slot " << slot_label; break; case ST_SEC_TIMING: str << "timing control for slot " << slot_label; break; case ST_SEC_SPEED: str << "speed control for slot " << slot_label; break; case ST_SEC_CONTROL: str << "mode control for slot " << slot_label; break; case ST_SEC_INDEX: str << "index control for slot " << slot_label; break; case ST_SEC_ROTATION: str << "rotation speed control for slot " << slot_label; break; case ST_SEC_INDEX_ROTATE: str << "rotation index control for slot " << slot_label; break; case ST_SEC_UNDEFINED: str << "undefined for slot " << slot_label; break; default: str << "unknown for slot " << slot_label; } return str.str(); } } /** * Convert a uint16_t representing a status message to a human-readable string. * @param message_id the status message value * @param data1 the first data value for the message * @param data2 the second data value for the message */ string StatusMessageIdToString(uint16_t message_id, int16_t data1, int16_t data2) { ostringstream str; switch (message_id) { case STS_CAL_FAIL: str << "Slot " << data1 << " failed calibration"; break; case STS_SENS_NOT_FOUND: str << "Sensor " << data1 << " not found"; break; case STS_SENS_ALWAYS_ON: str << "Sensor " << data1 << " always on"; break; case STS_FEEDBACK_ERROR: str << "Slot " << data1 << " feedback error"; break; case STS_INDEX_ERROR: str << "Slot " << data1 << " index circuit error"; break; case STS_LAMP_DOUSED: str << "Lamp doused"; break; case STS_LAMP_STRIKE: str<< "Lamp failed to strike"; break; case STS_LAMP_ACCESS_OPEN: str << "Lamp access open"; break; case STS_LAMP_ALWAYS_ON: str << "Lamp on without command"; break; case STS_OVERTEMP: str << "Sensor " << data1 << " over temp at " << data2 << " degrees C"; break; case STS_UNDERTEMP: str << "Sensor " << data1 << " under temp at " << data2 << " degrees C"; break; case STS_SENS_OUT_RANGE: str << "Sensor " << data1 << " out of range"; break; case STS_OVERVOLTAGE_PHASE: str << "Phase " << data1 << " over voltage at " << data2 << "V"; break; case STS_UNDERVOLTAGE_PHASE: str << "Phase " << data1 << " under voltage at " << data2 << "V"; break; case STS_OVERCURRENT: str << "Phase " << data1 << " over current at " << data2 << "V"; break; case STS_UNDERCURRENT: str << "Phase " << data1 << " under current at " << data2 << "V"; break; case STS_PHASE: str << "Phase " << data1 << " is at " << data2 << " degrees"; break; case STS_PHASE_ERROR: str << "Phase " << data1 << " error"; break; case STS_AMPS: str << data1 << " Amps"; break; case STS_VOLTS: str << data1 << " Volts"; break; case STS_DIMSLOT_OCCUPIED: str << "No Dimmer"; break; case STS_BREAKER_TRIP: str << "Tripped Breaker"; break; case STS_WATTS: str << data1 << " Watts"; break; case STS_DIM_FAILURE: str << "Dimmer Failure"; break; case STS_DIM_PANIC: str << "Dimmer panic mode"; break; case STS_LOAD_FAILURE: str << "Lamp or cable failure"; break; case STS_READY: str << "Slot " << data1 << " ready"; break; case STS_NOT_READY: str << "Slot " << data1 << " not ready"; break; case STS_LOW_FLUID: str << "Slot " << data1 << " low fluid"; break; case STS_EEPROM_ERROR: str << "EEPROM error"; break; case STS_RAM_ERROR: str << "RAM error"; break; case STS_FPGA_ERROR: str << "FPGA programming error"; break; case STS_PROXY_BROADCAST_DROPPED: // This is technically against the standard, which in 10.3.2.4 says "Each // Data Value shall be a signed integer." but I'm sure it's what was // intended. The same thing is technically true with the slots too. str << "Proxy Drop: PID " << strings::ToHex(reinterpret_cast(data1)) << " at TN " << data2; break; case STS_ASC_RXOK: str << "DMX ASC " << strings::ToHex(reinterpret_cast(data1)) << " received OK"; break; case STS_ASC_DROPPED: str << "DMX ASC " << strings::ToHex(reinterpret_cast(data1)) << " now dropped"; break; case STS_DMXNSCNONE: str << "DMX NSC never received"; break; case STS_DMXNSCLOSS: str << "DMX NSC received, now dropped"; break; case STS_DMXNSCERROR: str << "DMX NSC timing or packet error"; break; case STS_DMXNSC_OK: str << "DMX NSC received OK"; break; default: str << "Unknown, was status message " << message_id << " with data value" " 1 " << data1 << " and data value 2 " << data2; break; } return str.str(); } /** * Convert a uint8_t representing a status type to a human-readable string. * @param status_type the status type value */ string StatusTypeToString(uint8_t status_type) { switch (status_type) { case STATUS_NONE: return "None"; case STATUS_GET_LAST_MESSAGE: return "Get last messages"; case STATUS_ADVISORY: return "Advisory"; case STATUS_WARNING: return "Warning"; case STATUS_ERROR: return "Error"; case STATUS_ADVISORY_CLEARED: return "Advisory cleared"; case STATUS_WARNING_CLEARED: return "Warning cleared"; case STATUS_ERROR_CLEARED: return "Error cleared"; default: ostringstream str; str << "Unknown, was " << static_cast(status_type); return str.str(); } } /** * Convert a uint8_t representing a unit to a human-readable string. * @param unit the unit value */ string UnitToString(uint8_t unit) { switch (unit) { case UNITS_NONE: return ""; case UNITS_CENTIGRADE: return "degrees C"; case UNITS_VOLTS_DC: return "Volts (DC)"; case UNITS_VOLTS_AC_PEAK: return "Volts (AC Peak)"; case UNITS_VOLTS_AC_RMS: return "Volts (AC RMS)"; case UNITS_AMPERE_DC: return "Amps (DC)"; case UNITS_AMPERE_AC_PEAK: return "Amps (AC Peak)"; case UNITS_AMPERE_AC_RMS: return "Amps (AC RMS)"; case UNITS_HERTZ: return "Hz"; case UNITS_OHM: return "ohms"; case UNITS_WATT: return "W"; case UNITS_KILOGRAM: return "kg"; case UNITS_METERS: return "m"; case UNITS_METERS_SQUARED: return "m^2"; case UNITS_METERS_CUBED: return "m^3"; case UNITS_KILOGRAMMES_PER_METER_CUBED: return "kg/m^3"; case UNITS_METERS_PER_SECOND: return "m/s"; case UNITS_METERS_PER_SECOND_SQUARED: return "m/s^2"; case UNITS_NEWTON: return "newton"; case UNITS_JOULE: return "joule"; case UNITS_PASCAL: return "pascal"; case UNITS_SECOND: return "second"; case UNITS_DEGREE: return "degree"; case UNITS_STERADIAN: return "steradian"; case UNITS_CANDELA: return "candela"; case UNITS_LUMEN: return "lumen"; case UNITS_LUX: return "lux"; case UNITS_IRE: return "ire"; case UNITS_BYTE: return "bytes"; default: ostringstream str; str << "Unknown, was " << static_cast(unit); return str.str(); } } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/AckTimerResponder.cpp0000644000175000017500000003156613023355232021630 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * AckTimerResponder.cpp * Copyright (C) 2013 Simon Newton */ #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #include #include #include "ola/Constants.h" #include "ola/Clock.h" #include "ola/Logging.h" #include "ola/base/Array.h" #include "ola/network/NetworkUtils.h" #include "ola/rdm/AckTimerResponder.h" #include "ola/rdm/OpenLightingEnums.h" #include "ola/rdm/RDMEnums.h" #include "ola/rdm/ResponderHelper.h" namespace ola { namespace rdm { using ola::network::HostToNetwork; using ola::network::NetworkToHost; using std::string; using std::vector; AckTimerResponder::RDMOps *AckTimerResponder::RDMOps::instance = NULL; const AckTimerResponder::Personalities * AckTimerResponder::Personalities::Instance() { if (!instance) { PersonalityList personalities; personalities.push_back(Personality(0, "Personality 1")); personalities.push_back(Personality(5, "Personality 2")); personalities.push_back(Personality(10, "Personality 3")); personalities.push_back(Personality(20, "Personality 4")); instance = new Personalities(personalities); } return instance; } AckTimerResponder::Personalities * AckTimerResponder::Personalities::instance = NULL; const ResponderOps::ParamHandler AckTimerResponder::PARAM_HANDLERS[] = { { PID_QUEUED_MESSAGE, &AckTimerResponder::GetQueuedMessage, NULL}, { PID_DEVICE_INFO, &AckTimerResponder::GetDeviceInfo, NULL}, { PID_DEVICE_MODEL_DESCRIPTION, &AckTimerResponder::GetDeviceModelDescription, NULL}, { PID_MANUFACTURER_LABEL, &AckTimerResponder::GetManufacturerLabel, NULL}, { PID_DEVICE_LABEL, &AckTimerResponder::GetDeviceLabel, NULL}, { PID_SOFTWARE_VERSION_LABEL, &AckTimerResponder::GetSoftwareVersionLabel, NULL}, { PID_DMX_PERSONALITY, &AckTimerResponder::GetPersonality, &AckTimerResponder::SetPersonality}, { PID_DMX_PERSONALITY_DESCRIPTION, &AckTimerResponder::GetPersonalityDescription, NULL}, { PID_DMX_START_ADDRESS, &AckTimerResponder::GetDmxStartAddress, &AckTimerResponder::SetDmxStartAddress}, { PID_IDENTIFY_DEVICE, &AckTimerResponder::GetIdentify, &AckTimerResponder::SetIdentify}, { 0, NULL, NULL}, }; /* * This class contains the information required to return a response to Get * QUEUED_MESSAGE. */ class QueuedResponse { public: // Takes ownership of the param data QueuedResponse( const ola::TimeStamp &valid_after, rdm_pid pid, RDMCommand::RDMCommandClass command_class, const uint8_t *param_data, unsigned int param_data_size) : m_valid_after(valid_after), m_pid(pid), m_command_class(command_class), m_param_data(param_data), m_param_data_size(param_data_size) { } ~QueuedResponse() { if (m_param_data) { delete[] m_param_data; } } bool IsValid(const TimeStamp &now) const { return now >= m_valid_after; } rdm_pid Pid() const { return m_pid; } RDMCommand::RDMCommandClass CommandClass() const { return m_command_class; } const uint8_t* ParamData() const { return m_param_data; } unsigned int ParamDataSize() const { return m_param_data_size; } private: ola::TimeStamp m_valid_after; rdm_pid m_pid; RDMCommand::RDMCommandClass m_command_class; const uint8_t *m_param_data; unsigned int m_param_data_size; }; // Use 400ms for the ack timers. const uint16_t AckTimerResponder::ACK_TIMER_MS = 400; /** * New AckTimerResponder */ AckTimerResponder::AckTimerResponder(const UID &uid) : m_uid(uid), m_start_address(1), m_identify_mode(false), m_personality_manager(Personalities::Instance()) { } /** * Clean up */ AckTimerResponder::~AckTimerResponder() { STLDeleteElements(&m_upcoming_queued_messages); while (!m_queued_messages.empty()) { delete m_queued_messages.front(); m_queued_messages.pop(); } } /* * Handle an RDM Request */ void AckTimerResponder::SendRDMRequest(RDMRequest *request, RDMCallback *callback) { // Queue any messages here QueueAnyNewMessages(); OLA_DEBUG << " Queued message count is now " << m_queued_messages.size(); RDMOps::Instance()->HandleRDMRequest(this, m_uid, ROOT_RDM_DEVICE, request, callback); } /** * Get the number of queued messages, capping it at 255 */ uint8_t AckTimerResponder::QueuedMessageCount() const { unsigned int size = m_queued_messages.size(); return size > MAX_QUEUED_MESSAGE_COUNT ? MAX_QUEUED_MESSAGE_COUNT : size; } /** * Move any 'new' queued messages in to the queue. */ void AckTimerResponder::QueueAnyNewMessages() { TimeStamp now; m_clock.CurrentTime(&now); PendingResponses::iterator iter = m_upcoming_queued_messages.begin(); while (iter != m_upcoming_queued_messages.end()) { if ((*iter)->IsValid(now)) { m_queued_messages.push(*iter); iter = m_upcoming_queued_messages.erase(iter); } else { ++iter; } } } /** * Build a RDM response from a QueuedResponse */ RDMResponse *AckTimerResponder::ResponseFromQueuedMessage( const RDMRequest *request, const class QueuedResponse *queued_response) { switch (queued_response->CommandClass()) { case RDMCommand::GET_COMMAND_RESPONSE: return new RDMGetResponse( // coverity[SWAPPED_ARGUMENTS] request->DestinationUID(), request->SourceUID(), request->TransactionNumber(), RDM_ACK, QueuedMessageCount(), ROOT_RDM_DEVICE, queued_response->Pid(), queued_response->ParamData(), queued_response->ParamDataSize()); case RDMCommand::SET_COMMAND_RESPONSE: return new RDMSetResponse( // coverity[SWAPPED_ARGUMENTS] request->DestinationUID(), request->SourceUID(), request->TransactionNumber(), RDM_ACK, QueuedMessageCount(), ROOT_RDM_DEVICE, queued_response->Pid(), queued_response->ParamData(), queued_response->ParamDataSize()); default: OLA_WARN << "Queued message returning NULL, CC was " << static_cast(queued_response->CommandClass()); return NULL; } } /** * Return an empty STATUS_MESSAGES response. */ RDMResponse *AckTimerResponder::EmptyStatusMessage( const RDMRequest *request) { return GetResponseWithPid(request, PID_STATUS_MESSAGES, NULL, 0, RDM_ACK, QueuedMessageCount()); } /** * PID_QUEUED_MESSAGE */ RDMResponse *AckTimerResponder::GetQueuedMessage(const RDMRequest *request) { uint8_t status_type; if (!ResponderHelper::ExtractUInt8(request, &status_type)) { return NackWithReason(request, NR_FORMAT_ERROR, QueuedMessageCount()); } if (m_queued_messages.empty()) { // respond with empty status message return EmptyStatusMessage(request); } if (status_type == STATUS_GET_LAST_MESSAGE) { if (m_last_queued_message.get()) { return ResponseFromQueuedMessage(request, m_last_queued_message.get()); } else { return EmptyStatusMessage(request); } } m_last_queued_message.reset(m_queued_messages.front()); m_queued_messages.pop(); RDMResponse *response = ResponseFromQueuedMessage( request, m_last_queued_message.get()); OLA_DEBUG << *response; return response; } /** * PID_DEVICE_INFO */ RDMResponse *AckTimerResponder::GetDeviceInfo(const RDMRequest *request) { return ResponderHelper::GetDeviceInfo( request, OLA_ACK_TIMER_MODEL, PRODUCT_CATEGORY_TEST, 1, &m_personality_manager, m_start_address, 0, 0, QueuedMessageCount()); } /** * PID_DMX_PERSONALITY */ RDMResponse *AckTimerResponder::GetPersonality(const RDMRequest *request) { return ResponderHelper::GetPersonality(request, &m_personality_manager, QueuedMessageCount()); } RDMResponse *AckTimerResponder::SetPersonality(const RDMRequest *request) { return ResponderHelper::SetPersonality(request, &m_personality_manager, m_start_address, QueuedMessageCount()); } /** * PID_DMX_PERSONALITY_DESCRIPTION */ RDMResponse *AckTimerResponder::GetPersonalityDescription( const RDMRequest *request) { return ResponderHelper::GetPersonalityDescription( request, &m_personality_manager, QueuedMessageCount()); } /** * PID_DMX_START_ADDRESS */ RDMResponse *AckTimerResponder::GetDmxStartAddress(const RDMRequest *request) { return ResponderHelper::GetDmxAddress(request, &m_personality_manager, m_start_address, QueuedMessageCount()); } RDMResponse *AckTimerResponder::SetDmxStartAddress(const RDMRequest *request) { uint16_t address; if (!ResponderHelper::ExtractUInt16(request, &address)) { return NackWithReason(request, NR_FORMAT_ERROR, QueuedMessageCount()); } uint16_t end_address = (1 + DMX_UNIVERSE_SIZE - m_personality_manager.ActivePersonalityFootprint()); if (address == 0 || address > end_address) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE, QueuedMessageCount()); } else if (Footprint() == 0) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE, QueuedMessageCount()); } m_start_address = address; TimeStamp valid_after; m_clock.CurrentTime(&valid_after); valid_after += TimeInterval(0, ACK_TIMER_MS * 1000); QueuedResponse *our_response = new QueuedResponse( valid_after, PID_DMX_START_ADDRESS, RDMCommand::SET_COMMAND_RESPONSE, NULL, 0); m_upcoming_queued_messages.push_back(our_response); uint16_t ack_time = 1 + ACK_TIMER_MS / 100; ack_time = HostToNetwork(ack_time); return GetResponseFromData(request, reinterpret_cast(&ack_time), sizeof(ack_time), RDM_ACK_TIMER, QueuedMessageCount()); } /** * PID_IDENTIFY_DEVICE */ RDMResponse *AckTimerResponder::GetIdentify(const RDMRequest *request) { return ResponderHelper::GetBoolValue(request, m_identify_mode, QueuedMessageCount()); } RDMResponse *AckTimerResponder::SetIdentify(const RDMRequest *request) { uint8_t arg; if (!ResponderHelper::ExtractUInt8(request, &arg)) { return NackWithReason(request, NR_FORMAT_ERROR, QueuedMessageCount()); } if (arg != 0 && arg != 1) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE, QueuedMessageCount()); } bool old_value = m_identify_mode; m_identify_mode = arg; if (m_identify_mode != old_value) { OLA_INFO << "Ack Timer Responder" << m_uid << ", identify mode " << (m_identify_mode ? "on" : "off"); } TimeStamp valid_after; m_clock.CurrentTime(&valid_after); valid_after += TimeInterval(0, ACK_TIMER_MS * 1000); QueuedResponse *our_response = new QueuedResponse( valid_after, PID_IDENTIFY_DEVICE, RDMCommand::SET_COMMAND_RESPONSE, NULL, 0); m_upcoming_queued_messages.push_back(our_response); uint16_t ack_time = 1 + ACK_TIMER_MS / 100; ack_time = HostToNetwork(ack_time); return GetResponseFromData(request, reinterpret_cast(&ack_time), sizeof(ack_time), RDM_ACK_TIMER, QueuedMessageCount()); } RDMResponse *AckTimerResponder::GetDeviceModelDescription( const RDMRequest *request) { return ResponderHelper::GetString(request, "OLA Ack Timer Responder", QueuedMessageCount()); } RDMResponse *AckTimerResponder::GetManufacturerLabel( const RDMRequest *request) { return ResponderHelper::GetString(request, OLA_MANUFACTURER_LABEL, QueuedMessageCount()); } RDMResponse *AckTimerResponder::GetDeviceLabel(const RDMRequest *request) { return ResponderHelper::GetString(request, "Ack Timer Responder", QueuedMessageCount()); } RDMResponse *AckTimerResponder::GetSoftwareVersionLabel( const RDMRequest *request) { return ResponderHelper::GetString(request, string("OLA Version ") + VERSION, QueuedMessageCount()); } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/PidStoreHelper.cpp0000644000175000017500000001735613023355232021141 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * PidStoreHelper.cpp * Provides helper methods for loading / accessing the pid store, and dealing * with pids. * Copyright (C) 2011 Simon Newton */ #include #include #include "ola/Logging.h" #include "ola/StringUtils.h" #include "ola/rdm/PidStoreHelper.h" #include "ola/rdm/RDMEnums.h" #include "ola/rdm/RDMMessagePrinters.h" namespace ola { namespace rdm { using std::string; using std::vector; /** * @brief Set up a new PidStoreHelper object */ PidStoreHelper::PidStoreHelper(const string &pid_location, unsigned int initial_indent) : m_pid_location(pid_location.empty() ? RootPidStore::DataLocation() : pid_location), m_root_store(NULL), m_message_printer(initial_indent) { } /** * @brief Clean up */ PidStoreHelper::~PidStoreHelper() { if (m_root_store) { delete m_root_store; } } /** * @brief Init the PidStoreHelper, this loads the PID store */ bool PidStoreHelper::Init() { if (m_root_store) { OLA_WARN << "Root PID Store already loaded from: " << m_pid_location; return false; } m_root_store = ola::rdm::RootPidStore::LoadFromDirectory(m_pid_location); return m_root_store; } /** * @brief Lookup a PidDescriptor by name. * @param manufacturer_id the ESTA id of the manufacturer_id * @param pid_name the name of the pid * @return a PidDescriptor or NULL if the pid wasn't found. */ const ola::rdm::PidDescriptor *PidStoreHelper::GetDescriptor( const string &pid_name, uint16_t manufacturer_id) const { if (!m_root_store) { return NULL; } return m_root_store->GetDescriptor(pid_name, manufacturer_id); } /** * @brief Lookup a PidDescriptor by PID value. * @param manufacturer_id the ESTA id of the manufacturer_id * @param pid_value the pid to lookup * @return a PidDescriptor or NULL if the pid wasn't found. */ const ola::rdm::PidDescriptor *PidStoreHelper::GetDescriptor( uint16_t pid_value, uint16_t manufacturer_id) const { if (!m_root_store) { return NULL; } return m_root_store->GetDescriptor(pid_value, manufacturer_id); } /** * @brief Build a Message object from a series of input strings */ const ola::messaging::Message *PidStoreHelper::BuildMessage( const ola::messaging::Descriptor *descriptor, const vector &inputs) { const ola::messaging::Message *message = m_string_builder.GetMessage( inputs, descriptor); if (!message) { OLA_WARN << "Error building message: " << m_string_builder.GetError(); } return message; } /** * @brief Serialize a message to binary format */ const uint8_t *PidStoreHelper::SerializeMessage( const ola::messaging::Message *message, unsigned int *data_length) { return m_serializer.SerializeMessage(message, data_length); } /** * @brief DeSerialize a message */ const ola::messaging::Message *PidStoreHelper::DeserializeMessage( const ola::messaging::Descriptor *descriptor, const uint8_t *data, unsigned int data_length) { return m_deserializer.InflateMessage(descriptor, data, data_length); } /** * @brief Convert a message to a string * @param message the Message object to print * @returns a formatted string representation of the message. */ const string PidStoreHelper::MessageToString( const ola::messaging::Message *message) { return m_message_printer.AsString(message); } /** * @brief Pretty print a RDM message based on the PID. * * If we can't find a custom MessagePrinter we default to the * GenericMessagePrinter. * @param manufacturer_id the manufacturer ID * @param is_set true if the message is a set command, false otherwise * @param pid the pid value * @param message the Message object to print * @returns a formatted string representation of the message. */ const string PidStoreHelper::PrettyPrintMessage( uint16_t manufacturer_id, bool is_set, uint16_t pid, const ola::messaging::Message *message) { // switch based on command class and PID if (is_set) { { } } else { switch (pid) { case PID_PROXIED_DEVICES: { ProxiedDevicesPrinter printer; return printer.AsString(message); } case PID_STATUS_MESSAGES: { StatusMessagePrinter printer; return printer.AsString(message); } case PID_SUPPORTED_PARAMETERS: { SupportedParamsPrinter printer(manufacturer_id, m_root_store); return printer.AsString(message); } case PID_DEVICE_INFO: { DeviceInfoPrinter printer; return printer.AsString(message); } case PID_PRODUCT_DETAIL_ID_LIST: { ProductIdPrinter printer; return printer.AsString(message); } case PID_DEVICE_MODEL_DESCRIPTION: case PID_MANUFACTURER_LABEL: case PID_DEVICE_LABEL: case PID_SOFTWARE_VERSION_LABEL: case PID_BOOT_SOFTWARE_VERSION_LABEL: { LabelPrinter printer; return printer.AsString(message); } case PID_LANGUAGE_CAPABILITIES: { LanguageCapabilityPrinter printer; return printer.AsString(message); } case PID_REAL_TIME_CLOCK: { ClockPrinter printer; return printer.AsString(message); } case PID_SENSOR_DEFINITION: { SensorDefinitionPrinter printer; return printer.AsString(message); } case PID_SLOT_INFO: { SlotInfoPrinter printer; return printer.AsString(message); } } } return m_message_printer.AsString(message); } /** * @brief Return a string describing the schema for a descriptor */ const string PidStoreHelper::SchemaAsString( const ola::messaging::Descriptor *descriptor) { m_schema_printer.Reset(); descriptor->Accept(&m_schema_printer); return m_schema_printer.AsString(); } /** * @brief Return the list of PIDs supported including manufacturer PIDs. */ void PidStoreHelper::SupportedPids(uint16_t manufacturer_id, vector *pid_names) const { if (!m_root_store) { return; } vector descriptors; const ola::rdm::PidStore *store = m_root_store->EstaStore(); if (store) { store->AllPids(&descriptors); } store = m_root_store->ManufacturerStore(manufacturer_id); if (store) { store->AllPids(&descriptors); } vector::const_iterator iter; for (iter = descriptors.begin(); iter != descriptors.end(); ++iter) { string name = (*iter)->Name(); ola::ToLower(&name); pid_names->push_back(name); } } /** * @brief Return the list of PidDescriptors supported. * * The caller does not own the pointers, they are valid for the lifetime of the * PidStoreHelper. */ void PidStoreHelper::SupportedPids( uint16_t manufacturer_id, vector *descriptors) const { if (!m_root_store) { return; } const ola::rdm::PidStore *store = m_root_store->EstaStore(); if (store) { store->AllPids(descriptors); } store = m_root_store->ManufacturerStore(manufacturer_id); if (store) { store->AllPids(descriptors); } } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/Pids.proto0000644000175000017500000000561313023355232017521 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Pids.proto * Defines the structure for describing RDM PIDs * Copyright (C) 2010 Simon Newton */ package ola.rdm.pid; enum SubDeviceRange { ROOT_DEVICE = 1; // 0 ROOT_OR_ALL_SUBDEVICE = 2; // 0 - 512 or 0xffff ROOT_OR_SUBDEVICE = 3; // 0 - 512 ONLY_SUBDEVICES = 4; // 1 - 512 } enum FieldType { BOOL = 1; UINT8 = 2; UINT16 = 3; UINT32 = 4; STRING = 5; GROUP = 6; INT8 = 7; INT16 = 8; INT32 = 9; IPV4 = 10; UID = 11; MAC = 12; } // A value which has a label applied message LabeledValue { required int64 value = 1; required string label = 2; } // An allowable range, only used for int fields message Range { // min and max are inclusive required int64 min = 1; required int64 max = 2; } // A field within a frame, this can contain other fields message Field { required FieldType type = 1; required string name = 2; optional uint32 min_size = 3; // used for strings & groups optional uint32 max_size = 4; // used for strings & groups optional sint32 multiplier = 5; // used for ints, these are the exponents repeated LabeledValue label = 6; // values with labels applied repeated Range range = 7; // valid ranges repeated Field field = 8; // for type == GROUP } // Describes the format of a frame message FrameFormat { repeated Field field = 1; } // A definition for a PID message Pid { required string name = 1; // A short name required uint32 value = 2; // The 2 byte PID value optional FrameFormat get_request = 3; optional FrameFormat get_response = 4; optional FrameFormat set_request = 5; optional FrameFormat set_response = 6; optional SubDeviceRange get_sub_device_range = 7; optional SubDeviceRange set_sub_device_range = 8; optional FrameFormat discovery_request = 9; optional FrameFormat discovery_response = 10; optional SubDeviceRange discovery_sub_device_range = 11; } // Groups of Manufacturer PIDs message Manufacturer { required uint32 manufacturer_id = 1; required string manufacturer_name = 2; repeated Pid pid = 3; } // The PID Store, which holds all PIDs message PidStore { repeated Pid pid = 1; repeated Manufacturer manufacturer = 2; required uint64 version = 3; } ola-0.10.5.nojsmin/common/rdm/QueueingRDMController.cpp0000644000175000017500000002300113023355232022421 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * QueueingRDMController.cpp * The Jese DMX TRI device. * Copyright (C) 2010 Simon Newton */ #include #include #include #include #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/rdm/QueueingRDMController.h" #include "ola/rdm/RDMCommand.h" #include "ola/rdm/RDMEnums.h" #include "ola/rdm/UID.h" #include "ola/rdm/UIDSet.h" namespace ola { namespace rdm { using ola::rdm::RDMCommand; using ola::rdm::RDMRequest; using ola::rdm::UID; using ola::rdm::UIDSet; using std::string; using std::vector; /* * A new QueueingRDMController. This takes another controller as a argument, * and ensures that we only send one request at a time. */ QueueingRDMController::QueueingRDMController( RDMControllerInterface *controller, unsigned int max_queue_size) : m_controller(controller), m_max_queue_size(max_queue_size), m_rdm_request_pending(false), m_active(true), m_callback(ola::NewCallback(this, &QueueingRDMController::HandleRDMResponse)) { } /* * Shutdown */ QueueingRDMController::~QueueingRDMController() { // delete all outstanding requests while (!m_pending_requests.empty()) { outstanding_rdm_request outstanding_request = m_pending_requests.front(); if (outstanding_request.on_complete) { RunRDMCallback(outstanding_request.on_complete, RDM_FAILED_TO_SEND); } delete outstanding_request.request; m_pending_requests.pop(); } } /** * Pause the sending of RDM messages. This won't cancel any message in-flight. */ void QueueingRDMController::Pause() { m_active = false; } /** * Resume the sending of RDM requests. */ void QueueingRDMController::Resume() { m_active = true; MaybeSendRDMRequest(); } /** * Queue an RDM request for sending. */ void QueueingRDMController::SendRDMRequest(RDMRequest *request, RDMCallback *on_complete) { if (m_pending_requests.size() >= m_max_queue_size) { OLA_WARN << "RDM Queue is full, dropping request"; if (on_complete) { RunRDMCallback(on_complete, RDM_FAILED_TO_SEND); } delete request; return; } outstanding_rdm_request outstanding_request; outstanding_request.request = request; outstanding_request.on_complete = on_complete; m_pending_requests.push(outstanding_request); TakeNextAction(); } /** * Do the next action. */ void QueueingRDMController::TakeNextAction() { if (CheckForBlockingCondition()) return; MaybeSendRDMRequest(); } /** * This method runs before we decide to send another request and allows sub * classes (like the DiscoverableQueueingRDMController) to insert other actions * into the queue. * @returns true if some other action is running, false otherwise. */ bool QueueingRDMController::CheckForBlockingCondition() { return !m_active || m_rdm_request_pending; } /* * If we're not paused, send the next request. */ void QueueingRDMController::MaybeSendRDMRequest() { if (m_pending_requests.empty()) return; m_rdm_request_pending = true; DispatchNextRequest(); } /* * Send the next RDM request. */ void QueueingRDMController::DispatchNextRequest() { outstanding_rdm_request outstanding_request = m_pending_requests.front(); // We have to make a copy here because we pass ownership of the request to // the underlying controller. // We need to have the original request because we use it if we receive an // ACK_OVERFLOW. m_controller->SendRDMRequest(outstanding_request.request->Duplicate(), m_callback.get()); } /* * Handle the response to a RemoteGet command */ void QueueingRDMController::HandleRDMResponse(RDMReply *reply) { m_rdm_request_pending = false; if (m_pending_requests.empty()) { OLA_FATAL << "Received a response but the queue was empty!"; return; } bool was_ack_overflow = reply->StatusCode() == RDM_COMPLETED_OK && reply->Response() && reply->Response()->ResponseType() == ACK_OVERFLOW; // Check for ACK_OVERFLOW if (m_response.get()) { if (reply->StatusCode() != RDM_COMPLETED_OK || reply->Response() == NULL) { // We failed part way through an ACK_OVERFLOW m_frames.insert(m_frames.end(), reply->Frames().begin(), reply->Frames().end()); RDMReply new_reply(reply->StatusCode(), NULL, m_frames); RunCallback(&new_reply); m_response.reset(); m_frames.clear(); TakeNextAction(); } else { // Combine the data. m_response.reset(RDMResponse::CombineResponses( m_response.get(), reply->Response())); m_frames.insert(m_frames.end(), reply->Frames().begin(), reply->Frames().end()); if (!m_response.get()) { // The response was invalid RDMReply new_reply(RDM_INVALID_RESPONSE, NULL, m_frames); RunCallback(&new_reply); m_frames.clear(); TakeNextAction(); } else if (reply->Response()->ResponseType() != ACK_OVERFLOW) { RDMReply new_reply(RDM_COMPLETED_OK, m_response.release(), m_frames); RunCallback(&new_reply); m_response.reset(); m_frames.clear(); TakeNextAction(); } else { DispatchNextRequest(); } return; } } else if (was_ack_overflow) { // We're in an ACK_OVERFLOW sequence. m_frames.clear(); m_response.reset(reply->Response()->Duplicate()); m_frames.insert(m_frames.end(), reply->Frames().begin(), reply->Frames().end()); DispatchNextRequest(); } else { // Just pass the RDMReply on. RunCallback(reply); TakeNextAction(); } } void QueueingRDMController::RunCallback(RDMReply *reply) { outstanding_rdm_request outstanding_request = m_pending_requests.front(); m_pending_requests.pop(); if (outstanding_request.on_complete) { outstanding_request.on_complete->Run(reply); } delete outstanding_request.request; } /** * Constructor for the DiscoverableQueueingRDMController */ DiscoverableQueueingRDMController::DiscoverableQueueingRDMController( DiscoverableRDMControllerInterface *controller, unsigned int max_queue_size) : QueueingRDMController(controller, max_queue_size), m_discoverable_controller(controller) { } /** * Run the full RDM discovery routine. This will either run immediately or * after the current request completes. */ void DiscoverableQueueingRDMController::RunFullDiscovery( RDMDiscoveryCallback *callback) { GenericDiscovery(callback, true); } /** * Run the incremental RDM discovery routine. This will either run immediately * or after the current request completes. */ void DiscoverableQueueingRDMController::RunIncrementalDiscovery( RDMDiscoveryCallback *callback) { GenericDiscovery(callback, false); } /** * Override this so we can prioritize the discovery requests. */ void DiscoverableQueueingRDMController::TakeNextAction() { if (CheckForBlockingCondition()) return; // prioritize discovery above RDM requests if (!m_pending_discovery_callbacks.empty()) StartRDMDiscovery(); else MaybeSendRDMRequest(); } /** * Block if either a RDM request is pending, or another discovery process is * running. */ bool DiscoverableQueueingRDMController::CheckForBlockingCondition() { return (QueueingRDMController::CheckForBlockingCondition() || !m_discovery_callbacks.empty()); } /** * The generic discovery routine */ void DiscoverableQueueingRDMController::GenericDiscovery( RDMDiscoveryCallback *callback, bool full) { m_pending_discovery_callbacks.push_back(std::make_pair(full, callback)); TakeNextAction(); } /** * Run the rdm discovery routine for the underlying controller. * @pre m_pending_discovery_callbacks is not empty() */ void DiscoverableQueueingRDMController::StartRDMDiscovery() { bool full = false; m_discovery_callbacks.reserve(m_pending_discovery_callbacks.size()); PendingDiscoveryCallbacks::iterator iter = m_pending_discovery_callbacks.begin(); for (; iter != m_pending_discovery_callbacks.end(); iter++) { full |= iter->first; m_discovery_callbacks.push_back(iter->second); } m_pending_discovery_callbacks.clear(); RDMDiscoveryCallback *callback = NewSingleCallback( this, &DiscoverableQueueingRDMController::DiscoveryComplete); if (full) m_discoverable_controller->RunFullDiscovery(callback); else m_discoverable_controller->RunIncrementalDiscovery(callback); } /** * Called when discovery completes */ void DiscoverableQueueingRDMController::DiscoveryComplete( const ola::rdm::UIDSet &uids) { DiscoveryCallbacks::iterator iter = m_discovery_callbacks.begin(); for (; iter != m_discovery_callbacks.end(); ++iter) { if (*iter) (*iter)->Run(uids); } m_discovery_callbacks.clear(); TakeNextAction(); } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/DiscoveryAgentTestHelper.h0000644000175000017500000002752313023355232022640 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * DiscoveryAgentTestHelper.h * Helper classes for the DiscoveryAgent test. * Copyright (C) 2011 Simon Newton */ #ifndef COMMON_RDM_DISCOVERYAGENTTESTHELPER_H_ #define COMMON_RDM_DISCOVERYAGENTTESTHELPER_H_ #include #include #include #include #include "ola/Logging.h" #include "ola/rdm/UID.h" #include "ola/rdm/UIDSet.h" #include "ola/rdm/DiscoveryAgent.h" typedef std::vector ResponderList; /** * The interface for MockResponders */ class MockResponderInterface { public: virtual ~MockResponderInterface() {} virtual const ola::rdm::UID& GetUID() const = 0; virtual void UnMute() = 0; virtual bool Mute(const ola::rdm::UID &uid) = 0; virtual bool FormResponse(const ola::rdm::UID &upper, const ola::rdm::UID &lower, uint8_t *data, unsigned int *length) const = 0; enum {DISCOVERY_RESPONSE_SIZE = 24 }; }; /** * A MockResponder. */ class MockResponder: public MockResponderInterface { public: explicit MockResponder(const ola::rdm::UID &uid) : m_uid(uid), m_muted(false) { } const ola::rdm::UID& GetUID() const { return m_uid; } void UnMute() { m_muted = false; } virtual bool Mute(const ola::rdm::UID &uid) { if (m_uid == uid) { m_muted = true; return true; } return false; } bool FormResponse(const ola::rdm::UID &lower, const ola::rdm::UID &upper, uint8_t *data, unsigned int *length) const { if (!ShouldRespond(lower, upper)) return false; uint16_t manufacturer_id = m_uid.ManufacturerId(); uint32_t device_id = m_uid.DeviceId(); CPPUNIT_ASSERT(*length >= DISCOVERY_RESPONSE_SIZE); for (unsigned int i = 0; i < 7; i++) data[i] |= 0xfe; data[7] |= 0xaa; uint16_t checksum = 0; // manufacturer_id OrAndChecksum(data, 8, (manufacturer_id >> 8) | 0xaa, &checksum); OrAndChecksum(data, 9, (manufacturer_id >> 8) | 0x55, &checksum); OrAndChecksum(data, 10, manufacturer_id | 0xaa, &checksum); OrAndChecksum(data, 11, manufacturer_id | 0x55, &checksum); // device id OrAndChecksum(data, 12, (device_id >> 24) | 0xaa, &checksum); OrAndChecksum(data, 13, (device_id >> 24) | 0x55, &checksum); OrAndChecksum(data, 14, (device_id >> 16) | 0xaa, &checksum); OrAndChecksum(data, 15, (device_id >> 16) | 0x55, &checksum); OrAndChecksum(data, 16, (device_id >> 8) | 0xaa, &checksum); OrAndChecksum(data, 17, (device_id >> 8) | 0x55, &checksum); OrAndChecksum(data, 18, device_id | 0xaa, &checksum); OrAndChecksum(data, 19, device_id | 0x55, &checksum); data[20] |= (checksum >> 8) | 0xaa; data[21] |= (checksum >> 8) | 0x55; data[22] |= checksum | 0xaa; data[23] |= checksum | 0x55; *length = DISCOVERY_RESPONSE_SIZE; return true; } protected: virtual bool ShouldRespond(const ola::rdm::UID &lower, const ola::rdm::UID &upper) const { if (m_uid < lower || m_uid > upper) return false; if (m_muted) return false; return true; } ola::rdm::UID m_uid; bool m_muted; private: void OrAndChecksum(uint8_t *data, unsigned int offset, uint8_t value, uint16_t *checksum) const { data[offset] = value; *checksum += value; } }; /** * A responder which stops responding once the manufacturer_id matches. This * simulates a responder with broken UID inequality handling. */ class BiPolarResponder: public MockResponder { public: explicit BiPolarResponder(const ola::rdm::UID &uid) : MockResponder(uid) { } protected: bool ShouldRespond(const ola::rdm::UID &lower, const ola::rdm::UID &upper) const { if (m_uid < lower || m_uid > upper) return false; if (m_muted) return false; if (m_uid.ManufacturerId() == lower.ManufacturerId() && m_uid.ManufacturerId() == upper.ManufacturerId()) return false; return true; } }; /** * A responder which doesn't honor mute. */ class ObnoxiousResponder: public MockResponder { public: explicit ObnoxiousResponder(const ola::rdm::UID &uid) : MockResponder(uid) { } protected: bool ShouldRespond(const ola::rdm::UID &lower, const ola::rdm::UID &upper) const { if (m_uid < lower || m_uid > upper) return false; return true; } }; /** * A responder which replies to DUB with extra data */ class RamblingResponder: public MockResponder { public: explicit RamblingResponder(const ola::rdm::UID &uid) : MockResponder(uid) { } bool FormResponse(const ola::rdm::UID &lower, const ola::rdm::UID &upper, uint8_t *data, unsigned int *length) const { unsigned int data_size = *length; bool ok = MockResponder::FormResponse(lower, upper, data, length); if (ok && data_size > DISCOVERY_RESPONSE_SIZE) { // add some random data and increase the packet size data[DISCOVERY_RESPONSE_SIZE] = 0x52; (*length)++; } return ok; } }; /** * A responder which replies to DUB with too little data */ class BriefResponder: public MockResponder { public: explicit BriefResponder(const ola::rdm::UID &uid) : MockResponder(uid) { } bool FormResponse(const ola::rdm::UID &lower, const ola::rdm::UID &upper, uint8_t *data, unsigned int *length) const { bool ok = MockResponder::FormResponse(lower, upper, data, length); if (ok && *length > 1) (*length)--; return ok; } }; /** * A responder that doesn't respond to a mute message. */ class NonMutingResponder: public MockResponder { public: explicit NonMutingResponder(const ola::rdm::UID &uid) : MockResponder(uid) { } bool Mute(const ola::rdm::UID&) { return false; } }; /** * A responder that only mutes after N attempts */ class FlakeyMutingResponder: public MockResponder { public: explicit FlakeyMutingResponder(const ola::rdm::UID &uid, unsigned int threshold = 2) : MockResponder(uid), m_threshold(threshold), m_attempts(0) { } bool Mute(const ola::rdm::UID &uid) { if (m_uid != uid) return false; m_attempts++; if (m_attempts > m_threshold) { m_muted = true; return true; } return false; } void Reset() { m_attempts = 0; } private: unsigned int m_threshold; unsigned int m_attempts; }; /** * A proxy responder */ class ProxyResponder: public MockResponder { public: explicit ProxyResponder(const ola::rdm::UID &uid, const ResponderList &responders) : MockResponder(uid), m_responders(responders) { } ~ProxyResponder() { ResponderList::const_iterator iter = m_responders.begin(); for (; iter != m_responders.end(); ++iter) delete *iter; } void UnMute() { m_muted = false; // unmute everything behind this proxy ResponderList::const_iterator iter = m_responders.begin(); for (; iter != m_responders.end(); ++iter) (*iter)->UnMute(); } bool Mute(const ola::rdm::UID &uid) { bool r = MockResponder::Mute(uid); if (m_muted) { ResponderList::const_iterator iter = m_responders.begin(); for (; iter != m_responders.end(); ++iter) r |= (*iter)->Mute(uid); } return r; } bool FormResponse(const ola::rdm::UID &lower, const ola::rdm::UID &upper, uint8_t *data, unsigned int *length) const { bool r = MockResponder::FormResponse(lower, upper, data, length); if (m_muted) { ResponderList::const_iterator iter = m_responders.begin(); for (; iter != m_responders.end(); ++iter) { if (r) break; r |= (*iter)->FormResponse(lower, upper, data, length); } } return r; } private: ResponderList m_responders; }; /** * A class which implements the DiscoveryTargetInterface */ class MockDiscoveryTarget: public ola::rdm::DiscoveryTargetInterface { public: explicit MockDiscoveryTarget(const ResponderList &responders) : m_responders(responders), m_unmute_calls(0) { } ~MockDiscoveryTarget() { ResponderList::const_iterator iter = m_responders.begin(); for (; iter != m_responders.end(); ++iter) delete *iter; } void ResetCounters() { m_unmute_calls = 0; } unsigned int UnmuteCallCount() const { return m_unmute_calls; } // Mute a device void MuteDevice(const ola::rdm::UID &target, MuteDeviceCallback *mute_complete) { ResponderList::const_iterator iter = m_responders.begin(); for (; iter != m_responders.end(); ++iter) { if ((*iter)->Mute(target)) { mute_complete->Run(true); return; } } // if we made it this far the responder has gone mute_complete->Run(false); } // Un Mute all devices void UnMuteAll(UnMuteDeviceCallback *unmute_complete) { ResponderList::const_iterator iter = m_responders.begin(); for (; iter != m_responders.end(); ++iter) { (*iter)->UnMute(); } m_unmute_calls++; unmute_complete->Run(); } // Send a branch request void Branch(const ola::rdm::UID &lower, const ola::rdm::UID &upper, BranchCallback *callback) { // alloc twice the amount we need unsigned int data_size = 2 * MockResponder::DISCOVERY_RESPONSE_SIZE; uint8_t data[data_size]; memset(data, 0, data_size); bool valid = false; unsigned int actual_size = 0; ResponderList::const_iterator iter = m_responders.begin(); for (; iter != m_responders.end(); ++iter) { unsigned int data_used = data_size; if ((*iter)->FormResponse(lower, upper, data, &data_used)) { actual_size = std::max(data_used, actual_size); valid = true; } } if (valid) callback->Run(data, actual_size); else callback->Run(NULL, 0); } // Add a responder to the list of responders void AddResponder(MockResponderInterface *responder) { m_responders.push_back(responder); } // Remove a responder from the list void RemoveResponder(const ola::rdm::UID &uid) { ResponderList::iterator iter = m_responders.begin(); for (; iter != m_responders.end(); ++iter) { if ((*iter)->GetUID() == uid) { delete *iter; m_responders.erase(iter); break; } } } private: ResponderList m_responders; unsigned int m_unmute_calls; }; #endif // COMMON_RDM_DISCOVERYAGENTTESTHELPER_H_ ola-0.10.5.nojsmin/common/rdm/ResponderHelper.cpp0000644000175000017500000011026413023355232021341 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * ResponderHelper.cpp * Copyright (C) 2013 Simon Newton */ #define __STDC_LIMIT_MACROS // for UINT8_MAX & friends #include #include #include #include #include "ola/Clock.h" #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/base/Array.h" #include "ola/base/Macro.h" #include "ola/network/IPV4Address.h" #include "ola/network/Interface.h" #include "ola/network/InterfacePicker.h" #include "ola/network/MACAddress.h" #include "ola/network/NetworkUtils.h" #include "ola/rdm/RDMEnums.h" #include "ola/rdm/ResponderHelper.h" #include "ola/rdm/ResponderSensor.h" #include "ola/strings/Utils.h" namespace ola { namespace rdm { using ola::network::HostToNetwork; using ola::network::Interface; using ola::network::InterfacePicker; using ola::network::IPV4Address; using ola::network::MACAddress; using ola::network::NetworkToHost; using std::min; using std::string; using std::vector; template static bool GenericExtractValue(const RDMRequest *request, T *output) { T value; if (request->ParamDataSize() != sizeof(value)) { return false; } memcpy(reinterpret_cast(&value), request->ParamData(), sizeof(value)); *output = NetworkToHost(value); return true; } bool ResponderHelper::ExtractUInt8(const RDMRequest *request, uint8_t *output) { return GenericExtractValue(request, output); } bool ResponderHelper::ExtractUInt16(const RDMRequest *request, uint16_t *output) { return GenericExtractValue(request, output); } bool ResponderHelper::ExtractUInt32(const RDMRequest *request, uint32_t *output) { return GenericExtractValue(request, output); } RDMResponse *ResponderHelper::GetDeviceInfo( const RDMRequest *request, uint16_t device_model, rdm_product_category product_category, uint32_t software_version, uint16_t dmx_footprint, uint8_t current_personality, uint8_t personality_count, uint16_t dmx_start_address, uint16_t sub_device_count, uint8_t sensor_count, uint8_t queued_message_count) { if (request->ParamDataSize()) { return NackWithReason(request, NR_FORMAT_ERROR, queued_message_count); } PACK( struct device_info_s { uint16_t rdm_version; uint16_t model; uint16_t product_category; uint32_t software_version; uint16_t dmx_footprint; uint8_t current_personality; uint8_t personality_count; uint16_t dmx_start_address; uint16_t sub_device_count; uint8_t sensor_count; }); STATIC_ASSERT(sizeof(device_info_s) == 19); struct device_info_s device_info; device_info.rdm_version = HostToNetwork( static_cast(RDM_VERSION_1_0)); device_info.model = HostToNetwork(device_model); device_info.product_category = HostToNetwork( static_cast(product_category)); device_info.software_version = HostToNetwork(software_version); device_info.dmx_footprint = HostToNetwork(dmx_footprint); device_info.current_personality = current_personality; device_info.personality_count = personality_count; device_info.dmx_start_address = HostToNetwork(dmx_start_address); device_info.sub_device_count = HostToNetwork(sub_device_count); device_info.sensor_count = sensor_count; return GetResponseFromData( request, reinterpret_cast(&device_info), sizeof(device_info), RDM_ACK, queued_message_count); } RDMResponse *ResponderHelper::GetDeviceInfo( const RDMRequest *request, uint16_t device_model, rdm_product_category product_category, uint32_t software_version, const PersonalityManager *personality_manager, uint16_t start_address, uint16_t sub_device_count, uint8_t sensor_count, uint8_t queued_message_count) { return ResponderHelper::GetDeviceInfo( request, device_model, product_category, software_version, personality_manager->ActivePersonalityFootprint(), personality_manager->ActivePersonalityNumber(), personality_manager->PersonalityCount(), (personality_manager->ActivePersonalityFootprint() ? start_address : ZERO_FOOTPRINT_DMX_ADDRESS), sub_device_count, sensor_count, queued_message_count); } RDMResponse *ResponderHelper::GetProductDetailList( const RDMRequest *request, const vector &product_details, uint8_t queued_message_count) { if (request->ParamDataSize()) { return NackWithReason(request, NR_FORMAT_ERROR, queued_message_count); } uint16_t product_details_raw[product_details.size()]; for (unsigned int i = 0; i < product_details.size(); i++) { product_details_raw[i] = HostToNetwork(static_cast(product_details[i])); } return GetResponseFromData( request, reinterpret_cast(&product_details_raw), sizeof(product_details_raw), RDM_ACK, queued_message_count); } RDMResponse *ResponderHelper::GetPersonality( const RDMRequest *request, const PersonalityManager *personality_manager, uint8_t queued_message_count) { if (request->ParamDataSize()) { return NackWithReason(request, NR_FORMAT_ERROR, queued_message_count); } PACK( struct personality_info_s { uint8_t personality; uint8_t total; }); STATIC_ASSERT(sizeof(personality_info_s) == 2); struct personality_info_s personality_info = { personality_manager->ActivePersonalityNumber(), personality_manager->PersonalityCount() }; return GetResponseFromData( request, reinterpret_cast(&personality_info), sizeof(personality_info), RDM_ACK, queued_message_count); } RDMResponse *ResponderHelper::SetPersonality( const RDMRequest *request, PersonalityManager *personality_manager, uint16_t start_address, uint8_t queued_message_count) { uint8_t personality_number; if (!ExtractUInt8(request, &personality_number)) { return NackWithReason(request, NR_FORMAT_ERROR, queued_message_count); } const Personality *personality = personality_manager->Lookup( personality_number); if (!personality) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE, queued_message_count); } else if (start_address + personality->Footprint() - 1 > DMX_UNIVERSE_SIZE) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE, queued_message_count); } else { personality_manager->SetActivePersonality(personality_number); return EmptySetResponse(request, queued_message_count); } } RDMResponse *ResponderHelper::GetPersonalityDescription( const RDMRequest *request, const PersonalityManager *personality_manager, uint8_t queued_message_count) { uint8_t personality_number; if (!ExtractUInt8(request, &personality_number)) { return NackWithReason(request, NR_FORMAT_ERROR, queued_message_count); } const Personality *personality = personality_manager->Lookup( personality_number); if (!personality) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE, queued_message_count); } else { PACK( struct personality_description_s { uint8_t personality; uint16_t slots_required; char description[MAX_RDM_STRING_LENGTH]; }); STATIC_ASSERT(sizeof(personality_description_s) == 35); struct personality_description_s personality_description; personality_description.personality = personality_number; personality_description.slots_required = HostToNetwork(personality->Footprint()); size_t str_len = min(personality->Description().size(), sizeof(personality_description.description)); strncpy(personality_description.description, personality->Description().c_str(), str_len); unsigned int param_data_size = ( sizeof(personality_description) - sizeof(personality_description.description) + str_len); return GetResponseFromData( request, reinterpret_cast(&personality_description), param_data_size, RDM_ACK, queued_message_count); } } /** * Get slot info */ RDMResponse *ResponderHelper::GetSlotInfo( const RDMRequest *request, const PersonalityManager *personality_manager, uint8_t queued_message_count) { if (request->ParamDataSize()) { return NackWithReason(request, NR_FORMAT_ERROR, queued_message_count); } const SlotDataCollection *slot_data = personality_manager->ActivePersonality()->GetSlotData(); if (slot_data->SlotCount() == 0) { return EmptyGetResponse(request, queued_message_count); } PACK( struct slot_info_s { uint16_t offset; uint8_t type; uint16_t label; }); STATIC_ASSERT(sizeof(slot_info_s) == 5); slot_info_s slot_info_raw[slot_data->SlotCount()]; for (uint16_t slot = 0; slot < slot_data->SlotCount(); slot++) { const SlotData *sd = slot_data->Lookup(slot); slot_info_raw[slot].offset = HostToNetwork(slot); slot_info_raw[slot].type = static_cast(sd->SlotType()); slot_info_raw[slot].label = HostToNetwork(sd->SlotIDDefinition()); } return GetResponseFromData( request, reinterpret_cast(&slot_info_raw), sizeof(slot_info_raw), RDM_ACK, queued_message_count); } /** * Get a slot description */ RDMResponse *ResponderHelper::GetSlotDescription( const RDMRequest *request, const PersonalityManager *personality_manager, uint8_t queued_message_count) { uint16_t slot_number; if (!ExtractUInt16(request, &slot_number)) { return NackWithReason(request, NR_FORMAT_ERROR, queued_message_count); } const SlotData *slot_data = personality_manager->ActivePersonality()->GetSlotData(slot_number); if (!slot_data) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE, queued_message_count); } if (!slot_data->HasDescription()) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE, queued_message_count); } PACK( struct slot_description_s { uint16_t slot; char description[MAX_RDM_STRING_LENGTH]; }); STATIC_ASSERT(sizeof(slot_description_s) == 34); struct slot_description_s slot_description; slot_description.slot = HostToNetwork(slot_number); size_t str_len = min(slot_data->Description().size(), sizeof(slot_description.description)); strncpy(slot_description.description, slot_data->Description().c_str(), str_len); unsigned int param_data_size = ( sizeof(slot_description) - sizeof(slot_description.description) + str_len); return GetResponseFromData(request, reinterpret_cast(&slot_description), param_data_size, RDM_ACK, queued_message_count); } /** * Get slot default values */ RDMResponse *ResponderHelper::GetSlotDefaultValues( const RDMRequest *request, const PersonalityManager *personality_manager, uint8_t queued_message_count) { if (request->ParamDataSize()) { return NackWithReason(request, NR_FORMAT_ERROR, queued_message_count); } const SlotDataCollection *slot_data = personality_manager->ActivePersonality()->GetSlotData(); if (slot_data->SlotCount() == 0) { return EmptyGetResponse(request, queued_message_count); } PACK( struct slot_default_s { uint16_t offset; uint8_t value; }); STATIC_ASSERT(sizeof(slot_default_s) == 3); slot_default_s slot_default_raw[slot_data->SlotCount()]; for (uint16_t slot = 0; slot < slot_data->SlotCount(); slot++) { const SlotData *sd = slot_data->Lookup(slot); slot_default_raw[slot].offset = HostToNetwork(slot); slot_default_raw[slot].value = static_cast(sd->DefaultSlotValue()); } return GetResponseFromData( request, reinterpret_cast(&slot_default_raw), sizeof(slot_default_raw), RDM_ACK, queued_message_count); } /** * Get the start address */ RDMResponse *ResponderHelper::GetDmxAddress( const RDMRequest *request, const PersonalityManager *personality_manager, uint16_t start_address, uint8_t queued_message_count) { return ResponderHelper::GetUInt16Value( request, ((personality_manager->ActivePersonalityFootprint() == 0) ? ZERO_FOOTPRINT_DMX_ADDRESS : start_address), queued_message_count); } /** * Set the start address */ RDMResponse *ResponderHelper::SetDmxAddress( const RDMRequest *request, const PersonalityManager *personality_manager, uint16_t *dmx_address, uint8_t queued_message_count) { uint16_t address; if (!ResponderHelper::ExtractUInt16(request, &address)) { return NackWithReason(request, NR_FORMAT_ERROR); } uint16_t end_address = (1 + DMX_UNIVERSE_SIZE - personality_manager->ActivePersonalityFootprint()); if (address == 0 || address > end_address) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE, queued_message_count); } else if (personality_manager->ActivePersonalityFootprint() == 0) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE, queued_message_count); } else { *dmx_address = address; return EmptySetResponse(request, queued_message_count); } } /** * Get a sensor definition */ RDMResponse *ResponderHelper::GetSensorDefinition( const RDMRequest *request, const Sensors &sensor_list) { uint8_t sensor_number; if (!ResponderHelper::ExtractUInt8(request, &sensor_number)) { return NackWithReason(request, NR_FORMAT_ERROR); } if (sensor_number >= sensor_list.size()) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } PACK( struct sensor_definition_s { uint8_t sensor; uint8_t type; uint8_t unit; uint8_t prefix; int16_t range_min; int16_t range_max; int16_t normal_min; int16_t normal_max; uint8_t recorded_support; char description[MAX_RDM_STRING_LENGTH]; }); STATIC_ASSERT(sizeof(sensor_definition_s) == 45); const Sensor *sensor = sensor_list.at(sensor_number); struct sensor_definition_s sensor_definition; sensor_definition.sensor = sensor_number; sensor_definition.type = sensor->Type(); sensor_definition.unit = sensor->Unit(); sensor_definition.prefix = sensor->Prefix(); sensor_definition.range_min = HostToNetwork(sensor->RangeMin()); sensor_definition.range_max = HostToNetwork(sensor->RangeMax()); sensor_definition.normal_min = HostToNetwork(sensor->NormalMin()); sensor_definition.normal_max = HostToNetwork(sensor->NormalMax()); sensor_definition.recorded_support = sensor->RecordedSupportBitMask(); strings::CopyToFixedLengthBuffer(sensor->Description(), sensor_definition.description, arraysize(sensor_definition.description)); return GetResponseFromData( request, reinterpret_cast(&sensor_definition), sizeof(sensor_definition)); } /** * Get a sensor value */ RDMResponse *ResponderHelper::GetSensorValue( const RDMRequest *request, const Sensors &sensor_list) { uint8_t sensor_number; if (!ResponderHelper::ExtractUInt8(request, &sensor_number)) { return NackWithReason(request, NR_FORMAT_ERROR); } if (sensor_number >= sensor_list.size()) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } Sensor *sensor = sensor_list.at(sensor_number); struct sensor_value_s sensor_value = { sensor_number, HostToNetwork(sensor->FetchValue()), HostToNetwork(sensor->Lowest()), HostToNetwork(sensor->Highest()), HostToNetwork(sensor->Recorded()), }; return GetResponseFromData( request, reinterpret_cast(&sensor_value), sizeof(sensor_value)); } /** * Set a sensor value */ RDMResponse *ResponderHelper::SetSensorValue( const RDMRequest *request, const Sensors &sensor_list) { uint8_t sensor_number; if (!ResponderHelper::ExtractUInt8(request, &sensor_number)) { return NackWithReason(request, NR_FORMAT_ERROR); } int16_t value = 0; if (sensor_number == ALL_SENSORS) { Sensors::const_iterator iter = sensor_list.begin(); for (; iter != sensor_list.end(); ++iter) { value = (*iter)->Reset(); } } else if (sensor_number < sensor_list.size()) { Sensor *sensor = sensor_list.at(sensor_number); value = sensor->Reset(); } else { return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } struct sensor_value_s sensor_value = { sensor_number, HostToNetwork(value), HostToNetwork(value), HostToNetwork(value), HostToNetwork(value), }; return GetResponseFromData( request, reinterpret_cast(&sensor_value), sizeof(sensor_value)); } /** * Record a sensor */ RDMResponse *ResponderHelper::RecordSensor( const RDMRequest *request, const Sensors &sensor_list) { uint8_t sensor_number; if (!ResponderHelper::ExtractUInt8(request, &sensor_number)) { return NackWithReason(request, NR_FORMAT_ERROR); } if (sensor_number == ALL_SENSORS) { Sensors::const_iterator iter = sensor_list.begin(); for (; iter != sensor_list.end(); ++iter) { (*iter)->Record(); } } else if (sensor_number < sensor_list.size()) { Sensor *sensor = sensor_list.at(sensor_number); sensor->Record(); } else { return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } return GetResponseFromData(request, NULL, 0); } /** * Get the clock response. */ RDMResponse *ResponderHelper::GetRealTimeClock( const RDMRequest *request, uint8_t queued_message_count) { if (request->ParamDataSize()) { return NackWithReason(request, NR_FORMAT_ERROR, queued_message_count); } PACK( struct clock_s { uint16_t year; uint8_t month; uint8_t day; uint8_t hour; uint8_t minute; uint8_t second; }); STATIC_ASSERT(sizeof(clock_s) == 7); time_t now; now = time(NULL); struct tm tm_now; #ifdef _WIN32 tm_now = *localtime(&now); // NOLINT(runtime/threadsafe_fn) #else localtime_r(&now, &tm_now); #endif // _WIN32 struct clock_s clock; clock.year = HostToNetwork(static_cast(1900 + tm_now.tm_year)); clock.month = tm_now.tm_mon + 1; clock.day = tm_now.tm_mday; clock.hour = tm_now.tm_hour; clock.minute = tm_now.tm_min; clock.second = tm_now.tm_sec; return GetResponseFromData( request, reinterpret_cast(&clock), sizeof(clock), RDM_ACK, queued_message_count); } RDMResponse *ResponderHelper::GetListInterfaces( const RDMRequest *request, const NetworkManagerInterface *network_manager, uint8_t queued_message_count) { if (request->ParamDataSize()) { return NackWithReason(request, NR_FORMAT_ERROR, queued_message_count); } vector interfaces = network_manager->GetInterfacePicker()->GetInterfaces(false); if (interfaces.size() == 0) { return EmptyGetResponse(request, queued_message_count); } std::sort(interfaces.begin(), interfaces.end(), ola::network::InterfaceIndexOrdering()); PACK( struct list_interfaces_s { uint32_t index; uint16_t type; }); STATIC_ASSERT(sizeof(list_interfaces_s) == 6); list_interfaces_s list_interfaces[interfaces.size()]; for (uint16_t i = 0; i < interfaces.size(); i++) { list_interfaces[i].index = HostToNetwork(interfaces[i].index); list_interfaces[i].type = HostToNetwork( static_cast(interfaces[i].type)); } return GetResponseFromData( request, reinterpret_cast(&list_interfaces), sizeof(list_interfaces), RDM_ACK, queued_message_count); } RDMResponse *ResponderHelper::GetInterfaceLabel( const RDMRequest *request, const NetworkManagerInterface *network_manager, uint8_t queued_message_count) { uint32_t index; if (!ResponderHelper::ExtractUInt32(request, &index)) { return NackWithReason(request, NR_FORMAT_ERROR); } Interface interface; if (!FindInterface(network_manager, &interface, index)) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } PACK( struct interface_label_s { uint32_t index; char label[MAX_RDM_STRING_LENGTH]; }); STATIC_ASSERT(sizeof(interface_label_s) == 36); struct interface_label_s interface_label; interface_label.index = HostToNetwork(interface.index); size_t str_len = min(interface.name.size(), sizeof(interface_label.label)); strncpy(interface_label.label, interface.name.c_str(), str_len); unsigned int param_data_size = ( sizeof(interface_label) - sizeof(interface_label.label) + str_len); return GetResponseFromData(request, reinterpret_cast(&interface_label), param_data_size, RDM_ACK, queued_message_count); } RDMResponse *ResponderHelper::GetInterfaceHardwareAddressType1( const RDMRequest *request, const NetworkManagerInterface *network_manager, uint8_t queued_message_count) { uint32_t index; if (!ResponderHelper::ExtractUInt32(request, &index)) { return NackWithReason(request, NR_FORMAT_ERROR); } Interface interface; if (!FindInterface(network_manager, &interface, index)) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } // Only return type 1 (Ethernet) if (interface.type != Interface::ARP_ETHERNET_TYPE) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } PACK( struct interface_hardware_address_s { uint32_t index; uint8_t hardware_address[MACAddress::LENGTH]; }); STATIC_ASSERT(sizeof(interface_hardware_address_s) == 10); struct interface_hardware_address_s interface_hardware_address; interface_hardware_address.index = HostToNetwork(interface.index); interface.hw_address.Get(interface_hardware_address.hardware_address); return GetResponseFromData( request, reinterpret_cast(&interface_hardware_address), sizeof(interface_hardware_address), RDM_ACK, queued_message_count); } RDMResponse *ResponderHelper::GetIPV4CurrentAddress( const RDMRequest *request, const NetworkManagerInterface *network_manager, uint8_t queued_message_count) { uint32_t index; if (!ResponderHelper::ExtractUInt32(request, &index)) { return NackWithReason(request, NR_FORMAT_ERROR); } Interface interface; if (!FindInterface(network_manager, &interface, index)) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } PACK( struct ipv4_current_address_s { uint32_t index; uint32_t ipv4_address; uint8_t netmask; uint8_t dhcp; }); STATIC_ASSERT(sizeof(ipv4_current_address_s) == 10); struct ipv4_current_address_s ipv4_current_address; ipv4_current_address.index = HostToNetwork(interface.index); // Already in correct byte order ipv4_current_address.ipv4_address = interface.ip_address.AsInt(); uint8_t mask = UINT8_MAX; if (!IPV4Address::ToCIDRMask(interface.subnet_mask, &mask)) { OLA_WARN << "Error converting " << interface.subnet_mask << " to CIDR value"; } ipv4_current_address.netmask = mask; ipv4_current_address.dhcp = static_cast( network_manager->GetDHCPStatus(interface)); return GetResponseFromData( request, reinterpret_cast(&ipv4_current_address), sizeof(ipv4_current_address), RDM_ACK, queued_message_count); } RDMResponse *ResponderHelper::GetIPV4DefaultRoute( const RDMRequest *request, const NetworkManagerInterface *network_manager, uint8_t queued_message_count) { if (request->ParamDataSize()) { return NackWithReason(request, NR_FORMAT_ERROR, queued_message_count); } int32_t if_index = Interface::DEFAULT_INDEX; IPV4Address default_route; if (!network_manager->GetIPV4DefaultRoute(&if_index, &default_route)) { return NackWithReason(request, NR_HARDWARE_FAULT); } PACK( struct ipv4_default_route_s { uint32_t if_index; uint32_t default_route; }); STATIC_ASSERT(sizeof(ipv4_default_route_s) == 8); struct ipv4_default_route_s ipv4_default_route; if (if_index == Interface::DEFAULT_INDEX) { // No default route interface index set, return special value ipv4_default_route.if_index = HostToNetwork(NO_DEFAULT_ROUTE); } else { ipv4_default_route.if_index = HostToNetwork(if_index); } if (default_route.IsWildcard()) { // No default route set, return special value ipv4_default_route.default_route = HostToNetwork(NO_DEFAULT_ROUTE); } else { // Already in correct byte order ipv4_default_route.default_route = default_route.AsInt(); } return GetResponseFromData( request, reinterpret_cast(&ipv4_default_route), sizeof(ipv4_default_route), RDM_ACK, queued_message_count); } RDMResponse *ResponderHelper::GetDNSHostname( const RDMRequest *request, const NetworkManagerInterface *network_manager, uint8_t queued_message_count) { if (request->ParamDataSize()) { return NackWithReason(request, NR_FORMAT_ERROR, queued_message_count); } const string hostname = network_manager->GetHostname(); if (hostname.empty() || hostname.length() > MAX_RDM_HOSTNAME_LENGTH) { // Hostname outside of the allowed parameters for RDM, return an error return NackWithReason(request, NR_HARDWARE_FAULT); } else { return GetString(request, hostname, queued_message_count, MAX_RDM_HOSTNAME_LENGTH); } } RDMResponse *ResponderHelper::GetDNSDomainName( const RDMRequest *request, const NetworkManagerInterface *network_manager, uint8_t queued_message_count) { if (request->ParamDataSize()) { return NackWithReason(request, NR_FORMAT_ERROR, queued_message_count); } string domain_name = network_manager->GetDomainName(); if (domain_name.length() > MAX_RDM_DOMAIN_NAME_LENGTH) { // Domain name outside of the allowed parameters for RDM, return an error return NackWithReason(request, NR_HARDWARE_FAULT); } else { return GetString(request, domain_name, queued_message_count, MAX_RDM_DOMAIN_NAME_LENGTH); } } RDMResponse *ResponderHelper::GetDNSNameServer( const RDMRequest *request, const NetworkManagerInterface *network_manager, uint8_t queued_message_count) { uint8_t name_server_number; if (!ResponderHelper::ExtractUInt8(request, &name_server_number)) { return NackWithReason(request, NR_FORMAT_ERROR); } vector name_servers; if (!network_manager->GetNameServers(&name_servers)) { return NackWithReason(request, NR_HARDWARE_FAULT); } if ((name_server_number >= name_servers.size()) || (name_server_number > DNS_NAME_SERVER_MAX_INDEX)) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } PACK( struct name_server_s { uint8_t index; uint32_t address; }); STATIC_ASSERT(sizeof(name_server_s) == 5); struct name_server_s name_server; name_server.index = name_server_number; // s_addr is already in network byte order, so doesn't need converting name_server.address = name_servers.at(name_server_number).AsInt(); return GetResponseFromData( request, reinterpret_cast(&name_server), sizeof(name_server), RDM_ACK, queued_message_count); } RDMResponse *ResponderHelper::GetParamDescription( const RDMRequest *request, uint16_t pid, uint8_t pdl_size, rdm_data_type data_type, rdm_command_class command_class, rdm_pid_unit unit, rdm_pid_prefix prefix, uint32_t min_value, uint32_t default_value, uint32_t max_value, string description, uint8_t queued_message_count) { PACK( struct parameter_description_s { uint16_t pid; uint8_t pdl_size; uint8_t data_type; uint8_t command_class; uint8_t type; uint8_t unit; uint8_t prefix; uint32_t min_value; uint32_t default_value; uint32_t max_value; char description[MAX_RDM_STRING_LENGTH]; }); STATIC_ASSERT(sizeof(parameter_description_s) == 52); struct parameter_description_s param_description; param_description.pid = HostToNetwork(pid); param_description.pdl_size = HostToNetwork(pdl_size); param_description.data_type = HostToNetwork( static_cast(data_type)); param_description.command_class = HostToNetwork( static_cast(command_class)); param_description.type = 0; param_description.unit = HostToNetwork( static_cast(unit)); param_description.prefix = HostToNetwork( static_cast(prefix)); param_description.min_value = min_value; param_description.default_value = default_value; param_description.max_value = max_value; size_t str_len = min(description.size(), sizeof(param_description.description)); strncpy(param_description.description, description.c_str(), str_len); unsigned int param_data_size = ( sizeof(param_description) - sizeof(param_description.description) + str_len); return GetResponseFromData( request, reinterpret_cast(¶m_description), param_data_size, RDM_ACK, queued_message_count); } RDMResponse *ResponderHelper::GetASCIIParamDescription( const RDMRequest *request, uint16_t pid, rdm_command_class command_class, string description, uint8_t queued_message_count) { return GetParamDescription( request, pid, static_cast(MAX_RDM_STRING_LENGTH), DS_ASCII, command_class, UNITS_NONE, PREFIX_NONE, static_cast(0), static_cast(0), static_cast(0), description, queued_message_count); } RDMResponse *ResponderHelper::GetBitFieldParamDescription( const RDMRequest *request, uint16_t pid, uint8_t pdl_size, rdm_command_class command_class, string description, uint8_t queued_message_count) { return GetParamDescription( request, pid, pdl_size, DS_BIT_FIELD, command_class, UNITS_NONE, PREFIX_NONE, static_cast(0), static_cast(0), static_cast(0), description, queued_message_count); } /* * Handle a request that returns an IPv4 address */ RDMResponse *ResponderHelper::GetIPV4Address( const RDMRequest *request, const IPV4Address &value, uint8_t queued_message_count) { return GetUInt32Value(request, // Flip it back because s_addr is in network byte order // already NetworkToHost(value.AsInt()), queued_message_count); } /** * @brief Handle a request that returns a string * @note this truncates the string to max_length */ RDMResponse *ResponderHelper::GetString( const RDMRequest *request, const string &value, uint8_t queued_message_count, uint8_t max_length) { if (request->ParamDataSize()) { return NackWithReason(request, NR_FORMAT_ERROR, queued_message_count); } string sanitised_value = value.substr( 0, min(static_cast(value.length()), max_length)); return GetResponseFromData( request, reinterpret_cast(sanitised_value.data()), sanitised_value.size(), RDM_ACK, queued_message_count); } RDMResponse *ResponderHelper::EmptyGetResponse( const RDMRequest *request, uint8_t queued_message_count) { return GetResponseFromData(request, NULL, 0, RDM_ACK, queued_message_count); } RDMResponse *ResponderHelper::EmptySetResponse( const RDMRequest *request, uint8_t queued_message_count) { return GetResponseFromData(request, NULL, 0, RDM_ACK, queued_message_count); } RDMResponse *ResponderHelper::SetString( const RDMRequest *request, string *value, uint8_t queued_message_count, uint8_t max_length) { if (request->ParamDataSize() > max_length) { return NackWithReason(request, NR_FORMAT_ERROR, queued_message_count); } const string new_label(reinterpret_cast(request->ParamData()), request->ParamDataSize()); *value = new_label; return EmptySetResponse(request, queued_message_count); } RDMResponse *ResponderHelper::GetBoolValue(const RDMRequest *request, bool value, uint8_t queued_message_count) { if (request->ParamDataSize()) { return NackWithReason(request, NR_FORMAT_ERROR, queued_message_count); } uint8_t param = value ? 1 : 0; return GetResponseFromData(request, ¶m, sizeof(param), RDM_ACK, queued_message_count); } RDMResponse *ResponderHelper::SetBoolValue(const RDMRequest *request, bool *value, uint8_t queued_message_count) { uint8_t arg; if (!ResponderHelper::ExtractUInt8(request, &arg)) { return NackWithReason(request, NR_FORMAT_ERROR, queued_message_count); } if (arg == 0 || arg == 1) { *value = arg; return EmptySetResponse(request, queued_message_count); } else { return NackWithReason(request, NR_DATA_OUT_OF_RANGE, queued_message_count); } } template static RDMResponse *GenericGetIntValue(const RDMRequest *request, T value, uint8_t queued_message_count = 0) { if (request->ParamDataSize()) { return NackWithReason(request, NR_FORMAT_ERROR, queued_message_count); } T param = HostToNetwork(value); return GetResponseFromData( request, reinterpret_cast(¶m), sizeof(param), RDM_ACK, queued_message_count); } RDMResponse *ResponderHelper::GetUInt8Value( const RDMRequest *request, uint8_t value, uint8_t queued_message_count) { return GenericGetIntValue(request, value, queued_message_count); } RDMResponse *ResponderHelper::GetUInt16Value( const RDMRequest *request, uint16_t value, uint8_t queued_message_count) { return GenericGetIntValue(request, value, queued_message_count); } RDMResponse *ResponderHelper::GetUInt32Value( const RDMRequest *request, uint32_t value, uint8_t queued_message_count) { return GenericGetIntValue(request, value, queued_message_count); } template static RDMResponse *GenericSetIntValue(const RDMRequest *request, T *value, uint8_t queued_message_count = 0) { if (!GenericExtractValue(request, value)) { return NackWithReason(request, NR_FORMAT_ERROR, queued_message_count); } return ResponderHelper::EmptySetResponse(request, queued_message_count); } RDMResponse *ResponderHelper::SetUInt8Value( const RDMRequest *request, uint8_t *value, uint8_t queued_message_count) { return GenericSetIntValue(request, value, queued_message_count); } RDMResponse *ResponderHelper::SetUInt16Value( const RDMRequest *request, uint16_t *value, uint8_t queued_message_count) { return GenericSetIntValue(request, value, queued_message_count); } RDMResponse *ResponderHelper::SetUInt32Value( const RDMRequest *request, uint32_t *value, uint8_t queued_message_count) { return GenericSetIntValue(request, value, queued_message_count); } bool ResponderHelper::FindInterface( const NetworkManagerInterface *network_manager, Interface *interface, uint32_t index) { InterfacePicker::Options options; options.specific_only = true; return network_manager->GetInterfacePicker()->ChooseInterface( interface, index, options); } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/PidStoreLoader.h0000644000175000017500000001111113023355232020554 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * PidStoreLoader.h * This class does the heavy lifting for loading the PidStore from a protobuf. * It's separate so that PidStore.h doesn't have to include the Pids.pb.h * header. * Copyright (C) 2011 Simon Newton */ #ifndef COMMON_RDM_PIDSTORELOADER_H_ #define COMMON_RDM_PIDSTORELOADER_H_ #include #include #include #include #include #include #include "common/rdm/DescriptorConsistencyChecker.h" #include "common/rdm/Pids.pb.h" namespace ola { namespace rdm { /** * The PidStore Loader */ class PidStoreLoader { public: PidStoreLoader() {} /** * @brief Load PID information from a file. * @param file the path to the file to load * @param validate set to true if we should perform validation of the * contents. * @returns A pointer to a new RootPidStore or NULL if loading failed. */ const RootPidStore *LoadFromFile(const std::string &file, bool validate = true); /** * @brief Load PID information from a directory, including overrides. * @param directory the directory to load files from. * @param validate set to true if we should perform validation of the * contents. * @returns A pointer to a new RootPidStore or NULL if loading failed. * * This is an all-or-nothing load. Any error with cause us to abort the load. */ const RootPidStore *LoadFromDirectory(const std::string &directory, bool validate = true); /** * @brief Load Pid information from a stream * @param data the input stream. * @param validate set to true if we should perform validation of the * contents. * @returns A pointer to a new RootPidStore or NULL if loading failed. */ const RootPidStore *LoadFromStream(std::istream *data, bool validate = true); private: typedef std::map PidMap; typedef std::map ManufacturerMap; DescriptorConsistencyChecker m_checker; bool ReadFile(const std::string &file_path, ola::rdm::pid::PidStore *proto); const RootPidStore *BuildStore(const ola::rdm::pid::PidStore &store_pb, const ola::rdm::pid::PidStore &override_pb, bool validate); bool LoadFromProto(ManufacturerMap *pid_data, const ola::rdm::pid::PidStore &proto, bool validate); template bool GetPidList(PidMap *pid_map, const pb_object &store, bool validate, bool limit_pid_values); PidDescriptor *PidToDescriptor(const ola::rdm::pid::Pid &pid, bool validate); const ola::messaging::Descriptor* FrameFormatToDescriptor( const ola::rdm::pid::FrameFormat &format, bool validate); const ola::messaging::FieldDescriptor *FieldToFieldDescriptor( const ola::rdm::pid::Field &field); template const ola::messaging::FieldDescriptor *IntegerFieldToFieldDescriptor( const ola::rdm::pid::Field &field); const ola::messaging::FieldDescriptor *StringFieldToFieldDescriptor( const ola::rdm::pid::Field &field); const ola::messaging::FieldDescriptor *GroupFieldToFieldDescriptor( const ola::rdm::pid::Field &field); PidDescriptor::sub_device_validator ConvertSubDeviceValidator( const ola::rdm::pid::SubDeviceRange &sub_device_range); void FreeManufacturerMap(ManufacturerMap *data); static const char OVERRIDE_FILE_NAME[]; static const uint16_t ESTA_MANUFACTURER_ID; static const uint16_t MANUFACTURER_PID_MIN; static const uint16_t MANUFACTURER_PID_MAX; DISALLOW_COPY_AND_ASSIGN(PidStoreLoader); }; } // namespace rdm } // namespace ola #endif // COMMON_RDM_PIDSTORELOADER_H_ ola-0.10.5.nojsmin/common/rdm/DimmerSubDevice.cpp0000644000175000017500000001600113023355232021241 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * DimmerSubDevice.cpp * Copyright (C) 2013 Simon Newton */ #include "ola/rdm/DimmerSubDevice.h" #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #include #include "ola/base/Array.h" #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/network/NetworkUtils.h" #include "ola/rdm/OpenLightingEnums.h" #include "ola/rdm/RDMEnums.h" #include "ola/rdm/ResponderHelper.h" namespace ola { namespace rdm { using ola::network::HostToNetwork; using ola::network::NetworkToHost; using std::string; using std::vector; DimmerSubDevice::RDMOps *DimmerSubDevice::RDMOps::instance = NULL; const DimmerSubDevice::Personalities * DimmerSubDevice::Personalities::Instance() { if (!instance) { PersonalityList personalities; personalities.push_back(Personality(1, "8 bit dimming")); personalities.push_back(Personality(2, "16 bit dimming")); instance = new Personalities(personalities); } return instance; } DimmerSubDevice::Personalities *DimmerSubDevice::Personalities::instance = NULL; const ResponderOps::ParamHandler DimmerSubDevice::PARAM_HANDLERS[] = { { PID_DEVICE_INFO, &DimmerSubDevice::GetDeviceInfo, NULL}, { PID_PRODUCT_DETAIL_ID_LIST, &DimmerSubDevice::GetProductDetailList, NULL}, { PID_DEVICE_MODEL_DESCRIPTION, &DimmerSubDevice::GetDeviceModelDescription, NULL}, { PID_MANUFACTURER_LABEL, &DimmerSubDevice::GetManufacturerLabel, NULL}, { PID_DEVICE_LABEL, &DimmerSubDevice::GetDeviceLabel, NULL}, { PID_SOFTWARE_VERSION_LABEL, &DimmerSubDevice::GetSoftwareVersionLabel, NULL}, { PID_DMX_PERSONALITY, &DimmerSubDevice::GetPersonality, &DimmerSubDevice::SetPersonality}, { PID_DMX_PERSONALITY_DESCRIPTION, &DimmerSubDevice::GetPersonalityDescription, NULL}, { PID_DMX_START_ADDRESS, &DimmerSubDevice::GetDmxStartAddress, &DimmerSubDevice::SetDmxStartAddress}, { PID_IDENTIFY_DEVICE, &DimmerSubDevice::GetIdentify, &DimmerSubDevice::SetIdentify}, { PID_IDENTIFY_MODE, &DimmerSubDevice::GetIdentifyMode, &DimmerSubDevice::SetIdentifyMode}, { 0, NULL, NULL}, }; DimmerSubDevice::DimmerSubDevice(const UID &uid, uint16_t sub_device_number, uint16_t sub_device_count) : m_uid(uid), m_sub_device_number(sub_device_number), m_sub_device_count(sub_device_count), m_start_address(sub_device_number), m_identify_on(false), m_identify_mode(IDENTIFY_MODE_LOUD), m_personality_manager(Personalities::Instance()) { } /* * Handle an RDM Request */ void DimmerSubDevice::SendRDMRequest(RDMRequest *request, RDMCallback *callback) { RDMOps::Instance()->HandleRDMRequest(this, m_uid, m_sub_device_number, request, callback); } RDMResponse *DimmerSubDevice::GetDeviceInfo(const RDMRequest *request) { return ResponderHelper::GetDeviceInfo( request, OLA_DUMMY_DIMMER_MODEL, PRODUCT_CATEGORY_DIMMER, 1, &m_personality_manager, m_start_address, m_sub_device_count, 0); } bool DimmerSubDevice::SetDmxStartAddress(uint16_t start_address) { if (start_address < 1 || start_address + Footprint() - 1 > DMX_UNIVERSE_SIZE) return false; m_start_address = start_address; return true; } RDMResponse *DimmerSubDevice::GetProductDetailList( const RDMRequest *request) { // Shortcut for only one item in the vector return ResponderHelper::GetProductDetailList(request, vector (1, PRODUCT_DETAIL_TEST)); } RDMResponse *DimmerSubDevice::GetPersonality( const RDMRequest *request) { return ResponderHelper::GetPersonality(request, &m_personality_manager); } RDMResponse *DimmerSubDevice::SetPersonality( const RDMRequest *request) { return ResponderHelper::SetPersonality(request, &m_personality_manager, m_start_address); } RDMResponse *DimmerSubDevice::GetPersonalityDescription( const RDMRequest *request) { return ResponderHelper::GetPersonalityDescription( request, &m_personality_manager); } RDMResponse *DimmerSubDevice::GetDmxStartAddress( const RDMRequest *request) { return ResponderHelper::GetUInt16Value(request, m_start_address); } RDMResponse *DimmerSubDevice::SetDmxStartAddress( const RDMRequest *request) { return ResponderHelper::SetDmxAddress(request, &m_personality_manager, &m_start_address); } RDMResponse *DimmerSubDevice::GetDeviceModelDescription( const RDMRequest *request) { return ResponderHelper::GetString(request, "OLA Dimmer"); } RDMResponse *DimmerSubDevice::GetManufacturerLabel( const RDMRequest *request) { return ResponderHelper::GetString(request, OLA_MANUFACTURER_LABEL); } RDMResponse *DimmerSubDevice::GetDeviceLabel( const RDMRequest *request) { return ResponderHelper::GetString(request, "Dummy Dimmer"); } RDMResponse *DimmerSubDevice::GetSoftwareVersionLabel( const RDMRequest *request) { return ResponderHelper::GetString(request, string("OLA Version ") + VERSION); } RDMResponse *DimmerSubDevice::GetIdentify(const RDMRequest *request) { return ResponderHelper::GetBoolValue(request, m_identify_on); } RDMResponse *DimmerSubDevice::SetIdentify(const RDMRequest *request) { bool old_value = m_identify_on; RDMResponse *response = ResponderHelper::SetBoolValue( request, &m_identify_on); if (m_identify_on != old_value) { OLA_INFO << "Dummy dimmer device " << m_uid << ":" << m_sub_device_number << ", identify mode " << (m_identify_on ? "on" : "off"); } return response; } RDMResponse *DimmerSubDevice::GetIdentifyMode( const RDMRequest *request) { return ResponderHelper::GetUInt8Value(request, m_identify_mode); } RDMResponse *DimmerSubDevice::SetIdentifyMode( const RDMRequest *request) { uint8_t new_identify_mode; if (!ResponderHelper::ExtractUInt8(request, &new_identify_mode)) return NackWithReason(request, NR_FORMAT_ERROR); if (new_identify_mode != IDENTIFY_MODE_QUIET && new_identify_mode != IDENTIFY_MODE_LOUD) return NackWithReason(request, NR_DATA_OUT_OF_RANGE); m_identify_mode = new_identify_mode; return GetResponseFromData(request, NULL, 0); } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/ResponderLoadSensor.cpp0000644000175000017500000000232213023355232022166 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * ResponderLoadSensor.cpp * Copyright (C) 2013 Peter Newman */ #include "ola/Logging.h" #include "ola/rdm/ResponderLoadSensor.h" #include "ola/system/SystemUtils.h" namespace ola { namespace rdm { /** * Fetch a Sensor value */ int16_t LoadSensor::PollSensor() { double average; if (!ola::system::LoadAverage(m_load_average, &average)) { return LOAD_SENSOR_ERROR_VALUE; } else { return static_cast(average * 100); } } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/DescriptorConsistencyChecker.cpp0000644000175000017500000000535213023355232024066 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * DescriptorConsistencyChecker.cpp * Verify that we can determine the layout of a Descriptor. * Copyright (C) 2011 Simon Newton */ #include "common/rdm/DescriptorConsistencyChecker.h" namespace ola { namespace rdm { bool DescriptorConsistencyChecker::CheckConsistency( const ola::messaging::Descriptor *descriptor) { m_variable_sized_field_count = 0; descriptor->Accept(this); return m_variable_sized_field_count <= 1; } void DescriptorConsistencyChecker::Visit( const ola::messaging::BoolFieldDescriptor*) { } void DescriptorConsistencyChecker::Visit( const ola::messaging::IPV4FieldDescriptor*) { } void DescriptorConsistencyChecker::Visit( const ola::messaging::MACFieldDescriptor*) { } void DescriptorConsistencyChecker::Visit( const ola::messaging::UIDFieldDescriptor*) { } void DescriptorConsistencyChecker::Visit( const ola::messaging::StringFieldDescriptor *descriptor) { if (!descriptor->FixedSize()) { m_variable_sized_field_count++; } } void DescriptorConsistencyChecker::Visit( const ola::messaging::UInt8FieldDescriptor*) { } void DescriptorConsistencyChecker::Visit( const ola::messaging::UInt16FieldDescriptor*) { } void DescriptorConsistencyChecker::Visit( const ola::messaging::UInt32FieldDescriptor*) { } void DescriptorConsistencyChecker::Visit( const ola::messaging::Int8FieldDescriptor*) { } void DescriptorConsistencyChecker::Visit( const ola::messaging::Int16FieldDescriptor*) { } void DescriptorConsistencyChecker::Visit( const ola::messaging::Int32FieldDescriptor*) { } void DescriptorConsistencyChecker::Visit( const ola::messaging::FieldDescriptorGroup *descriptor) { if (!descriptor->FixedSize()) m_variable_sized_field_count++; // if the block size isn't fixed this descriptor isn't consistent. if (!descriptor->FixedBlockSize()) m_variable_sized_field_count++; } void DescriptorConsistencyChecker::PostVisit( const ola::messaging::FieldDescriptorGroup*) { } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/UID.cpp0000644000175000017500000000266113023355232016662 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * UID.cpp * The UID class. * Copyright (C) 2011 Simon Newton */ #include #include #include "ola/StringUtils.h" #include "ola/rdm/UID.h" namespace ola { namespace rdm { using std::string; using std::vector; UID* UID::FromString(const string &uid) { vector tokens; ola::StringSplit(uid, &tokens, ":"); if (tokens.size() != 2 || tokens[0].size() != 4 || tokens[1].size() != 8) { return NULL; } uint16_t esta_id; unsigned int device_id; if (!ola::HexStringToInt(tokens[0], &esta_id)) { return NULL; } if (!ola::HexStringToInt(tokens[1], &device_id)) { return NULL; } return new UID(esta_id, device_id); } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/MessageDeserializerTest.cpp0000644000175000017500000004014213023355232023024 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * MessageDeserializerTest.cpp * Test fixture for the MessageDeserializer classes * Copyright (C) 2011 Simon Newton */ #include #include #include #include #include "ola/Logging.h" #include "ola/messaging/Descriptor.h" #include "ola/messaging/Message.h" #include "ola/messaging/MessagePrinter.h" #include "ola/rdm/MessageSerializer.h" #include "ola/rdm/MessageDeserializer.h" #include "ola/testing/TestUtils.h" using ola::messaging::BoolFieldDescriptor; using ola::messaging::IPV4FieldDescriptor; using ola::messaging::Descriptor; using ola::messaging::FieldDescriptor; using ola::messaging::FieldDescriptorGroup; using ola::messaging::Int16FieldDescriptor; using ola::messaging::Int32FieldDescriptor; using ola::messaging::Int8FieldDescriptor; using ola::messaging::IPV4FieldDescriptor; using ola::messaging::MACFieldDescriptor; using ola::messaging::Message; using ola::messaging::GenericMessagePrinter; using ola::messaging::StringFieldDescriptor; using ola::messaging::UInt16FieldDescriptor; using ola::messaging::UInt32FieldDescriptor; using ola::messaging::UInt8FieldDescriptor; using ola::messaging::UIDFieldDescriptor; using ola::rdm::MessageDeserializer; using std::auto_ptr; using std::string; using std::vector; class MessageDeserializerTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(MessageDeserializerTest); CPPUNIT_TEST(testEmpty); CPPUNIT_TEST(testSimpleBigEndian); CPPUNIT_TEST(testSimpleLittleEndian); CPPUNIT_TEST(testIPV4); CPPUNIT_TEST(testMAC); CPPUNIT_TEST(testString); CPPUNIT_TEST(testUID); CPPUNIT_TEST(testWithGroups); CPPUNIT_TEST(testWithNestedFixedGroups); CPPUNIT_TEST(testWithNestedVariableGroups); CPPUNIT_TEST_SUITE_END(); public: void testEmpty(); void testSimpleBigEndian(); void testSimpleLittleEndian(); void testIPV4(); void testMAC(); void testString(); void testUID(); void testWithGroups(); void testWithNestedFixedGroups(); void testWithNestedVariableGroups(); private: MessageDeserializer m_deserializer; GenericMessagePrinter m_printer; }; CPPUNIT_TEST_SUITE_REGISTRATION(MessageDeserializerTest); /** * Check that empty messages work. */ void MessageDeserializerTest::testEmpty() { vector fields; Descriptor descriptor("Empty Descriptor", fields); auto_ptr empty_message(m_deserializer.InflateMessage( &descriptor, NULL, 0)); OLA_ASSERT_NOT_NULL(empty_message.get()); OLA_ASSERT_EQ(0u, empty_message->FieldCount()); // now and try to pass in too much data const uint8_t data[] = {0, 1, 2}; OLA_ASSERT_NULL(m_deserializer.InflateMessage( &descriptor, data, sizeof(data))); } /** * Test that simple (no variable sized fields) work big endian style. */ void MessageDeserializerTest::testSimpleBigEndian() { // build the descriptor vector fields; // All multi-byte fields default to big endian fields.push_back(new BoolFieldDescriptor("bool")); fields.push_back(new UInt8FieldDescriptor("uint8")); fields.push_back(new Int8FieldDescriptor("int8")); fields.push_back(new UInt16FieldDescriptor("uint16")); fields.push_back(new Int16FieldDescriptor("int16")); fields.push_back(new UInt32FieldDescriptor("uint32")); fields.push_back(new Int32FieldDescriptor("int32")); Descriptor descriptor("Test Descriptor", fields); // now setup the data const uint8_t big_endian_data[] = { 0, 10, 246, 1, 0x2c, 0xfe, 10, 1, 2, 3, 4, 0xfe, 6, 7, 8}; // try to inflate with no data OLA_ASSERT_NULL(m_deserializer.InflateMessage( &descriptor, NULL, 0)); // now inflate with too little data OLA_ASSERT_NULL(m_deserializer.InflateMessage( &descriptor, big_endian_data, 1)); // now inflate with too much data OLA_ASSERT_NULL(m_deserializer.InflateMessage( &descriptor, big_endian_data, sizeof(big_endian_data) + 1)); // now the correct amount & verify auto_ptr message(m_deserializer.InflateMessage( &descriptor, big_endian_data, sizeof(big_endian_data))); OLA_ASSERT_NOT_NULL(message.get()); OLA_ASSERT_EQ(7u, message->FieldCount()); const string expected = ( "bool: false\nuint8: 10\nint8: -10\nuint16: 300\nint16: -502\n" "uint32: 16909060\nint32: -33159416\n"); OLA_ASSERT_EQ(expected, m_printer.AsString(message.get())); } /** * Test that simple (no variable sized fields) work little endian style. */ void MessageDeserializerTest::testSimpleLittleEndian() { // build the descriptor vector fields; fields.push_back(new BoolFieldDescriptor("bool")); fields.push_back(new UInt8FieldDescriptor("uint8")); fields.push_back(new Int8FieldDescriptor("int8")); fields.push_back(new UInt16FieldDescriptor("uint16", true)); fields.push_back(new Int16FieldDescriptor("int16", true)); fields.push_back(new UInt32FieldDescriptor("uint32", true)); fields.push_back(new Int32FieldDescriptor("int32", true)); Descriptor descriptor("Test Descriptor", fields); // now setup the data const uint8_t little_endian_data[] = { 1, 10, 246, 0x2c, 1, 10, 0xfe, 4, 3, 2, 1, 8, 7, 6, 0xfe}; // try to inflate with no data OLA_ASSERT_NULL(m_deserializer.InflateMessage( &descriptor, NULL, 0)); // now inflate with too little data OLA_ASSERT_NULL(m_deserializer.InflateMessage( &descriptor, little_endian_data, 1)); // now inflate with too much data OLA_ASSERT_NULL(m_deserializer.InflateMessage( &descriptor, little_endian_data, sizeof(little_endian_data) + 1)); // now the correct amount & verify auto_ptr message(m_deserializer.InflateMessage( &descriptor, little_endian_data, sizeof(little_endian_data))); OLA_ASSERT_NOT_NULL(message.get()); OLA_ASSERT_EQ(7u, message->FieldCount()); const string expected = ( "bool: true\nuint8: 10\nint8: -10\nuint16: 300\nint16: -502\n" "uint32: 16909060\nint32: -33159416\n"); OLA_ASSERT_EQ(expected, m_printer.AsString(message.get())); } /** * Test IPV4 inflation. */ void MessageDeserializerTest::testIPV4() { // build the descriptor vector fields; fields.push_back(new IPV4FieldDescriptor("Address")); Descriptor descriptor("Test Descriptor", fields); // now setup the data const uint8_t big_endian_data[] = {10, 0, 0, 1}; // now the correct amount & verify auto_ptr message(m_deserializer.InflateMessage( &descriptor, big_endian_data, sizeof(big_endian_data))); OLA_ASSERT_NOT_NULL(message.get()); OLA_ASSERT_EQ(1u, message->FieldCount()); const string expected = "Address: 10.0.0.1\n"; OLA_ASSERT_EQ(expected, m_printer.AsString(message.get())); } /** * Test MAC inflation. */ void MessageDeserializerTest::testMAC() { // build the descriptor vector fields; fields.push_back(new MACFieldDescriptor("Address")); Descriptor descriptor("Test Descriptor", fields); // now setup the data const uint8_t big_endian_data[] = {1, 35, 69, 103, 137, 171}; // now the correct amount & verify auto_ptr message(m_deserializer.InflateMessage( &descriptor, big_endian_data, sizeof(big_endian_data))); OLA_ASSERT_NOT_NULL(message.get()); OLA_ASSERT_EQ(1u, message->FieldCount()); const string expected = "Address: 01:23:45:67:89:ab\n"; OLA_ASSERT_EQ(expected, m_printer.AsString(message.get())); } /** * Check that strings do the right thing */ void MessageDeserializerTest::testString() { vector fields; fields.push_back(new StringFieldDescriptor("string", 10, 10)); fields.push_back(new StringFieldDescriptor("string", 0, 32)); Descriptor descriptor("Test Descriptor", fields); // now setup the data const uint8_t data[] = "0123456789this is a longer string"; // try to inflate with too little OLA_ASSERT_NULL(m_deserializer.InflateMessage( &descriptor, data, 0)); OLA_ASSERT_NULL(m_deserializer.InflateMessage( &descriptor, data, 9)); // try to inflat with too much data OLA_ASSERT_NULL(m_deserializer.InflateMessage( &descriptor, data, 43)); // now to the right amount auto_ptr message(m_deserializer.InflateMessage( &descriptor, data, sizeof(data))); OLA_ASSERT_NOT_NULL(message.get()); OLA_ASSERT_EQ(2u, message->FieldCount()); const string expected = ( "string: 0123456789\nstring: this is a longer string\n"); OLA_ASSERT_EQ(expected, m_printer.AsString(message.get())); // now try with different sizes auto_ptr message2(m_deserializer.InflateMessage( &descriptor, data, 19)); OLA_ASSERT_NOT_NULL(message2.get()); OLA_ASSERT_EQ(2u, message2->FieldCount()); const string expected2 = ( "string: 0123456789\nstring: this is a\n"); OLA_ASSERT_EQ(expected2, m_printer.AsString(message2.get())); } /** * Test UID inflation. */ void MessageDeserializerTest::testUID() { // build the descriptor vector fields; fields.push_back(new UIDFieldDescriptor("Address")); Descriptor descriptor("Test Descriptor", fields); // now setup the data const uint8_t big_endian_data[] = {0x70, 0x7a, 0, 0, 0, 1}; // now the correct amount & verify auto_ptr message(m_deserializer.InflateMessage( &descriptor, big_endian_data, sizeof(big_endian_data))); OLA_ASSERT_NOT_NULL(message.get()); OLA_ASSERT_EQ(1u, message->FieldCount()); const string expected = "Address: 707a:00000001\n"; OLA_ASSERT_EQ(expected, m_printer.AsString(message.get())); } /* * Check the MessageSerializer works with variable sized groups. */ void MessageDeserializerTest::testWithGroups() { // build the descriptor vector group_fields; group_fields.push_back(new BoolFieldDescriptor("bool")); group_fields.push_back(new UInt8FieldDescriptor("uint8")); vector fields; fields.push_back(new FieldDescriptorGroup("group", group_fields, 0, 3)); Descriptor descriptor("Test Descriptor", fields); // now setup the inputs const uint8_t data[] = {0, 10, 1, 3, 0, 20, 1, 40}; // an empty message auto_ptr message(m_deserializer.InflateMessage( &descriptor, data, 0)); OLA_ASSERT_NOT_NULL(message.get()); OLA_ASSERT_EQ(0u, message->FieldCount()); // message with not enough data OLA_ASSERT_NULL(m_deserializer.InflateMessage( &descriptor, data, 1)); // a single instance of a group auto_ptr message2(m_deserializer.InflateMessage( &descriptor, data, 2)); OLA_ASSERT_NOT_NULL(message2.get()); OLA_ASSERT_EQ(1u, message2->FieldCount()); const string expected = "group {\n bool: false\n uint8: 10\n}\n"; OLA_ASSERT_EQ(expected, m_printer.AsString(message2.get())); // another message with not enough data OLA_ASSERT_NULL(m_deserializer.InflateMessage( &descriptor, data, 3)); // two instances of the group auto_ptr message3(m_deserializer.InflateMessage( &descriptor, data, 4)); OLA_ASSERT_NOT_NULL(message3.get()); OLA_ASSERT_EQ(2u, message3->FieldCount()); const string expected2 = ( "group {\n bool: false\n uint8: 10\n}\n" "group {\n bool: true\n uint8: 3\n}\n"); OLA_ASSERT_EQ(expected2, m_printer.AsString(message3.get())); // trhee instances of the group auto_ptr message4(m_deserializer.InflateMessage( &descriptor, data, 6)); OLA_ASSERT_NOT_NULL(message4.get()); OLA_ASSERT_EQ(3u, message4->FieldCount()); const string expected3 = ( "group {\n bool: false\n uint8: 10\n}\n" "group {\n bool: true\n uint8: 3\n}\n" "group {\n bool: false\n uint8: 20\n}\n"); OLA_ASSERT_EQ(expected3, m_printer.AsString(message4.get())); // message with too much data OLA_ASSERT_NULL(m_deserializer.InflateMessage( &descriptor, data, sizeof(data))); } /* * Test MessageSerializer with nested fixed groups. */ void MessageDeserializerTest::testWithNestedFixedGroups() { vector fields, group_fields, group_fields2; group_fields.push_back(new BoolFieldDescriptor("bool")); group_fields2.push_back(new UInt8FieldDescriptor("uint8")); group_fields2.push_back(new FieldDescriptorGroup("bar", group_fields, 2, 2)); fields.push_back(new FieldDescriptorGroup("", group_fields2, 0, 4)); Descriptor descriptor("Test Descriptor", fields); // now setup the inputs const uint8_t data[] = {0, 0, 0, 1, 0, 1, 2, 1, 0, 3, 1, 1}; // an empty mesage auto_ptr message(m_deserializer.InflateMessage( &descriptor, data, 0)); OLA_ASSERT_NOT_NULL(message.get()); OLA_ASSERT_EQ(0u, message->FieldCount()); // message with not enough data OLA_ASSERT_NULL(m_deserializer.InflateMessage( &descriptor, data, 1)); OLA_ASSERT_NULL(m_deserializer.InflateMessage( &descriptor, data, 2)); // a single instance of a group auto_ptr message2(m_deserializer.InflateMessage( &descriptor, data, 3)); OLA_ASSERT_NOT_NULL(message2.get()); OLA_ASSERT_EQ(1u, message2->FieldCount()); const string expected = ( " {\n uint8: 0\n bar {\n bool: false\n }\n bar {\n" " bool: false\n }\n}\n"); OLA_ASSERT_EQ(expected, m_printer.AsString(message2.get())); // four instances auto_ptr message3(m_deserializer.InflateMessage( &descriptor, data, sizeof(data))); OLA_ASSERT_NOT_NULL(message3.get()); OLA_ASSERT_EQ(4u, message3->FieldCount()); const string expected2 = ( " {\n uint8: 0\n bar {\n bool: false\n }\n bar {\n" " bool: false\n }\n}\n" " {\n uint8: 1\n bar {\n bool: false\n }\n bar {\n" " bool: true\n }\n}\n" " {\n uint8: 2\n bar {\n bool: true\n }\n bar {\n" " bool: false\n }\n}\n" " {\n uint8: 3\n bar {\n bool: true\n }\n bar {\n" " bool: true\n }\n}\n"); OLA_ASSERT_EQ(expected2, m_printer.AsString(message3.get())); // too much data OLA_ASSERT_NULL(m_deserializer.InflateMessage( &descriptor, data, sizeof(data) + 1)); } /* * Test MessageSerializer with nested variable groups, this should never * extract. */ void MessageDeserializerTest::testWithNestedVariableGroups() { vector fields, group_fields, group_fields2; group_fields.push_back(new BoolFieldDescriptor("bool")); group_fields2.push_back(new Int16FieldDescriptor("uint16")); group_fields2.push_back(new FieldDescriptorGroup("bar", group_fields, 0, 2)); fields.push_back(new FieldDescriptorGroup("", group_fields2, 0, 4)); Descriptor descriptor("Test Descriptor", fields); // an empty message would be valid. OLA_ASSERT_NULL(m_deserializer.InflateMessage( &descriptor, NULL, 0)); const uint8_t data[] = {0, 1, 0, 1}; // none of these are valid OLA_ASSERT_NULL(m_deserializer.InflateMessage( &descriptor, data, 1)); OLA_ASSERT_NULL(m_deserializer.InflateMessage( &descriptor, data, 2)); OLA_ASSERT_NULL(m_deserializer.InflateMessage( &descriptor, data, 3)); OLA_ASSERT_NULL(m_deserializer.InflateMessage( &descriptor, data, 4)); } ola-0.10.5.nojsmin/common/rdm/SensorResponder.cpp0000644000175000017500000002034513023355232021373 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SensorResponder.cpp * Copyright (C) 2013 Simon Newton */ #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #include #include #include "ola/base/Array.h" #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/math/Random.h" #include "ola/network/NetworkUtils.h" #include "ola/rdm/OpenLightingEnums.h" #include "ola/rdm/RDMEnums.h" #include "ola/rdm/ResponderHelper.h" #include "ola/rdm/ResponderLoadSensor.h" #include "ola/rdm/ResponderSensor.h" #include "ola/rdm/SensorResponder.h" #include "ola/stl/STLUtils.h" namespace ola { namespace rdm { using ola::network::HostToNetwork; using ola::network::NetworkToHost; using std::string; using std::vector; SensorResponder::RDMOps *SensorResponder::RDMOps::instance = NULL; const ResponderOps::ParamHandler SensorResponder::PARAM_HANDLERS[] = { { PID_DEVICE_INFO, &SensorResponder::GetDeviceInfo, NULL}, { PID_PRODUCT_DETAIL_ID_LIST, &SensorResponder::GetProductDetailList, NULL}, { PID_DEVICE_MODEL_DESCRIPTION, &SensorResponder::GetDeviceModelDescription, NULL}, { PID_MANUFACTURER_LABEL, &SensorResponder::GetManufacturerLabel, NULL}, { PID_DEVICE_LABEL, &SensorResponder::GetDeviceLabel, NULL}, { PID_SOFTWARE_VERSION_LABEL, &SensorResponder::GetSoftwareVersionLabel, NULL}, { PID_SENSOR_DEFINITION, &SensorResponder::GetSensorDefinition, NULL}, { PID_SENSOR_VALUE, &SensorResponder::GetSensorValue, &SensorResponder::SetSensorValue}, { PID_RECORD_SENSORS, NULL, &SensorResponder::RecordSensor}, { PID_IDENTIFY_DEVICE, &SensorResponder::GetIdentify, &SensorResponder::SetIdentify}, { 0, NULL, NULL}, }; /** * A class which represents a sensor. */ class FakeSensor: public Sensor { public: FakeSensor(ola::rdm::rdm_sensor_type type, ola::rdm::rdm_pid_unit unit, ola::rdm::rdm_pid_prefix prefix, const string &description, const SensorOptions &options) : Sensor(type, unit, prefix, description, options) { // set high / low to something Reset(); // Force recorded back to zero m_recorded = 0; } protected: int16_t PollSensor(); }; /** * Fetch a Sensor value */ int16_t FakeSensor::PollSensor() { // This is a fake sensor, so make a value return ola::math::Random(m_range_min, m_range_max); } /** * New SensorResponder */ SensorResponder::SensorResponder(const UID &uid) : m_uid(uid), m_identify_mode(false) { Sensor::SensorOptions fake_temperature_options; fake_temperature_options.recorded_value_support = true; fake_temperature_options.recorded_range_support = true; fake_temperature_options.range_min = 0; fake_temperature_options.range_max = 100; fake_temperature_options.normal_min = 10; fake_temperature_options.normal_max = 20; m_sensors.push_back(new FakeSensor(SENSOR_TEMPERATURE, UNITS_CENTIGRADE, PREFIX_NONE, "Fake Temperature", fake_temperature_options)); Sensor::SensorOptions fake_voltage_options; fake_voltage_options.recorded_value_support = true; fake_voltage_options.recorded_range_support = true; fake_voltage_options.range_min = 110; fake_voltage_options.range_max = 140; fake_voltage_options.normal_min = 119; fake_voltage_options.normal_max = 125; m_sensors.push_back(new FakeSensor(SENSOR_VOLTAGE, UNITS_VOLTS_DC, PREFIX_DECI, "Fake Voltage", fake_voltage_options)); Sensor::SensorOptions fake_beta_particle_counter_options; fake_beta_particle_counter_options.recorded_value_support = true; fake_beta_particle_counter_options.recorded_range_support = true; fake_beta_particle_counter_options.range_min = 0; fake_beta_particle_counter_options.range_max = 100; fake_beta_particle_counter_options.normal_min = 0; fake_beta_particle_counter_options.normal_max = 1; m_sensors.push_back(new FakeSensor(SENSOR_ITEMS, UNITS_NONE, PREFIX_KILO, "Fake Beta Particle Counter", fake_beta_particle_counter_options)); #ifdef HAVE_GETLOADAVG m_sensors.push_back(new LoadSensor(ola::system::LOAD_AVERAGE_1_MIN, "Load Average 1 minute")); m_sensors.push_back(new LoadSensor(ola::system::LOAD_AVERAGE_5_MINS, "Load Average 5 minutes")); m_sensors.push_back(new LoadSensor(ola::system::LOAD_AVERAGE_15_MINS, "Load Average 15 minutes")); #endif // HAVE_GETLOADAVG } SensorResponder::~SensorResponder() { STLDeleteElements(&m_sensors); } /* * Handle an RDM Request */ void SensorResponder::SendRDMRequest(RDMRequest *request, RDMCallback *callback) { RDMOps::Instance()->HandleRDMRequest(this, m_uid, ROOT_RDM_DEVICE, request, callback); } RDMResponse *SensorResponder::GetDeviceInfo( const RDMRequest *request) { return ResponderHelper::GetDeviceInfo( request, OLA_SENSOR_ONLY_MODEL, PRODUCT_CATEGORY_TEST, 2, 0, 1, 1, ZERO_FOOTPRINT_DMX_ADDRESS, 0, m_sensors.size()); } RDMResponse *SensorResponder::GetProductDetailList( const RDMRequest *request) { // Shortcut for only one item in the vector return ResponderHelper::GetProductDetailList( request, vector(1, PRODUCT_DETAIL_TEST)); } RDMResponse *SensorResponder::GetIdentify( const RDMRequest *request) { return ResponderHelper::GetBoolValue(request, m_identify_mode); } RDMResponse *SensorResponder::SetIdentify( const RDMRequest *request) { bool old_value = m_identify_mode; RDMResponse *response = ResponderHelper::SetBoolValue( request, &m_identify_mode); if (m_identify_mode != old_value) { OLA_INFO << "Sensor Device " << m_uid << ", identify mode " << (m_identify_mode ? "on" : "off"); } return response; } RDMResponse *SensorResponder::GetDeviceModelDescription( const RDMRequest *request) { return ResponderHelper::GetString(request, "OLA Sensor Device"); } RDMResponse *SensorResponder::GetManufacturerLabel( const RDMRequest *request) { return ResponderHelper::GetString(request, OLA_MANUFACTURER_LABEL); } RDMResponse *SensorResponder::GetDeviceLabel( const RDMRequest *request) { return ResponderHelper::GetString(request, "Sensor Device"); } RDMResponse *SensorResponder::GetSoftwareVersionLabel( const RDMRequest *request) { return ResponderHelper::GetString(request, string("OLA Version ") + VERSION); } /** * PID_SENSOR_DEFINITION */ RDMResponse *SensorResponder::GetSensorDefinition( const RDMRequest *request) { return ResponderHelper::GetSensorDefinition(request, m_sensors); } /** * PID_SENSOR_VALUE */ RDMResponse *SensorResponder::GetSensorValue(const RDMRequest *request) { return ResponderHelper::GetSensorValue(request, m_sensors); } RDMResponse *SensorResponder::SetSensorValue(const RDMRequest *request) { return ResponderHelper::SetSensorValue(request, m_sensors); } /** * PID_RECORD_SENSORS */ RDMResponse *SensorResponder::RecordSensor(const RDMRequest *request) { return ResponderHelper::RecordSensor(request, m_sensors); } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/MovingLightResponder.cpp0000644000175000017500000005153213023355232022353 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * MovingLightResponder.cpp * Copyright (C) 2013 Simon Newton */ #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #include #include #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/base/Array.h" #include "ola/network/NetworkUtils.h" #include "ola/rdm/MovingLightResponder.h" #include "ola/rdm/OpenLightingEnums.h" #include "ola/rdm/RDMEnums.h" #include "ola/rdm/RDMHelper.h" #include "ola/rdm/ResponderHelper.h" #include "ola/rdm/ResponderSlotData.h" #include "ola/StringUtils.h" namespace ola { namespace rdm { using ola::network::HostToNetwork; using ola::network::NetworkToHost; using std::string; using std::vector; MovingLightResponder::RDMOps *MovingLightResponder::RDMOps::instance = NULL; const MovingLightResponder::Personalities * MovingLightResponder::Personalities::Instance() { if (!instance) { SlotDataCollection::SlotDataList p1_slot_data; p1_slot_data.push_back( SlotData::PrimarySlot(SD_INTENSITY, 0, "Intensity Coarse")); // 0 p1_slot_data.push_back( SlotData::SecondarySlot(ST_SEC_FINE, 0, 0, "Intensity Fine")); // 1 p1_slot_data.push_back( SlotData::SecondarySlot(ST_SEC_CONTROL, 0, 0, "Shutter")); // 2 p1_slot_data.push_back(SlotData::PrimarySlot(SD_PAN, 127)); // 3 p1_slot_data.push_back( SlotData::SecondarySlot(ST_SEC_SPEED, 3, 0, "Pan Speed")); // 4 p1_slot_data.push_back(SlotData::PrimarySlot(SD_TILT, 127)); // 5 p1_slot_data.push_back( SlotData::SecondarySlot(ST_SEC_TIMING, 5, 0, "Tilt Timing")); // 6 p1_slot_data.push_back(SlotData::PrimarySlot(SD_ROTO_GOBO_WHEEL, 0)); // 7 p1_slot_data.push_back( SlotData::SecondarySlot(ST_SEC_INDEX, 7, 0)); // 8 p1_slot_data.push_back(SlotData::PrimarySlot(SD_PRISM_WHEEL, 0)); // 9 p1_slot_data.push_back( SlotData::SecondarySlot(ST_SEC_ROTATION, 8, 0)); // 10 p1_slot_data.push_back(SlotData::PrimarySlot(SD_EFFECTS_WHEEL, 0)); // 11 p1_slot_data.push_back( SlotData::SecondarySlot(ST_SEC_INDEX_ROTATE, 8, 0)); // 12 p1_slot_data.push_back( SlotData::PrimarySlot(SD_FIXTURE_SPEED, 0, "Speed")); // 13 p1_slot_data.push_back( SlotData::SecondarySlot(ST_SEC_SPEED, 13, 0, "Speed ^ 2")); // 14 p1_slot_data.push_back( SlotData::PrimarySlot(SD_UNDEFINED, 0, "Open Sourceiness Foo")); // 15 p1_slot_data.push_back( SlotData::SecondarySlot(ST_SEC_UNDEFINED, 15, 0, "Open Sourceiness Bar")); // 16 SlotDataCollection::SlotDataList p2_slot_data; p2_slot_data.push_back(SlotData::PrimarySlot(SD_INTENSITY, 0)); p2_slot_data.push_back(SlotData::PrimarySlot(SD_PAN, 127)); p2_slot_data.push_back(SlotData::PrimarySlot(SD_TILT, 127)); p2_slot_data.push_back(SlotData::PrimarySlot(SD_COLOR_WHEEL, 0)); p2_slot_data.push_back(SlotData::PrimarySlot(SD_STATIC_GOBO_WHEEL, 0)); SlotDataCollection::SlotDataList p4_slot_data; p4_slot_data.push_back( SlotData::PrimarySlot(SD_INTENSITY, 0, "")); p4_slot_data.push_back( SlotData::SecondarySlot(ST_SEC_FINE, 0, 0, "")); PersonalityList personalities; personalities.push_back(Personality(17, "Full", SlotDataCollection(p1_slot_data))); personalities.push_back(Personality(5, "Basic", SlotDataCollection(p2_slot_data))); personalities.push_back(Personality(0, "No Channels")); personalities.push_back(Personality(3, // One more slot than highest "Quirks Mode", SlotDataCollection(p4_slot_data))); instance = new Personalities(personalities); } return instance; } MovingLightResponder::Personalities * MovingLightResponder::Personalities::instance = NULL; const ResponderOps::ParamHandler MovingLightResponder::PARAM_HANDLERS[] = { { PID_PARAMETER_DESCRIPTION, &MovingLightResponder::GetParamDescription, NULL}, { PID_DEVICE_INFO, &MovingLightResponder::GetDeviceInfo, NULL}, { PID_PRODUCT_DETAIL_ID_LIST, &MovingLightResponder::GetProductDetailList, NULL}, { PID_DEVICE_MODEL_DESCRIPTION, &MovingLightResponder::GetDeviceModelDescription, NULL}, { PID_MANUFACTURER_LABEL, &MovingLightResponder::GetManufacturerLabel, NULL}, { PID_DEVICE_LABEL, &MovingLightResponder::GetDeviceLabel, &MovingLightResponder::SetDeviceLabel}, { PID_FACTORY_DEFAULTS, &MovingLightResponder::GetFactoryDefaults, &MovingLightResponder::SetFactoryDefaults}, { PID_LANGUAGE_CAPABILITIES, &MovingLightResponder::GetLanguageCapabilities, NULL}, { PID_LANGUAGE, &MovingLightResponder::GetLanguage, &MovingLightResponder::SetLanguage}, { PID_SOFTWARE_VERSION_LABEL, &MovingLightResponder::GetSoftwareVersionLabel, NULL}, { PID_DMX_PERSONALITY, &MovingLightResponder::GetPersonality, &MovingLightResponder::SetPersonality}, { PID_DMX_PERSONALITY_DESCRIPTION, &MovingLightResponder::GetPersonalityDescription, NULL}, { PID_SLOT_INFO, &MovingLightResponder::GetSlotInfo, NULL}, { PID_SLOT_DESCRIPTION, &MovingLightResponder::GetSlotDescription, NULL}, { PID_DEFAULT_SLOT_VALUE, &MovingLightResponder::GetSlotDefaultValues, NULL}, { PID_DMX_START_ADDRESS, &MovingLightResponder::GetDmxStartAddress, &MovingLightResponder::SetDmxStartAddress}, { PID_DEVICE_HOURS, &MovingLightResponder::GetDeviceHours, &MovingLightResponder::SetDeviceHours}, { PID_LAMP_HOURS, &MovingLightResponder::GetLampHours, &MovingLightResponder::SetLampHours}, { PID_LAMP_STRIKES, &MovingLightResponder::GetLampStrikes, &MovingLightResponder::SetLampStrikes}, { PID_LAMP_STATE, &MovingLightResponder::GetLampState, &MovingLightResponder::SetLampState}, { PID_LAMP_ON_MODE, &MovingLightResponder::GetLampOnMode, &MovingLightResponder::SetLampOnMode}, { PID_DEVICE_POWER_CYCLES, &MovingLightResponder::GetDevicePowerCycles, &MovingLightResponder::SetDevicePowerCycles}, { PID_IDENTIFY_DEVICE, &MovingLightResponder::GetIdentify, &MovingLightResponder::SetIdentify}, { PID_DISPLAY_INVERT, &MovingLightResponder::GetDisplayInvert, &MovingLightResponder::SetDisplayInvert}, { PID_DISPLAY_LEVEL, &MovingLightResponder::GetDisplayLevel, &MovingLightResponder::SetDisplayLevel}, { PID_PAN_INVERT, &MovingLightResponder::GetPanInvert, &MovingLightResponder::SetPanInvert}, { PID_TILT_INVERT, &MovingLightResponder::GetTiltInvert, &MovingLightResponder::SetTiltInvert}, { PID_PAN_TILT_SWAP, &MovingLightResponder::GetPanTiltSwap, &MovingLightResponder::SetPanTiltSwap}, { PID_REAL_TIME_CLOCK, &MovingLightResponder::GetRealTimeClock, NULL}, { PID_RESET_DEVICE, NULL, &MovingLightResponder::SetResetDevice}, { PID_POWER_STATE, &MovingLightResponder::GetPowerState, &MovingLightResponder::SetPowerState}, { OLA_MANUFACTURER_PID_CODE_VERSION, &MovingLightResponder::GetOlaCodeVersion, NULL}, { 0, NULL, NULL}, }; /** * New MovingLightResponder */ MovingLightResponder::MovingLightResponder(const UID &uid) : m_uid(uid), m_start_address(1), m_language("en"), m_identify_mode(false), m_pan_invert(false), m_tilt_invert(false), m_device_hours(0), m_lamp_hours(0), m_lamp_strikes(0), m_lamp_state(LAMP_ON), m_lamp_on_mode(LAMP_ON_MODE_DMX), m_device_power_cycles(0), m_display_invert(DISPLAY_INVERT_AUTO), m_display_level(255), m_pan_tilt_swap(false), m_power_state(POWER_STATE_NORMAL), m_device_label("Dummy Moving Light"), m_personality_manager(Personalities::Instance()) { } /* * Handle an RDM Request */ void MovingLightResponder::SendRDMRequest(RDMRequest *request, RDMCallback *callback) { RDMOps::Instance()->HandleRDMRequest(this, m_uid, ROOT_RDM_DEVICE, request, callback); } RDMResponse *MovingLightResponder::GetParamDescription( const RDMRequest *request) { // Check that it's MANUFACTURER_PID_CODE_VERSION being requested uint16_t parameter_id; if (!ResponderHelper::ExtractUInt16(request, ¶meter_id)) { return NackWithReason(request, NR_FORMAT_ERROR); } if (parameter_id != OLA_MANUFACTURER_PID_CODE_VERSION) { OLA_WARN << "Dummy responder received param description request with " "unknown PID, expected " << OLA_MANUFACTURER_PID_CODE_VERSION << ", got " << parameter_id; return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } else { return ResponderHelper::GetASCIIParamDescription( request, OLA_MANUFACTURER_PID_CODE_VERSION, CC_GET, "Code Version"); } } RDMResponse *MovingLightResponder::GetDeviceInfo( const RDMRequest *request) { return ResponderHelper::GetDeviceInfo( request, OLA_DUMMY_MOVING_LIGHT_MODEL, PRODUCT_CATEGORY_FIXTURE_MOVING_YOKE, 2, &m_personality_manager, m_start_address, 0, 0); } /** * Reset to factory defaults */ RDMResponse *MovingLightResponder::GetFactoryDefaults( const RDMRequest *request) { if (request->ParamDataSize()) { return NackWithReason(request, NR_FORMAT_ERROR); } uint8_t using_defaults = ( m_start_address == 1 && m_personality_manager.ActivePersonalityNumber() == 1 && m_identify_mode == false); return GetResponseFromData(request, &using_defaults, sizeof(using_defaults)); } RDMResponse *MovingLightResponder::SetFactoryDefaults( const RDMRequest *request) { if (request->ParamDataSize()) { return NackWithReason(request, NR_FORMAT_ERROR); } m_start_address = 1; m_personality_manager.SetActivePersonality(1); m_identify_mode = 0; return ResponderHelper::EmptySetResponse(request); } RDMResponse *MovingLightResponder::GetLanguageCapabilities( const RDMRequest *request) { if (request->ParamDataSize()) { return NackWithReason(request, NR_FORMAT_ERROR); } const char languages[] = { 'e', 'n', 'f', 'r', 'd', 'e', }; return GetResponseFromData(request, reinterpret_cast(languages), arraysize(languages)); } RDMResponse *MovingLightResponder::GetLanguage( const RDMRequest *request) { if (request->ParamDataSize()) { return NackWithReason(request, NR_FORMAT_ERROR); } return GetResponseFromData( request, reinterpret_cast(m_language.c_str()), m_language.size()); } RDMResponse *MovingLightResponder::SetLanguage( const RDMRequest *request) { if (request->ParamDataSize() != 2) { return NackWithReason(request, NR_FORMAT_ERROR); } const string new_lang(reinterpret_cast(request->ParamData()), request->ParamDataSize()); if (new_lang != "en" && new_lang != "fr" && new_lang != "de") { return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } m_language = new_lang; return ResponderHelper::EmptySetResponse(request); } RDMResponse *MovingLightResponder::GetProductDetailList( const RDMRequest *request) { // Shortcut for only one item in the vector return ResponderHelper::GetProductDetailList( request, vector(1, PRODUCT_DETAIL_TEST)); } RDMResponse *MovingLightResponder::GetPersonality( const RDMRequest *request) { return ResponderHelper::GetPersonality(request, &m_personality_manager); } RDMResponse *MovingLightResponder::SetPersonality( const RDMRequest *request) { return ResponderHelper::SetPersonality(request, &m_personality_manager, m_start_address); } RDMResponse *MovingLightResponder::GetPersonalityDescription( const RDMRequest *request) { return ResponderHelper::GetPersonalityDescription( request, &m_personality_manager); } RDMResponse *MovingLightResponder::GetSlotInfo( const RDMRequest *request) { return ResponderHelper::GetSlotInfo(request, &m_personality_manager); } RDMResponse *MovingLightResponder::GetSlotDescription( const RDMRequest *request) { return ResponderHelper::GetSlotDescription(request, &m_personality_manager); } RDMResponse *MovingLightResponder::GetSlotDefaultValues( const RDMRequest *request) { return ResponderHelper::GetSlotDefaultValues(request, &m_personality_manager); } RDMResponse *MovingLightResponder::GetDmxStartAddress( const RDMRequest *request) { return ResponderHelper::GetDmxAddress(request, &m_personality_manager, m_start_address); } RDMResponse *MovingLightResponder::SetDmxStartAddress( const RDMRequest *request) { return ResponderHelper::SetDmxAddress(request, &m_personality_manager, &m_start_address); } RDMResponse *MovingLightResponder::GetDeviceHours( const RDMRequest *request) { return ResponderHelper::GetUInt32Value(request, m_device_hours++); } RDMResponse *MovingLightResponder::SetDeviceHours( const RDMRequest *request) { return ResponderHelper::SetUInt32Value(request, &m_device_hours); } RDMResponse *MovingLightResponder::GetLampHours( const RDMRequest *request) { return ResponderHelper::GetUInt32Value(request, m_lamp_hours++); } RDMResponse *MovingLightResponder::SetLampHours( const RDMRequest *request) { return ResponderHelper::SetUInt32Value(request, &m_lamp_hours); } RDMResponse *MovingLightResponder::GetLampStrikes( const RDMRequest *request) { return ResponderHelper::GetUInt32Value(request, m_lamp_strikes); } RDMResponse *MovingLightResponder::SetLampStrikes( const RDMRequest *request) { return ResponderHelper::SetUInt32Value(request, &m_lamp_strikes); } RDMResponse *MovingLightResponder::GetLampState( const RDMRequest *request) { uint8_t value = m_lamp_state; return ResponderHelper::GetUInt8Value(request, value); } RDMResponse *MovingLightResponder::SetLampState( const RDMRequest *request) { uint8_t new_value; if (!ResponderHelper::ExtractUInt8(request, &new_value)) { return NackWithReason(request, NR_FORMAT_ERROR); } if (new_value > static_cast(LAMP_STANDBY)) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } m_lamp_state = static_cast(new_value); return ResponderHelper::EmptySetResponse(request); } RDMResponse *MovingLightResponder::GetLampOnMode( const RDMRequest *request) { uint8_t value = m_lamp_on_mode; return ResponderHelper::GetUInt8Value(request, value); } RDMResponse *MovingLightResponder::SetLampOnMode( const RDMRequest *request) { uint8_t new_value; if (!ResponderHelper::ExtractUInt8(request, &new_value)) { return NackWithReason(request, NR_FORMAT_ERROR); } if (new_value > static_cast(LAMP_ON_MODE_ON_AFTER_CAL)) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } m_lamp_on_mode = static_cast(new_value); return ResponderHelper::EmptySetResponse(request); } RDMResponse *MovingLightResponder::GetDevicePowerCycles( const RDMRequest *request) { return ResponderHelper::GetUInt32Value(request, m_device_power_cycles++); } RDMResponse *MovingLightResponder::SetDevicePowerCycles( const RDMRequest *request) { return ResponderHelper::SetUInt32Value(request, &m_device_power_cycles); } RDMResponse *MovingLightResponder::GetIdentify( const RDMRequest *request) { return ResponderHelper::GetBoolValue(request, m_identify_mode); } RDMResponse *MovingLightResponder::SetIdentify( const RDMRequest *request) { bool old_value = m_identify_mode; RDMResponse *response = ResponderHelper::SetBoolValue( request, &m_identify_mode); if (m_identify_mode != old_value) { OLA_INFO << "Dummy Moving Light " << m_uid << ", identify mode " << (m_identify_mode ? "on" : "off"); } return response; } RDMResponse *MovingLightResponder::GetDisplayInvert( const RDMRequest *request) { uint8_t value = m_display_invert; return ResponderHelper::GetUInt8Value(request, value); } RDMResponse *MovingLightResponder::SetDisplayInvert( const RDMRequest *request) { uint8_t new_value; if (!ResponderHelper::ExtractUInt8(request, &new_value)) { return NackWithReason(request, NR_FORMAT_ERROR); } if (new_value > static_cast(DISPLAY_INVERT_AUTO)) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } m_display_invert = static_cast(new_value); return ResponderHelper::EmptySetResponse(request); } RDMResponse *MovingLightResponder::GetDisplayLevel( const RDMRequest *request) { return ResponderHelper::GetUInt8Value(request, m_display_level); } RDMResponse *MovingLightResponder::SetDisplayLevel( const RDMRequest *request) { return ResponderHelper::SetUInt8Value(request, &m_display_level); } RDMResponse *MovingLightResponder::GetPanInvert( const RDMRequest *request) { return ResponderHelper::GetBoolValue(request, m_pan_invert); } RDMResponse *MovingLightResponder::SetPanInvert( const RDMRequest *request) { return ResponderHelper::SetBoolValue(request, &m_pan_invert); } RDMResponse *MovingLightResponder::GetTiltInvert( const RDMRequest *request) { return ResponderHelper::GetBoolValue(request, m_tilt_invert); } RDMResponse *MovingLightResponder::SetTiltInvert( const RDMRequest *request) { return ResponderHelper::SetBoolValue(request, &m_tilt_invert); } RDMResponse *MovingLightResponder::GetPanTiltSwap( const RDMRequest *request) { return ResponderHelper::GetBoolValue(request, m_pan_tilt_swap); } RDMResponse *MovingLightResponder::SetPanTiltSwap( const RDMRequest *request) { return ResponderHelper::SetBoolValue(request, &m_pan_tilt_swap); } RDMResponse *MovingLightResponder::GetRealTimeClock( const RDMRequest *request) { return ResponderHelper::GetRealTimeClock(request); } RDMResponse *MovingLightResponder::GetPowerState( const RDMRequest *request) { uint8_t value = m_power_state; return ResponderHelper::GetUInt8Value(request, value); } RDMResponse *MovingLightResponder::SetPowerState( const RDMRequest *request) { uint8_t new_value; if (!ResponderHelper::ExtractUInt8(request, &new_value)) { return NackWithReason(request, NR_FORMAT_ERROR); } if (!UIntToPowerState(new_value, &m_power_state)) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } return ResponderHelper::EmptySetResponse(request); } RDMResponse *MovingLightResponder::SetResetDevice( const RDMRequest *request) { uint8_t value; rdm_reset_device_mode reset_device_enum; if (!ResponderHelper::ExtractUInt8(request, &value)) { return NackWithReason(request, NR_FORMAT_ERROR); } if (!UIntToResetDevice(value, &reset_device_enum)) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } string reset_type = ResetDeviceToString(reset_device_enum); ToLower(&reset_type); OLA_INFO << "Dummy Moving Light " << m_uid << " " << reset_type << " reset device"; return ResponderHelper::EmptySetResponse(request); } RDMResponse *MovingLightResponder::GetDeviceModelDescription( const RDMRequest *request) { return ResponderHelper::GetString(request, "OLA Moving Light"); } RDMResponse *MovingLightResponder::GetManufacturerLabel( const RDMRequest *request) { return ResponderHelper::GetString(request, OLA_MANUFACTURER_LABEL); } RDMResponse *MovingLightResponder::GetDeviceLabel( const RDMRequest *request) { return ResponderHelper::GetString(request, m_device_label); } RDMResponse *MovingLightResponder::SetDeviceLabel( const RDMRequest *request) { return ResponderHelper::SetString(request, &m_device_label); } RDMResponse *MovingLightResponder::GetSoftwareVersionLabel( const RDMRequest *request) { return ResponderHelper::GetString(request, string("OLA Version ") + VERSION); } RDMResponse *MovingLightResponder::GetOlaCodeVersion( const RDMRequest *request) { return ResponderHelper::GetString(request, VERSION); } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/ResponderSettings.cpp0000644000175000017500000000453613023355232021726 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * ResponderSettings.cpp * Copyright (C) 2013 Simon Newton */ #include "ola/rdm/ResponderSettings.h" #include #include #include "ola/base/Array.h" #include "ola/network/NetworkUtils.h" #include "ola/rdm/RDMCommand.h" #include "ola/strings/Utils.h" namespace ola { namespace rdm { using std::string; BasicSetting::BasicSetting(const ArgType description) : m_description(description) { } unsigned int BasicSetting::GenerateDescriptionResponse(uint8_t index, uint8_t *data) const { description_s *output = reinterpret_cast(data); output->setting = index; strings::CopyToFixedLengthBuffer(m_description, output->description, arraysize(output->description)); return (sizeof(description_s) - MAX_RDM_STRING_LENGTH + std::min(static_cast(MAX_RDM_STRING_LENGTH), m_description.size())); } FrequencyModulationSetting::FrequencyModulationSetting(const ArgType &arg) : m_frequency(arg.frequency), m_description(arg.description) { } unsigned int FrequencyModulationSetting::GenerateDescriptionResponse( uint8_t index, uint8_t *data) const { description_s *output = reinterpret_cast(data); output->setting = index; output->frequency = ola::network::HostToNetwork(m_frequency); strings::CopyToFixedLengthBuffer(m_description, output->description, arraysize(output->description)); return (sizeof(description_s) - MAX_RDM_STRING_LENGTH + m_description.size()); } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/RDMCommandSerializer.cpp0000644000175000017500000001220613023355232022210 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * RDMCommandSerializer.cpp * Write RDMCommands to a memory buffer. * Copyright (C) 2012 Simon Newton */ #include #include #include "ola/io/BigEndianStream.h" #include "ola/rdm/RDMCommand.h" #include "ola/rdm/RDMCommandSerializer.h" #include "ola/rdm/RDMPacket.h" #include "ola/util/Utils.h" namespace ola { namespace rdm { using ola::utils::SplitUInt16; unsigned int RDMCommandSerializer::RequiredSize( const RDMCommand &command) { if (command.ParamDataSize() > MAX_PARAM_DATA_LENGTH) { return 0; } // Don't use command.MessageLength() here, since it may be overridden. return sizeof(RDMCommandHeader) + command.ParamDataSize() + CHECKSUM_LENGTH; } bool RDMCommandSerializer::Pack(const RDMCommand &command, ola::io::ByteString *output) { const unsigned int packet_length = RequiredSize(command); if (packet_length == 0) { return false; } size_t front = output->size(); RDMCommandHeader header; PopulateHeader(&header, command); output->append(reinterpret_cast(&header), sizeof(header)); output->append(command.ParamData(), command.ParamDataSize()); uint16_t checksum = START_CODE; for (unsigned int i = front; i < output->size(); i++) { checksum += (*output)[i]; } checksum = command.Checksum(checksum); output->push_back(checksum >> 8); output->push_back(checksum & 0xff); return true; } bool RDMCommandSerializer::PackWithStartCode(const RDMCommand &command, ola::io::ByteString *output) { output->push_back(START_CODE); return Pack(command, output); } bool RDMCommandSerializer::Pack(const RDMCommand &command, uint8_t *buffer, unsigned int *size) { const unsigned int packet_length = RequiredSize(command); if (packet_length == 0 || *size < packet_length) { return false; } // The buffer pointer may not be aligned, so we incur a copy here. RDMCommandHeader header; PopulateHeader(&header, command); memcpy(buffer, &header, sizeof(header)); memcpy(buffer + sizeof(RDMCommandHeader), command.ParamData(), command.ParamDataSize()); uint16_t checksum = START_CODE; for (unsigned int i = 0; i < packet_length - CHECKSUM_LENGTH; i++) { checksum += buffer[i]; } checksum = command.Checksum(checksum); buffer[packet_length - CHECKSUM_LENGTH] = checksum >> 8; buffer[packet_length - CHECKSUM_LENGTH + 1] = checksum & 0xff; *size = packet_length; return true; } bool RDMCommandSerializer::Write(const RDMCommand &command, ola::io::IOStack *stack) { const unsigned int packet_length = RequiredSize(command); if (packet_length == 0) { return false; } RDMCommandHeader header; PopulateHeader(&header, command); uint16_t checksum = START_CODE; const uint8_t *ptr = reinterpret_cast(&header); for (unsigned int i = 0; i < sizeof(header); i++) { checksum += ptr[i]; } ptr = command.ParamData(); for (unsigned int i = 0; i < command.ParamDataSize(); i++) { checksum += ptr[i]; } checksum = command.Checksum(checksum); // now perform the write in reverse order (since it's a stack). ola::io::BigEndianOutputStream output(stack); output << checksum; output.Write(command.ParamData(), command.ParamDataSize()); output.Write(reinterpret_cast(&header), sizeof(header)); return true; } /** * Populate the RDMCommandHeader struct. * @param header a pointer to the RDMCommandHeader to populate * @param command the RDMCommand to use */ void RDMCommandSerializer::PopulateHeader(RDMCommandHeader *header, const RDMCommand &command) { header->sub_start_code = command.SubStartCode(); header->message_length = command.MessageLength(); command.DestinationUID().Pack(header->destination_uid, UID::UID_SIZE); command.SourceUID().Pack(header->source_uid, UID::UID_SIZE); header->transaction_number = command.TransactionNumber(); header->port_id = command.PortIdResponseType(); header->message_count = command.MessageCount(); SplitUInt16(command.SubDevice(), &header->sub_device[0], &header->sub_device[1]); header->command_class = command.CommandClass(); SplitUInt16(command.ParamId(), &header->param_id[0], &header->param_id[1]); header->param_data_length = command.ParamDataSize(); } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/DimmerRootDevice.cpp0000644000175000017500000001722613023355232021445 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * DimmerRootDevice.cpp * Copyright (C) 2013 Simon Newton */ #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #include #include #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/base/Array.h" #include "ola/network/NetworkUtils.h" #include "ola/rdm/DimmerRootDevice.h" #include "ola/rdm/DimmerSubDevice.h" #include "ola/rdm/OpenLightingEnums.h" #include "ola/rdm/RDMEnums.h" #include "ola/rdm/ResponderHelper.h" namespace ola { namespace rdm { using ola::network::HostToNetwork; using ola::network::NetworkToHost; using std::string; using std::vector; DimmerRootDevice::RDMOps *DimmerRootDevice::RDMOps::instance = NULL; const ResponderOps::ParamHandler DimmerRootDevice::PARAM_HANDLERS[] = { { PID_DEVICE_INFO, &DimmerRootDevice::GetDeviceInfo, NULL}, { PID_PRODUCT_DETAIL_ID_LIST, &DimmerRootDevice::GetProductDetailList, NULL}, { PID_DEVICE_MODEL_DESCRIPTION, &DimmerRootDevice::GetDeviceModelDescription, NULL}, { PID_MANUFACTURER_LABEL, &DimmerRootDevice::GetManufacturerLabel, NULL}, { PID_DEVICE_LABEL, &DimmerRootDevice::GetDeviceLabel, NULL}, { PID_SOFTWARE_VERSION_LABEL, &DimmerRootDevice::GetSoftwareVersionLabel, NULL}, { PID_IDENTIFY_DEVICE, &DimmerRootDevice::GetIdentify, &DimmerRootDevice::SetIdentify}, { PID_DMX_BLOCK_ADDRESS, &DimmerRootDevice::GetDmxBlockAddress, &DimmerRootDevice::SetDmxBlockAddress}, { PID_IDENTIFY_MODE, &DimmerRootDevice::GetIdentifyMode, &DimmerRootDevice::SetIdentifyMode}, { 0, NULL, NULL} }; /** * Create a new dimmer root device. Ownership of the DimmerSubDevices is not * transferred. */ DimmerRootDevice::DimmerRootDevice(const UID &uid, SubDeviceMap sub_devices) : m_uid(uid), m_identify_on(false), m_identify_mode(IDENTIFY_MODE_LOUD), m_sub_devices(sub_devices) { if (m_sub_devices.size() > MAX_SUBDEVICE_NUMBER) { OLA_FATAL << "More than " << MAX_SUBDEVICE_NUMBER << " sub devices created for device " << uid; } } /* * Handle an RDM Request */ void DimmerRootDevice::SendRDMRequest(RDMRequest *request, RDMCallback *callback) { RDMOps::Instance()->HandleRDMRequest(this, m_uid, ROOT_RDM_DEVICE, request, callback); } RDMResponse *DimmerRootDevice::GetDeviceInfo(const RDMRequest *request) { if (request->ParamDataSize()) { return NackWithReason(request, NR_FORMAT_ERROR); } return ResponderHelper::GetDeviceInfo( request, OLA_DUMMY_DIMMER_MODEL, PRODUCT_CATEGORY_DIMMER, 1, 0, 1, 1, // personality 0xffff, // start address m_sub_devices.size(), 0); } RDMResponse *DimmerRootDevice::GetProductDetailList(const RDMRequest *request) { // Shortcut for only one item in the vector return ResponderHelper::GetProductDetailList(request, vector(1, PRODUCT_DETAIL_TEST)); } RDMResponse *DimmerRootDevice::GetDeviceModelDescription( const RDMRequest *request) { return ResponderHelper::GetString(request, "OLA Dimmer"); } RDMResponse *DimmerRootDevice::GetManufacturerLabel(const RDMRequest *request) { return ResponderHelper::GetString(request, OLA_MANUFACTURER_LABEL); } RDMResponse *DimmerRootDevice::GetDeviceLabel(const RDMRequest *request) { return ResponderHelper::GetString(request, "Dummy Dimmer"); } RDMResponse *DimmerRootDevice::GetSoftwareVersionLabel( const RDMRequest *request) { return ResponderHelper::GetString(request, string("OLA Version ") + VERSION); } RDMResponse *DimmerRootDevice::GetIdentify(const RDMRequest *request) { return ResponderHelper::GetBoolValue(request, m_identify_on); } RDMResponse *DimmerRootDevice::SetIdentify(const RDMRequest *request) { bool old_value = m_identify_on; RDMResponse *response = ResponderHelper::SetBoolValue( request, &m_identify_on); if (m_identify_on != old_value) { OLA_INFO << "Dimmer Root Device " << m_uid << ", identify mode " << (m_identify_on ? "on" : "off"); } return response; } RDMResponse *DimmerRootDevice::GetDmxBlockAddress(const RDMRequest *request) { if (request->ParamDataSize()) { return NackWithReason(request, NR_FORMAT_ERROR); } PACK( struct block_address_pdl { uint16_t total_footprint; uint16_t base_address; }); STATIC_ASSERT(sizeof(block_address_pdl) == 4); block_address_pdl pdl; pdl.base_address = 0; pdl.total_footprint = 0; uint16_t next_address = 0; for (SubDeviceMap::const_iterator iter = m_sub_devices.begin(); iter != m_sub_devices.end(); ++iter) { if (iter->second->Footprint() != 0) { if (next_address == iter->second->GetDmxStartAddress()) { next_address += iter->second->Footprint(); } else if (next_address == 0) { next_address = iter->second->GetDmxStartAddress() + iter->second->Footprint(); pdl.base_address = iter->second->GetDmxStartAddress(); } else { pdl.base_address = 0xFFFF; } pdl.total_footprint += iter->second->Footprint(); } } pdl.base_address = HostToNetwork(pdl.base_address); pdl.total_footprint = HostToNetwork(pdl.total_footprint); return GetResponseFromData(request, reinterpret_cast(&pdl), sizeof(pdl)); } RDMResponse *DimmerRootDevice::SetDmxBlockAddress(const RDMRequest *request) { uint16_t base_start_address = 0; uint16_t total_footprint = 0; if (!ResponderHelper::ExtractUInt16(request, &base_start_address)) { return NackWithReason(request, NR_FORMAT_ERROR); } for (SubDeviceMap::const_iterator i = m_sub_devices.begin(); i != m_sub_devices.end(); ++i) { total_footprint += i->second->Footprint(); } if (base_start_address < 1 || base_start_address + total_footprint - 1 > DMX_MAX_SLOT_VALUE) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } for (SubDeviceMap::const_iterator iter = m_sub_devices.begin(); iter != m_sub_devices.end(); ++iter) { // We don't check here because we already have for every Sub Device iter->second->SetDmxStartAddress(base_start_address); base_start_address += iter->second->Footprint(); } return GetResponseFromData(request, NULL, 0); } RDMResponse *DimmerRootDevice::GetIdentifyMode(const RDMRequest *request) { return ResponderHelper::GetUInt8Value(request, m_identify_mode); } RDMResponse *DimmerRootDevice::SetIdentifyMode(const RDMRequest *request) { uint8_t new_identify_mode; if (!ResponderHelper::ExtractUInt8(request, &new_identify_mode)) return NackWithReason(request, NR_FORMAT_ERROR); if (new_identify_mode != IDENTIFY_MODE_QUIET && new_identify_mode != IDENTIFY_MODE_LOUD) return NackWithReason(request, NR_DATA_OUT_OF_RANGE); m_identify_mode = static_cast(new_identify_mode); return ResponderHelper::EmptySetResponse(request); } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/RDMMessageInterationTest.cpp0000644000175000017500000002137313023355232023066 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * RDMMessageInterationTest.cpp * Test fixture for the StringBuilder classes * Copyright (C) 2011 Simon Newton */ #include #include #include #include #include #include #include #include #include #include #include #include #include "common/rdm/PidStoreLoader.h" #include "ola/testing/TestUtils.h" using ola::messaging::Descriptor; using ola::messaging::Message; using ola::rdm::PidDescriptor; using ola::rdm::PidStore; using ola::rdm::StringMessageBuilder; using std::auto_ptr; using std::string; using std::vector; class RDMMessageInterationTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(RDMMessageInterationTest); CPPUNIT_TEST(testProxiedDevices); CPPUNIT_TEST(testDeviceInfoRequest); CPPUNIT_TEST(testParameterDescription); CPPUNIT_TEST(testDeviceModelDescription); CPPUNIT_TEST_SUITE_END(); public: void testProxiedDevices(); void testDeviceInfoRequest(); void testDeviceModelDescription(); void testParameterDescription(); void setUp() { ola::rdm::PidStoreLoader loader; m_store.reset(loader.LoadFromFile( TEST_SRC_DIR "/common/rdm/testdata/test_pids.proto")); OLA_ASSERT_NOT_NULL(m_store.get()); m_esta_store = m_store->EstaStore(); OLA_ASSERT_NOT_NULL(m_esta_store); } private: std::auto_ptr m_store; const ola::rdm::PidStore *m_esta_store; ola::rdm::StringMessageBuilder m_builder; ola::messaging::GenericMessagePrinter m_printer; ola::rdm::MessageSerializer m_serializer; ola::rdm::MessageDeserializer m_deserializer; }; CPPUNIT_TEST_SUITE_REGISTRATION(RDMMessageInterationTest); /** * test PROXIED_DEVICES */ void RDMMessageInterationTest::testProxiedDevices() { const PidDescriptor *device_info_pid = m_esta_store->LookupPID(ola::rdm::PID_PROXIED_DEVICES); OLA_ASSERT_NOT_NULL(device_info_pid); const Descriptor *descriptor = device_info_pid->GetResponse(); OLA_ASSERT_TRUE(descriptor); vector inputs; inputs.push_back("31344"); // manufacturer ID inputs.push_back("1"); // device id inputs.push_back("31344"); // manufacturer ID inputs.push_back("2"); // device id inputs.push_back("21324"); // manufacturer ID inputs.push_back("1"); // device id auto_ptr message(m_builder.GetMessage(inputs, descriptor)); OLA_ASSERT_TRUE(message.get()); unsigned int data_length; const uint8_t *data = m_serializer.SerializeMessage(message.get(), &data_length); OLA_ASSERT_TRUE(data); OLA_ASSERT_EQ(18u, data_length); auto_ptr inflated_message( m_deserializer.InflateMessage(descriptor, data, data_length)); OLA_ASSERT_TRUE(inflated_message.get()); const string input = m_printer.AsString(message.get()); const string output = m_printer.AsString(inflated_message.get()); OLA_ASSERT_EQ(input, output); const string expected = ( "uids {\n manufacturer_id: 31344\n device_id: 1\n}\n" "uids {\n manufacturer_id: 31344\n device_id: 2\n}\n" "uids {\n manufacturer_id: 21324\n device_id: 1\n}\n"); OLA_ASSERT_EQ(expected, output); } /** * test Device Info Request */ void RDMMessageInterationTest::testDeviceInfoRequest() { const PidDescriptor *device_info_pid = m_esta_store->LookupPID(ola::rdm::PID_DEVICE_INFO); OLA_ASSERT_TRUE(device_info_pid); const Descriptor *descriptor = device_info_pid->GetResponse(); OLA_ASSERT_TRUE(descriptor); vector inputs; inputs.push_back("1"); // major inputs.push_back("0"); // minor inputs.push_back("300"); // device model inputs.push_back("400"); // product category inputs.push_back("40000"); // software version inputs.push_back("512"); // dmx footprint inputs.push_back("1"); // current personality inputs.push_back("5"); // personality count inputs.push_back("1"); // dmx start address inputs.push_back("0"); // sub device count inputs.push_back("6"); // sensor count auto_ptr message(m_builder.GetMessage(inputs, descriptor)); OLA_ASSERT_TRUE(message.get()); unsigned int data_length; const uint8_t *data = m_serializer.SerializeMessage(message.get(), &data_length); OLA_ASSERT_TRUE(data); OLA_ASSERT_EQ(19u, data_length); auto_ptr inflated_message( m_deserializer.InflateMessage(descriptor, data, data_length)); OLA_ASSERT_TRUE(inflated_message.get()); const string input = m_printer.AsString(message.get()); const string output = m_printer.AsString(inflated_message.get()); OLA_ASSERT_EQ(input, output); const string expected = ( "protocol_major: 1\nprotocol_minor: 0\ndevice_model: 300\n" "product_category: 400\nsoftware_version: 40000\n" "dmx_footprint: 512\ncurrent_personality: 1\npersonality_count: 5\n" "dmx_start_address: 1\nsub_device_count: 0\nsensor_count: 6\n"); OLA_ASSERT_EQ(expected, output); } /** * test device model description works */ void RDMMessageInterationTest::testDeviceModelDescription() { const PidDescriptor *device_model_pid = m_esta_store->LookupPID(ola::rdm::PID_DEVICE_MODEL_DESCRIPTION); OLA_ASSERT_TRUE(device_model_pid); const Descriptor *descriptor = device_model_pid->GetResponse(); OLA_ASSERT_TRUE(descriptor); vector inputs; inputs.push_back("wigglelight 2000"); // description auto_ptr message(m_builder.GetMessage(inputs, descriptor)); OLA_ASSERT_TRUE(message.get()); unsigned int data_length; const uint8_t *data = m_serializer.SerializeMessage(message.get(), &data_length); OLA_ASSERT_TRUE(data); OLA_ASSERT_EQ(16u, data_length); auto_ptr inflated_message( m_deserializer.InflateMessage(descriptor, data, data_length)); OLA_ASSERT_TRUE(inflated_message.get()); const string input = m_printer.AsString(message.get()); const string output = m_printer.AsString(inflated_message.get()); OLA_ASSERT_EQ(input, output); const string expected = "description: wigglelight 2000\n"; OLA_ASSERT_EQ(expected, output); } /** * test parameter description works */ void RDMMessageInterationTest::testParameterDescription() { const PidDescriptor *param_description_pid = m_esta_store->LookupPID(ola::rdm::PID_PARAMETER_DESCRIPTION); OLA_ASSERT_TRUE(param_description_pid); const Descriptor *descriptor = param_description_pid->GetResponse(); OLA_ASSERT_TRUE(descriptor); vector inputs; inputs.push_back("8000"); // pid inputs.push_back("2"); // pdl size inputs.push_back("6"); // data type inputs.push_back("3"); // command class inputs.push_back("0"); // type (unused) inputs.push_back("1"); // unit inputs.push_back("0"); // prefix inputs.push_back("0"); // min valid value inputs.push_back("400"); // max valid value inputs.push_back("0"); // default value inputs.push_back("room temp"); // description auto_ptr message(m_builder.GetMessage(inputs, descriptor)); OLA_ASSERT_TRUE(message.get()); unsigned int data_length; const uint8_t *data = m_serializer.SerializeMessage(message.get(), &data_length); OLA_ASSERT_TRUE(data); OLA_ASSERT_EQ(29u, data_length); auto_ptr inflated_message( m_deserializer.InflateMessage(descriptor, data, data_length)); OLA_ASSERT_TRUE(inflated_message.get()); const string input = m_printer.AsString(message.get()); const string output = m_printer.AsString(inflated_message.get()); OLA_ASSERT_EQ(input, output); const string expected = ( "pid: 8000\npdl_size: 2\ndata_type: 6\ncommand_class: 3\n" "type: 0\nunit: 1\nprefix: 0\nmin_value: 0\nmax_value: 400\n" "default_value: 0\ndescription: room temp\n"); OLA_ASSERT_EQ(expected, output); } ola-0.10.5.nojsmin/common/rdm/ResponderSlotData.cpp0000644000175000017500000000710213023355232021631 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * ResponderSlotData.cpp * Manages slot data for a personality for a RDM responder. * Copyright (C) 2013 Peter Newman */ #ifndef COMMON_RDM_RESPONDERSLOTDATA_H_ #define COMMON_RDM_RESPONDERSLOTDATA_H_ #include #include "ola/Logging.h" #include "ola/rdm/ResponderSlotData.h" namespace ola { namespace rdm { using std::string; SlotData SlotData::PrimarySlot(rdm_slot_definition slot_definition, uint8_t default_slot_value) { if (slot_definition == SD_UNDEFINED) { OLA_WARN << "Undefined slot definition and no slot description!"; } return SlotData(ST_PRIMARY, slot_definition, default_slot_value); } SlotData SlotData::PrimarySlot(rdm_slot_definition slot_definition, uint8_t default_slot_value, const string &description) { if (slot_definition == SD_UNDEFINED && description.empty()) { OLA_WARN << "Undefined slot definition and no slot description!"; } return SlotData(ST_PRIMARY, slot_definition, default_slot_value, description); } SlotData SlotData::SecondarySlot(rdm_slot_type slot_type, uint16_t primary_slot, uint8_t default_slot_value) { if (slot_type == ST_PRIMARY) { OLA_WARN << "Secondary slot created with slot_type == ST_PRIMARY"; } return SlotData(slot_type, primary_slot, default_slot_value); } SlotData SlotData::SecondarySlot(rdm_slot_type slot_type, uint16_t primary_slot, uint8_t default_slot_value, const string &description) { if (slot_type == ST_PRIMARY) { OLA_WARN << "Secondary slot created with slot_type == ST_PRIMARY: " << description; } return SlotData(slot_type, primary_slot, default_slot_value, description); } SlotData::SlotData(rdm_slot_type slot_type, uint16_t slot_id, uint8_t default_slot_value) : m_slot_type(slot_type), m_slot_id(slot_id), m_default_slot_value(default_slot_value), m_has_description(false) { } SlotData::SlotData(rdm_slot_type slot_type, uint16_t slot_id, uint8_t default_slot_value, const string &description) : m_slot_type(slot_type), m_slot_id(slot_id), m_default_slot_value(default_slot_value), m_has_description(true), m_description(description) { } SlotDataCollection::SlotDataCollection(const SlotDataList &slot_data) : m_slot_data(slot_data) { } uint16_t SlotDataCollection::SlotCount() const { return m_slot_data.size(); } const SlotData *SlotDataCollection::Lookup(uint16_t slot) const { if (slot >= m_slot_data.size()) return NULL; return &m_slot_data[slot]; } } // namespace rdm } // namespace ola #endif // COMMON_RDM_RESPONDERSLOTDATA_H_ ola-0.10.5.nojsmin/common/rdm/GroupSizeCalculator.cpp0000644000175000017500000002155013023355232022200 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * GroupSizeCalculator.cpp * Copyright (C) 2011 Simon Newton */ #include #include #include #include #include "common/rdm/GroupSizeCalculator.h" namespace ola { namespace rdm { using ola::messaging::FieldDescriptor; using ola::messaging::FieldDescriptorGroup; using std::vector; /** * Figure out the number of group repetitions required. * * This method is *not* re-entrant. * @param token_count the number of tokens supplied * @param descriptor the descriptor to use to build the Message * @param[out] group_repeat_count the number of repeated groups * @returns the state of the calculator as a calculator_state. */ GroupSizeCalculator::calculator_state GroupSizeCalculator::CalculateGroupSize( unsigned int token_count, const ola::messaging::Descriptor *descriptor, unsigned int *group_repeat_count) { m_groups.clear(); m_non_groups.clear(); // split out the fields into singular fields and groups for (unsigned int i = 0; i < descriptor->FieldCount(); ++i) descriptor->GetField(i)->Accept(this); unsigned int required_tokens = m_non_groups.size(); if (required_tokens > token_count) return INSUFFICIENT_TOKENS; // this takes care of the easy case where there are no groups if (m_groups.empty()) { if (required_tokens == token_count) { return NO_VARIABLE_GROUPS; } else { OLA_WARN << "Got an incorrect number of tokens, expecting " << required_tokens << " tokens, got " << token_count; return EXTRA_TOKENS; } } // check all groups, looking for multiple non-fixed sized groups unsigned int variable_group_counter = 0; unsigned int variable_group_token_count = 0; const FieldDescriptorGroup *variable_group = NULL; vector::const_iterator iter = m_groups.begin(); for (; iter != m_groups.end(); ++iter) { unsigned int group_size; if (!m_simple_calculator.CalculateTokensRequired(*iter, &group_size)) return NESTED_VARIABLE_GROUPS; if ((*iter)->FixedSize()) { required_tokens += (*iter)->MinBlocks() * group_size; } else { // variable sized group variable_group_token_count = group_size; variable_group = *iter; if (++variable_group_counter > 1) return MULTIPLE_VARIABLE_GROUPS; } } if (required_tokens > token_count) return INSUFFICIENT_TOKENS; if (!variable_group_counter) { if (required_tokens == token_count) { return NO_VARIABLE_GROUPS; } else { OLA_WARN << "Got an incorrect number of tokens, expecting " << required_tokens << " tokens, got " << token_count; return EXTRA_TOKENS; } } // now we have a single variable sized group and a 0 or more tokens remaining unsigned int remaining_tokens = token_count - required_tokens; // some groups limit the number of blocks, check for that here if (variable_group->MaxBlocks() != FieldDescriptorGroup::UNLIMITED_BLOCKS && variable_group->MaxBlocks() * variable_group_token_count < remaining_tokens) return EXTRA_TOKENS; if (remaining_tokens % variable_group_token_count) return MISMATCHED_TOKENS; *group_repeat_count = remaining_tokens / variable_group_token_count; return SINGLE_VARIABLE_GROUP; } void GroupSizeCalculator::Visit( const ola::messaging::BoolFieldDescriptor *descriptor) { m_non_groups.push_back(descriptor); } void GroupSizeCalculator::Visit( const ola::messaging::IPV4FieldDescriptor *descriptor) { m_non_groups.push_back(descriptor); } void GroupSizeCalculator::Visit( const ola::messaging::MACFieldDescriptor *descriptor) { m_non_groups.push_back(descriptor); } void GroupSizeCalculator::Visit( const ola::messaging::UIDFieldDescriptor *descriptor) { m_non_groups.push_back(descriptor); } void GroupSizeCalculator::Visit( const ola::messaging::StringFieldDescriptor *descriptor) { m_non_groups.push_back(descriptor); } void GroupSizeCalculator::Visit( const ola::messaging::UInt8FieldDescriptor *descriptor) { m_non_groups.push_back(descriptor); } void GroupSizeCalculator::Visit( const ola::messaging::UInt16FieldDescriptor *descriptor) { m_non_groups.push_back(descriptor); } void GroupSizeCalculator::Visit( const ola::messaging::UInt32FieldDescriptor *descriptor) { m_non_groups.push_back(descriptor); } void GroupSizeCalculator::Visit( const ola::messaging::Int8FieldDescriptor *descriptor) { m_non_groups.push_back(descriptor); } void GroupSizeCalculator::Visit( const ola::messaging::Int16FieldDescriptor *descriptor) { m_non_groups.push_back(descriptor); } void GroupSizeCalculator::Visit( const ola::messaging::Int32FieldDescriptor *descriptor) { m_non_groups.push_back(descriptor); } void GroupSizeCalculator::Visit( const ola::messaging::FieldDescriptorGroup *descriptor) { m_groups.push_back(descriptor); } void GroupSizeCalculator::PostVisit( const ola::messaging::FieldDescriptorGroup *descriptor) { (void) descriptor; } // StaticGroupTokenCalculator //----------------------------------------------------------------------------- /** * For a group of fields, figure out the number of inputs required to build a * single instance of the group. This assumes that the group does not contain * any variable-sized groups but it may contain fixed sized nested groups. * @param descriptor the group descriptor * @param token_count the number of inputs required to build a single instance * of this group. * @return true if we could calculate the inputs required, false if this group * was of a variable size. */ bool StaticGroupTokenCalculator::CalculateTokensRequired( const class ola::messaging::FieldDescriptorGroup *descriptor, unsigned int *token_count) { // reset the stack while (!m_token_count.empty()) { m_token_count.pop(); } m_token_count.push(0); m_variable_sized_group_encountered = false; for (unsigned int i = 0; i < descriptor->FieldCount(); ++i) { descriptor->GetField(i)->Accept(this); } if (m_variable_sized_group_encountered) { return false; } *token_count = m_token_count.top(); m_token_count.pop(); return true; } void StaticGroupTokenCalculator::Visit( OLA_UNUSED const ola::messaging::BoolFieldDescriptor *descriptor) { m_token_count.top()++; } void StaticGroupTokenCalculator::Visit( OLA_UNUSED const ola::messaging::IPV4FieldDescriptor *descriptor) { m_token_count.top()++; } void StaticGroupTokenCalculator::Visit( OLA_UNUSED const ola::messaging::MACFieldDescriptor *descriptor) { m_token_count.top()++; } void StaticGroupTokenCalculator::Visit( OLA_UNUSED const ola::messaging::UIDFieldDescriptor *descriptor) { m_token_count.top()++; } void StaticGroupTokenCalculator::Visit( OLA_UNUSED const ola::messaging::StringFieldDescriptor *descriptor) { m_token_count.top()++; } void StaticGroupTokenCalculator::Visit( OLA_UNUSED const ola::messaging::UInt8FieldDescriptor *descriptor) { m_token_count.top()++; } void StaticGroupTokenCalculator::Visit( OLA_UNUSED const ola::messaging::UInt16FieldDescriptor *descriptor) { m_token_count.top()++; } void StaticGroupTokenCalculator::Visit( OLA_UNUSED const ola::messaging::UInt32FieldDescriptor *descriptor) { m_token_count.top()++; } void StaticGroupTokenCalculator::Visit( OLA_UNUSED const ola::messaging::Int8FieldDescriptor *descriptor) { m_token_count.top()++; } void StaticGroupTokenCalculator::Visit( OLA_UNUSED const ola::messaging::Int16FieldDescriptor *descriptor) { m_token_count.top()++; } void StaticGroupTokenCalculator::Visit( OLA_UNUSED const ola::messaging::Int32FieldDescriptor *descriptor) { m_token_count.top()++; } void StaticGroupTokenCalculator::Visit( const ola::messaging::FieldDescriptorGroup *descriptor) { m_token_count.push(0); if (!descriptor->FixedSize()) { m_variable_sized_group_encountered = true; } } void StaticGroupTokenCalculator::PostVisit( const ola::messaging::FieldDescriptorGroup *descriptor) { unsigned int group_length = m_token_count.top(); m_token_count.pop(); m_token_count.top() += group_length * descriptor->MinBlocks(); } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/RDMFrameTest.cpp0000644000175000017500000000544413023355232020500 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * RDMFrameTest.cpp * Test fixture for the RDMFrame. * Copyright (C) 2015 Simon Newton */ #include #include "ola/base/Array.h" #include "ola/io/ByteString.h" #include "ola/rdm/RDMFrame.h" #include "ola/testing/TestUtils.h" using ola::io::ByteString; using ola::rdm::RDMFrame; class RDMFrameTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(RDMFrameTest); CPPUNIT_TEST(testRDMFrame); CPPUNIT_TEST(testPrependStartCode); CPPUNIT_TEST_SUITE_END(); public: void testRDMFrame(); void testPrependStartCode(); }; CPPUNIT_TEST_SUITE_REGISTRATION(RDMFrameTest); void RDMFrameTest::testRDMFrame() { const uint8_t raw_data[] = {1, 2, 3, 4, 5}; RDMFrame frame(raw_data, arraysize(raw_data)); OLA_ASSERT_DATA_EQUALS(raw_data, arraysize(raw_data), frame.data.data(), frame.data.size()); OLA_ASSERT_EQ(0u, frame.timing.response_time); OLA_ASSERT_EQ(0u, frame.timing.break_time); OLA_ASSERT_EQ(0u, frame.timing.mark_time); OLA_ASSERT_EQ(0u, frame.timing.data_time); ByteString input_data(raw_data, arraysize(raw_data)); RDMFrame frame2(input_data); OLA_ASSERT_DATA_EQUALS(input_data.data(), input_data.size(), frame.data.data(), frame.data.size()); OLA_ASSERT_EQ(0u, frame2.timing.response_time); OLA_ASSERT_EQ(0u, frame2.timing.break_time); OLA_ASSERT_EQ(0u, frame2.timing.mark_time); OLA_ASSERT_EQ(0u, frame2.timing.data_time); } void RDMFrameTest::testPrependStartCode() { const uint8_t raw_data[] = {1, 2, 3, 4, 5}; RDMFrame::Options options(true); RDMFrame frame(raw_data, arraysize(raw_data), options); ByteString expected_data(1, 0xcc); expected_data.append(raw_data, arraysize(raw_data)); OLA_ASSERT_DATA_EQUALS(expected_data.data(), expected_data.size(), frame.data.data(), frame.data.size()); ByteString input_data(raw_data, arraysize(raw_data)); RDMFrame frame2(input_data, options); OLA_ASSERT_DATA_EQUALS(expected_data.data(), expected_data.size(), frame2.data.data(), frame2.data.size()); } ola-0.10.5.nojsmin/common/rdm/VariableFieldSizeCalculator.cpp0000644000175000017500000001407413023355232023600 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * VariableFieldSizeCalculator.cpp * Copyright (C) 2011 Simon Newton */ #include #include #include "common/rdm/VariableFieldSizeCalculator.h" namespace ola { namespace rdm { using ola::messaging::FieldDescriptorGroup; using ola::messaging::StringFieldDescriptor; /** * Figure out the size of a variable-length field in a descriptor. The variable * field may be a string or a repeated group of fields. Multiple-variable * length fields are not supported as this doesn't allow us to determine the * boundary of the individual fields within a message. * * This method is *not* re-entrant. * @param data_size the size in bytes of the data in this message * @param descriptor The descriptor to use to build the Message * @param variable_field_size a pointer to a int which is set to the length of * the variable field within this mesage. * @returns A enum which indicates if one (or more) variable length fields * exist, and if only one exists, what type it is. */ VariableFieldSizeCalculator::calculator_state VariableFieldSizeCalculator::CalculateFieldSize( unsigned int data_size, const class ola::messaging::Descriptor *descriptor, unsigned int *variable_field_size) { m_fixed_size_sum = 0; m_variable_string_fields.clear(); m_variable_group_fields.clear(); // split out the fields into fixed and variable length for (unsigned int i = 0; i < descriptor->FieldCount(); ++i) descriptor->GetField(i)->Accept(this); if (data_size < m_fixed_size_sum) return TOO_SMALL; unsigned int variable_string_field_count = m_variable_string_fields.size(); unsigned int variable_group_field_count = m_variable_group_fields.size(); if (variable_string_field_count + variable_group_field_count > 1) return MULTIPLE_VARIABLE_FIELDS; if (variable_string_field_count + variable_group_field_count == 0) return data_size > m_fixed_size_sum ? TOO_LARGE : FIXED_SIZE; // we know there is only one, now we need to work out the number of // repeatitions or length if it's a string unsigned int bytes_remaining = data_size - m_fixed_size_sum; if (variable_string_field_count) { // variable string const StringFieldDescriptor *string_descriptor = m_variable_string_fields[0]; if (bytes_remaining < string_descriptor->MinSize()) return TOO_SMALL; if (bytes_remaining > string_descriptor->MaxSize()) return TOO_LARGE; *variable_field_size = bytes_remaining; return VARIABLE_STRING; } else { // variable group const FieldDescriptorGroup *group_descriptor = m_variable_group_fields[0]; if (!group_descriptor->FixedBlockSize()) return NESTED_VARIABLE_GROUPS; unsigned int block_size = group_descriptor->BlockSize(); if (group_descriptor->LimitedSize() && bytes_remaining > block_size * group_descriptor->MaxBlocks()) return TOO_LARGE; if (bytes_remaining % block_size) return MISMATCHED_SIZE; unsigned int repeat_count = bytes_remaining / block_size; if (repeat_count < group_descriptor->MinBlocks()) return TOO_SMALL; if (group_descriptor->MaxBlocks() != FieldDescriptorGroup::UNLIMITED_BLOCKS && repeat_count > static_cast(group_descriptor->MaxBlocks())) return TOO_LARGE; *variable_field_size = repeat_count; return VARIABLE_GROUP; } } void VariableFieldSizeCalculator::Visit( const ola::messaging::BoolFieldDescriptor *descriptor) { m_fixed_size_sum += descriptor->MaxSize(); } void VariableFieldSizeCalculator::Visit( const ola::messaging::IPV4FieldDescriptor *descriptor) { m_fixed_size_sum += descriptor->MaxSize(); } void VariableFieldSizeCalculator::Visit( const ola::messaging::MACFieldDescriptor *descriptor) { m_fixed_size_sum += descriptor->MaxSize(); } void VariableFieldSizeCalculator::Visit( const ola::messaging::UIDFieldDescriptor *descriptor) { m_fixed_size_sum += descriptor->MaxSize(); } void VariableFieldSizeCalculator::Visit( const ola::messaging::StringFieldDescriptor *descriptor) { if (descriptor->FixedSize()) m_fixed_size_sum += descriptor->MaxSize(); else m_variable_string_fields.push_back(descriptor); } void VariableFieldSizeCalculator::Visit( const ola::messaging::UInt8FieldDescriptor *descriptor) { m_fixed_size_sum += descriptor->MaxSize(); } void VariableFieldSizeCalculator::Visit( const ola::messaging::UInt16FieldDescriptor *descriptor) { m_fixed_size_sum += descriptor->MaxSize(); } void VariableFieldSizeCalculator::Visit( const ola::messaging::UInt32FieldDescriptor *descriptor) { m_fixed_size_sum += descriptor->MaxSize(); } void VariableFieldSizeCalculator::Visit( const ola::messaging::Int8FieldDescriptor *descriptor) { m_fixed_size_sum += descriptor->MaxSize(); } void VariableFieldSizeCalculator::Visit( const ola::messaging::Int16FieldDescriptor *descriptor) { m_fixed_size_sum += descriptor->MaxSize(); } void VariableFieldSizeCalculator::Visit( const ola::messaging::Int32FieldDescriptor *descriptor) { m_fixed_size_sum += descriptor->MaxSize(); } void VariableFieldSizeCalculator::Visit( const ola::messaging::FieldDescriptorGroup *descriptor) { if (descriptor->FixedSize()) m_fixed_size_sum += descriptor->MaxSize(); else m_variable_group_fields.push_back(descriptor); } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/NetworkManager.h0000644000175000017500000000403713023355232020631 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * NetworkManager.h * Talks to the machine's network systems to get/set data. * Copyright (C) 2013 Peter Newman */ /** * @addtogroup rdm_resp * @{ * @file NetworkManager.h * @brief Gets/sets real config about a network. * @} */ #ifndef COMMON_RDM_NETWORKMANAGER_H_ #define COMMON_RDM_NETWORKMANAGER_H_ #include #include #include #include "ola/rdm/NetworkManagerInterface.h" namespace ola { namespace rdm { /** * @brief A NetworkManager which reflects the actual host network * configuration. */ class NetworkManager : public NetworkManagerInterface { public: NetworkManager() : NetworkManagerInterface() { m_interface_picker.reset(ola::network::InterfacePicker::NewPicker()); } const ola::network::InterfacePicker *GetInterfacePicker() const; rdm_dhcp_status GetDHCPStatus(const ola::network::Interface &iface) const; bool GetIPV4DefaultRoute(int32_t *if_index, ola::network::IPV4Address *default_route) const; const std::string GetHostname() const; const std::string GetDomainName() const; bool GetNameServers( std::vector *name_servers) const; private: std::auto_ptr m_interface_picker; }; } // namespace rdm } // namespace ola #endif // COMMON_RDM_NETWORKMANAGER_H_ ola-0.10.5.nojsmin/common/rdm/DescriptorConsistencyChecker.h0000644000175000017500000000531513023355232023532 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * DescriptorConsistencyChecker.h * Verify that we can determine the layout of a Descriptor. * * In order for the binary unpacker to work, we need to be able to determine * the size and offset of every field within a descriptor, without consdering * the data itself. This means the following are unsupported: * * - nested non-fixed sized groups * - multiple variable-sized fields e.g multiple strings * - variable-sized fields within groups * * Copyright (C) 2011 Simon Newton */ #ifndef COMMON_RDM_DESCRIPTORCONSISTENCYCHECKER_H_ #define COMMON_RDM_DESCRIPTORCONSISTENCYCHECKER_H_ #include #include namespace ola { namespace rdm { /** * Check that a RDM Descriptor is consistent. */ class DescriptorConsistencyChecker : public ola::messaging::FieldDescriptorVisitor { public: DescriptorConsistencyChecker() : m_variable_sized_field_count(0) { } bool Descend() const { return false; } bool CheckConsistency(const ola::messaging::Descriptor *descriptor); void Visit(const ola::messaging::BoolFieldDescriptor*); void Visit(const ola::messaging::IPV4FieldDescriptor*); void Visit(const ola::messaging::MACFieldDescriptor*); void Visit(const ola::messaging::UIDFieldDescriptor*); void Visit(const ola::messaging::StringFieldDescriptor*); void Visit(const ola::messaging::UInt8FieldDescriptor*); void Visit(const ola::messaging::UInt16FieldDescriptor*); void Visit(const ola::messaging::UInt32FieldDescriptor*); void Visit(const ola::messaging::Int8FieldDescriptor*); void Visit(const ola::messaging::Int16FieldDescriptor*); void Visit(const ola::messaging::Int32FieldDescriptor*); void Visit(const ola::messaging::FieldDescriptorGroup*); void PostVisit(const ola::messaging::FieldDescriptorGroup*); private: unsigned int m_variable_sized_field_count; }; } // namespace rdm } // namespace ola #endif // COMMON_RDM_DESCRIPTORCONSISTENCYCHECKER_H_ ola-0.10.5.nojsmin/common/rdm/testdata/0000755000175000017500000000000013155164170017346 5ustar wouterwouterola-0.10.5.nojsmin/common/rdm/testdata/inconsistent_pid.proto0000644000175000017500000000045113023355232024002 0ustar wouterwouterpid { name: "PROXIED_DEVICES" value: 16 get_request { } get_response { field { type: STRING name: "label1" max_size: 32 } field { type: STRING name: "label2" max_size: 32 } } get_sub_device_range: ROOT_DEVICE } version: 1302986774 ola-0.10.5.nojsmin/common/rdm/testdata/invalid_esta_pid.proto0000644000175000017500000000053113023355232023723 0ustar wouterwouterpid { name: "PROXIED_DEVICES" value: 32769 get_request { } get_response { field { type: GROUP name: "uids" field { type: UINT16 name: "manufacturer_id" } field { type: UINT32 name: "device_id" } } } get_sub_device_range: ROOT_DEVICE } version: 1302986774 ola-0.10.5.nojsmin/common/rdm/testdata/duplicate_pid_name.proto0000644000175000017500000000123013023355232024230 0ustar wouterwouterpid { name: "PROXIED_DEVICES" value: 16 get_request { } get_response { field { type: GROUP name: "uids" field { type: UINT16 name: "manufacturer_id" } field { type: UINT32 name: "device_id" } } } get_sub_device_range: ROOT_DEVICE } pid { name: "PROXIED_DEVICES" value: 17 get_request { } get_response { field { type: GROUP name: "uids" field { type: UINT16 name: "manufacturer_id" } field { type: UINT32 name: "device_id" } } } get_sub_device_range: ROOT_DEVICE } version: 1302986774 ola-0.10.5.nojsmin/common/rdm/testdata/pids/0000755000175000017500000000000013155164170020305 5ustar wouterwouterola-0.10.5.nojsmin/common/rdm/testdata/pids/pids1.proto0000644000175000017500000000160413023355232022406 0ustar wouterwouterpid { name: "PROXIED_DEVICES" value: 16 get_request { } get_response { field { type: GROUP name: "uids" field { type: UINT16 name: "manufacturer_id" } field { type: UINT32 name: "device_id" } } } get_sub_device_range: ROOT_DEVICE } pid { name: "PROXIED_DEVICE_COUNT" value: 17 get_request { } get_response { field { type: UINT16 name: "device_count" } field { type: BOOL name: "list_changed" } } get_sub_device_range: ROOT_DEVICE } manufacturer { manufacturer_id: 31344 manufacturer_name: "Open Lighting" pid { name: "SERIAL_NUMBER" value: 32768 set_request { field { type: UINT32 name: "serial_number" } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } } version: 1302986774 ola-0.10.5.nojsmin/common/rdm/testdata/pids/pids2.proto0000644000175000017500000000332713023355232022413 0ustar wouterwouterpid { name: "COMMS_STATUS" value: 21 get_request { } get_response { field { type: UINT16 name: "short_message" } field { type: UINT16 name: "length_mismatch" } field { type: UINT16 name: "checksum_fail" } } get_sub_device_range: ROOT_DEVICE set_request { } set_response { } set_sub_device_range: ROOT_DEVICE } pid { name: "QUEUED_MESSAGE" value: 32 get_request { field { type: UINT8 name: "status_type" label { value: 1 label: "Last Message" } label { value: 2 label: "Advisory" } label { value: 3 label: "Warning" } label { value: 4 label: "Error" } } } get_response { } get_sub_device_range: ROOT_DEVICE } manufacturer { manufacturer_id: 161 manufacturer_name: "Creative Lighting And Sound Systems Pty Ltd." pid { name: "DEVICE_MODE" value: 32768 get_request { } get_response { field { type: UINT8 name: "mode" label { value: 0 label: "DMX512" } label { value: 1 label: "DALI" } label { value: 2 label: "DSI" } } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT8 name: "mode" label { value: 0 label: "DMX512" } label { value: 1 label: "DALI" } label { value: 2 label: "DSI" } } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } } version: 1302986774 ola-0.10.5.nojsmin/common/rdm/testdata/pids/overrides.proto0000644000175000017500000000045313023355232023371 0ustar wouterwoutermanufacturer { manufacturer_id: 31344 manufacturer_name: "Open Lighting" pid { name: "FOO_BAR" value: 32768 get_request { } get_response { field { type: UINT32 name: "baz" } } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } } version: 1 ola-0.10.5.nojsmin/common/rdm/testdata/duplicate_pid_value.proto0000644000175000017500000000122213023355232024425 0ustar wouterwouterpid { name: "PROXIED_DEVICES" value: 16 get_request { } get_response { field { type: GROUP name: "uids" field { type: UINT16 name: "manufacturer_id" } field { type: UINT32 name: "device_id" } } } get_sub_device_range: ROOT_DEVICE } pid { name: "OTHER_PID" value: 16 get_request { } get_response { field { type: GROUP name: "uids" field { type: UINT16 name: "manufacturer_id" } field { type: UINT32 name: "device_id" } } } get_sub_device_range: ROOT_DEVICE } version: 1302986774 ola-0.10.5.nojsmin/common/rdm/testdata/duplicate_manufacturer.proto0000644000175000017500000000116413023355232025156 0ustar wouterwoutermanufacturer { manufacturer_id: 31344 manufacturer_name: "Open Lighting" pid { name: "SERIAL_NUMBER" value: 32768 set_request { field { type: UINT32 name: "serial_number" } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } } manufacturer { manufacturer_id: 31344 manufacturer_name: "Open Lighting" pid { name: "SERIAL_NUMBER" value: 32768 set_request { field { type: UINT32 name: "serial_number" } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } } version: 1302986774 ola-0.10.5.nojsmin/common/rdm/testdata/test_pids.proto0000644000175000017500000014666713023355232022450 0ustar wouterwouterpid { name: "PROXIED_DEVICES" value: 16 get_request { } get_response { field { type: GROUP name: "uids" field { type: UINT16 name: "manufacturer_id" } field { type: UINT32 name: "device_id" } } } get_sub_device_range: ROOT_DEVICE } pid { name: "PROXIED_DEVICE_COUNT" value: 17 get_request { } get_response { field { type: UINT16 name: "device_count" } field { type: BOOL name: "list_changed" } } get_sub_device_range: ROOT_DEVICE } pid { name: "COMMS_STATUS" value: 21 get_request { } get_response { field { type: UINT16 name: "short_message" } field { type: UINT16 name: "length_mismatch" } field { type: UINT16 name: "checksum_fail" } } get_sub_device_range: ROOT_DEVICE set_request { } set_response { } set_sub_device_range: ROOT_DEVICE } pid { name: "QUEUED_MESSAGE" value: 32 get_request { field { type: UINT8 name: "status_type" label { value: 1 label: "Last Message" } label { value: 2 label: "Advisory" } label { value: 3 label: "Warning" } label { value: 4 label: "Error" } } } get_response { } get_sub_device_range: ROOT_DEVICE } pid { name: "STATUS_MESSAGES" value: 48 get_request { field { type: UINT8 name: "status_type" label { value: 0 label: "None" } label { value: 1 label: "Last Message" } label { value: 2 label: "Advisory" } label { value: 3 label: "Warning" } label { value: 4 label: "Error" } } } get_response { field { type: GROUP name: "messages" field { type: UINT16 name: "sub_device" } field { type: UINT8 name: "status_type" } field { type: UINT16 name: "message_id" } field { type: INT16 name: "value1" } field { type: INT16 name: "value2" } } } get_sub_device_range: ROOT_DEVICE } pid { name: "STATUS_ID_DESCRIPTION" value: 49 get_request { field { type: UINT16 name: "status_id" } } get_response { field { type: STRING name: "label" max_size: 32 } } get_sub_device_range: ROOT_DEVICE } pid { name: "CLEAR_STATUS_ID" value: 50 set_request { } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "SUB_DEVICE_STATUS_REPORT_THRESHOLD" value: 51 get_request { } get_response { field { type: UINT8 name: "status_type" } } get_sub_device_range: ONLY_SUBDEVICES set_request { field { type: UINT8 name: "status_type" label { value: 0 label: "None" } label { value: 2 label: "Advisory" } label { value: 3 label: "Warning" } label { value: 4 label: "Error" } } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "SUPPORTED_PARAMETERS" value: 80 get_request { } get_response { field { type: GROUP name: "params" field { type: UINT16 name: "param_id" } } } get_sub_device_range: ROOT_OR_SUBDEVICE } pid { name: "PARAMETER_DESCRIPTION" value: 81 get_request { field { type: UINT16 name: "pid" } } get_response { field { type: UINT16 name: "pid" } field { type: UINT8 name: "pdl_size" } field { type: UINT8 name: "data_type" } field { type: UINT8 name: "command_class" } field { type: UINT8 name: "type" } field { type: UINT8 name: "unit" } field { type: UINT8 name: "prefix" } field { type: UINT32 name: "min_value" } field { type: UINT32 name: "max_value" } field { type: UINT32 name: "default_value" } field { type: STRING name: "description" max_size: 32 } } get_sub_device_range: ROOT_DEVICE } pid { name: "DEVICE_INFO" value: 96 get_request { } get_response { field { type: UINT8 name: "protocol_major" } field { type: UINT8 name: "protocol_minor" } field { type: UINT16 name: "device_model" } field { type: UINT16 name: "product_category" } field { type: UINT32 name: "software_version" } field { type: UINT16 name: "dmx_footprint" } field { type: UINT8 name: "current_personality" } field { type: UINT8 name: "personality_count" } field { type: UINT16 name: "dmx_start_address" } field { type: UINT16 name: "sub_device_count" } field { type: UINT8 name: "sensor_count" } } get_sub_device_range: ROOT_OR_SUBDEVICE } pid { name: "PRODUCT_DETAIL_ID_LIST" value: 112 get_request { } get_response { field { type: GROUP name: "detail_ids" max_size: 6 field { type: UINT16 name: "detail_id" } } } get_sub_device_range: ROOT_OR_SUBDEVICE } pid { name: "DEVICE_MODEL_DESCRIPTION" value: 128 get_request { } get_response { field { type: STRING name: "description" max_size: 32 } } get_sub_device_range: ROOT_OR_SUBDEVICE } pid { name: "MANUFACTURER_LABEL" value: 129 get_request { } get_response { field { type: STRING name: "label" max_size: 32 } } get_sub_device_range: ROOT_OR_SUBDEVICE } pid { name: "DEVICE_LABEL" value: 130 get_request { } get_response { field { type: STRING name: "label" max_size: 32 } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: STRING name: "label" max_size: 32 } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "FACTORY_DEFAULTS" value: 144 get_request { } get_response { field { type: BOOL name: "using_defaults" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "LANGUAGE_CAPABILITIES" value: 160 get_request { } get_response { field { type: GROUP name: "languages" field { type: STRING name: "language" min_size: 2 max_size: 2 } } } get_sub_device_range: ROOT_OR_SUBDEVICE } pid { name: "LANGUAGE" value: 176 get_request { } get_response { field { type: STRING name: "language" max_size: 2 } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: STRING name: "language" max_size: 2 } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "SOFTWARE_VERSION_LABEL" value: 192 get_request { } get_response { field { type: STRING name: "label" max_size: 32 } } get_sub_device_range: ROOT_OR_SUBDEVICE } pid { name: "BOOT_SOFTWARE_VERSION_ID" value: 193 get_request { } get_response { field { type: UINT32 name: "version" } } get_sub_device_range: ROOT_OR_SUBDEVICE } pid { name: "BOOT_SOFTWARE_VERSION_LABEL" value: 194 get_request { } get_response { field { type: STRING name: "label" max_size: 32 } } get_sub_device_range: ROOT_OR_SUBDEVICE } pid { name: "DMX_PERSONALITY" value: 224 get_request { } get_response { field { type: UINT8 name: "current_personality" } field { type: UINT8 name: "personality_count" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT8 name: "personality" range { min: 0 max: 255 } } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "DMX_PERSONALITY_DESCRIPTION" value: 225 get_request { field { type: UINT8 name: "personality" range { min: 0 max: 255 } } } get_response { field { type: UINT8 name: "personality" } field { type: UINT16 name: "slots_required" } field { type: STRING name: "name" max_size: 32 } } get_sub_device_range: ROOT_OR_SUBDEVICE } pid { name: "DMX_START_ADDRESS" value: 240 get_request { } get_response { field { type: UINT16 name: "dmx_address" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT16 name: "dmx_address" range { min: 1 max: 512 } } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "SLOT_INFO" value: 288 get_request { } get_response { field { type: GROUP name: "slots" field { type: UINT16 name: "slot_offset" } field { type: UINT8 name: "slot_type" } field { type: UINT16 name: "slot_label_id" } } } get_sub_device_range: ROOT_OR_SUBDEVICE } pid { name: "SLOT_DESCRIPTION" value: 289 get_request { field { type: UINT16 name: "slot_number" } } get_response { field { type: UINT16 name: "slot_number" } field { type: STRING name: "name" max_size: 32 } } get_sub_device_range: ROOT_OR_SUBDEVICE } pid { name: "DEFAULT_SLOT_VALUE" value: 290 get_request { } get_response { field { type: GROUP name: "slot_values" field { type: UINT16 name: "slot_offset" } field { type: UINT8 name: "default_slot_value" } } } get_sub_device_range: ROOT_OR_SUBDEVICE } pid { name: "SENSOR_DEFINITION" value: 512 get_request { field { type: UINT8 name: "sensor_number" range { min: 0 max: 254 } } } get_response { field { type: UINT8 name: "sensor_number" } field { type: UINT8 name: "type" } field { type: UINT8 name: "unit" } field { type: UINT8 name: "prefix" } field { type: INT16 name: "range_min" label { value: -32768 label: "Undefined" } range { min: -32768 max: 32767 } } field { type: INT16 name: "range_max" label { value: 32767 label: "Undefined" } range { min: -32767 max: 32767 } } field { type: INT16 name: "normal_min" label { value: -32768 label: "Undefined" } range { min: -32768 max: 32767 } } field { type: INT16 name: "normal_max" label { value: 32767 label: "Undefined" } range { min: -32768 max: 32767 } } field { type: UINT8 name: "supports_recording" } field { type: STRING name: "name" max_size: 32 } } get_sub_device_range: ROOT_OR_SUBDEVICE } pid { name: "SENSOR_VALUE" value: 513 get_request { field { type: UINT8 name: "sensor_number" range { min: 0 max: 254 } } } get_response { field { type: UINT8 name: "sensor_number" } field { type: INT16 name: "present_value" } field { type: INT16 name: "lowest" } field { type: INT16 name: "highest" } field { type: INT16 name: "recorded" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT8 name: "sensor_number" label { value: 255 label: "All Sensors" } range { min: 0 max: 255 } } } set_response { field { type: UINT8 name: "sensor_number" } field { type: UINT16 name: "present_value" } field { type: UINT16 name: "lowest" } field { type: UINT16 name: "highest" } field { type: UINT16 name: "recorded" } } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "RECORD_SENSORS" value: 514 set_request { field { type: UINT8 name: "sensor_number" label { value: 255 label: "All Sensors" } range { min: 0 max: 255 } } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "DEVICE_HOURS" value: 1024 get_request { } get_response { field { type: UINT32 name: "hours" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT32 name: "hours" } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "LAMP_HOURS" value: 1025 get_request { } get_response { field { type: UINT32 name: "hours" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT32 name: "hours" } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "LAMP_STRIKES" value: 1026 get_request { } get_response { field { type: UINT32 name: "strikes" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT32 name: "strikes" } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "LAMP_STATE" value: 1027 get_request { } get_response { field { type: UINT8 name: "state" label { value: 0 label: "Off" } label { value: 1 label: "On" } label { value: 2 label: "Strike" } label { value: 3 label: "Standby" } label { value: 4 label: "Not Present" } label { value: 127 label: "Error" } } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT8 name: "state" label { value: 0 label: "Off" } label { value: 1 label: "On" } label { value: 2 label: "Strike" } label { value: 3 label: "Standby" } range { min: 0 max: 3 } range { min: 128 max: 223 } } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "LAMP_ON_MODE" value: 1028 get_request { } get_response { field { type: UINT8 name: "mode" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT8 name: "mode" label { value: 0 label: "Off" } label { value: 1 label: "DMX" } label { value: 2 label: "On" } label { value: 3 label: "On After Calibration" } range { min: 0 max: 3 } range { min: 128 max: 223 } } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "DEVICE_POWER_CYCLES" value: 1029 get_request { } get_response { field { type: UINT32 name: "power_cycles" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT32 name: "power_cycles" } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "DISPLAY_INVERT" value: 1280 get_request { } get_response { field { type: UINT8 name: "invert_status" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT8 name: "invert_status" label { value: 0 label: "Off" } label { value: 1 label: "On" } label { value: 2 label: "Auto" } } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "DISPLAY_LEVEL" value: 1281 get_request { } get_response { field { type: UINT8 name: "level" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT8 name: "level" } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "PAN_INVERT" value: 1536 get_request { } get_response { field { type: BOOL name: "invert" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: BOOL name: "invert" } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "TILT_INVERT" value: 1537 get_request { } get_response { field { type: BOOL name: "invert" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: BOOL name: "invert" } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "PAN_TILT_SWAP" value: 1538 get_request { } get_response { field { type: BOOL name: "swap" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: BOOL name: "swap" } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "REAL_TIME_CLOCK" value: 1539 get_request { } get_response { field { type: UINT16 name: "year" } field { type: UINT8 name: "month" } field { type: UINT8 name: "day" } field { type: UINT8 name: "hour" } field { type: UINT8 name: "minute" } field { type: UINT8 name: "second" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT16 name: "year" range { min: 2003 max: 65535 } } field { type: UINT8 name: "month" range { min: 1 max: 12 } } field { type: UINT8 name: "day" range { min: 1 max: 31 } } field { type: UINT8 name: "hour" range { min: 0 max: 23 } } field { type: UINT8 name: "minute" range { min: 0 max: 59 } } field { type: UINT8 name: "second" range { min: 0 max: 60 } } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "IDENTIFY_DEVICE" value: 4096 get_request { } get_response { field { type: BOOL name: "identify_state" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: BOOL name: "identify_state" } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "RESET_DEVICE" value: 4097 set_request { field { type: UINT8 name: "reset_mode" label { value: 1 label: "Warm" } label { value: 255 label: "Cold" } } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "POWER_STATE" value: 4112 get_request { } get_response { field { type: UINT8 name: "power_state" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT8 name: "power_state" label { value: 0 label: "Full Off" } label { value: 1 label: "Shutdown" } label { value: 2 label: "Standby" } label { value: 255 label: "Normal" } } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "PERFORM_SELFTEST" value: 4128 get_request { } get_response { field { type: BOOL name: "tests_active" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT8 name: "test_number" label { value: 0 label: "Off" } label { value: 255 label: "All" } range { min: 0 max: 255 } } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "SELF_TEST_DESCRIPTION" value: 4129 get_request { field { type: UINT8 name: "test_number" } } get_response { field { type: UINT8 name: "test_number" } field { type: STRING name: "description" max_size: 32 } } get_sub_device_range: ROOT_OR_SUBDEVICE } pid { name: "CAPTURE_PRESET" value: 4144 set_request { field { type: UINT16 name: "scene" range { min: 1 max: 65534 } } field { type: UINT16 name: "fade_up_time" multiplier: -1 } field { type: UINT16 name: "fade_down_time" multiplier: -1 } field { type: UINT16 name: "wait_time" multiplier: -1 } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "PRESET_PLAYBACK" value: 4145 get_request { } get_response { field { type: UINT16 name: "mode" } field { type: UINT8 name: "level" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT16 name: "mode" label { value: 0 label: "Off" } label { value: 65535 label: "All" } range { min: 0 max: 65535 } } field { type: UINT8 name: "level" } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "IDENTIFY_MODE" value: 32688 get_request { } get_response { field { type: UINT8 name: "identify_mode" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT8 name: "identify_mode" label { value: 0 label: "Quiet" } label { value: 255 label: "Loud" } } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "PRESET_INFO" value: 32689 get_request { } get_response { field { type: BOOL name: "level_field_supported" } field { type: BOOL name: "preset_sequence_supported" } field { type: BOOL name: "split_times_supported" } field { type: BOOL name: "fail_infitite_delay_supported" } field { type: BOOL name: "fail_infitite_hold_supported" } field { type: BOOL name: "startup_infitite_hold_supported" } field { type: UINT16 name: "max_scene_number" } field { type: UINT16 name: "min_preset_fade_time" multiplier: -1 } field { type: UINT16 name: "max_preset_fade_time" multiplier: -1 } field { type: UINT16 name: "min_preset_wait_time" multiplier: -1 } field { type: UINT16 name: "max_preset_wait_time" multiplier: -1 } field { type: UINT16 name: "min_fail_delay_time" multiplier: -1 } field { type: UINT16 name: "max_fail_delay_time" multiplier: -1 } field { type: UINT16 name: "min_fail_hold_time" multiplier: -1 } field { type: UINT16 name: "max_fail_hold_time" multiplier: -1 } field { type: UINT16 name: "min_startup_delay_time" multiplier: -1 } field { type: UINT16 name: "max_startup_delay_time" multiplier: -1 } field { type: UINT16 name: "min_startup_hold_time" multiplier: -1 } field { type: UINT16 name: "max_startup_hold_time" multiplier: -1 } } get_sub_device_range: ROOT_OR_SUBDEVICE } pid { name: "PRESET_STATUS" value: 32690 get_request { field { type: UINT16 name: "scene_number" range { min: 1 max: 65534 } } } get_response { field { type: UINT16 name: "scene_number" range { min: 1 max: 65534 } } field { type: UINT16 name: "up_fade_time" multiplier: -1 } field { type: UINT16 name: "down_fade_time" multiplier: -1 } field { type: UINT16 name: "wait_time" multiplier: -1 } field { type: UINT16 name: "programmed" label { value: 0 label: "Not Programmed" } label { value: 1 label: "Programmed" } label { value: 2 label: "Read Only" } } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT16 name: "scene_number" range { min: 1 max: 65534 } } field { type: UINT16 name: "up_fade_time" multiplier: -1 } field { type: UINT16 name: "down_fade_time" multiplier: -1 } field { type: UINT16 name: "wait_time" multiplier: -1 } field { type: BOOL name: "clear_preset" } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "PRESET_MERGEMODE" value: 32691 get_request { } get_response { field { type: UINT8 name: "merge_mode" label { value: 0 label: "Default" } label { value: 1 label: "HTP" } label { value: 2 label: "LTP" } label { value: 3 label: "DMX Only" } label { value: 255 label: "Other" } } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT8 name: "merge_mode" label { value: 0 label: "Default" } label { value: 1 label: "HTP" } label { value: 2 label: "LTP" } label { value: 3 label: "DMX Only" } label { value: 255 label: "Other" } } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "POWER_ON_SELF_TEST" value: 32692 get_request { } get_response { field { type: BOOL name: "power_on_self_test" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: BOOL name: "power_on_self_test" } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "DMX_BLOCK_ADDRESS" value: 32752 get_request { } get_response { field { type: UINT16 name: "sub_device_footprint" } field { type: UINT16 name: "base_dmx_address" } } get_sub_device_range: ROOT_DEVICE set_request { field { type: UINT16 name: "base_dmx_address" range { min: 1 max: 512 } } } set_response { } set_sub_device_range: ROOT_DEVICE } pid { name: "DMX_FAIL_MODE" value: 32753 get_request { } get_response { field { type: UINT16 name: "scene_number" } field { type: UINT16 name: "loss_of_signal_delay" multiplier: -1 label { value: 65535 label: "Infinite" } range { min: 0 max: 65535 } } field { type: UINT16 name: "hold_time" multiplier: -1 label { value: 65535 label: "Infinite" } range { min: 0 max: 65535 } } field { type: UINT8 name: "level" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT16 name: "scene_number" label { value: 0 label: "Fixed Level" } range { min: 0 max: 255 } } field { type: UINT16 name: "loss_of_signal_delay" multiplier: -1 label { value: 65535 label: "Infinite" } range { min: 0 max: 65535 } } field { type: UINT16 name: "hold_time" multiplier: -1 label { value: 65535 label: "Infinite" } range { min: 0 max: 65535 } } field { type: UINT8 name: "level" } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "DMX_STARTUP_MODE" value: 32754 get_request { } get_response { field { type: UINT16 name: "scene_number" } field { type: UINT16 name: "startup_delay" multiplier: -1 label { value: 65535 label: "Infinite" } range { min: 0 max: 65535 } } field { type: UINT16 name: "hold_time" multiplier: -1 label { value: 65535 label: "Infinite" } range { min: 0 max: 65535 } } field { type: UINT8 name: "level" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT16 name: "scene_number" label { value: 0 label: "Fixed Level" } range { min: 0 max: 255 } } field { type: UINT16 name: "startup_delay" multiplier: -1 label { value: 65535 label: "Infinite" } range { min: 0 max: 65535 } } field { type: UINT16 name: "hold_time" multiplier: -1 label { value: 65535 label: "Infinite" } range { min: 0 max: 65535 } } field { type: UINT8 name: "level" } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "DIMMER_INFO" value: 32755 get_request { } get_response { field { type: UINT16 name: "minimum_level_lower" } field { type: UINT16 name: "minimum_level_upper" } field { type: UINT16 name: "maximum_level_lower" } field { type: UINT16 name: "maximum_level_upper" } field { type: UINT8 name: "number_curves_supported" } field { type: UINT8 name: "levels_resolution" range { min: 0 max: 16 } } field { type: BOOL name: "split_levels_supported" } } get_sub_device_range: ROOT_OR_SUBDEVICE } pid { name: "MINIMUM_LEVEL" value: 32756 get_request { } get_response { field { type: UINT16 name: "minimum_level_increasing" } field { type: UINT16 name: "minimum_level_decreasing" } field { type: BOOL name: "on_below_minimum" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT16 name: "minimum_level_increasing" } field { type: UINT16 name: "minimum_level_decreasing" } field { type: BOOL name: "on_below_minimum" } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "MAXIMUM_LEVEL" value: 32757 get_request { } get_response { field { type: UINT16 name: "maximum_level" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT16 name: "maximum_level" } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "CURVE" value: 32758 get_request { } get_response { field { type: UINT8 name: "current_curve" } field { type: UINT8 name: "number_curves" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT8 name: "curve" range { min: 1 max: 4080 } } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "CURVE_DESCRIPTION" value: 32759 get_request { field { type: UINT8 name: "curve_number" range { min: 1 max: 255 } } } get_response { field { type: UINT8 name: "curve_number" range { min: 1 max: 255 } } field { type: STRING name: "curve_description" max_size: 32 } } get_sub_device_range: ROOT_OR_SUBDEVICE } pid { name: "OUTPUT_RESPONSE_TIME" value: 32760 get_request { } get_response { field { type: UINT8 name: "current_response_time" } field { type: UINT8 name: "number_response_options" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT8 name: "response_time" range { min: 1 max: 255 } } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "OUTPUT_RESPONSE_TIME_DESCRIPTION" value: 32761 get_request { field { type: UINT8 name: "response_time" range { min: 1 max: 255 } } } get_response { field { type: UINT8 name: "response_time" range { min: 1 max: 255 } } field { type: STRING name: "response_time_description" max_size: 32 } } get_sub_device_range: ROOT_OR_SUBDEVICE } pid { name: "MODULATION_FREQUENCY" value: 32762 get_request { } get_response { field { type: UINT8 name: "current_moduluation_frequency" } field { type: UINT8 name: "number_modluation_frequencies" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT8 name: "modulation_frequency" range { min: 1 max: 255 } } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "MODULATION_FREQUENCY_DESCRIPTION" value: 32763 get_request { field { type: UINT8 name: "modulation_frequency" range { min: 1 max: 255 } } } get_response { field { type: UINT8 name: "modulation_frequency" range { min: 1 max: 255 } } field { type: UINT32 name: "frequency" } field { type: STRING name: "modulation_frequence_description" max_size: 32 } } get_sub_device_range: ROOT_OR_SUBDEVICE } pid { name: "BURN_IN" value: 32764 get_request { } get_response { field { type: UINT8 name: "hours_remaining" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT8 name: "hours" } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "LOCK_PIN" value: 32765 get_request { } get_response { field { type: UINT16 name: "pin_code" range { min: 0 max: 9999 } } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT16 name: "new_pin_code" range { min: 0 max: 9999 } } field { type: UINT16 name: "current_pin_code" range { min: 0 max: 9999 } } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "LOCK_STATE" value: 32766 get_request { } get_response { field { type: UINT8 name: "current_lock_state" label { value: 0 label: "Unlocked" } range { min: 0 max: 255 } } field { type: UINT8 name: "number_of_lock_states" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT16 name: "pin_code" range { min: 0 max: 9999 } } field { type: UINT8 name: "lock_state" label { value: 0 label: "Unlocked" } range { min: 0 max: 255 } } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "LOCK_STATE_DESCRIPTION" value: 32767 get_request { field { type: UINT8 name: "lock_state" range { min: 1 max: 255 } } } get_response { field { type: UINT8 name: "lock_state" range { min: 1 max: 255 } } field { type: STRING name: "lock_state_description" max_size: 32 } } get_sub_device_range: ROOT_OR_SUBDEVICE } manufacturer { manufacturer_id: 161 manufacturer_name: "Creative Lighting And Sound Systems Pty Ltd." pid { name: "DEVICE_MODE" value: 32768 get_request { } get_response { field { type: UINT8 name: "mode" label { value: 0 label: "DMX512" } label { value: 1 label: "DALI" } label { value: 2 label: "DSI" } } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT8 name: "mode" label { value: 0 label: "DMX512" } label { value: 1 label: "DALI" } label { value: 2 label: "DSI" } } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } } manufacturer { manufacturer_id: 18501 manufacturer_name: "Howard Eaton Lighting Ltd." pid { name: "PWRUP_TEST" value: 51287 get_request { } get_response { field { type: BOOL name: "enabled" } field { type: UINT8 name: "max_allowed" } } get_sub_device_range: ROOT_DEVICE set_request { field { type: BOOL name: "enabled" } } set_response { } set_sub_device_range: ROOT_DEVICE } pid { name: "INTERNAL_STATS" value: 51298 get_request { } get_response { field { type: UINT16 name: "dmx_nsc_packet_count" } field { type: UINT16 name: "dmx_asc_packet_count" } field { type: UINT16 name: "rdm_asc_packet_count" } field { type: UINT8 name: "uart_errors" } field { type: UINT8 name: "device_minutes" } field { type: UINT8 name: "brownout_count" } field { type: UINT8 name: "watchdog_resets" } field { type: UINT8 name: "software_resets" } field { type: UINT16 name: "dither_adjust" } field { type: UINT8 name: "record_sensor_counts" } } get_sub_device_range: ROOT_DEVICE set_request { } set_response { } set_sub_device_range: ROOT_DEVICE } } manufacturer { manufacturer_id: 19041 manufacturer_name: "Jands Pty Ltd." pid { name: "NE_FAULT_DETECT_MODE" value: 32896 get_request { } get_response { field { type: BOOL name: "enabled" } } get_sub_device_range: ROOT_DEVICE set_request { field { type: BOOL name: "enabled" } } set_response { } set_sub_device_range: ROOT_DEVICE } pid { name: "DMX_PROTECT_MODE" value: 32898 get_request { } get_response { field { type: BOOL name: "enabled" } } get_sub_device_range: ROOT_DEVICE set_request { field { type: BOOL name: "enabled" } } set_response { } set_sub_device_range: ROOT_DEVICE } pid { name: "DMX_LOSS_MODE" value: 32900 get_request { } get_response { field { type: UINT8 name: "mode" label { value: 0 label: "Hold" } label { value: 1 label: "Fade to scene #1" } } } get_sub_device_range: ROOT_DEVICE set_request { field { type: UINT8 name: "mode" label { value: 0 label: "Hold" } label { value: 1 label: "Fade to scene #1" } } } set_response { } set_sub_device_range: ROOT_DEVICE } pid { name: "PREHEAT_LEVEL" value: 32902 get_request { } get_response { field { type: UINT8 name: "level" label { value: 0 label: "Off" } } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT8 name: "level" label { value: 0 label: "Off" } range { min: 0 max: 50 } } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "OUTPUT_CAP_VALUE" value: 32904 get_request { } get_response { field { type: UINT8 name: "cap" label { value: 0 label: "Off" } label { value: 1 label: "95%" } label { value: 2 label: "90%" } label { value: 3 label: "85%" } label { value: 4 label: "80%" } label { value: 5 label: "75%" } label { value: 6 label: "70%" } label { value: 7 label: "65%" } label { value: 8 label: "60%" } label { value: 9 label: "55%" } label { value: 10 label: "50%" } label { value: 11 label: "45%" } label { value: 12 label: "40%" } } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT8 name: "cap" label { value: 0 label: "Off" } label { value: 1 label: "95%" } label { value: 2 label: "90%" } label { value: 3 label: "85%" } label { value: 4 label: "80%" } label { value: 5 label: "75%" } label { value: 6 label: "70%" } label { value: 7 label: "65%" } label { value: 8 label: "60%" } label { value: 9 label: "55%" } label { value: 10 label: "50%" } label { value: 11 label: "45%" } label { value: 12 label: "40%" } } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "DMX_TERM_MODE" value: 32906 get_request { } get_response { field { type: BOOL name: "enabled" } } get_sub_device_range: ROOT_DEVICE set_request { field { type: BOOL name: "enabled" } } set_response { } set_sub_device_range: ROOT_DEVICE } } manufacturer { manufacturer_id: 19541 manufacturer_name: "LumenRadio AB" pid { name: "FULL_DISCOVERY" value: 32768 get_request { } get_response { field { type: BOOL name: "enabled" } } get_sub_device_range: ROOT_DEVICE set_request { field { type: BOOL name: "enabled" } } set_response { } set_sub_device_range: ROOT_DEVICE } pid { name: "OUTPUT_DEFAULT_VALUE" value: 32770 get_request { } get_response { field { type: UINT8 name: "dmx_level" } } get_sub_device_range: ROOT_DEVICE set_request { field { type: UINT8 name: "dmx_level" } } set_response { field { type: UINT8 name: "dmx_level" } } set_sub_device_range: ROOT_DEVICE } pid { name: "DALI_FADE_TIME" value: 32771 get_request { } get_response { field { type: UINT8 name: "fade_time" } } get_sub_device_range: ROOT_DEVICE set_request { field { type: UINT8 name: "fade_time" } } set_response { field { type: UINT8 name: "fade_time" } } set_sub_device_range: ROOT_DEVICE } pid { name: "INCREMENTAL_DISCOVERY_INTERVAL" value: 33025 get_request { } get_response { field { type: UINT16 name: "interval" multiplier: -1 } } get_sub_device_range: ROOT_DEVICE set_request { field { type: UINT16 name: "interval" multiplier: -1 range { min: 257 max: 65535 } } } set_response { } set_sub_device_range: ROOT_DEVICE } pid { name: "ACK_TIMER_FACTOR" value: 33026 get_request { } get_response { field { type: UINT16 name: "timer_factor" } } get_sub_device_range: ROOT_DEVICE set_request { field { type: UINT16 name: "timer_factor" range { min: 257 max: 65535 } } } set_response { } set_sub_device_range: ROOT_DEVICE } } manufacturer { manufacturer_id: 21324 manufacturer_name: "Soundlight" pid { name: "DMX_HOLD_MODE" value: 33009 get_request { } get_response { field { type: UINT8 name: "mode" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT8 name: "mode" label { value: 0 label: "Outputs to 0%" } label { value: 1 label: "Output to 100%" } label { value: 2 label: "Hold" } label { value: 3 label: "Go to predefined scene" } } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "MODIFY_SENSOR_DEFINITION" value: 33280 get_request { field { type: UINT8 name: "sensor_number" } } get_response { field { type: UINT8 name: "sensor_number" } field { type: UINT8 name: "type" } field { type: UINT8 name: "unit" } field { type: UINT8 name: "prefix" } field { type: UINT16 name: "range_min" } field { type: UINT16 name: "range_max" } field { type: UINT16 name: "normal_min" } field { type: UINT16 name: "normal_max" } field { type: UINT8 name: "supports_recording" } field { type: STRING name: "name" max_size: 20 } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT8 name: "sensor_number" } field { type: UINT8 name: "type" } field { type: UINT8 name: "unit" } field { type: UINT8 name: "prefix" } field { type: UINT16 name: "range_min" } field { type: UINT16 name: "range_max" } field { type: UINT16 name: "normal_min" } field { type: UINT16 name: "normal_max" } field { type: UINT8 name: "supports_recording" } field { type: STRING name: "name" max_size: 20 } } set_response { } set_sub_device_range: ROOT_OR_SUBDEVICE } pid { name: "DC_OFFSET" value: 56334 get_request { } get_response { field { type: GROUP name: "dc_offsets" field { type: UINT8 name: "offset_value" } } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: GROUP name: "dc_offsets" field { type: UINT8 name: "offset_value" } } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "DC_FADER_OFFSET" value: 56335 set_request { field { type: GROUP name: "offsets" field { type: UINT8 name: "offset_value" } } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "DC_CALIBRATION" value: 56522 get_request { } get_response { field { type: UINT8 name: "scale_value" } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT8 name: "scale_value" } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } pid { name: "CURVE_DEFINITION" value: 56525 get_request { } get_response { field { type: UINT8 name: "curve_number" } field { type: UINT8 name: "total_curves" } field { type: UINT8 name: "segment_count" } field { type: UINT8 name: "interpolation_method" label { value: 0 label: "Step" } label { value: 1 label: "Linear" } label { value: 2 label: "Square" } label { value: 3 label: "Cubic" } } field { type: UINT8 name: "start_value" } field { type: GROUP name: "curve_values" field { type: UINT8 name: "value" } } } get_sub_device_range: ROOT_OR_SUBDEVICE set_request { field { type: UINT8 name: "curve_number" } field { type: UINT8 name: "total_curves" } field { type: UINT8 name: "segment_count" } field { type: UINT8 name: "interpolation_method" label { value: 0 label: "Step" } label { value: 1 label: "Linear" } label { value: 2 label: "Square" } label { value: 3 label: "Cubic" } } field { type: UINT8 name: "start_value" } field { type: GROUP name: "curve_values" field { type: UINT8 name: "value" } } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } } manufacturer { manufacturer_id: 31344 manufacturer_name: "Open Lighting" pid { name: "SERIAL_NUMBER" value: 32768 set_request { field { type: UINT32 name: "serial_number" } } set_response { } set_sub_device_range: ROOT_OR_ALL_SUBDEVICE } } version: 1302986774 ola-0.10.5.nojsmin/common/rdm/RDMHelperTest.cpp0000644000175000017500000000366413023355232020667 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * RDMHelperTest.cpp * Test fixture for the RDM Helper code * Copyright (C) 2014 Peter Newman */ #include #include #include #include "ola/rdm/RDMEnums.h" #include "ola/rdm/RDMHelper.h" #include "ola/testing/TestUtils.h" using std::string; using ola::rdm::StatusMessageIdToString; class RDMHelperTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(RDMHelperTest); CPPUNIT_TEST(testStatusMessageIdToString); CPPUNIT_TEST_SUITE_END(); public: void testStatusMessageIdToString(); }; CPPUNIT_TEST_SUITE_REGISTRATION(RDMHelperTest); /* * Test the StatusMessageIdToString function. */ void RDMHelperTest::testStatusMessageIdToString() { OLA_ASSERT_EQ(string("Slot 25 failed calibration"), StatusMessageIdToString(ola::rdm::STS_CAL_FAIL, 25, 0)); OLA_ASSERT_EQ(string("Proxy Drop: PID 0xabcd at TN 1"), StatusMessageIdToString(ola::rdm::STS_PROXY_BROADCAST_DROPPED, 0xABCD, 1)); OLA_ASSERT_EQ(string("Proxy Drop: PID 0xff00 at TN 255"), StatusMessageIdToString(ola::rdm::STS_PROXY_BROADCAST_DROPPED, 0xFF00, 255)); } ola-0.10.5.nojsmin/common/rdm/RDMFrame.cpp0000644000175000017500000000352613023355232017637 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * RDMFrame.cpp * The RDMFrame object. * Copyright (C) 2015 Simon Newton */ #include "ola/rdm/RDMFrame.h" #include #include #include namespace ola { namespace rdm { RDMFrame::RDMFrame(const uint8_t *raw_data, unsigned int length, const Options &options) { if (options.prepend_start_code) { data.push_back(START_CODE); } data.append(raw_data, length); memset(reinterpret_cast(&timing), 0, sizeof(timing)); } RDMFrame::RDMFrame(const ola::io::ByteString &frame_data, const Options &options) { if (options.prepend_start_code) { data.push_back(START_CODE); } data.append(frame_data); memset(reinterpret_cast(&timing), 0, sizeof(timing)); } bool RDMFrame::operator==(const RDMFrame &other) const { return (data == other.data && timing.response_time == other.timing.response_time && timing.break_time == other.timing.break_time && timing.mark_time == other.timing.mark_time && timing.data_time == other.timing.data_time); } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/NetworkManager.cpp0000644000175000017500000000364313023355232021166 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * NetworkManager.cpp * Copyright (C) 2013 Peter Newman */ #include "common/rdm/NetworkManager.h" #include #include #include "ola/network/NetworkUtils.h" namespace ola { namespace rdm { using ola::network::Interface; using ola::network::InterfacePicker; using ola::network::IPV4Address; using std::string; using std::vector; const InterfacePicker *NetworkManager::GetInterfacePicker() const { return m_interface_picker.get(); } rdm_dhcp_status NetworkManager::GetDHCPStatus(const Interface&) const { // It's a challenge to determine DHCP state, so we always return // DHCP_STATUS_UNKNOWN. return DHCP_STATUS_UNKNOWN; } bool NetworkManager::GetIPV4DefaultRoute(int32_t *if_index, IPV4Address *default_route) const { return ola::network::DefaultRoute(if_index, default_route); } const string NetworkManager::GetHostname() const { return ola::network::Hostname(); } const string NetworkManager::GetDomainName() const { return ola::network::DomainName(); } bool NetworkManager::GetNameServers(vector *name_servers) const { return ola::network::NameServers(name_servers); } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/MessageDeserializer.cpp0000644000175000017500000001745313023355232022175 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * MessageDeserializer.cpp * Inflate a Message object from raw data. * Copyright (C) 2011 Simon Newton */ #include #include #include #include #include #include #include #include #include "common/rdm/VariableFieldSizeCalculator.h" namespace ola { namespace rdm { using ola::messaging::MessageFieldInterface; using std::string; using std::vector; MessageDeserializer::MessageDeserializer() : m_data(NULL), m_length(0), m_offset(0), m_variable_field_size(0), m_insufficient_data(false) { } MessageDeserializer::~MessageDeserializer() { CleanUpVector(); } /** * @brief Deserialize a memory location and return a message */ const ola::messaging::Message *MessageDeserializer::InflateMessage( const ola::messaging::Descriptor *descriptor, const uint8_t *data, unsigned int length) { if (!data && length) { return NULL; } m_data = data; m_length = length; m_offset = 0; m_insufficient_data = false; CleanUpVector(); VariableFieldSizeCalculator calculator; VariableFieldSizeCalculator::calculator_state state = calculator.CalculateFieldSize( length, descriptor, &m_variable_field_size); switch (state) { case VariableFieldSizeCalculator::TOO_SMALL: case VariableFieldSizeCalculator::TOO_LARGE: return NULL; case VariableFieldSizeCalculator::FIXED_SIZE: case VariableFieldSizeCalculator::VARIABLE_STRING: case VariableFieldSizeCalculator::VARIABLE_GROUP: break; case VariableFieldSizeCalculator::MULTIPLE_VARIABLE_FIELDS: case VariableFieldSizeCalculator::NESTED_VARIABLE_GROUPS: case VariableFieldSizeCalculator::MISMATCHED_SIZE: return NULL; } message_vector root_messages; m_message_stack.push(root_messages); descriptor->Accept(this); // this should never trigger because we check the length in the // VariableFieldSizeCalculator if (m_insufficient_data) { return NULL; } const ola::messaging::Message *message = new ola::messaging::Message( m_message_stack.top()); m_message_stack.top().clear(); return message; } void MessageDeserializer::Visit( const ola::messaging::BoolFieldDescriptor *descriptor) { if (!CheckForData(descriptor->MaxSize())) { return; } m_message_stack.top().push_back( new ola::messaging::BoolMessageField(descriptor, m_data[m_offset++])); } void MessageDeserializer::Visit( const ola::messaging::IPV4FieldDescriptor *descriptor) { if (!CheckForData(descriptor->MaxSize())) { return; } uint32_t data; memcpy(&data, m_data + m_offset, sizeof(data)); m_offset += sizeof(data); m_message_stack.top().push_back( new ola::messaging::IPV4MessageField( descriptor, ola::network::IPV4Address(data))); } void MessageDeserializer::Visit( const ola::messaging::MACFieldDescriptor *descriptor) { if (!CheckForData(descriptor->MaxSize())) { return; } ola::network::MACAddress mac_address(m_data + m_offset); m_offset += descriptor->MaxSize(); m_message_stack.top().push_back( new ola::messaging::MACMessageField(descriptor, mac_address)); } void MessageDeserializer::Visit( const ola::messaging::UIDFieldDescriptor *descriptor) { if (!CheckForData(descriptor->MaxSize())) { return; } ola::rdm::UID uid(m_data + m_offset); m_offset += descriptor->MaxSize(); m_message_stack.top().push_back( new ola::messaging::UIDMessageField(descriptor, uid)); } void MessageDeserializer::Visit( const ola::messaging::StringFieldDescriptor *descriptor) { unsigned int string_size; if (descriptor->FixedSize()) { string_size = descriptor->MaxSize(); } else { // variable sized string, the length is in m_variable_field_size string_size = m_variable_field_size; } if (!CheckForData(string_size)) { return; } string value(reinterpret_cast(m_data + m_offset), string_size); ShortenString(&value); m_offset += string_size; m_message_stack.top().push_back( new ola::messaging::StringMessageField(descriptor, value)); } void MessageDeserializer::Visit( const ola::messaging::IntegerFieldDescriptor *descriptor) { IntVisit(descriptor); } void MessageDeserializer::Visit( const ola::messaging::IntegerFieldDescriptor *descriptor) { IntVisit(descriptor); } void MessageDeserializer::Visit( const ola::messaging::IntegerFieldDescriptor *descriptor) { IntVisit(descriptor); } void MessageDeserializer::Visit( const ola::messaging::IntegerFieldDescriptor *descriptor) { IntVisit(descriptor); } void MessageDeserializer::Visit( const ola::messaging::IntegerFieldDescriptor *descriptor) { IntVisit(descriptor); } void MessageDeserializer::Visit( const ola::messaging::IntegerFieldDescriptor *descriptor) { IntVisit(descriptor); } /** * @brief Visit a group field */ void MessageDeserializer::Visit( const ola::messaging::FieldDescriptorGroup *descriptor) { unsigned int iterations = descriptor->FixedSize() ? descriptor->MinBlocks() : m_variable_field_size; for (unsigned int i = 0; i < iterations; ++i) { vector fields; m_message_stack.push(fields); for (unsigned int j = 0; j < descriptor->FieldCount(); ++j) { descriptor->GetField(j)->Accept(this); } const vector &populated_fields = m_message_stack.top(); const ola::messaging::MessageFieldInterface *message = new ola::messaging::GroupMessageField(descriptor, populated_fields); m_message_stack.pop(); m_message_stack.top().push_back(message); } } /** * @brief Check that there is at least required_size bytes of data left. */ bool MessageDeserializer::CheckForData(unsigned int required_size) { if (required_size <= m_length - m_offset) { return true; } m_insufficient_data = true; return false; } /** * @brief Remove any old messages from the stack. */ void MessageDeserializer::CleanUpVector() { while (!m_message_stack.empty()) { const message_vector &fields = m_message_stack.top(); message_vector::const_iterator iter = fields.begin(); for (; iter != fields.end(); ++iter) { delete *iter; } m_message_stack.pop(); } } /** * @brief Deserialize an integer value, converting from little endian if needed */ template void MessageDeserializer::IntVisit( const ola::messaging::IntegerFieldDescriptor *descriptor) { if (!CheckForData(sizeof(int_type))) { return; } int_type value; memcpy(reinterpret_cast(&value), m_data + m_offset, sizeof(int_type)); m_offset += sizeof(int_type); if (descriptor->IsLittleEndian()) { value = ola::network::LittleEndianToHost(value); } else { value = ola::network::NetworkToHost(value); } m_message_stack.top().push_back( new ola::messaging::BasicMessageField(descriptor, value)); } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/DiscoveryAgent.cpp0000644000175000017500000002674413023355232021177 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * DiscoveryAgent.cpp * Implements the RDM Discovery algorithm. * Copyright (C) 2011 Simon Newton */ #include "ola/Callback.h" #include "ola/Logging.h" #include "ola/rdm/DiscoveryAgent.h" #include "ola/rdm/UID.h" #include "ola/rdm/UIDSet.h" #include "ola/strings/Format.h" #include "ola/util/Utils.h" namespace ola { namespace rdm { using ola::utils::JoinUInt8; DiscoveryAgent::DiscoveryAgent(DiscoveryTargetInterface *target) : m_target(target), m_on_complete(NULL), m_unmute_callback( ola::NewCallback(this, &DiscoveryAgent::UnMuteComplete)), m_incremental_mute_callback( ola::NewCallback(this, &DiscoveryAgent::IncrementalMuteComplete)), m_branch_mute_callback( ola::NewCallback(this, &DiscoveryAgent::BranchMuteComplete)), m_branch_callback( ola::NewCallback(this, &DiscoveryAgent::BranchComplete)), m_muting_uid(0, 0), m_unmute_count(0), m_mute_attempts(0), m_tree_corrupt(false) { } DiscoveryAgent::~DiscoveryAgent() { Abort(); } void DiscoveryAgent::Abort() { while (!m_uid_ranges.empty()) { UIDRange *range = m_uid_ranges.top(); delete range; m_uid_ranges.pop(); } if (m_on_complete) { DiscoveryCompleteCallback *callback = m_on_complete; m_on_complete = NULL; UIDSet uids; callback->Run(false, uids); } } void DiscoveryAgent::StartFullDiscovery( DiscoveryCompleteCallback *on_complete) { InitDiscovery(on_complete, false); } void DiscoveryAgent::StartIncrementalDiscovery( DiscoveryCompleteCallback *on_complete) { InitDiscovery(on_complete, true); } /* * Start the discovery process * @param on_complete the callback to run when discovery completes * @param incremental true if this is incremental, false otherwise */ void DiscoveryAgent::InitDiscovery( DiscoveryCompleteCallback *on_complete, bool incremental) { if (m_on_complete) { OLA_WARN << "Discovery procedure already running"; UIDSet uids; on_complete->Run(false, uids); return; } m_on_complete = on_complete; // this should be empty, but clear it out anyway while (!m_uids_to_mute.empty()) { m_uids_to_mute.pop(); } // this should also be empty while (!m_uid_ranges.empty()) { FreeCurrentRange(); } if (incremental) { UIDSet::Iterator iter = m_uids.Begin(); for (; iter != m_uids.End(); ++iter) { m_uids_to_mute.push(*iter); } } else { m_uids.Clear(); } m_bad_uids.Clear(); m_tree_corrupt = false; // push the first range on to the branch stack UID lower(0, 0); m_uid_ranges.push(new UIDRange(lower, UID::AllDevices(), NULL)); m_unmute_count = 0; m_target->UnMuteAll(m_unmute_callback.get()); } /* * Called when the UnMute completes. This resends the Unmute command up to * BROADCAST_UNMUTE_REPEATS times and then starts muting previously known * devices (incremental only). */ void DiscoveryAgent::UnMuteComplete() { if (m_uid_ranges.empty()) { // Abort() was called return; } m_unmute_count++; if (m_unmute_count < BROADCAST_UNMUTE_REPEATS) { m_target->UnMuteAll(m_unmute_callback.get()); return; } MaybeMuteNextDevice(); } /* * If we're in incremental mode, mute previously discovered devices. Otherwise * proceed to the branch stage. */ void DiscoveryAgent::MaybeMuteNextDevice() { if (m_uids_to_mute.empty()) { SendDiscovery(); } else { m_muting_uid = m_uids_to_mute.front(); m_uids_to_mute.pop(); OLA_DEBUG << "Muting previously discovered responder: " << m_muting_uid; m_target->MuteDevice(m_muting_uid, m_incremental_mute_callback.get()); } } /** * Called when we mute a device during incremental discovery. */ void DiscoveryAgent::IncrementalMuteComplete(bool status) { if (!status) { m_uids.RemoveUID(m_muting_uid); OLA_WARN << "Unable to mute " << m_muting_uid << ", device has gone"; } else { OLA_DEBUG << "Muted " << m_muting_uid; } MaybeMuteNextDevice(); } /* * Send a Discovery Unique Branch request. */ void DiscoveryAgent::SendDiscovery() { if (m_uid_ranges.empty()) { // we're hit the end of the stack, now we're done if (m_on_complete) { m_on_complete->Run(!m_tree_corrupt, m_uids); m_on_complete = NULL; } else { OLA_WARN << "Discovery complete but no callback"; } return; } UIDRange *range = m_uid_ranges.top(); if (range->uids_discovered == 0) { range->attempt++; } if (range->failures == MAX_BRANCH_FAILURES || range->attempt == MAX_EMPTY_BRANCH_ATTEMPTS || range->branch_corrupt) { // limit reached, move on to the next branch OLA_DEBUG << "Hit failure limit for (" << range->lower << ", " << range->upper << ")"; if (range->parent) range->parent->branch_corrupt = true; FreeCurrentRange(); SendDiscovery(); } else { OLA_DEBUG << "DUB " << range->lower << " - " << range->upper << ", attempt " << range->attempt << ", uids found: " << range->uids_discovered << ", failures " << range->failures << ", corrupted " << range->branch_corrupt; m_target->Branch(range->lower, range->upper, m_branch_callback.get()); } } /* * Handle a DUB response (inc. timeouts). * @param data the raw response, excluding the start code * @param length the length of the response, 0 if no response was received. */ void DiscoveryAgent::BranchComplete(const uint8_t *data, unsigned int length) { OLA_INFO << "BranchComplete, got " << length; if (length == 0) { // timeout if (!m_uid_ranges.empty()) { FreeCurrentRange(); } SendDiscovery(); return; } // Must at least have the separator, the EUID and the checksum if (length < 1 + EUID_SIZE + CHECKSUM_SIZE) { HandleCollision(); return; } unsigned int offset = 0; while (data[offset] != PREAMBLE_SEPARATOR && offset < PREAMBLE_SIZE - 1) { if (data[offset] != PREAMBLE) { OLA_INFO << "Preamble " << offset << " " << strings::ToHex(data[offset]); HandleCollision(); return; } offset++; } if (data[offset] != PREAMBLE_SEPARATOR) { OLA_INFO << "Preamble separator" << offset << " " << strings::ToHex(data[offset]); HandleCollision(); return; } offset++; unsigned int remaining = length - offset; if (remaining < EUID_SIZE + CHECKSUM_SIZE) { OLA_INFO << "Insufficient data remaining, was " << remaining; HandleCollision(); return; } typedef struct { uint8_t euid11; uint8_t euid10; uint8_t euid9; uint8_t euid8; uint8_t euid7; uint8_t euid6; uint8_t euid5; uint8_t euid4; uint8_t euid3; uint8_t euid2; uint8_t euid1; uint8_t euid0; uint8_t ecs3; uint8_t ecs2; uint8_t ecs1; uint8_t ecs0; } dub_response_structure; const dub_response_structure *response = reinterpret_cast(data + offset); uint16_t calculated_checksum = 0; for (unsigned int i = offset; i < offset + EUID_SIZE; i++) { calculated_checksum += data[i]; } uint16_t recovered_checksum = JoinUInt8((response->ecs3 & response->ecs2), (response->ecs1 & response->ecs0)); if (recovered_checksum != calculated_checksum) { OLA_INFO << "Recovered checksum: " << recovered_checksum << " != " << "calculated checksum: " << calculated_checksum; HandleCollision(); return; } // ok this is a valid response uint16_t manufacturer_id = JoinUInt8((response->euid11 & response->euid10), (response->euid9 & response->euid8)); uint32_t device_id = JoinUInt8((response->euid7 & response->euid6), (response->euid5 & response->euid4), (response->euid3 & response->euid2), (response->euid1 & response->euid0)); UIDRange *range = m_uid_ranges.top(); // we store this as an instance variable so we don't have to create a new // callback each time. UID located_uid = UID(manufacturer_id, device_id); if (m_uids.Contains(located_uid)) { OLA_WARN << "Previous muted responder " << located_uid << " continues to respond"; range->failures++; // ignore this and continue on to the next branch. SendDiscovery(); } else if (m_bad_uids.Contains(located_uid)) { // we've already tried this one range->failures++; SendDiscovery(); } else { m_muting_uid = located_uid; m_mute_attempts = 0; OLA_INFO << "Muting " << m_muting_uid; m_target->MuteDevice(m_muting_uid, m_branch_mute_callback.get()); } } /* * Called when we successfull mute a device during the branch stage. */ void DiscoveryAgent::BranchMuteComplete(bool status) { m_mute_attempts++; if (status) { m_uids.AddUID(m_muting_uid); m_uid_ranges.top()->uids_discovered++; } else { // failed to mute, if we haven't reached the limit try it again if (m_mute_attempts < MAX_MUTE_ATTEMPTS) { OLA_INFO << "Muting " << m_muting_uid; m_target->MuteDevice(m_muting_uid, m_branch_mute_callback.get()); return; } else { // this UID is bad, either it was a phantom or it doesn't response to // mute commands OLA_INFO << m_muting_uid << " didn't respond to MUTE, marking as bad"; m_bad_uids.AddUID(m_muting_uid); } } SendDiscovery(); } /* * Handle a DUB collision. */ void DiscoveryAgent::HandleCollision() { UIDRange *range = m_uid_ranges.top(); UID lower_uid = range->lower; UID upper_uid = range->upper; if (lower_uid == upper_uid) { range->failures++; OLA_WARN << "End of tree reached!!!"; SendDiscovery(); return; } // work out the mid point uint64_t lower = ((static_cast(lower_uid.ManufacturerId()) << 32) + lower_uid.DeviceId()); uint64_t upper = ((static_cast(upper_uid.ManufacturerId()) << 32) + upper_uid.DeviceId()); uint64_t mid = (lower + upper) / 2; UID mid_uid(mid >> 32, mid); mid++; UID mid_plus_one_uid(mid >> 32, mid); OLA_INFO << "Collision, spliting into: " << lower_uid << " - " << mid_uid << " , " << mid_plus_one_uid << " - " << upper_uid; range->uids_discovered = 0; // add both ranges to the stack m_uid_ranges.push(new UIDRange(lower_uid, mid_uid, range)); m_uid_ranges.push(new UIDRange(mid_plus_one_uid, upper_uid, range)); SendDiscovery(); } /* * Deletes the current range from the stack, and pops it. */ void DiscoveryAgent::FreeCurrentRange() { UIDRange *range = m_uid_ranges.top(); if (m_uid_ranges.size() == 1) { // top of stack if (range->branch_corrupt) { OLA_INFO << "Discovery tree is corrupted"; m_tree_corrupt = true; } } else { range->parent->uids_discovered += range->uids_discovered; } delete range; m_uid_ranges.pop(); } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/ResponderPersonality.cpp0000644000175000017500000000701013023355232022425 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * ResponderPersonality.cpp * Manages personalities for a RDM responder. * Copyright (C) 2013 Simon Newton */ #ifndef COMMON_RDM_RESPONDERPERSONALITY_H_ #define COMMON_RDM_RESPONDERPERSONALITY_H_ #include #include "ola/rdm/ResponderPersonality.h" #include "ola/rdm/ResponderSlotData.h" #include "ola/stl/STLUtils.h" namespace ola { namespace rdm { using std::string; /** * Create a new personality. * @param footprint the number of dmx slots consumed * @param description the personality name (32 chars) */ Personality::Personality(uint16_t footprint, const string &description) : m_footprint(footprint), m_description(description) { } Personality::Personality(uint16_t footprint, const string &description, const SlotDataCollection &slot_data) : m_footprint(footprint), m_description(description), m_slot_data(slot_data) { } /** * Takes ownership of the personalites */ PersonalityCollection::PersonalityCollection( const PersonalityList &personalities) : m_personalities(personalities) { } /** * Clean up */ PersonalityCollection::~PersonalityCollection() { } /** * @returns the number of personalities */ uint8_t PersonalityCollection::PersonalityCount() const { return m_personalities.size(); } /** * Look up a personality by index */ const Personality *PersonalityCollection::Lookup(uint8_t personality) const { if (personality == 0 || personality > m_personalities.size()) return NULL; return &m_personalities[personality - 1]; } PersonalityManager::PersonalityManager( const PersonalityCollection *personalities) : m_personalities(personalities), m_active_personality(1) { } uint8_t PersonalityManager::PersonalityCount() const { return m_personalities->PersonalityCount(); } bool PersonalityManager::SetActivePersonality(uint8_t personality) { if (personality == 0 || personality > m_personalities->PersonalityCount()) return false; m_active_personality = personality; return true; } const Personality *PersonalityManager::ActivePersonality() const { return m_personalities->Lookup(m_active_personality); } uint16_t PersonalityManager::ActivePersonalityFootprint() const { const Personality *personality = m_personalities->Lookup( m_active_personality); return personality ? personality->Footprint() : 0; } string PersonalityManager::ActivePersonalityDescription() const { const Personality *personality = m_personalities->Lookup( m_active_personality); return personality ? personality->Description() : ""; } // Lookup a personality. Personalities are numbers from 1. const Personality *PersonalityManager::Lookup(uint8_t personality) const { return m_personalities->Lookup(personality); } } // namespace rdm } // namespace ola #endif // COMMON_RDM_RESPONDERPERSONALITY_H_ ola-0.10.5.nojsmin/common/rdm/UIDAllocatorTest.cpp0000644000175000017500000000502013023355232021353 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * UIDAllocatorTest.cpp * Test fixture for the UIDAllocator * Copyright (C) 2013 Simon Newton */ #include #include #include "ola/rdm/UID.h" #include "ola/rdm/UIDAllocator.h" #include "ola/testing/TestUtils.h" using ola::rdm::UID; using ola::rdm::UIDAllocator; using std::auto_ptr; class UIDAllocatorTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(UIDAllocatorTest); CPPUNIT_TEST(testAllocator); CPPUNIT_TEST_SUITE_END(); public: void testAllocator(); }; CPPUNIT_TEST_SUITE_REGISTRATION(UIDAllocatorTest); /* * Test the Allocator works. */ void UIDAllocatorTest::testAllocator() { UID uid(1, 0xffffff00); UIDAllocator allocator(uid); for (unsigned int i = 0xffffff00; i < 0xffffffff; i++) { auto_ptr uid(allocator.AllocateNext()); OLA_ASSERT_NOT_NULL(uid.get()); OLA_ASSERT_EQ(i, uid->DeviceId()); } OLA_ASSERT_NULL(allocator.AllocateNext()); OLA_ASSERT_NULL(allocator.AllocateNext()); OLA_ASSERT_NULL(allocator.AllocateNext()); // try another allocator that has a custom upper bound UIDAllocator bounded_allocator(uid, 0xffffff10); for (unsigned int i = 0xffffff00; i <= 0xffffff10; i++) { auto_ptr uid(bounded_allocator.AllocateNext()); OLA_ASSERT_NOT_NULL(uid.get()); OLA_ASSERT_EQ(i, uid->DeviceId()); } OLA_ASSERT_NULL(bounded_allocator.AllocateNext()); OLA_ASSERT_NULL(bounded_allocator.AllocateNext()); // confirm we never hand out the broadcast id UID uid2(1, 0xfffffff0); UIDAllocator bounded_allocator2(uid2, 0xffffffff); for (unsigned int i = 0xfffffff0; i < 0xffffffff; i++) { auto_ptr uid(bounded_allocator2.AllocateNext()); OLA_ASSERT_NOT_NULL(uid.get()); OLA_ASSERT_EQ(i, uid->DeviceId()); } OLA_ASSERT_NULL(bounded_allocator2.AllocateNext()); } ola-0.10.5.nojsmin/common/rdm/RDMCommandTest.cpp0000644000175000017500000012443413023355232021025 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * RDMCommandTest.cpp * Test fixture for the RDMCommand classes * Copyright (C) 2010 Simon Newton */ #include #include #include #include #include #include #include "common/rdm/TestHelper.h" #include "ola/Logging.h" #include "ola/base/Array.h" #include "ola/io/ByteString.h" #include "ola/network/NetworkUtils.h" #include "ola/rdm/RDMCommand.h" #include "ola/rdm/RDMCommandSerializer.h" #include "ola/rdm/RDMEnums.h" #include "ola/rdm/UID.h" #include "ola/util/Utils.h" #include "ola/testing/TestUtils.h" using ola::io::ByteString; using ola::rdm::RDMCommand; using ola::rdm::RDMCommandSerializer; using ola::rdm::RDMDiscoveryRequest; using ola::rdm::RDMDiscoveryResponse; using ola::rdm::RDMGetRequest; using ola::rdm::RDMGetResponse; using ola::rdm::RDMRequest; using ola::rdm::RDMResponse; using ola::rdm::RDMSetRequest; using ola::rdm::RDMSetResponse; using ola::rdm::UID; using ola::utils::SplitUInt16; using std::auto_ptr; using std::ostringstream; using std::string; /* * Calculate a checksum for a packet and update it */ void UpdateChecksum(uint8_t *expected, unsigned int expected_length) { unsigned int checksum = RDMCommand::START_CODE; for (unsigned int i = 0 ; i < expected_length - 2; i++) { checksum += expected[i]; } SplitUInt16(checksum, &expected[expected_length - 2], &expected[expected_length - 1]); } void UpdateChecksum(ByteString *data) { unsigned int checksum = RDMCommand::START_CODE; for (unsigned int i = 0 ; i < data->size() - 2; i++) { checksum += (*data)[i]; } SplitUInt16(checksum, &data->at(data->size() - 2), &data->at(data->size() - 1)); } class RDMCommandTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(RDMCommandTest); CPPUNIT_TEST(testGetRequestCreation); CPPUNIT_TEST(testGetWithExtraData); CPPUNIT_TEST(testSetWithParamData); CPPUNIT_TEST(testRequestOverrides); CPPUNIT_TEST(testRequestMutation); CPPUNIT_TEST(testRequestInflation); CPPUNIT_TEST(testResponseMutation); CPPUNIT_TEST(testResponseInflation); CPPUNIT_TEST(testNackWithReason); CPPUNIT_TEST(testGetResponseFromData); CPPUNIT_TEST(testCombineResponses); CPPUNIT_TEST(testDiscoveryCommand); CPPUNIT_TEST(testMuteRequest); CPPUNIT_TEST(testUnMuteRequest); CPPUNIT_TEST(testCommandInflation); CPPUNIT_TEST(testDiscoveryResponseInflation); CPPUNIT_TEST_SUITE_END(); public: RDMCommandTest() : m_source(1, 2), m_destination(3, 4) { } void setUp(); void testGetRequestCreation(); void testGetWithExtraData(); void testSetWithParamData(); void testRequestOverrides(); void testRequestMutation(); void testRequestInflation(); void testResponseMutation(); void testResponseInflation(); void testNackWithReason(); void testGetResponseFromData(); void testCombineResponses(); void testDiscoveryCommand(); void testMuteRequest(); void testUnMuteRequest(); void testCommandInflation(); void testDiscoveryResponseInflation(); private: UID m_source; UID m_destination; static uint8_t EXPECTED_GET_BUFFER[]; static uint8_t EXPECTED_SET_BUFFER[]; static uint8_t EXPECTED_GET_RESPONSE_BUFFER[]; static uint8_t EXPECTED_DISCOVERY_REQUEST[]; static uint8_t EXPECTED_MUTE_REQUEST[]; static uint8_t EXPECTED_UNMUTE_REQUEST[]; static uint8_t MUTE_RESPONSE[]; }; CPPUNIT_TEST_SUITE_REGISTRATION(RDMCommandTest); uint8_t RDMCommandTest::EXPECTED_GET_BUFFER[] = { 1, 24, // sub code & length 0, 3, 0, 0, 0, 4, // dst uid 0, 1, 0, 0, 0, 2, // src uid 0, 1, 0, 0, 10, // transaction, port id, msg count & sub device 0x20, 1, 40, 0, // command, param id, param data length 0, 0 // checksum, filled in below }; uint8_t RDMCommandTest::EXPECTED_SET_BUFFER[] = { 1, 28, // sub code & length 0, 3, 0, 0, 0, 4, // dst uid 0, 1, 0, 0, 0, 2, // src uid 0, 1, 0, 0, 10, // transaction, port id, msg count & sub device 0x30, 1, 40, 4, // command, param id, param data length 0xa5, 0xa5, 0xa5, 0xa5, // param data 0, 0 // checksum, filled in below }; uint8_t RDMCommandTest::EXPECTED_GET_RESPONSE_BUFFER[] = { 1, 28, // sub code & length 0, 3, 0, 0, 0, 4, // dst uid 0, 1, 0, 0, 0, 2, // src uid 0, 1, 0, 0, 10, // transaction, port id, msg count & sub device 0x21, 1, 40, 4, // command, param id, param data length 0x5a, 0x5a, 0x5a, 0x5a, // param data 0, 0 // checksum, filled in below }; uint8_t RDMCommandTest::EXPECTED_DISCOVERY_REQUEST[] = { 1, 36, // sub code & length 255, 255, 255, 255, 255, 255, // dst uid 0, 1, 0, 0, 0, 2, // src uid 1, 1, 0, 0, 0, // transaction, port id, msg count & sub device 0x10, 0, 1, 12, // command, param id, param data length 1, 2, 0, 0, 3, 4, // lower uid 5, 6, 0, 0, 7, 8, // upper uid 0, 0 // checksum, filled in below }; uint8_t RDMCommandTest::EXPECTED_MUTE_REQUEST[] = { 1, 24, // sub code & length 0, 3, 0, 0, 0, 4, // dst uid 0, 1, 0, 0, 0, 2, // src uid 1, 1, 0, 0, 0, // transaction, port id, msg count & sub device 0x10, 0, 2, 0, // command, param id, param data length 0, 0 // checksum, filled in below }; uint8_t RDMCommandTest::EXPECTED_UNMUTE_REQUEST[] = { 1, 24, // sub code & length 0, 3, 0, 0, 0, 4, // dst uid 0, 1, 0, 0, 0, 2, // src uid 1, 1, 0, 0, 0, // transaction, port id, msg count & sub device 0x10, 0, 3, 0, // command, param id, param data length 0, 0 // checksum, filled in below }; uint8_t RDMCommandTest::MUTE_RESPONSE[] = { 1, 24, // sub code & length 0, 1, 0, 0, 0, 2, // dst uid 0, 3, 0, 0, 0, 4, // src uid 1, 1, 0, 0, 0, // transaction, response type, msg count & sub device 0x11, 0, 2, 0, // command, param id, param data length 0, 0 // checksum, filled in below }; /* * Fill in the checksums */ void RDMCommandTest::setUp() { UpdateChecksum(EXPECTED_GET_BUFFER, sizeof(EXPECTED_GET_BUFFER)); UpdateChecksum(EXPECTED_SET_BUFFER, sizeof(EXPECTED_SET_BUFFER)); UpdateChecksum(EXPECTED_GET_RESPONSE_BUFFER, sizeof(EXPECTED_GET_RESPONSE_BUFFER)); UpdateChecksum(EXPECTED_DISCOVERY_REQUEST, sizeof(EXPECTED_DISCOVERY_REQUEST)); UpdateChecksum(EXPECTED_MUTE_REQUEST, sizeof(EXPECTED_MUTE_REQUEST)); UpdateChecksum(EXPECTED_UNMUTE_REQUEST, sizeof(EXPECTED_UNMUTE_REQUEST)); UpdateChecksum(MUTE_RESPONSE, sizeof(MUTE_RESPONSE)); } void RDMCommandTest::testGetRequestCreation() { RDMGetRequest command(m_source, m_destination, 0, // transaction # 1, // port id 10, // sub device 296, // param id NULL, // data 0); // data length OLA_ASSERT_EQ(ola::rdm::SUB_START_CODE, command.SubStartCode()); OLA_ASSERT_EQ((uint8_t) 24, command.MessageLength()); OLA_ASSERT_EQ(m_source, command.SourceUID()); OLA_ASSERT_EQ(m_destination, command.DestinationUID()); OLA_ASSERT_EQ((uint8_t) 0, command.TransactionNumber()); OLA_ASSERT_EQ((uint8_t) 1, command.PortIdResponseType()); OLA_ASSERT_EQ((uint8_t) 1, command.PortId()); OLA_ASSERT_EQ((uint8_t) 0, command.MessageCount()); OLA_ASSERT_EQ((uint16_t) 10, command.SubDevice()); OLA_ASSERT_EQ(RDMCommand::GET_COMMAND, command.CommandClass()); OLA_ASSERT_EQ((uint16_t) 296, command.ParamId()); OLA_ASSERT_NULL(command.ParamData()); OLA_ASSERT_EQ(0u, command.ParamDataSize()); OLA_ASSERT_EQ((uint16_t) 0, command.Checksum(0)); OLA_ASSERT_FALSE(command.IsDUB()); // Test ToString() and <<. ostringstream str; str << command; OLA_ASSERT_FALSE(str.str().empty()); OLA_ASSERT_EQ(str.str(), command.ToString()); } void RDMCommandTest::testGetWithExtraData() { uint8_t data[232]; memset(data, 0, arraysize(data)); RDMGetRequest command(m_source, m_destination, 1, // transaction # 1, // port id 10, // sub device 123, // param id data, // data arraysize(data)); // data length OLA_ASSERT_EQ(ola::rdm::SUB_START_CODE, command.SubStartCode()); OLA_ASSERT_EQ(m_source, command.SourceUID()); OLA_ASSERT_EQ(m_destination, command.DestinationUID()); OLA_ASSERT_EQ((uint8_t) 1, command.TransactionNumber()); OLA_ASSERT_EQ((uint8_t) 1, command.PortIdResponseType()); OLA_ASSERT_EQ((uint8_t) 1, command.PortId()); OLA_ASSERT_EQ((uint8_t) 0, command.MessageCount()); OLA_ASSERT_EQ((uint16_t) 10, command.SubDevice()); OLA_ASSERT_EQ(RDMCommand::GET_COMMAND, command.CommandClass()); OLA_ASSERT_EQ((uint16_t) 123, command.ParamId()); OLA_ASSERT_DATA_EQUALS(reinterpret_cast(&data), arraysize(data), command.ParamData(), command.ParamDataSize()); OLA_ASSERT_EQ((uint16_t) 0, command.Checksum(0)); OLA_ASSERT_FALSE(command.IsDUB()); } void RDMCommandTest::testSetWithParamData() { uint32_t data_value = 0xa5a5a5a5; RDMSetRequest command(m_source, m_destination, 3, // transaction # 1, // port id 13, // sub device 296, // param id reinterpret_cast(&data_value), // data sizeof(data_value)); // data length OLA_ASSERT_EQ(ola::rdm::SUB_START_CODE, command.SubStartCode()); OLA_ASSERT_EQ((uint8_t) 28, command.MessageLength()); OLA_ASSERT_EQ(m_source, command.SourceUID()); OLA_ASSERT_EQ(m_destination, command.DestinationUID()); OLA_ASSERT_EQ((uint8_t) 3, command.TransactionNumber()); OLA_ASSERT_EQ((uint8_t) 1, command.PortIdResponseType()); OLA_ASSERT_EQ((uint8_t) 1, command.PortId()); OLA_ASSERT_EQ((uint8_t) 0, command.MessageCount()); OLA_ASSERT_EQ((uint16_t) 13, command.SubDevice()); OLA_ASSERT_EQ(RDMCommand::SET_COMMAND, command.CommandClass()); OLA_ASSERT_EQ((uint16_t) 296, command.ParamId()); OLA_ASSERT_DATA_EQUALS(reinterpret_cast(&data_value), sizeof(data_value), command.ParamData(), command.ParamDataSize()); OLA_ASSERT_EQ((uint16_t) 0, command.Checksum(0)); OLA_ASSERT_FALSE(command.IsDUB()); } void RDMCommandTest::testRequestOverrides() { RDMRequest::OverrideOptions options; options.SetMessageLength(10); options.SetChecksum(999); options.sub_start_code = 5; options.message_count = 9; RDMGetRequest command(m_source, m_destination, 0, // transaction # 1, // port id 10, // sub device 296, // param id NULL, // data 0, // data length options); OLA_ASSERT_EQ((uint8_t) 5, command.SubStartCode()); OLA_ASSERT_EQ((uint8_t) 10, command.MessageLength()); OLA_ASSERT_EQ(m_source, command.SourceUID()); OLA_ASSERT_EQ(m_destination, command.DestinationUID()); OLA_ASSERT_EQ((uint8_t) 0, command.TransactionNumber()); OLA_ASSERT_EQ((uint8_t) 1, command.PortId()); OLA_ASSERT_EQ((uint8_t) 9, command.MessageCount()); OLA_ASSERT_EQ((uint16_t) 10, command.SubDevice()); OLA_ASSERT_EQ(RDMCommand::GET_COMMAND, command.CommandClass()); OLA_ASSERT_EQ((uint16_t) 296, command.ParamId()); OLA_ASSERT_NULL(command.ParamData()); OLA_ASSERT_EQ(0u, command.ParamDataSize()); OLA_ASSERT_EQ((uint16_t) 999u, command.Checksum(0)); } void RDMCommandTest::testRequestMutation() { UID new_uid(5, 6); RDMGetRequest command(m_source, m_destination, 0, // transaction # 1, // port id 10, // sub device 296, // param id NULL, // data 0); command.SetSourceUID(new_uid); command.SetTransactionNumber(99); command.SetPortId(5); OLA_ASSERT_EQ(ola::rdm::SUB_START_CODE, command.SubStartCode()); OLA_ASSERT_EQ((uint8_t) 24, command.MessageLength()); OLA_ASSERT_EQ(new_uid, command.SourceUID()); OLA_ASSERT_EQ(m_destination, command.DestinationUID()); OLA_ASSERT_EQ((uint8_t) 99, command.TransactionNumber()); OLA_ASSERT_EQ((uint8_t) 5, command.PortIdResponseType()); OLA_ASSERT_EQ((uint8_t) 5, command.PortId()); OLA_ASSERT_EQ((uint8_t) 0, command.MessageCount()); OLA_ASSERT_EQ((uint16_t) 10, command.SubDevice()); OLA_ASSERT_EQ(RDMCommand::GET_COMMAND, command.CommandClass()); OLA_ASSERT_EQ((uint16_t) 296, command.ParamId()); OLA_ASSERT_NULL(command.ParamData()); OLA_ASSERT_EQ(0u, command.ParamDataSize()); OLA_ASSERT_EQ((uint16_t) 0, command.Checksum(0)); OLA_ASSERT_FALSE(command.IsDUB()); } /* * Test that we can inflate RDM request messages correctly */ void RDMCommandTest::testRequestInflation() { UID source(1, 2); UID destination(3, 4); auto_ptr command(RDMRequest::InflateFromData(NULL, 10)); OLA_ASSERT_NULL(command.get()); // now try a proper command but with no length command.reset(RDMRequest::InflateFromData(EXPECTED_GET_BUFFER, 0)); OLA_ASSERT_NULL(command.get()); // Try a valid command command.reset(RDMRequest::InflateFromData(EXPECTED_GET_BUFFER, arraysize(EXPECTED_GET_BUFFER))); OLA_ASSERT_NOT_NULL(command.get()); RDMGetRequest expected_command(source, destination, 0, // transaction # 1, // port id 10, // sub device 296, // param id NULL, // data 0); // data length OLA_ASSERT_TRUE(expected_command == *command); // An invalid Command class ByteString invalid_command(EXPECTED_GET_BUFFER, arraysize(EXPECTED_GET_BUFFER)); invalid_command[19] = 0x44; command.reset(RDMRequest::InflateFromData(invalid_command.data(), invalid_command.size())); OLA_ASSERT_NULL(command.get()); // A SET request command.reset(RDMRequest::InflateFromData(EXPECTED_SET_BUFFER, arraysize(EXPECTED_SET_BUFFER))); OLA_ASSERT_NOT_NULL(command.get()); uint8_t expected_data[] = {0xa5, 0xa5, 0xa5, 0xa5}; OLA_ASSERT_DATA_EQUALS(expected_data, arraysize(expected_data), command->ParamData(), command->ParamDataSize()); // Change the param length and make sure the checksum fails ByteString bad_packet(EXPECTED_GET_BUFFER, arraysize(EXPECTED_GET_BUFFER)); bad_packet[22] = 255; command.reset(RDMRequest::InflateFromData(bad_packet.data(), bad_packet.size())); OLA_ASSERT_NULL(command.get()); // Make sure we can't pass a bad param length larger than the buffer UpdateChecksum(&bad_packet); command.reset(RDMRequest::InflateFromData(bad_packet.data(), bad_packet.size())); OLA_ASSERT_NULL(command.get()); // Change the param length of another packet and make sure the checksum fails bad_packet.assign(EXPECTED_SET_BUFFER, arraysize(EXPECTED_SET_BUFFER)); bad_packet[22] = 5; UpdateChecksum(&bad_packet); command.reset(RDMRequest::InflateFromData(bad_packet.data(), bad_packet.size())); OLA_ASSERT_NULL(command.get()); // A non-0 length with a NULL pointer command.reset(RDMRequest::InflateFromData(NULL, 32)); OLA_ASSERT_NULL(command.get()); // Try to inflate a response command.reset(RDMRequest::InflateFromData( EXPECTED_GET_RESPONSE_BUFFER, arraysize(EXPECTED_GET_RESPONSE_BUFFER))); OLA_ASSERT_NULL(command.get()); } void RDMCommandTest::testResponseMutation() { UID new_uid(5, 6); RDMGetResponse command(m_source, m_destination, 0, // transaction # 0, // response type 0, // message count 10, // sub device 100, // param id NULL, // data 0); command.SetDestinationUID(new_uid); command.SetTransactionNumber(99); OLA_ASSERT_EQ(ola::rdm::SUB_START_CODE, command.SubStartCode()); OLA_ASSERT_EQ((uint8_t) 24, command.MessageLength()); OLA_ASSERT_EQ(m_source, command.SourceUID()); OLA_ASSERT_EQ(new_uid, command.DestinationUID()); OLA_ASSERT_EQ((uint8_t) 99, command.TransactionNumber()); OLA_ASSERT_EQ((uint8_t) 0, command.PortIdResponseType()); OLA_ASSERT_EQ((uint8_t) 0, command.MessageCount()); OLA_ASSERT_EQ((uint16_t) 10, command.SubDevice()); OLA_ASSERT_EQ(RDMCommand::GET_COMMAND_RESPONSE, command.CommandClass()); OLA_ASSERT_EQ((uint16_t) 100, command.ParamId()); OLA_ASSERT_NULL(command.ParamData()); OLA_ASSERT_EQ(0u, command.ParamDataSize()); OLA_ASSERT_EQ((uint16_t) 0, command.Checksum(0)); } /* * Test that we can inflate RDM response correctly */ void RDMCommandTest::testResponseInflation() { UID source(1, 2); UID destination(3, 4); ola::rdm::RDMStatusCode code; RDMResponse *command = RDMResponse::InflateFromData(NULL, 10, &code); OLA_ASSERT_NULL(command); OLA_ASSERT_EQ(ola::rdm::RDM_PACKET_TOO_SHORT, code); ByteString empty_string; command = RDMResponse::InflateFromData(empty_string, &code); OLA_ASSERT_EQ(ola::rdm::RDM_PACKET_TOO_SHORT, code); OLA_ASSERT_NULL(command); command = RDMResponse::InflateFromData(EXPECTED_GET_RESPONSE_BUFFER, 0, &code); OLA_ASSERT_EQ(ola::rdm::RDM_PACKET_TOO_SHORT, code); OLA_ASSERT_NULL(command); command = RDMResponse::InflateFromData( EXPECTED_GET_RESPONSE_BUFFER, sizeof(EXPECTED_GET_RESPONSE_BUFFER), &code); OLA_ASSERT_NOT_NULL(command); OLA_ASSERT_EQ(ola::rdm::RDM_COMPLETED_OK, code); uint8_t expected_data[] = {0x5a, 0x5a, 0x5a, 0x5a}; OLA_ASSERT_EQ(4u, command->ParamDataSize()); OLA_ASSERT_EQ(0, memcmp(expected_data, command->ParamData(), command->ParamDataSize())); uint32_t data_value = 0x5a5a5a5a; RDMGetResponse expected_command(source, destination, 0, // transaction # 1, // port id 0, // message count 10, // sub device 296, // param id reinterpret_cast(&data_value), sizeof(data_value)); // data length OLA_ASSERT_TRUE(expected_command == *command); delete command; // now try from a string ByteString response_string(EXPECTED_GET_RESPONSE_BUFFER, sizeof(EXPECTED_GET_RESPONSE_BUFFER)); command = RDMResponse::InflateFromData(response_string, &code); OLA_ASSERT_EQ(ola::rdm::RDM_COMPLETED_OK, code); OLA_ASSERT_NOT_NULL(command); OLA_ASSERT_EQ(4u, command->ParamDataSize()); OLA_ASSERT_EQ(0, memcmp(expected_data, command->ParamData(), command->ParamDataSize())); OLA_ASSERT_TRUE(expected_command == *command); delete command; // change the param length and make sure the checksum fails uint8_t *bad_packet = new uint8_t[arraysize(EXPECTED_GET_RESPONSE_BUFFER)]; memcpy(bad_packet, EXPECTED_GET_RESPONSE_BUFFER, arraysize(EXPECTED_GET_RESPONSE_BUFFER)); bad_packet[22] = 255; command = RDMResponse::InflateFromData( bad_packet, arraysize(EXPECTED_GET_RESPONSE_BUFFER), &code); OLA_ASSERT_EQ(ola::rdm::RDM_CHECKSUM_INCORRECT, code); OLA_ASSERT_NULL(command); // now make sure we can't pass a bad param length larger than the buffer UpdateChecksum(bad_packet, sizeof(EXPECTED_GET_RESPONSE_BUFFER)); command = RDMResponse::InflateFromData( bad_packet, sizeof(EXPECTED_GET_RESPONSE_BUFFER), &code); OLA_ASSERT_EQ(ola::rdm::RDM_PARAM_LENGTH_MISMATCH, code); OLA_ASSERT_NULL(command); delete[] bad_packet; // change the param length of another packet and make sure the checksum fails bad_packet = new uint8_t[sizeof(EXPECTED_SET_BUFFER)]; memcpy(bad_packet, EXPECTED_SET_BUFFER, sizeof(EXPECTED_SET_BUFFER)); bad_packet[22] = 5; UpdateChecksum(bad_packet, sizeof(EXPECTED_SET_BUFFER)); command = RDMResponse::InflateFromData( bad_packet, sizeof(EXPECTED_SET_BUFFER), &code); OLA_ASSERT_EQ(ola::rdm::RDM_PARAM_LENGTH_MISMATCH, code); OLA_ASSERT_NULL(command); delete[] bad_packet; // now try to inflate a request command = RDMResponse::InflateFromData( EXPECTED_GET_BUFFER, sizeof(EXPECTED_GET_BUFFER), &code); OLA_ASSERT_NULL(command); ByteString request_string(EXPECTED_GET_BUFFER, arraysize(EXPECTED_GET_BUFFER)); command = RDMResponse::InflateFromData(request_string, &code); OLA_ASSERT_EQ(ola::rdm::RDM_INVALID_COMMAND_CLASS, code); OLA_ASSERT_NULL(command); } /** * Test that we can build nack messages */ void RDMCommandTest::testNackWithReason() { UID source(1, 2); UID destination(3, 4); RDMGetRequest get_command(source, destination, 0, // transaction # 1, // port id 10, // sub device 296, // param id NULL, // data 0); // data length auto_ptr response( NackWithReason(&get_command, ola::rdm::NR_UNKNOWN_PID)); OLA_ASSERT_NOT_NULL(response.get()); OLA_ASSERT_EQ(destination, response->SourceUID()); OLA_ASSERT_EQ(source, response->DestinationUID()); OLA_ASSERT_EQ((uint8_t) 0, response->TransactionNumber()); OLA_ASSERT_EQ((uint8_t) ola::rdm::RDM_NACK_REASON, response->ResponseType()); OLA_ASSERT_EQ((uint8_t) 0, response->MessageCount()); OLA_ASSERT_EQ((uint16_t) 10, response->SubDevice()); OLA_ASSERT_EQ(RDMCommand::GET_COMMAND_RESPONSE, response->CommandClass()); OLA_ASSERT_EQ((uint16_t) 296, response->ParamId()); OLA_ASSERT_EQ(2u, response->ParamDataSize()); OLA_ASSERT_EQ((uint16_t) ola::rdm::NR_UNKNOWN_PID, NackReasonFromResponse(response.get())); response.reset(NackWithReason(&get_command, ola::rdm::NR_SUB_DEVICE_OUT_OF_RANGE)); OLA_ASSERT_NOT_NULL(response.get()); OLA_ASSERT_EQ(destination, response->SourceUID()); OLA_ASSERT_EQ(source, response->DestinationUID()); OLA_ASSERT_EQ((uint8_t) 0, response->TransactionNumber()); OLA_ASSERT_EQ((uint8_t) ola::rdm::RDM_NACK_REASON, response->ResponseType()); OLA_ASSERT_EQ((uint8_t) 0, response->MessageCount()); OLA_ASSERT_EQ((uint16_t) 10, response->SubDevice()); OLA_ASSERT_EQ(RDMCommand::GET_COMMAND_RESPONSE, response->CommandClass()); OLA_ASSERT_EQ((uint16_t) 296, response->ParamId()); OLA_ASSERT_EQ(2u, response->ParamDataSize()); OLA_ASSERT_EQ((uint16_t) ola::rdm::NR_SUB_DEVICE_OUT_OF_RANGE, NackReasonFromResponse(response.get())); RDMSetRequest set_command(source, destination, 0, // transaction # 1, // port id 10, // sub device 296, // param id NULL, // data 0); // data length response.reset(NackWithReason(&set_command, ola::rdm::NR_WRITE_PROTECT)); OLA_ASSERT_NOT_NULL(response.get()); OLA_ASSERT_EQ(destination, response->SourceUID()); OLA_ASSERT_EQ(source, response->DestinationUID()); OLA_ASSERT_EQ((uint8_t) 0, response->TransactionNumber()); OLA_ASSERT_EQ((uint8_t) ola::rdm::RDM_NACK_REASON, response->ResponseType()); OLA_ASSERT_EQ((uint8_t) 0, response->MessageCount()); OLA_ASSERT_EQ((uint16_t) 10, response->SubDevice()); OLA_ASSERT_EQ(RDMCommand::SET_COMMAND_RESPONSE, response->CommandClass()); OLA_ASSERT_EQ((uint16_t) 296, response->ParamId()); OLA_ASSERT_EQ(2u, response->ParamDataSize()); OLA_ASSERT_EQ((uint16_t) ola::rdm::NR_WRITE_PROTECT, NackReasonFromResponse(response.get())); } void RDMCommandTest::testGetResponseFromData() { UID source(1, 2); UID destination(3, 4); RDMGetRequest get_command(source, destination, 0, // transaction # 1, // port id 10, // sub device 296, // param id NULL, // data 0); // data length RDMResponse *response = GetResponseFromData(&get_command, NULL, 0); OLA_ASSERT_NOT_NULL(response); OLA_ASSERT_EQ(destination, response->SourceUID()); OLA_ASSERT_EQ(source, response->DestinationUID()); OLA_ASSERT_EQ((uint8_t) 0, response->TransactionNumber()); OLA_ASSERT_EQ((uint8_t) ola::rdm::RDM_ACK, response->ResponseType()); OLA_ASSERT_EQ((uint8_t) 0, response->MessageCount()); OLA_ASSERT_EQ((uint16_t) 10, response->SubDevice()); OLA_ASSERT_EQ(RDMCommand::GET_COMMAND_RESPONSE, response->CommandClass()); OLA_ASSERT_EQ((uint16_t) 296, response->ParamId()); OLA_ASSERT_NULL(response->ParamData()); OLA_ASSERT_EQ(0u, response->ParamDataSize()); delete response; RDMSetRequest set_command(source, destination, 0, // transaction # 1, // port id 10, // sub device 296, // param id NULL, // data 0); // data length response = GetResponseFromData(&set_command, NULL, 0); OLA_ASSERT_NOT_NULL(response); OLA_ASSERT_EQ(destination, response->SourceUID()); OLA_ASSERT_EQ(source, response->DestinationUID()); OLA_ASSERT_EQ((uint8_t) 0, response->TransactionNumber()); OLA_ASSERT_EQ((uint8_t) ola::rdm::RDM_ACK, response->ResponseType()); OLA_ASSERT_EQ((uint8_t) 0, response->MessageCount()); OLA_ASSERT_EQ((uint16_t) 10, response->SubDevice()); OLA_ASSERT_EQ(RDMCommand::SET_COMMAND_RESPONSE, response->CommandClass()); OLA_ASSERT_EQ((uint16_t) 296, response->ParamId()); OLA_ASSERT_NULL(response->ParamData()); OLA_ASSERT_EQ(0u, response->ParamDataSize()); delete response; uint32_t data_value = 0xa5a5a5a5; response = GetResponseFromData( &get_command, reinterpret_cast(&data_value), sizeof(data_value)); OLA_ASSERT_NOT_NULL(response); OLA_ASSERT_EQ(destination, response->SourceUID()); OLA_ASSERT_EQ(source, response->DestinationUID()); OLA_ASSERT_EQ((uint8_t) 0, response->TransactionNumber()); OLA_ASSERT_EQ((uint8_t) ola::rdm::RDM_ACK, response->ResponseType()); OLA_ASSERT_EQ((uint8_t) 0, response->MessageCount()); OLA_ASSERT_EQ((uint16_t) 10, response->SubDevice()); OLA_ASSERT_EQ(RDMCommand::GET_COMMAND_RESPONSE, response->CommandClass()); OLA_ASSERT_EQ((uint16_t) 296, response->ParamId()); OLA_ASSERT_EQ(data_value, *(reinterpret_cast(response->ParamData()))); OLA_ASSERT_EQ((unsigned int) sizeof(data_value), response->ParamDataSize()); delete response; } /** * Check that CombineResponses() works. */ void RDMCommandTest::testCombineResponses() { UID source(1, 2); UID destination(3, 4); uint16_t param_id = 296; uint32_t data_value = 0x5a5a5a5a; RDMGetResponse response1(source, destination, 0, // transaction # ola::rdm::RDM_ACK, // response type 0, // message count 10, // sub device param_id, // param id reinterpret_cast(&data_value), sizeof(data_value)); // data length uint32_t data_value2 = 0xa5a5a5a5; RDMGetResponse response2(source, destination, 1, // transaction # ola::rdm::RDM_ACK, // response type 0, // message count 10, // sub device param_id, // param id reinterpret_cast(&data_value2), sizeof(data_value2)); // data length const RDMResponse *combined_response = RDMResponse::CombineResponses( &response1, &response2); OLA_ASSERT_NOT_NULL(combined_response); OLA_ASSERT_EQ(RDMCommand::GET_COMMAND_RESPONSE, combined_response->CommandClass()); OLA_ASSERT_EQ(source, combined_response->SourceUID()); OLA_ASSERT_EQ(destination, combined_response->DestinationUID()); OLA_ASSERT_EQ((uint8_t) 0, combined_response->TransactionNumber()); OLA_ASSERT_EQ((uint8_t) 0, combined_response->MessageCount()); OLA_ASSERT_EQ((uint16_t) 10, combined_response->SubDevice()); OLA_ASSERT_EQ(param_id, combined_response->ParamId()); OLA_ASSERT_EQ(8u, combined_response->ParamDataSize()); const uint8_t *combined_data = combined_response->ParamData(); const uint32_t expected_data[] = {0x5a5a5a5a, 0xa5a5a5a5}; OLA_ASSERT_EQ(0, memcmp(expected_data, combined_data, sizeof(expected_data))); delete combined_response; // try to combine with a response with no data RDMGetResponse response3(source, destination, 1, // transaction # ola::rdm::RDM_ACK, // response type 0, // message count 10, // sub device param_id, // param id NULL, 0); combined_response = RDMResponse::CombineResponses( &response1, &response3); OLA_ASSERT_NOT_NULL(combined_response); OLA_ASSERT_EQ(RDMCommand::GET_COMMAND_RESPONSE, combined_response->CommandClass()); OLA_ASSERT_EQ(source, combined_response->SourceUID()); OLA_ASSERT_EQ(destination, combined_response->DestinationUID()); OLA_ASSERT_EQ((uint8_t) 0, combined_response->TransactionNumber()); OLA_ASSERT_EQ((uint8_t) 0, combined_response->MessageCount()); OLA_ASSERT_EQ((uint16_t) 10, combined_response->SubDevice()); OLA_ASSERT_EQ(param_id, combined_response->ParamId()); OLA_ASSERT_EQ(4u, combined_response->ParamDataSize()); combined_data = combined_response->ParamData(); OLA_ASSERT_EQ(data_value, *(reinterpret_cast(combined_data))); delete combined_response; // combining a GetResponse with a SetResponse is invalid RDMSetResponse response4(source, destination, 1, // transaction # ola::rdm::RDM_ACK, // response type 0, // message count 10, // sub device param_id, // param id NULL, 0); combined_response = RDMResponse::CombineResponses( &response1, &response4); OLA_ASSERT_FALSE(combined_response); combined_response = RDMResponse::CombineResponses( &response4, &response1); OLA_ASSERT_FALSE(combined_response); // combine two set responses RDMSetResponse response5(source, destination, 0, // transaction # ola::rdm::RDM_ACK, // response type 0, // message count 10, // sub device param_id, // param id reinterpret_cast(&data_value), sizeof(data_value)); // data length combined_response = RDMResponse::CombineResponses( &response5, &response4); OLA_ASSERT_NOT_NULL(combined_response); OLA_ASSERT_EQ(RDMCommand::SET_COMMAND_RESPONSE, combined_response->CommandClass()); OLA_ASSERT_EQ(source, combined_response->SourceUID()); OLA_ASSERT_EQ(destination, combined_response->DestinationUID()); OLA_ASSERT_EQ((uint8_t) 0, combined_response->TransactionNumber()); OLA_ASSERT_EQ((uint8_t) 0, combined_response->MessageCount()); OLA_ASSERT_EQ((uint16_t) 10, combined_response->SubDevice()); OLA_ASSERT_EQ(param_id, combined_response->ParamId()); OLA_ASSERT_EQ(4u, combined_response->ParamDataSize()); combined_data = combined_response->ParamData(); OLA_ASSERT_EQ(data_value, *(reinterpret_cast(combined_data))); delete combined_response; // combine two responses so that the size exceeds 231 bytes const unsigned int first_block_size = 200; const unsigned int second_block_size = 100; uint8_t data_block1[first_block_size]; uint8_t data_block2[second_block_size]; uint8_t expected_combined_data[first_block_size + second_block_size]; memset(data_block1, 0xff, first_block_size); memset(data_block2, 0xac, second_block_size); memcpy(expected_combined_data, data_block1, first_block_size); memcpy(expected_combined_data + first_block_size, data_block2, second_block_size); RDMSetResponse response6(source, destination, 0, // transaction # ola::rdm::RDM_ACK, // response type 0, // message count 10, // sub device param_id, // param id data_block1, sizeof(data_block1)); RDMSetResponse response7(source, destination, 1, // transaction # ola::rdm::RDM_ACK, // response type 0, // message count 10, // sub device param_id, // param id data_block2, sizeof(data_block2)); combined_response = RDMResponse::CombineResponses( &response6, &response7); OLA_ASSERT_NOT_NULL(combined_response); OLA_ASSERT_EQ(RDMCommand::SET_COMMAND_RESPONSE, combined_response->CommandClass()); OLA_ASSERT_EQ(source, combined_response->SourceUID()); OLA_ASSERT_EQ(destination, combined_response->DestinationUID()); OLA_ASSERT_EQ((uint8_t) 0, combined_response->TransactionNumber()); OLA_ASSERT_EQ((uint8_t) 0, combined_response->MessageCount()); OLA_ASSERT_EQ((uint16_t) 10, combined_response->SubDevice()); OLA_ASSERT_EQ(param_id, combined_response->ParamId()); OLA_ASSERT_EQ(300u, combined_response->ParamDataSize()); OLA_ASSERT_DATA_EQUALS(expected_combined_data, first_block_size + second_block_size, combined_response->ParamData(), combined_response->ParamDataSize()); delete combined_response; } /** * Check the discovery command */ void RDMCommandTest::testDiscoveryCommand() { UID lower(0x0102, 0x0304); UID upper(0x0506, 0x0708); const uint8_t expected_data[] = { 1, 2, 0, 0, 3, 4, 5, 6, 0, 0, 7, 8 }; auto_ptr request( NewDiscoveryUniqueBranchRequest(m_source, lower, upper, 1)); OLA_ASSERT_EQ(RDMCommand::DISCOVER_COMMAND, request->CommandClass()); OLA_ASSERT_EQ(ola::rdm::SUB_START_CODE, request->SubStartCode()); OLA_ASSERT_EQ((uint8_t) 36, request->MessageLength()); OLA_ASSERT_EQ(m_source, request->SourceUID()); OLA_ASSERT_EQ(UID::AllDevices(), request->DestinationUID()); OLA_ASSERT_EQ((uint8_t) 1, request->TransactionNumber()); OLA_ASSERT_EQ((uint8_t) 1, request->PortIdResponseType()); OLA_ASSERT_EQ((uint8_t) 1, request->PortId()); OLA_ASSERT_EQ((uint8_t) 0, request->MessageCount()); OLA_ASSERT_EQ((uint16_t) 0, request->SubDevice()); OLA_ASSERT_EQ(RDMCommand::DISCOVER_COMMAND, request->CommandClass()); OLA_ASSERT_EQ((uint16_t) 0x0001, request->ParamId()); OLA_ASSERT_DATA_EQUALS(expected_data, arraysize(expected_data), request->ParamData(), request->ParamDataSize()); OLA_ASSERT_EQ((uint16_t) 0, request->Checksum(0)); OLA_ASSERT_TRUE(request->IsDUB()); } /** * Check the mute command */ void RDMCommandTest::testMuteRequest() { auto_ptr request( NewMuteRequest(m_source, m_destination, 1)); OLA_ASSERT_EQ(ola::rdm::SUB_START_CODE, request->SubStartCode()); OLA_ASSERT_EQ((uint8_t) 24, request->MessageLength()); OLA_ASSERT_EQ(m_source, request->SourceUID()); OLA_ASSERT_EQ(m_destination, request->DestinationUID()); OLA_ASSERT_EQ((uint8_t) 1, request->TransactionNumber()); OLA_ASSERT_EQ((uint8_t) 1, request->PortIdResponseType()); OLA_ASSERT_EQ((uint8_t) 1, request->PortId()); OLA_ASSERT_EQ((uint8_t) 0, request->MessageCount()); OLA_ASSERT_EQ((uint16_t) 0, request->SubDevice()); OLA_ASSERT_EQ(RDMCommand::DISCOVER_COMMAND, request->CommandClass()); OLA_ASSERT_EQ((uint16_t) 0x0002, request->ParamId()); OLA_ASSERT_NULL(request->ParamData()); OLA_ASSERT_EQ(0u, request->ParamDataSize()); OLA_ASSERT_EQ((uint16_t) 0, request->Checksum(0)); OLA_ASSERT_FALSE(request->IsDUB()); } /** * Check the UnMute Command */ void RDMCommandTest::testUnMuteRequest() { auto_ptr request( NewUnMuteRequest(m_source, m_destination, 1)); OLA_ASSERT_EQ(ola::rdm::SUB_START_CODE, request->SubStartCode()); OLA_ASSERT_EQ((uint8_t) 24, request->MessageLength()); OLA_ASSERT_EQ(m_source, request->SourceUID()); OLA_ASSERT_EQ(m_destination, request->DestinationUID()); OLA_ASSERT_EQ((uint8_t) 1, request->TransactionNumber()); OLA_ASSERT_EQ((uint8_t) 1, request->PortIdResponseType()); OLA_ASSERT_EQ((uint8_t) 1, request->PortId()); OLA_ASSERT_EQ((uint8_t) 0, request->MessageCount()); OLA_ASSERT_EQ((uint16_t) 0, request->SubDevice()); OLA_ASSERT_EQ(RDMCommand::DISCOVER_COMMAND, request->CommandClass()); OLA_ASSERT_EQ((uint16_t) 0x0003, request->ParamId()); OLA_ASSERT_NULL(request->ParamData()); OLA_ASSERT_EQ(0u, request->ParamDataSize()); OLA_ASSERT_EQ((uint16_t) 0, request->Checksum(0)); OLA_ASSERT_FALSE(request->IsDUB()); } /** * Test that the generic InflateFromData method works. */ void RDMCommandTest::testCommandInflation() { const UID source(1, 2); const UID destination(3, 4); const UID lower(0x0102, 0x0304); const UID upper(0x0506, 0x0708); auto_ptr command(RDMCommand::Inflate(NULL, 10)); OLA_ASSERT_NULL(command.get()); command.reset(RDMCommand::Inflate(EXPECTED_GET_BUFFER, 0)); OLA_ASSERT_NULL(command.get()); command.reset(RDMRequest::Inflate(EXPECTED_GET_BUFFER, sizeof(EXPECTED_GET_BUFFER))); OLA_ASSERT_NOT_NULL(command.get()); RDMGetRequest expected_request(source, destination, 0, // transaction # 1, // port id 10, // sub device 296, // param id NULL, // data 0); // data length OLA_ASSERT_TRUE(expected_request == *command); command.reset(RDMCommand::Inflate(EXPECTED_SET_BUFFER, sizeof(EXPECTED_SET_BUFFER))); OLA_ASSERT_NOT_NULL(command.get()); uint8_t expected_data[] = {0xa5, 0xa5, 0xa5, 0xa5}; OLA_ASSERT_EQ(4u, command->ParamDataSize()); OLA_ASSERT_EQ(0, memcmp(expected_data, command->ParamData(), command->ParamDataSize())); // now try a response. command.reset(RDMCommand::Inflate(EXPECTED_GET_RESPONSE_BUFFER, sizeof(EXPECTED_GET_RESPONSE_BUFFER))); OLA_ASSERT_NOT_NULL(command.get()); uint8_t expected_data2[] = {0x5a, 0x5a, 0x5a, 0x5a}; OLA_ASSERT_EQ(4u, command->ParamDataSize()); OLA_ASSERT_EQ(0, memcmp(expected_data2, command->ParamData(), command->ParamDataSize())); uint32_t data_value = 0x5a5a5a5a; RDMGetResponse expected_response(source, destination, 0, // transaction # 1, // port id 0, // message count 10, // sub device 296, // param id reinterpret_cast(&data_value), sizeof(data_value)); // data length OLA_ASSERT_TRUE(expected_response == *command); // test DUB command.reset(RDMCommand::Inflate(EXPECTED_DISCOVERY_REQUEST, sizeof(EXPECTED_DISCOVERY_REQUEST))); OLA_ASSERT_NOT_NULL(command.get()); auto_ptr discovery_request( NewDiscoveryUniqueBranchRequest(source, lower, upper, 1)); OLA_ASSERT_TRUE(*discovery_request == *command); // test mute command.reset(RDMCommand::Inflate(EXPECTED_MUTE_REQUEST, sizeof(EXPECTED_MUTE_REQUEST))); OLA_ASSERT_NOT_NULL(command.get()); discovery_request.reset(NewMuteRequest(source, destination, 1)); OLA_ASSERT_TRUE(*discovery_request == *command); // test unmute command.reset(RDMCommand::Inflate(EXPECTED_UNMUTE_REQUEST, sizeof(EXPECTED_UNMUTE_REQUEST))); OLA_ASSERT_NOT_NULL(command.get()); discovery_request.reset(NewUnMuteRequest(source, destination, 1)); OLA_ASSERT_TRUE(*discovery_request == *command); } void RDMCommandTest::testDiscoveryResponseInflation() { auto_ptr command; command.reset(RDMRequest::Inflate(MUTE_RESPONSE, arraysize(MUTE_RESPONSE))); OLA_ASSERT_NOT_NULL(command.get()); OLA_ASSERT_EQ(RDMCommand::DISCOVER_COMMAND_RESPONSE, command->CommandClass()); OLA_ASSERT_EQ((uint16_t) 2, command->ParamId()); OLA_ASSERT_EQ(0u, command->ParamDataSize()); } ola-0.10.5.nojsmin/common/rdm/RDMReply.cpp0000644000175000017500000000556413023355232017704 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * RDMReply.cpp * The RDMReply object. * Copyright (C) 2015 Simon Newton */ #include "ola/rdm/RDMReply.h" #include #include #include #include using ola::rdm::RDMResponse; namespace { bool ResponsesAreEqual(const RDMResponse *response1, const RDMResponse *response2) { if (response1 == NULL && response2 == NULL) { return true; } if (response1 == NULL || response2 == NULL) { return false; } return *response1 == *response2; } } // namespace namespace ola { namespace rdm { RDMReply::RDMReply(RDMStatusCode status_code) : m_status_code(status_code) { } RDMReply::RDMReply(RDMStatusCode status_code, RDMResponse *response) : m_status_code(status_code), m_response(response) { } RDMReply::RDMReply(RDMStatusCode status_code, RDMResponse *response, const RDMFrames &frames) : m_status_code(status_code), m_response(response), m_frames(frames) { } bool RDMReply::operator==(const RDMReply &other) const { return (m_status_code == other.m_status_code && ResponsesAreEqual(m_response.get(), other.m_response.get()) && m_frames == other.m_frames); } std::string RDMReply::ToString() const { std::ostringstream str; str << StatusCodeToString(m_status_code); if (m_response.get()) { str << ": " << *m_response.get(); } return str.str(); } RDMReply* RDMReply::FromFrame(const RDMFrame &frame, const RDMRequest *request) { RDMFrames frames; frames.push_back(frame); ola::rdm::RDMStatusCode status_code = RDM_INVALID_RESPONSE; RDMResponse *response = NULL; if (frame.data.size() > 1) { // Skip over the start code. response = ola::rdm::RDMResponse::InflateFromData( frame.data.data() + 1, frame.data.size() - 1, &status_code, request); } return new RDMReply(status_code, response, frames); } RDMReply* RDMReply::DUBReply(const RDMFrame &frame) { RDMFrames frames; frames.push_back(frame); return new RDMReply(ola::rdm::RDM_DUB_RESPONSE, NULL, frames); } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/NetworkResponder.cpp0000644000175000017500000001751013023355232021553 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * NetworkResponder.cpp * Copyright (C) 2013 Peter Newman */ #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #include #include #include "common/rdm/FakeNetworkManager.h" #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/base/Array.h" #include "ola/network/IPV4Address.h" #include "ola/network/InterfacePicker.h" #include "ola/network/MACAddress.h" #include "ola/network/NetworkUtils.h" #include "ola/rdm/NetworkResponder.h" #include "ola/rdm/OpenLightingEnums.h" #include "ola/rdm/RDMEnums.h" #include "ola/rdm/ResponderHelper.h" #include "ola/stl/STLUtils.h" namespace ola { namespace rdm { using ola::network::HostToNetwork; using ola::network::Interface; using ola::network::InterfacePicker; using ola::network::IPV4Address; using ola::network::MACAddress; using ola::network::NetworkToHost; using std::string; using std::vector; using std::auto_ptr; NetworkResponder::RDMOps *NetworkResponder::RDMOps::instance = NULL; const ResponderOps::ParamHandler NetworkResponder::PARAM_HANDLERS[] = { { PID_DEVICE_INFO, &NetworkResponder::GetDeviceInfo, NULL}, { PID_PRODUCT_DETAIL_ID_LIST, &NetworkResponder::GetProductDetailList, NULL}, { PID_DEVICE_MODEL_DESCRIPTION, &NetworkResponder::GetDeviceModelDescription, NULL}, { PID_MANUFACTURER_LABEL, &NetworkResponder::GetManufacturerLabel, NULL}, { PID_DEVICE_LABEL, &NetworkResponder::GetDeviceLabel, NULL}, { PID_SOFTWARE_VERSION_LABEL, &NetworkResponder::GetSoftwareVersionLabel, NULL}, { PID_IDENTIFY_DEVICE, &NetworkResponder::GetIdentify, &NetworkResponder::SetIdentify}, { PID_LIST_INTERFACES, &NetworkResponder::GetListInterfaces, NULL}, { PID_INTERFACE_LABEL, &NetworkResponder::GetInterfaceLabel, NULL}, { PID_INTERFACE_HARDWARE_ADDRESS_TYPE1, &NetworkResponder::GetInterfaceHardwareAddressType1, NULL}, { PID_IPV4_CURRENT_ADDRESS, &NetworkResponder::GetIPV4CurrentAddress, NULL}, { PID_IPV4_DEFAULT_ROUTE, &NetworkResponder::GetIPV4DefaultRoute, NULL}, { PID_DNS_HOSTNAME, &NetworkResponder::GetDNSHostname, NULL}, { PID_DNS_DOMAIN_NAME, &NetworkResponder::GetDNSDomainName, NULL}, { PID_DNS_NAME_SERVER, &NetworkResponder::GetDNSNameServer, NULL}, { 0, NULL, NULL}, }; /** * New NetworkResponder */ NetworkResponder::NetworkResponder(const UID &uid) : m_uid(uid), m_identify_mode(false) { vector interfaces; interfaces.push_back(Interface( "eth0", IPV4Address::FromStringOrDie("10.0.0.20"), IPV4Address::FromStringOrDie("10.0.0.255"), IPV4Address::FromStringOrDie("255.255.0.0"), MACAddress::FromStringOrDie("01:23:45:67:89:ab"), false, 1, Interface::ARP_ETHERNET_TYPE)); interfaces.push_back(Interface( "eth2", IPV4Address::FromStringOrDie("192.168.0.1"), IPV4Address::FromStringOrDie("192.168.0.254"), IPV4Address::FromStringOrDie("255.255.255.0"), MACAddress::FromStringOrDie("45:67:89:ab:cd:ef"), false, 2, Interface::ARP_ETHERNET_TYPE)); vector name_servers; name_servers.push_back(IPV4Address::FromStringOrDie("10.0.0.1")); name_servers.push_back(IPV4Address::FromStringOrDie("10.0.0.2")); name_servers.push_back(IPV4Address::FromStringOrDie("10.0.0.3")); m_network_manager.reset(new FakeNetworkManager( interfaces, 1, IPV4Address::FromStringOrDie("10.0.0.254"), "foo", "bar.com", name_servers)); } NetworkResponder::~NetworkResponder() { } /* * Handle an RDM Request */ void NetworkResponder::SendRDMRequest(RDMRequest *request, RDMCallback *callback) { RDMOps::Instance()->HandleRDMRequest(this, m_uid, ROOT_RDM_DEVICE, request, callback); } RDMResponse *NetworkResponder::GetDeviceInfo( const RDMRequest *request) { return ResponderHelper::GetDeviceInfo( request, OLA_E137_2_MODEL, PRODUCT_CATEGORY_TEST, 2, 0, 1, 1, ZERO_FOOTPRINT_DMX_ADDRESS, 0, 0); } RDMResponse *NetworkResponder::GetProductDetailList( const RDMRequest *request) { // Shortcut for only one item in the vector return ResponderHelper::GetProductDetailList( request, vector(1, PRODUCT_DETAIL_TEST)); } RDMResponse *NetworkResponder::GetIdentify( const RDMRequest *request) { return ResponderHelper::GetBoolValue(request, m_identify_mode); } RDMResponse *NetworkResponder::SetIdentify( const RDMRequest *request) { bool old_value = m_identify_mode; RDMResponse *response = ResponderHelper::SetBoolValue( request, &m_identify_mode); if (m_identify_mode != old_value) { OLA_INFO << "Network Device " << m_uid << ", identify mode " << (m_identify_mode ? "on" : "off"); } return response; } RDMResponse *NetworkResponder::GetDeviceModelDescription( const RDMRequest *request) { return ResponderHelper::GetString(request, "OLA Network Device"); } RDMResponse *NetworkResponder::GetManufacturerLabel( const RDMRequest *request) { return ResponderHelper::GetString(request, OLA_MANUFACTURER_LABEL); } RDMResponse *NetworkResponder::GetDeviceLabel(const RDMRequest *request) { return ResponderHelper::GetString(request, "Network Device"); } RDMResponse *NetworkResponder::GetSoftwareVersionLabel( const RDMRequest *request) { return ResponderHelper::GetString(request, string("OLA Version ") + VERSION); } RDMResponse *NetworkResponder::GetListInterfaces(const RDMRequest *request) { return ResponderHelper::GetListInterfaces(request, m_network_manager.get()); } RDMResponse *NetworkResponder::GetInterfaceLabel(const RDMRequest *request) { return ResponderHelper::GetInterfaceLabel(request, m_network_manager.get()); } RDMResponse *NetworkResponder::GetInterfaceHardwareAddressType1( const RDMRequest *request) { return ResponderHelper::GetInterfaceHardwareAddressType1( request, m_network_manager.get()); } RDMResponse *NetworkResponder::GetIPV4CurrentAddress( const RDMRequest *request) { return ResponderHelper::GetIPV4CurrentAddress(request, m_network_manager.get()); } RDMResponse *NetworkResponder::GetIPV4DefaultRoute(const RDMRequest *request) { return ResponderHelper::GetIPV4DefaultRoute(request, m_network_manager.get()); } RDMResponse *NetworkResponder::GetDNSHostname(const RDMRequest *request) { return ResponderHelper::GetDNSHostname(request, m_network_manager.get()); } RDMResponse *NetworkResponder::GetDNSDomainName(const RDMRequest *request) { return ResponderHelper::GetDNSDomainName(request, m_network_manager.get()); } RDMResponse *NetworkResponder::GetDNSNameServer(const RDMRequest *request) { return ResponderHelper::GetDNSNameServer(request, m_network_manager.get()); } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/DimmerResponder.cpp0000644000175000017500000000436313023355232021341 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * DimmerResponder.cpp * A fake dimmer responder for OLA. * Copyright (C) 2013 Simon Newton */ #include #include #include #include "ola/rdm/DimmerResponder.h" #include "ola/rdm/DimmerRootDevice.h" #include "ola/rdm/DimmerSubDevice.h" namespace ola { namespace rdm { /** * Create a new dummy dimmer responder. * @param uid the UID of the responder * @param number_of_subdevices the number of sub devices for this responder. * Valid range is 0 to 512. */ DimmerResponder::DimmerResponder(const UID &uid, uint16_t number_of_subdevices) { uint16_t sub_devices = std::min(MAX_SUBDEVICE_NUMBER, number_of_subdevices); for (uint16_t i = 1; i <= sub_devices; i++) { DimmerSubDevice *sub_device = new DimmerSubDevice(uid, i, sub_devices); STLInsertIfNotPresent(&m_sub_devices, i, sub_device); m_dispatcher.AddSubDevice(i, sub_device); } m_root_device.reset(new DimmerRootDevice(uid, m_sub_devices)); } /** * Cleanup this responder */ DimmerResponder::~DimmerResponder() { STLDeleteValues(&m_sub_devices); } /* * Handle an RDM Request. This just uses the SubDeviceDispatcher to call the * correct sub device. */ void DimmerResponder::SendRDMRequest(RDMRequest *request, RDMCallback *callback) { if (request->SubDevice() == ROOT_RDM_DEVICE) { m_root_device->SendRDMRequest(request, callback); } else { m_dispatcher.SendRDMRequest(request, callback); } } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/CommandPrinter.cpp0000644000175000017500000003327213023355232021165 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * CommandPrinter.cpp * Write out RDMCommands in a human-readable format. * Copyright (C) 2012 Simon Newton */ #include #include #include #include #include #include #include #include #include namespace ola { namespace rdm { using ola::messaging::Descriptor; using ola::messaging::Message; using ola::network::NetworkToHost; using std::auto_ptr; using std::endl; using std::string; /** * Constructor * @param output the ostream to write to. * @param pid_helper a pointer to a PidStoreHelper object */ CommandPrinter::CommandPrinter(std::ostream *output, PidStoreHelper *pid_helper) : m_output(output), m_pid_helper(pid_helper) { } void CommandPrinter::Print(const class RDMCommand *, bool, bool) { *m_output << "Unknown RDM Command class"; } void CommandPrinter::Print(const class RDMRequest *request, bool summarize, bool unpack_param_data) { DisplayRequest(request, summarize, unpack_param_data); } void CommandPrinter::Print(const class RDMResponse *response, bool summarize, bool unpack_param_data) { DisplayResponse(response, summarize, unpack_param_data); } void CommandPrinter::Print(const class RDMDiscoveryRequest *request, bool summarize, bool unpack_param_data) { DisplayDiscoveryRequest(request, summarize, unpack_param_data); } void CommandPrinter::Print(const class RDMDiscoveryResponse *response, bool summarize, bool unpack_param_data) { DisplayDiscoveryResponse(response, summarize, unpack_param_data); } /** * Write out a RDM Request * @param request the request to format * @param summarize enable the one line summary * @param unpack_param_data if the summary isn't enabled, this controls if we * unpack and display parameter data. */ void CommandPrinter::DisplayRequest(const RDMRequest *request, bool summarize, bool unpack_param_data) { const PidDescriptor *descriptor = m_pid_helper->GetDescriptor( request->ParamId(), request->DestinationUID().ManufacturerId()); bool is_get = request->CommandClass() == RDMCommand::GET_COMMAND; if (summarize) { AppendUIDsAndType(request, (is_get ? "GET" : "SET")); *m_output << ", port: " << std::dec << static_cast(request->PortId()) << ", "; AppendPidString(request, descriptor); } else { AppendVerboseUIDs(request); AppendPortId(request); AppendHeaderFields(request, (is_get ? "GET" : "SET")); *m_output << " Param ID : 0x" << std::setfill('0') << std::setw(4) << std::hex << request->ParamId(); if (descriptor) *m_output << " (" << descriptor->Name() << ")"; *m_output << endl; *m_output << " Param data len : " << std::dec << request->ParamDataSize() << endl; DisplayParamData(descriptor, unpack_param_data, true, is_get, request->ParamData(), request->ParamDataSize()); } } /** * Write out a RDM Response * @param response the response to format * @param summarize enable the one line summary * @param unpack_param_data if the summary isn't enabled, this controls if we * unpack and display parameter data. */ void CommandPrinter::DisplayResponse(const RDMResponse *response, bool summarize, bool unpack_param_data) { const PidDescriptor *descriptor = m_pid_helper->GetDescriptor( response->ParamId(), response->SourceUID().ManufacturerId()); bool is_get = response->CommandClass() == RDMCommand::GET_COMMAND_RESPONSE; if (summarize) { AppendUIDsAndType(response, (is_get ? "GET_RESPONSE" : "SET_RESPONSE")); *m_output << ", response type: "; AppendResponseType(response); *m_output << ", "; AppendPidString(response, descriptor); } else { AppendVerboseUIDs(response); AppendVerboseResponseType(response); AppendHeaderFields(response, (is_get ? "GET_RESPONSE" : "SET_RESPONSE")); *m_output << " Param ID : 0x" << std::setfill('0') << std::setw(4) << std::hex << response->ParamId(); if (descriptor) *m_output << " (" << descriptor->Name() << ")"; *m_output << endl; *m_output << " Param data len : " << std::dec << response->ParamDataSize() << endl; DisplayParamData(descriptor, unpack_param_data, false, is_get, response->ParamData(), response->ParamDataSize()); } } /** * Write out a RDM discovery request * @param request the request to format * @param summarize enable the one line summary * @param unpack_param_data if the summary isn't enabled, this controls if we * unpack and display parameter data. */ void CommandPrinter::DisplayDiscoveryRequest( const RDMDiscoveryRequest *request, bool summarize, bool unpack_param_data) { string param_name; switch (request->ParamId()) { case ola::rdm::PID_DISC_UNIQUE_BRANCH: param_name = "DISC_UNIQUE_BRANCH"; break; case ola::rdm::PID_DISC_MUTE: param_name = "DISC_MUTE"; break; case ola::rdm::PID_DISC_UN_MUTE: param_name = "DISC_UN_MUTE"; break; } if (summarize) { AppendUIDsAndType(request, "DISCOVERY_COMMAND"); *m_output << ", PID 0x" << std::hex << std::setfill('0') << std::setw(4) << request->ParamId(); if (!param_name.empty()) *m_output << " (" << param_name << ")"; if (request->ParamId() == ola::rdm::PID_DISC_UNIQUE_BRANCH && request->ParamDataSize() == 2 * UID::UID_SIZE) { const uint8_t *param_data = request->ParamData(); UID lower(param_data); UID upper(param_data + UID::UID_SIZE); *m_output << ", (" << lower << ", " << upper << ")"; } else { *m_output << ", pdl: " << std::dec << request->ParamDataSize(); } *m_output << endl; } else { AppendVerboseUIDs(request); AppendPortId(request); AppendHeaderFields(request, "DISCOVERY_COMMAND"); *m_output << " Param ID : 0x" << std::setfill('0') << std::setw(4) << std::hex << request->ParamId(); if (!param_name.empty()) *m_output << " (" << param_name << ")"; *m_output << endl; *m_output << " Param data len : " << std::dec << request->ParamDataSize() << endl; DisplayParamData(NULL, unpack_param_data, true, false, request->ParamData(), request->ParamDataSize()); } } /** * Write out a RDM discovery response. * @param response the response to format. * @param summarize enable the one line summary * @param unpack_param_data if the summary isn't enabled, this controls if we * unpack and display parameter data. */ void CommandPrinter::DisplayDiscoveryResponse( const RDMDiscoveryResponse *response, bool summarize, bool unpack_param_data) { string param_name; switch (response->ParamId()) { case ola::rdm::PID_DISC_UNIQUE_BRANCH: param_name = "DISC_UNIQUE_BRANCH"; break; case ola::rdm::PID_DISC_MUTE: param_name = "DISC_MUTE"; break; case ola::rdm::PID_DISC_UN_MUTE: param_name = "DISC_UN_MUTE"; break; } if (summarize) { AppendUIDsAndType(response, "DISCOVERY_COMMAND_RESPONSE"); *m_output << ", PID 0x" << std::hex << std::setfill('0') << std::setw(4) << response->ParamId(); if (!param_name.empty()) *m_output << " (" << param_name << ")"; if (response->ParamId() == ola::rdm::PID_DISC_UNIQUE_BRANCH && response->ParamDataSize() == 2 * UID::UID_SIZE) { const uint8_t *param_data = response->ParamData(); UID lower(param_data); UID upper(param_data + UID::UID_SIZE); *m_output << ", (" << lower << ", " << upper << ")"; } else { *m_output << ", pdl: " << std::dec << response->ParamDataSize(); } *m_output << endl; } else { AppendVerboseUIDs(response); AppendVerboseResponseType(response); AppendHeaderFields(response, "DISCOVERY_COMMAND_RESPONSE"); *m_output << " Param ID : 0x" << std::setfill('0') << std::setw(4) << std::hex << response->ParamId(); if (!param_name.empty()) *m_output << " (" << param_name << ")"; *m_output << endl; *m_output << " Param data len : " << std::dec << response->ParamDataSize() << endl; DisplayParamData(NULL, unpack_param_data, true, false, response->ParamData(), response->ParamDataSize()); } } /** * Append the src/dst UIDs & type */ void CommandPrinter::AppendUIDsAndType(const class RDMCommand *command, const char *message_type) { *m_output << command->SourceUID() << " -> " << command->DestinationUID() << " " << message_type << ", sub-device: " << std::dec << command->SubDevice() << ", tn: " << static_cast(command->TransactionNumber()); } void CommandPrinter::AppendPortId(const class RDMRequest *request) { *m_output << " Port ID : " << std::dec << static_cast(request->PortId()) << endl; } void CommandPrinter::AppendVerboseUIDs(const class RDMCommand *command) { *m_output << " Source UID : " << command->SourceUID() << endl; *m_output << " Dest UID : " << command->DestinationUID() << endl; *m_output << " Transaction # : " << std::dec << static_cast(command->TransactionNumber()) << endl; } void CommandPrinter::AppendResponseType(const RDMResponse *response) { switch (response->ResponseType()) { case ola::rdm::RDM_ACK: *m_output << "ACK"; break; case ola::rdm::RDM_ACK_TIMER: *m_output << "ACK TIMER"; break; case ola::rdm::RDM_NACK_REASON: uint16_t reason; if (GetNackReason(response, &reason)) { *m_output << "NACK (" << ola::rdm::NackReasonToString(reason) << ")"; } else { *m_output << "Malformed NACK "; } break; case ola::rdm::ACK_OVERFLOW: *m_output << "ACK OVERFLOW"; break; default: *m_output << "Unknown (" << response->ResponseType() << ")"; } } void CommandPrinter::AppendVerboseResponseType( const RDMResponse *response) { *m_output << " Response Type : "; AppendResponseType(response); *m_output << endl; } void CommandPrinter::AppendHeaderFields( const RDMCommand *command, const char *command_class) { *m_output << " Message count : " << std::dec << static_cast(command->MessageCount()) << endl; *m_output << " Sub device : " << std::dec << command->SubDevice() << endl; *m_output << " Command class : " << command_class << endl; } /** * Append the PID descriptor */ void CommandPrinter::AppendPidString(const RDMCommand *command, const PidDescriptor *descriptor) { *m_output << "PID 0x" << std::hex << std::setfill('0') << std::setw(4) << command->ParamId(); if (descriptor) *m_output << " (" << descriptor->Name() << ")"; *m_output << ", pdl: " << std::dec << command->ParamDataSize() << endl; } /** * Format parameter data. */ void CommandPrinter::DisplayParamData( const PidDescriptor *pid_descriptor, bool unpack_param_data, bool is_request, bool is_get, const uint8_t *param_data, unsigned int data_length) { if (!data_length) { return; } *m_output << " Param data:" << endl; if (unpack_param_data && pid_descriptor) { const Descriptor *descriptor = NULL; if (is_request) { descriptor = (is_get ? pid_descriptor->GetRequest() : pid_descriptor->SetRequest()); } else { descriptor = (is_get ? pid_descriptor->GetResponse() : pid_descriptor->SetResponse()); } if (descriptor) { auto_ptr message( m_pid_helper->DeserializeMessage(descriptor, param_data, data_length)); if (message.get()) { *m_output << m_pid_helper->MessageToString(message.get()); return; } } } // otherwise just display the raw data, indent 4, 8 bytes per line ola::FormatData(m_output, param_data, data_length, 4, 8); } /** * Get the nack reason. */ bool CommandPrinter::GetNackReason(const RDMCommand *response, uint16_t *reason) { if (response->ParamDataSize() == 2) { memcpy(reinterpret_cast(reason), response->ParamData(), sizeof(*reason)); *reason = NetworkToHost(*reason); return true; } else { return false; } } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/AdvancedDimmerResponder.cpp0000644000175000017500000007273313023355232022775 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * AdvancedDimmerResponder.cpp * Copyright (C) 2013 Simon Newton */ #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #include #include #include #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/base/Array.h" #include "ola/network/NetworkUtils.h" #include "ola/rdm/AdvancedDimmerResponder.h" #include "ola/rdm/OpenLightingEnums.h" #include "ola/rdm/RDMEnums.h" #include "ola/rdm/ResponderHelper.h" #include "ola/rdm/ResponderSettings.h" namespace ola { namespace rdm { using ola::network::HostToNetwork; using ola::network::NetworkToHost; using std::max; using std::min; using std::string; using std::vector; const uint8_t AdvancedDimmerResponder::DIMMER_RESOLUTION = 14; const uint16_t AdvancedDimmerResponder::LOWER_MAX_LEVEL = 0x7fff; const uint16_t AdvancedDimmerResponder::UPPER_MAX_LEVEL = 0xffff; const uint16_t AdvancedDimmerResponder::LOWER_MIN_LEVEL = 0x0; const uint16_t AdvancedDimmerResponder::UPPER_MIN_LEVEL = 0x7fff; const unsigned int AdvancedDimmerResponder::PRESET_COUNT = 6; const uint16_t AdvancedDimmerResponder::MIN_FAIL_DELAY_TIME = 10; const uint16_t AdvancedDimmerResponder::MIN_FAIL_HOLD_TIME = 0; const uint16_t AdvancedDimmerResponder::MAX_FAIL_DELAY_TIME = 0x00ff; const uint16_t AdvancedDimmerResponder::MAX_FAIL_HOLD_TIME = 0xff00; const uint16_t AdvancedDimmerResponder::MIN_STARTUP_DELAY_TIME = 0; const uint16_t AdvancedDimmerResponder::MIN_STARTUP_HOLD_TIME = 0; const uint16_t AdvancedDimmerResponder::MAX_STARTUP_DELAY_TIME = 1200; const uint16_t AdvancedDimmerResponder::MAX_STARTUP_HOLD_TIME = 36000; const uint16_t AdvancedDimmerResponder::INFINITE_TIME = 0xffff; const char* AdvancedDimmerResponder::CURVES[] = { "Linear Curve", "Square Law Curve", "S Curve", }; const char* AdvancedDimmerResponder::RESPONSE_TIMES[] = { "Super fast", "Fast", "Slow", "Very slow", }; const FrequencyModulationSetting::ArgType AdvancedDimmerResponder::PWM_FREQUENCIES[] = { {120, "120Hz"}, {500, "500Hz"}, {1000, "1kHz"}, {5000, "5kHz"}, {10000, "10kHz"}, }; const char* AdvancedDimmerResponder::LOCK_STATES[] = { "Unlocked", "Start Address Locked", "Address and Personalities Locked", }; const SettingCollection AdvancedDimmerResponder::CurveSettings(CURVES, arraysize(CURVES)); const SettingCollection AdvancedDimmerResponder::ResponseTimeSettings( RESPONSE_TIMES, arraysize(RESPONSE_TIMES)); const SettingCollection AdvancedDimmerResponder::FrequencySettings( PWM_FREQUENCIES, arraysize(PWM_FREQUENCIES)); const SettingCollection AdvancedDimmerResponder::LockSettings( LOCK_STATES, arraysize(LOCK_STATES), true); RDMResponse *AdvancedDimmerResponder:: LockManager::SetWithPin(const RDMRequest *request, uint16_t pin) { PACK( struct lock_s { uint16_t pin; uint8_t state; }); STATIC_ASSERT(sizeof(lock_s) == 3); lock_s data; if (request->ParamDataSize() != sizeof(lock_s)) { return NackWithReason(request, NR_FORMAT_ERROR); } memcpy(reinterpret_cast(&data), request->ParamData(), sizeof(data)); data.pin = NetworkToHost(data.pin); if (data.pin != pin) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } if (!ChangeSetting(data.state)) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } return ResponderHelper::EmptySetResponse(request); } const AdvancedDimmerResponder::Personalities * AdvancedDimmerResponder::Personalities::Instance() { if (!instance) { PersonalityList personalities; personalities.push_back(Personality(12, "6-Channel 16-bit")); instance = new Personalities(personalities); } return instance; } AdvancedDimmerResponder::Personalities * AdvancedDimmerResponder::Personalities::instance = NULL; AdvancedDimmerResponder::RDMOps * AdvancedDimmerResponder::RDMOps::instance = NULL; const ResponderOps::ParamHandler AdvancedDimmerResponder::PARAM_HANDLERS[] = { { PID_DEVICE_INFO, &AdvancedDimmerResponder::GetDeviceInfo, NULL}, { PID_PRODUCT_DETAIL_ID_LIST, &AdvancedDimmerResponder::GetProductDetailList, NULL}, { PID_DEVICE_MODEL_DESCRIPTION, &AdvancedDimmerResponder::GetDeviceModelDescription, NULL}, { PID_MANUFACTURER_LABEL, &AdvancedDimmerResponder::GetManufacturerLabel, NULL}, { PID_DEVICE_LABEL, &AdvancedDimmerResponder::GetDeviceLabel, NULL}, { PID_SOFTWARE_VERSION_LABEL, &AdvancedDimmerResponder::GetSoftwareVersionLabel, NULL}, { PID_DMX_PERSONALITY, &AdvancedDimmerResponder::GetPersonality, &AdvancedDimmerResponder::SetPersonality}, { PID_DMX_PERSONALITY_DESCRIPTION, &AdvancedDimmerResponder::GetPersonalityDescription, NULL}, { PID_DMX_START_ADDRESS, &AdvancedDimmerResponder::GetDmxStartAddress, &AdvancedDimmerResponder::SetDmxStartAddress}, { PID_IDENTIFY_DEVICE, &AdvancedDimmerResponder::GetIdentify, &AdvancedDimmerResponder::SetIdentify}, { PID_CAPTURE_PRESET, NULL, &AdvancedDimmerResponder::SetCapturePreset}, { PID_PRESET_PLAYBACK, &AdvancedDimmerResponder::GetPresetPlayback, &AdvancedDimmerResponder::SetPresetPlayback}, { PID_DIMMER_INFO, &AdvancedDimmerResponder::GetDimmerInfo, NULL}, { PID_MINIMUM_LEVEL, &AdvancedDimmerResponder::GetMinimumLevel, &AdvancedDimmerResponder::SetMinimumLevel}, { PID_MAXIMUM_LEVEL, &AdvancedDimmerResponder::GetMaximumLevel, &AdvancedDimmerResponder::SetMaximumLevel}, { PID_DMX_FAIL_MODE, &AdvancedDimmerResponder::GetFailMode, &AdvancedDimmerResponder::SetFailMode}, { PID_DMX_STARTUP_MODE, &AdvancedDimmerResponder::GetStartUpMode, &AdvancedDimmerResponder::SetStartUpMode}, { PID_BURN_IN, &AdvancedDimmerResponder::GetBurnIn, &AdvancedDimmerResponder::SetBurnIn}, { PID_CURVE, &AdvancedDimmerResponder::GetCurve, &AdvancedDimmerResponder::SetCurve}, { PID_CURVE_DESCRIPTION, &AdvancedDimmerResponder::GetCurveDescription, NULL}, { PID_OUTPUT_RESPONSE_TIME, &AdvancedDimmerResponder::GetResponseTime, &AdvancedDimmerResponder::SetResponseTime}, { PID_OUTPUT_RESPONSE_TIME_DESCRIPTION, &AdvancedDimmerResponder::GetResponseTimeDescription, NULL}, { PID_MODULATION_FREQUENCY, &AdvancedDimmerResponder::GetPWMFrequency, &AdvancedDimmerResponder::SetPWMFrequency}, { PID_MODULATION_FREQUENCY_DESCRIPTION, &AdvancedDimmerResponder::GetPWMFrequencyDescription, NULL}, { PID_LOCK_STATE, &AdvancedDimmerResponder::GetLockState, &AdvancedDimmerResponder::SetLockState}, { PID_LOCK_STATE_DESCRIPTION, &AdvancedDimmerResponder::GetLockStateDescription, NULL}, { PID_LOCK_PIN, &AdvancedDimmerResponder::GetLockPin, &AdvancedDimmerResponder::SetLockPin}, { PID_POWER_ON_SELF_TEST, &AdvancedDimmerResponder::GetPowerOnSelfTest, &AdvancedDimmerResponder::SetPowerOnSelfTest}, { PID_PRESET_STATUS, &AdvancedDimmerResponder::GetPresetStatus, &AdvancedDimmerResponder::SetPresetStatus}, { PID_PRESET_MERGEMODE, &AdvancedDimmerResponder::GetPresetMergeMode, &AdvancedDimmerResponder::SetPresetMergeMode}, { PID_PRESET_INFO, &AdvancedDimmerResponder::GetPresetInfo, NULL}, { 0, NULL, NULL}, }; /** * Create a new dimmer device. */ AdvancedDimmerResponder::AdvancedDimmerResponder(const UID &uid) : m_uid(uid), m_identify_state(false), m_start_address(1), m_lock_pin(0), m_maximum_level(UPPER_MAX_LEVEL), m_identify_mode(IDENTIFY_MODE_QUIET), m_burn_in(0), m_power_on_self_test(true), m_personality_manager(Personalities::Instance()), m_curve_settings(&CurveSettings), m_response_time_settings(&ResponseTimeSettings), m_lock_settings(&LockSettings), m_frequency_settings(&FrequencySettings), m_presets(PRESET_COUNT), m_preset_scene(0), m_preset_level(0), m_preset_mergemode(MERGEMODE_DEFAULT) { m_min_level.min_level_increasing = 10; m_min_level.min_level_decreasing = 20; m_min_level.on_below_min = true; m_fail_mode.scene = 0; m_fail_mode.delay = MIN_FAIL_DELAY_TIME; m_fail_mode.hold_time = MIN_FAIL_HOLD_TIME; m_fail_mode.level = 0; m_startup_mode.scene = 0; m_startup_mode.delay = MIN_STARTUP_DELAY_TIME; m_startup_mode.hold_time = MIN_STARTUP_HOLD_TIME; m_startup_mode.level = 255; // make the first preset read only m_presets[0].programmed = PRESET_PROGRAMMED_READ_ONLY; } /* * Handle an RDM Request */ void AdvancedDimmerResponder::SendRDMRequest(RDMRequest *request, RDMCallback *callback) { RDMOps::Instance()->HandleRDMRequest(this, m_uid, ROOT_RDM_DEVICE, request, callback); } RDMResponse *AdvancedDimmerResponder::GetDeviceInfo( const RDMRequest *request) { return ResponderHelper::GetDeviceInfo( request, OLA_E137_DIMMER_MODEL, PRODUCT_CATEGORY_DIMMER, 1, &m_personality_manager, m_start_address, 0, 0); } RDMResponse *AdvancedDimmerResponder::GetProductDetailList( const RDMRequest *request) { // Shortcut for only one item in the vector return ResponderHelper::GetProductDetailList(request, vector(1, PRODUCT_DETAIL_TEST)); } RDMResponse *AdvancedDimmerResponder::GetDeviceModelDescription( const RDMRequest *request) { return ResponderHelper::GetString(request, "OLA E1.37-1 Dimmer"); } RDMResponse *AdvancedDimmerResponder::GetManufacturerLabel( const RDMRequest *request) { return ResponderHelper::GetString(request, OLA_MANUFACTURER_LABEL); } RDMResponse *AdvancedDimmerResponder::GetDeviceLabel( const RDMRequest *request) { return ResponderHelper::GetString(request, "Dummy Adv Dimmer"); } RDMResponse *AdvancedDimmerResponder::GetSoftwareVersionLabel( const RDMRequest *request) { return ResponderHelper::GetString(request, string("OLA Version ") + VERSION); } RDMResponse *AdvancedDimmerResponder::GetPersonality( const RDMRequest *request) { return ResponderHelper::GetPersonality(request, &m_personality_manager); } RDMResponse *AdvancedDimmerResponder::SetPersonality( const RDMRequest *request) { if (m_lock_settings.CurrentSetting() > 1) { return NackWithReason(request, NR_WRITE_PROTECT); } return ResponderHelper::SetPersonality(request, &m_personality_manager, m_start_address); } RDMResponse *AdvancedDimmerResponder::GetPersonalityDescription( const RDMRequest *request) { return ResponderHelper::GetPersonalityDescription( request, &m_personality_manager); } RDMResponse *AdvancedDimmerResponder::GetDmxStartAddress( const RDMRequest *request) { return ResponderHelper::GetDmxAddress(request, &m_personality_manager, m_start_address); } RDMResponse *AdvancedDimmerResponder::SetDmxStartAddress( const RDMRequest *request) { if (m_lock_settings.CurrentSetting() > 0) { return NackWithReason(request, NR_WRITE_PROTECT); } return ResponderHelper::SetDmxAddress(request, &m_personality_manager, &m_start_address); } RDMResponse *AdvancedDimmerResponder::GetDimmerInfo( const RDMRequest *request) { if (request->ParamDataSize()) { return NackWithReason(request, NR_FORMAT_ERROR); } PACK( struct dimmer_info_s { uint16_t min_level_lower; uint16_t min_level_upper; uint16_t max_level_lower; uint16_t max_level_upper; uint8_t curve_count; uint8_t level_resolution; uint8_t level_support; }); STATIC_ASSERT(sizeof(dimmer_info_s) == 11); struct dimmer_info_s dimmer_info; dimmer_info.min_level_lower = HostToNetwork(LOWER_MIN_LEVEL); dimmer_info.min_level_upper = HostToNetwork(UPPER_MIN_LEVEL); dimmer_info.max_level_lower = HostToNetwork(LOWER_MAX_LEVEL); dimmer_info.max_level_upper = HostToNetwork(UPPER_MAX_LEVEL); dimmer_info.curve_count = CurveSettings.Count(); dimmer_info.level_resolution = DIMMER_RESOLUTION; dimmer_info.level_support = 1; return GetResponseFromData( request, reinterpret_cast(&dimmer_info), sizeof(dimmer_info), RDM_ACK); } RDMResponse *AdvancedDimmerResponder::GetMinimumLevel( const RDMRequest *request) { if (request->ParamDataSize()) { return NackWithReason(request, NR_FORMAT_ERROR); } min_level_s output = m_min_level; output.min_level_increasing = HostToNetwork(output.min_level_increasing); output.min_level_decreasing = HostToNetwork(output.min_level_decreasing); return GetResponseFromData( request, reinterpret_cast(&output), sizeof(output), RDM_ACK); } RDMResponse *AdvancedDimmerResponder::SetMinimumLevel( const RDMRequest *request) { min_level_s args; if (request->ParamDataSize() != sizeof(args)) { return NackWithReason(request, NR_FORMAT_ERROR); } memcpy(reinterpret_cast(&args), request->ParamData(), sizeof(args)); args.min_level_increasing = NetworkToHost(args.min_level_increasing); args.min_level_decreasing = NetworkToHost(args.min_level_decreasing); if (!ValueBetweenRange(args.min_level_decreasing, LOWER_MIN_LEVEL, UPPER_MIN_LEVEL) || !ValueBetweenRange(args.min_level_increasing, LOWER_MIN_LEVEL, UPPER_MIN_LEVEL) || args.on_below_min > 1) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } else { m_min_level = args; return ResponderHelper::EmptySetResponse(request); } } RDMResponse *AdvancedDimmerResponder::GetMaximumLevel( const RDMRequest *request) { return ResponderHelper::GetUInt16Value(request, m_maximum_level); } RDMResponse *AdvancedDimmerResponder::SetMaximumLevel( const RDMRequest *request) { uint16_t arg; if (!ResponderHelper::ExtractUInt16(request, &arg)) { return NackWithReason(request, NR_FORMAT_ERROR); } if (!ValueBetweenRange(arg, LOWER_MAX_LEVEL, UPPER_MAX_LEVEL)) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } else { m_maximum_level = arg; return ResponderHelper::EmptySetResponse(request); } } RDMResponse *AdvancedDimmerResponder::GetIdentify( const RDMRequest *request) { return ResponderHelper::GetBoolValue(request, m_identify_state); } RDMResponse *AdvancedDimmerResponder::SetIdentify( const RDMRequest *request) { bool old_value = m_identify_state; RDMResponse *response = ResponderHelper::SetBoolValue( request, &m_identify_state); if (m_identify_state != old_value) { OLA_INFO << "E1.37-1 Dimmer Device " << m_uid << ", identify state " << (m_identify_state ? "on" : "off"); } return response; } RDMResponse *AdvancedDimmerResponder::SetCapturePreset( const RDMRequest *request) { PACK( struct preset_s { uint16_t scene; uint16_t fade_up_time; uint16_t fade_down_time; uint16_t wait_time; }); STATIC_ASSERT(sizeof(preset_s) == 8); preset_s args; if (request->ParamDataSize() != sizeof(args)) { return NackWithReason(request, NR_FORMAT_ERROR); } memcpy(reinterpret_cast(&args), request->ParamData(), sizeof(args)); args.scene = NetworkToHost(args.scene); args.fade_up_time = NetworkToHost(args.fade_up_time); args.fade_down_time = NetworkToHost(args.fade_down_time); args.wait_time = NetworkToHost(args.wait_time); if (args.scene == 0 || args.scene >= m_presets.size()) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } Preset &preset = m_presets[args.scene - 1]; if (preset.programmed == PRESET_PROGRAMMED_READ_ONLY) { return NackWithReason(request, NR_WRITE_PROTECT); } preset.fade_up_time = args.fade_up_time; preset.fade_down_time = args.fade_down_time; preset.wait_time = args.wait_time; preset.programmed = PRESET_PROGRAMMED; return ResponderHelper::EmptySetResponse(request); } RDMResponse *AdvancedDimmerResponder::GetPresetPlayback( const RDMRequest *request) { if (request->ParamDataSize()) { return NackWithReason(request, NR_FORMAT_ERROR); } preset_playback_s output; output.mode = HostToNetwork(m_preset_scene); output.level = m_preset_level; return GetResponseFromData( request, reinterpret_cast(&output), sizeof(output), RDM_ACK); } RDMResponse *AdvancedDimmerResponder::SetPresetPlayback( const RDMRequest *request) { preset_playback_s args; if (request->ParamDataSize() != sizeof(args)) { return NackWithReason(request, NR_FORMAT_ERROR); } memcpy(reinterpret_cast(&args), request->ParamData(), sizeof(args)); args.mode = NetworkToHost(args.mode); if (args.mode >= m_presets.size() && args.mode != PRESET_PLAYBACK_ALL) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } m_preset_scene = args.mode; m_preset_level = args.level; return ResponderHelper::EmptySetResponse(request); } RDMResponse *AdvancedDimmerResponder::GetIdentifyMode( const RDMRequest *request) { return ResponderHelper::GetUInt8Value(request, m_identify_mode); } RDMResponse *AdvancedDimmerResponder::SetIdentifyMode( const RDMRequest *request) { uint8_t arg; if (!ResponderHelper::ExtractUInt8(request, &arg)) { return NackWithReason(request, NR_FORMAT_ERROR); } if (arg == static_cast(IDENTIFY_MODE_QUIET) || arg == static_cast(IDENTIFY_MODE_LOUD)) { m_identify_mode = static_cast(arg); return ResponderHelper::EmptySetResponse(request); } else { return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } } RDMResponse *AdvancedDimmerResponder::GetBurnIn( const RDMRequest *request) { return ResponderHelper::GetUInt8Value(request, m_burn_in); } RDMResponse *AdvancedDimmerResponder::SetBurnIn( const RDMRequest *request) { uint8_t arg; if (!ResponderHelper::ExtractUInt8(request, &arg)) { return NackWithReason(request, NR_FORMAT_ERROR); } // We start the 'clock' immediately, so the hours remaining is one less than // what was requested. m_burn_in = (arg ? arg - 1 : 0); return ResponderHelper::EmptySetResponse(request); } RDMResponse *AdvancedDimmerResponder::GetCurve( const RDMRequest *request) { return m_curve_settings.Get(request); } RDMResponse *AdvancedDimmerResponder::SetCurve( const RDMRequest *request) { return m_curve_settings.Set(request); } RDMResponse *AdvancedDimmerResponder::GetCurveDescription( const RDMRequest *request) { return m_curve_settings.GetDescription(request); } RDMResponse *AdvancedDimmerResponder::GetResponseTime( const RDMRequest *request) { return m_response_time_settings.Get(request); } RDMResponse *AdvancedDimmerResponder::SetResponseTime( const RDMRequest *request) { return m_response_time_settings.Set(request); } RDMResponse *AdvancedDimmerResponder::GetResponseTimeDescription( const RDMRequest *request) { return m_response_time_settings.GetDescription(request); } RDMResponse *AdvancedDimmerResponder::GetPWMFrequency( const RDMRequest *request) { return m_frequency_settings.Get(request); } RDMResponse *AdvancedDimmerResponder::SetPWMFrequency( const RDMRequest *request) { return m_frequency_settings.Set(request); } RDMResponse *AdvancedDimmerResponder::GetPWMFrequencyDescription( const RDMRequest *request) { return m_frequency_settings.GetDescription(request); } RDMResponse *AdvancedDimmerResponder::GetLockState( const RDMRequest *request) { return m_lock_settings.Get(request); } RDMResponse *AdvancedDimmerResponder::SetLockState( const RDMRequest *request) { return m_lock_settings.SetWithPin(request, m_lock_pin); } RDMResponse *AdvancedDimmerResponder::GetLockStateDescription( const RDMRequest *request) { return m_lock_settings.GetDescription(request); } RDMResponse *AdvancedDimmerResponder::GetLockPin( const RDMRequest *request) { return ResponderHelper::GetUInt16Value(request, m_lock_pin, 0); } RDMResponse *AdvancedDimmerResponder::SetLockPin( const RDMRequest *request) { PACK( struct set_pin_s { uint16_t new_pin; uint16_t current_pin; }); STATIC_ASSERT(sizeof(set_pin_s) == 4); set_pin_s data; if (request->ParamDataSize() != sizeof(data)) { return NackWithReason(request, NR_FORMAT_ERROR); } memcpy(reinterpret_cast(&data), request->ParamData(), sizeof(data)); data.new_pin = NetworkToHost(data.new_pin); data.current_pin = NetworkToHost(data.current_pin); if (data.current_pin != m_lock_pin) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } if (data.new_pin > MAX_LOCK_PIN) { return NackWithReason(request, NR_FORMAT_ERROR); } m_lock_pin = data.new_pin; return ResponderHelper::EmptySetResponse(request); } RDMResponse *AdvancedDimmerResponder::GetPowerOnSelfTest( const RDMRequest *request) { return ResponderHelper::GetBoolValue(request, m_power_on_self_test); } RDMResponse *AdvancedDimmerResponder::SetPowerOnSelfTest( const RDMRequest *request) { return ResponderHelper::SetBoolValue(request, &m_power_on_self_test); } RDMResponse *AdvancedDimmerResponder::GetPresetStatus( const RDMRequest *request) { uint16_t arg; if (!ResponderHelper::ExtractUInt16(request, &arg)) { return NackWithReason(request, NR_FORMAT_ERROR); } if (arg == 0 || arg > m_presets.size()) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } preset_status_s output; const Preset &preset = m_presets[arg - 1]; output.scene = HostToNetwork(arg); output.fade_up_time = HostToNetwork(preset.fade_up_time); output.fade_down_time = HostToNetwork(preset.fade_down_time); output.wait_time = HostToNetwork(preset.wait_time); output.programmed = preset.programmed; return GetResponseFromData( request, reinterpret_cast(&output), sizeof(output), RDM_ACK); } RDMResponse *AdvancedDimmerResponder::SetPresetStatus( const RDMRequest *request) { preset_status_s args; if (request->ParamDataSize() != sizeof(args)) { return NackWithReason(request, NR_FORMAT_ERROR); } memcpy(reinterpret_cast(&args), request->ParamData(), sizeof(args)); uint16_t scene = NetworkToHost(args.scene); if (scene == 0 || scene > m_presets.size()) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } Preset &preset = m_presets[scene - 1]; if (preset.programmed == PRESET_PROGRAMMED_READ_ONLY) { return NackWithReason(request, NR_WRITE_PROTECT); } if (args.programmed > 1) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } if (args.programmed == 1) { preset.fade_up_time = 0; preset.fade_down_time = 0; preset.wait_time = 0; preset.programmed = PRESET_NOT_PROGRAMMED; } else { preset.fade_up_time = NetworkToHost(args.fade_up_time); preset.fade_down_time = NetworkToHost(args.fade_down_time); preset.wait_time = NetworkToHost(args.wait_time); preset.programmed = PRESET_PROGRAMMED; } return ResponderHelper::EmptySetResponse(request); } RDMResponse *AdvancedDimmerResponder::GetPresetInfo( const RDMRequest *request) { if (request->ParamDataSize()) { return NackWithReason(request, NR_FORMAT_ERROR); } PACK( struct preset_info_s { uint8_t level_supported; uint8_t preset_seq_supported; uint8_t split_times_supported; uint8_t fail_infinite_delay_supported; uint8_t fail_infinite_hold_supported; uint8_t startup_infinite_hold_supported; uint16_t max_scene_number; uint16_t min_preset_fade_time; uint16_t max_preset_fade_time; uint16_t min_preset_wait_time; uint16_t max_preset_wait_time; uint16_t min_fail_delay_time; uint16_t max_fail_delay_time; uint16_t min_fail_hold_time; uint16_t max_fail_hold_time; uint16_t min_startup_delay; uint16_t max_startup_delay; uint16_t min_startup_hold; uint16_t max_startup_hold; }); STATIC_ASSERT(sizeof(preset_info_s) == 32); uint16_t preset_count = m_presets.size(); preset_info_s preset_info = { 1, // level_supported 1, // preset_seq_supported 1, // split_times_supported 1, // fail_infinite_delay_supported 1, // fail_infinite_hold_supported 1, // startup_infinite_hold_supported HostToNetwork(preset_count), 0, 0xfffe, // fade time 0, 0xfffe, // wait time HostToNetwork(MIN_FAIL_DELAY_TIME), HostToNetwork(MAX_FAIL_DELAY_TIME), // fail delay HostToNetwork(MIN_FAIL_HOLD_TIME), HostToNetwork(MAX_FAIL_HOLD_TIME), // fail hold time HostToNetwork(MIN_STARTUP_DELAY_TIME), HostToNetwork(MAX_STARTUP_DELAY_TIME), // startup delay HostToNetwork(MIN_STARTUP_HOLD_TIME), HostToNetwork(MAX_STARTUP_HOLD_TIME), // startup hold time }; return GetResponseFromData( request, reinterpret_cast(&preset_info), sizeof(preset_info), RDM_ACK); } RDMResponse *AdvancedDimmerResponder::GetPresetMergeMode( const RDMRequest *request) { if (request->ParamDataSize()) { return NackWithReason(request, NR_FORMAT_ERROR); } uint8_t output = m_preset_mergemode; return GetResponseFromData(request, &output, sizeof(output), RDM_ACK); } RDMResponse *AdvancedDimmerResponder::SetPresetMergeMode( const RDMRequest *request) { uint8_t arg; if (!ResponderHelper::ExtractUInt8(request, &arg)) { return NackWithReason(request, NR_FORMAT_ERROR); } if (arg > MERGEMODE_DMX_ONLY) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } m_preset_mergemode = static_cast(arg); return ResponderHelper::EmptySetResponse(request); } RDMResponse *AdvancedDimmerResponder::GetFailMode( const RDMRequest *request) { if (request->ParamDataSize()) { return NackWithReason(request, NR_FORMAT_ERROR); } fail_mode_s fail_mode = { HostToNetwork(m_fail_mode.scene), HostToNetwork(m_fail_mode.delay), HostToNetwork(m_fail_mode.hold_time), m_fail_mode.level }; return GetResponseFromData( request, reinterpret_cast(&fail_mode), sizeof(fail_mode), RDM_ACK); } RDMResponse *AdvancedDimmerResponder::SetFailMode( const RDMRequest *request) { fail_mode_s args; if (request->ParamDataSize() != sizeof(args)) { return NackWithReason(request, NR_FORMAT_ERROR); } memcpy(reinterpret_cast(&args), request->ParamData(), sizeof(args)); uint16_t scene = NetworkToHost(args.scene); if (scene >= m_presets.size()) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } m_fail_mode.scene = NetworkToHost(args.scene); uint16_t delay = NetworkToHost(args.delay); if (delay == INFINITE_TIME) { m_fail_mode.delay = INFINITE_TIME; } else { m_fail_mode.delay = max(MIN_FAIL_DELAY_TIME, min(MAX_FAIL_DELAY_TIME, delay)); } uint16_t hold = NetworkToHost(args.hold_time); if (hold == INFINITE_TIME) { m_fail_mode.hold_time = INFINITE_TIME; } else { m_fail_mode.hold_time = max(MIN_FAIL_HOLD_TIME, min(MAX_FAIL_HOLD_TIME, hold)); } m_fail_mode.level = args.level; return ResponderHelper::EmptySetResponse(request); } RDMResponse *AdvancedDimmerResponder::GetStartUpMode( const RDMRequest *request) { if (request->ParamDataSize()) { return NackWithReason(request, NR_FORMAT_ERROR); } startup_mode_s startup_mode = { HostToNetwork(m_startup_mode.scene), HostToNetwork(m_startup_mode.delay), HostToNetwork(m_startup_mode.hold_time), m_startup_mode.level }; return GetResponseFromData( request, reinterpret_cast(&startup_mode), sizeof(startup_mode), RDM_ACK); } RDMResponse *AdvancedDimmerResponder::SetStartUpMode( const RDMRequest *request) { startup_mode_s args; if (request->ParamDataSize() != sizeof(args)) { return NackWithReason(request, NR_FORMAT_ERROR); } memcpy(reinterpret_cast(&args), request->ParamData(), sizeof(args)); uint16_t scene = NetworkToHost(args.scene); if (scene >= m_presets.size()) { return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } m_startup_mode.scene = NetworkToHost(args.scene); uint16_t delay = NetworkToHost(args.delay); if (delay == INFINITE_TIME) { m_startup_mode.delay = INFINITE_TIME; } else { m_startup_mode.delay = max(MIN_STARTUP_DELAY_TIME, min(MAX_STARTUP_DELAY_TIME, delay)); } uint16_t hold = NetworkToHost(args.hold_time); if (hold == INFINITE_TIME) { m_startup_mode.hold_time = INFINITE_TIME; } else { m_startup_mode.hold_time = max(MIN_STARTUP_HOLD_TIME, min(MAX_STARTUP_HOLD_TIME, hold)); } m_startup_mode.level = args.level; return ResponderHelper::EmptySetResponse(request); } bool AdvancedDimmerResponder::ValueBetweenRange(const uint16_t value, const uint16_t lower, const uint16_t upper) { return value >= lower && value <= upper; } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/GroupSizeCalculatorTest.cpp0000644000175000017500000002502513023355232023041 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * GroupSizeCalculatorTest.cpp * Test fixture for the GroupSizeCalculator and StaticGroupTokenCalculator * classes. * Copyright (C) 2011 Simon Newton */ #include #include #include "ola/Logging.h" #include "ola/messaging/Descriptor.h" #include "common/rdm/GroupSizeCalculator.h" #include "ola/testing/TestUtils.h" using ola::messaging::BoolFieldDescriptor; using ola::messaging::Descriptor; using ola::messaging::FieldDescriptor; using ola::messaging::FieldDescriptorGroup; using ola::messaging::IPV4FieldDescriptor; using ola::messaging::Int16FieldDescriptor; using ola::messaging::Int32FieldDescriptor; using ola::messaging::Int8FieldDescriptor; using ola::messaging::StringFieldDescriptor; using ola::messaging::UIDFieldDescriptor; using ola::messaging::UInt16FieldDescriptor; using ola::messaging::UInt32FieldDescriptor; using ola::messaging::UInt8FieldDescriptor; using ola::rdm::GroupSizeCalculator; using std::vector; class GroupSizeCalculatorTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(GroupSizeCalculatorTest); CPPUNIT_TEST(testSimpleCases); CPPUNIT_TEST(testWithFixedGroups); CPPUNIT_TEST(testSingleVariableSizedGroup); CPPUNIT_TEST(testMultipleVariableSizedGroups); CPPUNIT_TEST(testNestedVariableSizedGroups); CPPUNIT_TEST_SUITE_END(); public: void testSimpleCases(); void testWithFixedGroups(); void testSingleVariableSizedGroup(); void testMultipleVariableSizedGroups(); void testNestedVariableSizedGroups(); private: ola::rdm::GroupSizeCalculator m_calculator; ola::rdm::StaticGroupTokenCalculator m_static_calculator; }; CPPUNIT_TEST_SUITE_REGISTRATION(GroupSizeCalculatorTest); /** * Test that we can determine the token count for simple descriptors. */ void GroupSizeCalculatorTest::testSimpleCases() { vector fields; fields.push_back(new BoolFieldDescriptor("bool1")); fields.push_back(new UInt8FieldDescriptor("uint8")); fields.push_back(new UInt16FieldDescriptor("uint16")); fields.push_back(new UInt32FieldDescriptor("uint32")); fields.push_back(new Int8FieldDescriptor("int8")); fields.push_back(new Int16FieldDescriptor("int16")); fields.push_back(new Int32FieldDescriptor("int32")); fields.push_back(new StringFieldDescriptor("string", 0, 32)); fields.push_back(new IPV4FieldDescriptor("address")); fields.push_back(new UIDFieldDescriptor("uid")); Descriptor descriptor("Test Descriptor", fields); unsigned int token_count, group_repeat_count; OLA_ASSERT_TRUE( m_static_calculator.CalculateTokensRequired(&descriptor, &token_count)); OLA_ASSERT_EQ(10u, token_count); OLA_ASSERT_EQ( GroupSizeCalculator::INSUFFICIENT_TOKENS, m_calculator.CalculateGroupSize( 1, &descriptor, &group_repeat_count)); OLA_ASSERT_EQ( GroupSizeCalculator::INSUFFICIENT_TOKENS, m_calculator.CalculateGroupSize( 9, &descriptor, &group_repeat_count)); OLA_ASSERT_EQ( GroupSizeCalculator::NO_VARIABLE_GROUPS, m_calculator.CalculateGroupSize( 10, &descriptor, &group_repeat_count)); OLA_ASSERT_EQ( GroupSizeCalculator::EXTRA_TOKENS, m_calculator.CalculateGroupSize( 11, &descriptor, &group_repeat_count)); } /** * Check the calculators work with fixed groups. */ void GroupSizeCalculatorTest::testWithFixedGroups() { vector group_fields, group_fields2; group_fields.push_back(new BoolFieldDescriptor("bool")); group_fields.push_back(new UInt8FieldDescriptor("uint8")); const FieldDescriptorGroup *fixed_group = new FieldDescriptorGroup( "", group_fields, 2, 2); group_fields2.push_back(new Int16FieldDescriptor("int16")); group_fields2.push_back(new UInt16FieldDescriptor("uint16")); group_fields2.push_back(new BoolFieldDescriptor("uint16")); const FieldDescriptorGroup *fixed_group2 = new FieldDescriptorGroup( "", group_fields2, 4, 4); unsigned int token_count, group_repeat_count; // first check the static calculator OLA_ASSERT_TRUE( m_static_calculator.CalculateTokensRequired(fixed_group, &token_count)); OLA_ASSERT_EQ(2u, token_count); OLA_ASSERT_TRUE( m_static_calculator.CalculateTokensRequired(fixed_group2, &token_count)); OLA_ASSERT_EQ(3u, token_count); // now check the main calculator vector fields; fields.push_back(fixed_group); fields.push_back(fixed_group2); Descriptor descriptor("Test Descriptor", fields); OLA_ASSERT_EQ( GroupSizeCalculator::INSUFFICIENT_TOKENS, m_calculator.CalculateGroupSize( 4, &descriptor, &group_repeat_count)); OLA_ASSERT_EQ( GroupSizeCalculator::INSUFFICIENT_TOKENS, m_calculator.CalculateGroupSize( 12, &descriptor, &group_repeat_count)); OLA_ASSERT_EQ( GroupSizeCalculator::INSUFFICIENT_TOKENS, m_calculator.CalculateGroupSize( 15, &descriptor, &group_repeat_count)); OLA_ASSERT_EQ( GroupSizeCalculator::NO_VARIABLE_GROUPS, m_calculator.CalculateGroupSize( 16, &descriptor, &group_repeat_count)); OLA_ASSERT_EQ( GroupSizeCalculator::EXTRA_TOKENS, m_calculator.CalculateGroupSize( 17, &descriptor, &group_repeat_count)); } /* * Test that a single variable-sized group passes */ void GroupSizeCalculatorTest::testSingleVariableSizedGroup() { vector group_fields, group_fields2; group_fields.push_back(new BoolFieldDescriptor("bool")); group_fields.push_back(new UInt8FieldDescriptor("uint8")); const FieldDescriptorGroup *variable_group = new FieldDescriptorGroup( "", group_fields, 0, 2); vector fields; // add some static fields as well fields.push_back(new UInt8FieldDescriptor("uint8")); fields.push_back(new UInt16FieldDescriptor("uint16")); fields.push_back(variable_group); fields.push_back(new UInt32FieldDescriptor("uint32")); Descriptor descriptor("Test Descriptor", fields); unsigned int group_repeat_count; OLA_ASSERT_EQ( GroupSizeCalculator::INSUFFICIENT_TOKENS, m_calculator.CalculateGroupSize( 0, &descriptor, &group_repeat_count)); OLA_ASSERT_EQ( GroupSizeCalculator::INSUFFICIENT_TOKENS, m_calculator.CalculateGroupSize( 2, &descriptor, &group_repeat_count)); OLA_ASSERT_EQ( GroupSizeCalculator::SINGLE_VARIABLE_GROUP, m_calculator.CalculateGroupSize( 3, &descriptor, &group_repeat_count)); OLA_ASSERT_EQ(0u, group_repeat_count); OLA_ASSERT_EQ( GroupSizeCalculator::SINGLE_VARIABLE_GROUP, m_calculator.CalculateGroupSize( 5, &descriptor, &group_repeat_count)); OLA_ASSERT_EQ(1u, group_repeat_count); OLA_ASSERT_EQ( GroupSizeCalculator::SINGLE_VARIABLE_GROUP, m_calculator.CalculateGroupSize( 7, &descriptor, &group_repeat_count)); OLA_ASSERT_EQ(2u, group_repeat_count); OLA_ASSERT_EQ( GroupSizeCalculator::EXTRA_TOKENS, m_calculator.CalculateGroupSize( 8, &descriptor, &group_repeat_count)); } /** * Test that multiple variable-sized groups fail */ void GroupSizeCalculatorTest::testMultipleVariableSizedGroups() { vector group_fields, group_fields2; group_fields.push_back(new BoolFieldDescriptor("bool")); group_fields.push_back(new UInt8FieldDescriptor("uint8")); const FieldDescriptorGroup *variable_group = new FieldDescriptorGroup( "", group_fields, 0, 2); group_fields2.push_back(new Int16FieldDescriptor("int16")); group_fields2.push_back(new UInt16FieldDescriptor("uint16")); group_fields2.push_back(new BoolFieldDescriptor("uint16")); const FieldDescriptorGroup *variable_group2 = new FieldDescriptorGroup( "", group_fields2, 0, 4); vector fields; fields.push_back(variable_group); fields.push_back(variable_group2); Descriptor descriptor("Test Descriptor", fields); unsigned int token_count, group_repeat_count; // first check these the static calculator OLA_ASSERT_TRUE( m_static_calculator.CalculateTokensRequired(variable_group, &token_count)); OLA_ASSERT_EQ(2u, token_count); OLA_ASSERT_TRUE( m_static_calculator.CalculateTokensRequired(variable_group2, &token_count)); OLA_ASSERT_EQ(3u, token_count); // now check the main calculator. OLA_ASSERT_EQ( GroupSizeCalculator::MULTIPLE_VARIABLE_GROUPS, m_calculator.CalculateGroupSize( 10, &descriptor, &group_repeat_count)); } /* * Test that a nested, variable sized groups fail */ void GroupSizeCalculatorTest::testNestedVariableSizedGroups() { vector fields, group_fields, group_fields2; group_fields.push_back(new BoolFieldDescriptor("bool")); group_fields.push_back(new UInt8FieldDescriptor("uint8")); group_fields2.push_back(new Int16FieldDescriptor("int16")); group_fields2.push_back(new FieldDescriptorGroup("", group_fields, 0, 2)); const FieldDescriptorGroup *nested_variable_group = new FieldDescriptorGroup( "", group_fields2, 0, 4); fields.push_back(new Int16FieldDescriptor("int16")); fields.push_back(nested_variable_group); Descriptor descriptor("Test Descriptor", fields); // first check these the static calculator unsigned int token_count, group_repeat_count; OLA_ASSERT_TRUE( !m_static_calculator.CalculateTokensRequired( nested_variable_group, &token_count)); // now check the main calculator. OLA_ASSERT_EQ( GroupSizeCalculator::NESTED_VARIABLE_GROUPS, m_calculator.CalculateGroupSize( 10, &descriptor, &group_repeat_count)); } ola-0.10.5.nojsmin/common/rdm/DiscoveryAgentTest.cpp0000644000175000017500000004013713023355232022027 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * DiscoveryAgentTest.cpp * Test fixture for the DiscoveryAgent class * Copyright (C) 2011 Simon Newton */ #include #include #include "ola/Logging.h" #include "ola/rdm/UID.h" #include "ola/rdm/UIDSet.h" #include "ola/rdm/DiscoveryAgent.h" #include "common/rdm/DiscoveryAgentTestHelper.h" #include "ola/testing/TestUtils.h" using ola::rdm::UID; using ola::rdm::UIDSet; using ola::rdm::DiscoveryAgent; using std::vector; typedef vector ResponderList; class DiscoveryAgentTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(DiscoveryAgentTest); CPPUNIT_TEST(testNoReponders); CPPUNIT_TEST(testSingleResponder); CPPUNIT_TEST(testResponderWithBroadcastUID); CPPUNIT_TEST(testMultipleResponders); CPPUNIT_TEST(testObnoxiousResponder); CPPUNIT_TEST(testRamblingResponder); CPPUNIT_TEST(testBipolarResponder); CPPUNIT_TEST(testBriefResponder); CPPUNIT_TEST(testNonMutingResponder); CPPUNIT_TEST(testFlakeyResponder); CPPUNIT_TEST(testProxy); CPPUNIT_TEST_SUITE_END(); public: DiscoveryAgentTest() : CppUnit::TestFixture(), m_callback_run(false) { } void testNoReponders(); void testSingleResponder(); void testResponderWithBroadcastUID(); void testMultipleResponders(); void testObnoxiousResponder(); void testRamblingResponder(); void testBriefResponder(); void testBipolarResponder(); void testNonMutingResponder(); void testFlakeyResponder(); void testProxy(); private: bool m_callback_run; void DiscoverySuccessful(const UIDSet *expected, bool successful, const UIDSet &received); void DiscoveryFailed(const UIDSet *expected, bool successful, const UIDSet &received); void PopulateResponderListFromUIDs(const UIDSet &uids, ResponderList *responders); }; CPPUNIT_TEST_SUITE_REGISTRATION(DiscoveryAgentTest); /** * Called when discovery completes */ void DiscoveryAgentTest::DiscoverySuccessful(const UIDSet *expected, bool successful, const UIDSet &received) { OLA_INFO << "in discovery callback, size is " << received.Size() << ", state: " << successful; OLA_ASSERT_TRUE(successful); OLA_ASSERT_EQ(*expected, received); m_callback_run = true; } /** * Called when discovery completes and fails for some reason. */ void DiscoveryAgentTest::DiscoveryFailed(const UIDSet *expected, bool successful, const UIDSet &received) { OLA_INFO << "in discovery callback, size is " << received.Size() << ", state: " << successful; OLA_ASSERT_FALSE(successful); OLA_ASSERT_EQ(*expected, received); m_callback_run = true; } /** * Build a vector of MockResponder objects with the given uids. */ void DiscoveryAgentTest::PopulateResponderListFromUIDs( const UIDSet &uids, ResponderList *responders) { UIDSet::Iterator iter = uids.Begin(); for (; iter != uids.End(); iter++) { responders->push_back(new MockResponder(*iter)); } } /* * Test the case where we have no responders. */ void DiscoveryAgentTest::testNoReponders() { UIDSet uids; ResponderList responders; PopulateResponderListFromUIDs(uids, &responders); MockDiscoveryTarget target(responders); DiscoveryAgent agent(&target); agent.StartFullDiscovery( ola::NewSingleCallback(this, &DiscoveryAgentTest::DiscoverySuccessful, static_cast(&uids))); OLA_ASSERT_TRUE(m_callback_run); OLA_ASSERT_EQ(3u, target.UnmuteCallCount()); // now try incremental target.ResetCounters(); agent.StartIncrementalDiscovery( ola::NewSingleCallback(this, &DiscoveryAgentTest::DiscoverySuccessful, static_cast(&uids))); OLA_ASSERT_TRUE(m_callback_run); OLA_ASSERT_EQ(3u, target.UnmuteCallCount()); } /** * Test single responder */ void DiscoveryAgentTest::testSingleResponder() { UIDSet uids; ResponderList responders; uids.AddUID(UID(1, 10)); PopulateResponderListFromUIDs(uids, &responders); MockDiscoveryTarget target(responders); DiscoveryAgent agent(&target); OLA_INFO << "starting discovery with one responder"; agent.StartFullDiscovery( ola::NewSingleCallback(this, &DiscoveryAgentTest::DiscoverySuccessful, static_cast(&uids))); OLA_ASSERT_TRUE(m_callback_run); m_callback_run = false; // now try incremental OLA_INFO << "starting incremental discovery with one responder"; agent.StartIncrementalDiscovery( ola::NewSingleCallback(this, &DiscoveryAgentTest::DiscoverySuccessful, static_cast(&uids))); OLA_ASSERT_TRUE(m_callback_run); } /** * Test single responder with a broadcast UID */ void DiscoveryAgentTest::testResponderWithBroadcastUID() { UIDSet uids; ResponderList responders; uids.AddUID(UID(0xffff, 0xffffffff)); PopulateResponderListFromUIDs(uids, &responders); MockDiscoveryTarget target(responders); DiscoveryAgent agent(&target); agent.StartFullDiscovery( ola::NewSingleCallback(this, &DiscoveryAgentTest::DiscoverySuccessful, static_cast(&uids))); OLA_ASSERT_TRUE(m_callback_run); m_callback_run = false; // now try incremental agent.StartIncrementalDiscovery( ola::NewSingleCallback(this, &DiscoveryAgentTest::DiscoverySuccessful, static_cast(&uids))); OLA_ASSERT_TRUE(m_callback_run); } /** * Test multiple responders */ void DiscoveryAgentTest::testMultipleResponders() { UIDSet uids; ResponderList responders; UID uid_to_remove(0x7a70, 0x00002001); uids.AddUID(uid_to_remove); uids.AddUID(UID(0x7a70, 0x00002002)); uids.AddUID(UID(0x7a77, 0x00002002)); PopulateResponderListFromUIDs(uids, &responders); MockDiscoveryTarget target(responders); DiscoveryAgent agent(&target); OLA_INFO << "starting discovery with two responder"; agent.StartFullDiscovery( ola::NewSingleCallback(this, &DiscoveryAgentTest::DiscoverySuccessful, static_cast(&uids))); OLA_ASSERT_TRUE(m_callback_run); m_callback_run = false; // now try incremental, adding one uid and removing another UID uid_to_add(0x8080, 0x00103456); uids.RemoveUID(uid_to_remove); uids.AddUID(uid_to_add); // update the responder list target.RemoveResponder(uid_to_remove); target.AddResponder(new MockResponder(uid_to_add)); OLA_INFO << "starting incremental discovery with modified responder list"; agent.StartIncrementalDiscovery( ola::NewSingleCallback(this, &DiscoveryAgentTest::DiscoverySuccessful, static_cast(&uids))); OLA_ASSERT_TRUE(m_callback_run); } /** * Test a responder that continues to responder when muted. */ void DiscoveryAgentTest::testObnoxiousResponder() { UIDSet uids; ResponderList responders; uids.AddUID(UID(0x7a70, 0x00002002)); PopulateResponderListFromUIDs(uids, &responders); // add the ObnoxiousResponders UID obnoxious_uid = UID(0x7a77, 0x00002002); UID obnoxious_uid2 = UID(0x7a77, 0x00003030); uids.AddUID(obnoxious_uid); uids.AddUID(obnoxious_uid2); responders.push_back(new ObnoxiousResponder(obnoxious_uid)); responders.push_back(new ObnoxiousResponder(obnoxious_uid2)); MockDiscoveryTarget target(responders); DiscoveryAgent agent(&target); OLA_INFO << "starting discovery with obnoxious responder"; agent.StartFullDiscovery( ola::NewSingleCallback(this, &DiscoveryAgentTest::DiscoveryFailed, static_cast(&uids))); OLA_ASSERT_TRUE(m_callback_run); m_callback_run = false; // now try incremental, adding one uid and removing another OLA_INFO << "starting incremental discovery with modified responder list"; agent.StartIncrementalDiscovery( ola::NewSingleCallback(this, &DiscoveryAgentTest::DiscoveryFailed, static_cast(&uids))); OLA_ASSERT_TRUE(m_callback_run); } /** * Test a responder that replies with responses larger than the DUB size */ void DiscoveryAgentTest::testRamblingResponder() { const UID normal_responder_uid(0x7a70, 0x00002002); const UID rambling_responder_uid(0x7a77, 0x0002002); UIDSet uids; ResponderList responders; uids.AddUID(normal_responder_uid); PopulateResponderListFromUIDs(uids, &responders); // add the RamblingResponder responders.push_back(new RamblingResponder(rambling_responder_uid)); MockDiscoveryTarget target(responders); DiscoveryAgent agent(&target); uids.AddUID(rambling_responder_uid); OLA_INFO << "starting discovery with rambling responder"; agent.StartFullDiscovery( ola::NewSingleCallback(this, &DiscoveryAgentTest::DiscoverySuccessful, static_cast(&uids))); OLA_ASSERT_TRUE(m_callback_run); } /** * Test a responder that replies with too little data. */ void DiscoveryAgentTest::testBriefResponder() { UIDSet uids; ResponderList responders; uids.AddUID(UID(0x7a70, 0x00002002)); PopulateResponderListFromUIDs(uids, &responders); // add the BriefResponder UID brief_uid = UID(0x7a77, 0x00002002); responders.push_back(new BriefResponder(brief_uid)); MockDiscoveryTarget target(responders); DiscoveryAgent agent(&target); OLA_INFO << "starting discovery with brief responder"; agent.StartFullDiscovery( ola::NewSingleCallback(this, &DiscoveryAgentTest::DiscoveryFailed, static_cast(&uids))); OLA_ASSERT_TRUE(m_callback_run); } /** * Test a responder that can't make up it's mind about it's UID */ void DiscoveryAgentTest::testBipolarResponder() { UIDSet uids; ResponderList responders; uids.AddUID(UID(0x7a70, 0x00002002)); PopulateResponderListFromUIDs(uids, &responders); // add the BiPolarResponders UID bipolar_uid = UID(0x7a77, 0x00002002); UID bipolar_uid2 = UID(0x7a77, 0x00003030); responders.push_back(new BiPolarResponder(bipolar_uid)); responders.push_back(new BiPolarResponder(bipolar_uid2)); MockDiscoveryTarget target(responders); DiscoveryAgent agent(&target); OLA_INFO << "starting discovery with BiPolarResponder responder"; agent.StartFullDiscovery( ola::NewSingleCallback(this, &DiscoveryAgentTest::DiscoveryFailed, static_cast(&uids))); OLA_ASSERT_TRUE(m_callback_run); m_callback_run = false; // now try incremental, adding one uid and removing another OLA_INFO << "starting incremental discovery with modified responder list"; agent.StartIncrementalDiscovery( ola::NewSingleCallback(this, &DiscoveryAgentTest::DiscoveryFailed, static_cast(&uids))); OLA_ASSERT_TRUE(m_callback_run); } /** * Test a responder that doesn't respond to a mute message. */ void DiscoveryAgentTest::testNonMutingResponder() { UIDSet uids; ResponderList responders; uids.AddUID(UID(0x7a70, 0x00002002)); PopulateResponderListFromUIDs(uids, &responders); // add the NonMutingResponders UID non_muting_uid = UID(0x7a77, 0x00002002); UID non_muting_uid2 = UID(0x7a77, 0x00003030); responders.push_back(new NonMutingResponder(non_muting_uid)); responders.push_back(new NonMutingResponder(non_muting_uid2)); MockDiscoveryTarget target(responders); DiscoveryAgent agent(&target); OLA_INFO << "starting discovery with NonMutingResponder responder"; agent.StartFullDiscovery( ola::NewSingleCallback(this, &DiscoveryAgentTest::DiscoveryFailed, static_cast(&uids))); OLA_ASSERT_TRUE(m_callback_run); m_callback_run = false; } /** * Test a responder that only acks a mute request after N attempts. */ void DiscoveryAgentTest::testFlakeyResponder() { UIDSet uids; ResponderList responders; uids.AddUID(UID(0x7a70, 0x00002002)); PopulateResponderListFromUIDs(uids, &responders); // add the NonMutingResponders UID flakey_uid = UID(0x7a77, 0x00002002); UID flakey_uid2 = UID(0x7a77, 0x00003030); uids.AddUID(flakey_uid); uids.AddUID(flakey_uid2); FlakeyMutingResponder *flakey_responder1 = new FlakeyMutingResponder( flakey_uid); FlakeyMutingResponder *flakey_responder2 = new FlakeyMutingResponder( flakey_uid2); responders.push_back(flakey_responder1); responders.push_back(flakey_responder2); MockDiscoveryTarget target(responders); DiscoveryAgent agent(&target); OLA_INFO << "starting discovery with flakey responder"; agent.StartFullDiscovery( ola::NewSingleCallback(this, &DiscoveryAgentTest::DiscoverySuccessful, static_cast(&uids))); OLA_ASSERT_TRUE(m_callback_run); m_callback_run = false; // now try incremental flakey_responder1->Reset(); flakey_responder2->Reset(); OLA_INFO << "starting incremental discovery with flakey responder list"; agent.StartIncrementalDiscovery( ola::NewSingleCallback(this, &DiscoveryAgentTest::DiscoverySuccessful, static_cast(&uids))); OLA_ASSERT_TRUE(m_callback_run); } /** * Test a proxy. */ void DiscoveryAgentTest::testProxy() { UIDSet proxied_uids, proxied_uids2; ResponderList proxied_responders, proxied_responders2, responders; proxied_uids.AddUID(UID(0x7a70, 0x00002002)); proxied_uids.AddUID(UID(0x8080, 0x00001234)); proxied_uids.AddUID(UID(0x9000, 0x00005678)); proxied_uids.AddUID(UID(0x1020, 0x00005678)); PopulateResponderListFromUIDs(proxied_uids, &proxied_responders); proxied_uids2.AddUID(UID(0x7a71, 0x00002002)); proxied_uids2.AddUID(UID(0x8081, 0x00001234)); proxied_uids2.AddUID(UID(0x9001, 0x00005678)); proxied_uids2.AddUID(UID(0x1021, 0x00005678)); PopulateResponderListFromUIDs(proxied_uids2, &proxied_responders2); // add the two proxies UIDSet uids = proxied_uids.Union(proxied_uids2); UID proxy_uid = UID(0x1010, 0x00002002); uids.AddUID(proxy_uid); responders.push_back(new ProxyResponder(proxy_uid, proxied_responders)); UID proxy_uid2 = UID(0x1010, 0x00001999); uids.AddUID(proxy_uid2); responders.push_back(new ProxyResponder(proxy_uid2, proxied_responders2)); // add some other responders UID responder(0x0001, 0x00000001); UID responder2(0x0001, 0x10000001); uids.AddUID(responder); uids.AddUID(responder2); responders.push_back(new MockResponder(responder)); responders.push_back(new MockResponder(responder2)); MockDiscoveryTarget target(responders); DiscoveryAgent agent(&target); OLA_INFO << "starting discovery with Proxy responder"; agent.StartFullDiscovery( ola::NewSingleCallback(this, &DiscoveryAgentTest::DiscoverySuccessful, static_cast(&uids))); OLA_ASSERT_TRUE(m_callback_run); m_callback_run = false; } ola-0.10.5.nojsmin/common/rdm/RDMAPITest.cpp0000644000175000017500000010626113023355232020056 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * RDMAPITest.cpp * Test fixture for the RDM API class * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include #include "ola/StringUtils.h" #include "ola/base/Macro.h" #include "ola/network/NetworkUtils.h" #include "ola/rdm/RDMAPI.h" #include "ola/rdm/UID.h" #include "ola/rdm/RDMAPIImplInterface.h" #include "ola/testing/TestUtils.h" using ola::NewSingleCallback; using ola::network::HostToNetwork; using ola::rdm::RDMAPI; using ola::rdm::ResponseStatus; using ola::rdm::ResponseStatus; using ola::rdm::UID; using std::deque; using std::string; using std::vector; class ExpectedResult { public: unsigned int universe; const UID uid; uint16_t sub_device; uint16_t pid; const string return_data; const uint8_t *data; unsigned int data_length; ExpectedResult(unsigned int universe, const UID &uid, uint16_t sub_device, uint16_t pid, const string &return_data, const uint8_t *data_arg = NULL, unsigned int data_length = 0): universe(universe), uid(uid), sub_device(sub_device), pid(pid), return_data(return_data), data(NULL), data_length(data_length) { if (data_arg) { uint8_t *d = new uint8_t[data_length]; memcpy(d, data_arg, data_length); data = d; } } ~ExpectedResult() { if (data) delete[] data; } }; class MockRDMAPIImpl: public ola::rdm::RDMAPIImplInterface { public: bool RDMGet(rdm_callback *callback, unsigned int universe, const UID &uid, uint16_t sub_device, uint16_t pid, const uint8_t *data = NULL, unsigned int data_length = 0) { OLA_ASSERT_TRUE(m_get_expected.size()); const ExpectedResult *result = m_get_expected.front(); OLA_ASSERT_EQ(result->universe, universe); OLA_ASSERT_EQ(result->uid, uid); OLA_ASSERT_EQ(result->sub_device, sub_device); OLA_ASSERT_EQ(result->pid, pid); (void) data; (void) data_length; ResponseStatus status; status.response_code = uid.IsBroadcast() ? ola::rdm::RDM_WAS_BROADCAST: ola::rdm::RDM_COMPLETED_OK; status.response_type = ola::rdm::RDM_ACK; status.message_count = 0; callback->Run(status, result->return_data); delete result; m_get_expected.pop_front(); return true; } bool RDMGet(rdm_pid_callback *callback, unsigned int universe, const UID &uid, uint16_t sub_device, uint16_t pid, const uint8_t *data = NULL, unsigned int data_length = 0) { OLA_ASSERT_TRUE(m_get_expected.size()); const ExpectedResult *result = m_get_expected.front(); OLA_ASSERT_EQ(result->universe, universe); OLA_ASSERT_EQ(result->uid, uid); OLA_ASSERT_EQ(result->sub_device, sub_device); OLA_ASSERT_EQ(result->pid, pid); (void) data; (void) data_length; ResponseStatus status; status.response_code = uid.IsBroadcast() ? ola::rdm::RDM_WAS_BROADCAST: ola::rdm::RDM_COMPLETED_OK; status.response_type = ola::rdm::RDM_ACK; status.message_count = 0; callback->Run(status, pid, result->return_data); delete result; m_get_expected.pop_front(); return true; } bool RDMSet(rdm_callback *callback, unsigned int universe, const UID &uid, uint16_t sub_device, uint16_t pid, const uint8_t *data = NULL, unsigned int data_length = 0) { OLA_ASSERT_TRUE(m_set_expected.size()); const ExpectedResult *result = m_set_expected.front(); OLA_ASSERT_EQ(result->universe, universe); OLA_ASSERT_EQ(result->uid, uid); OLA_ASSERT_EQ(result->sub_device, sub_device); OLA_ASSERT_EQ(result->pid, pid); if (result->data) { OLA_ASSERT_EQ(result->data_length, data_length); OLA_ASSERT_EQ(0, memcmp(result->data, data, data_length)); } ResponseStatus status; status.response_code = uid.IsBroadcast() ? ola::rdm::RDM_WAS_BROADCAST: ola::rdm::RDM_COMPLETED_OK; status.response_type = ola::rdm::RDM_ACK; status.message_count = 0; callback->Run(status, result->return_data); delete result; m_set_expected.pop_front(); return true; } void AddExpectedGet( // const ResponseStatus &status, const string &return_data, unsigned int universe, const UID &uid, uint16_t sub_device, uint16_t pid, const uint8_t *data = NULL, unsigned int data_length = 0) { ExpectedResult *expected_result = new ExpectedResult(universe, uid, sub_device, pid, return_data, data, data_length); m_get_expected.push_back(expected_result); } void AddExpectedSet(unsigned int universe, const UID &uid, uint16_t sub_device, uint16_t pid, const uint8_t *data = NULL, unsigned int data_length = 0) { string s; ExpectedResult *expected_result = new ExpectedResult(universe, uid, sub_device, pid, s, data, data_length); m_set_expected.push_back(expected_result); } void Verify() { OLA_ASSERT_FALSE(m_get_expected.size()); OLA_ASSERT_FALSE(m_set_expected.size()); } private: deque m_get_expected; deque m_set_expected; }; class RDMAPITest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(RDMAPITest); CPPUNIT_TEST(testProxyCommands); CPPUNIT_TEST(testNetworkCommands); CPPUNIT_TEST(testRDMInformation); CPPUNIT_TEST(testProductInformation); CPPUNIT_TEST(testDmxSetup); CPPUNIT_TEST_SUITE_END(); public: RDMAPITest(): m_api(&m_impl), m_uid(1, 2), m_bcast_uid(UID::AllDevices()), m_group_uid(UID::VendorcastAddress(52)), m_test_uid1(4, 5), m_test_uid2(7, 9) { } void testProxyCommands(); void testNetworkCommands(); void testRDMInformation(); void testProductInformation(); void testDmxSetup(); void setUp() {} void tearDown(); private: static const unsigned int UNIVERSE = 1; static const char BROADCAST_ERROR[]; static const char DEVICE_RANGE_ERROR[]; static const char DEVICE_RANGE_BCAST_ERROR[]; static const char TEST_DESCRIPTION[]; MockRDMAPIImpl m_impl; RDMAPI m_api; UID m_uid; UID m_bcast_uid; UID m_group_uid; UID m_test_uid1; UID m_test_uid2; // check that a RDM call failed because we tried to send to the bcast UID void CheckForBroadcastError(string *error) { OLA_ASSERT_EQ(string(BROADCAST_ERROR), *error); error->clear(); } // check that a RDM call failed because we tried to send to all devices void CheckForDeviceRangeError(string *error) { OLA_ASSERT_EQ(string(DEVICE_RANGE_ERROR), *error); error->clear(); } void CheckForDeviceRangeBcastError(string *error) { OLA_ASSERT_EQ(string(DEVICE_RANGE_BCAST_ERROR), *error); error->clear(); } // check that a RDM command was successful void CheckResponseStatus(const ResponseStatus &status) { OLA_ASSERT_EQ(ola::rdm::RDM_COMPLETED_OK, status.response_code); } // check that a RDM command was successful and broadcast void CheckWasBroadcast(const ResponseStatus &status) { OLA_ASSERT_EQ(ola::rdm::RDM_WAS_BROADCAST, status.response_code); } void CheckProxiedDeviceCount(const ResponseStatus &status, uint16_t count, bool changed) { CheckResponseStatus(status); OLA_ASSERT_EQ(static_cast(2), count); OLA_ASSERT_EQ(false, changed); } void CheckProxiedDevices(const ResponseStatus &status, const vector &devices) { CheckResponseStatus(status); OLA_ASSERT_EQ(static_cast(2), devices.size()); OLA_ASSERT_EQ(m_test_uid1, devices[0]); OLA_ASSERT_EQ(m_test_uid2, devices[1]); } void CheckCommsStatus(const ResponseStatus &status, uint16_t short_message, uint16_t length_mismatch, uint16_t checksum_fail) { CheckResponseStatus(status); OLA_ASSERT_EQ(static_cast(14), short_message); OLA_ASSERT_EQ(static_cast(187), length_mismatch); OLA_ASSERT_EQ(static_cast(92), checksum_fail); } void CheckLabel(const ResponseStatus &status, const string &description) { CheckResponseStatus(status); OLA_ASSERT_EQ(string(TEST_DESCRIPTION), description); } void CheckSupportedParams(const ResponseStatus &status, const vector ¶ms) { CheckResponseStatus(status); OLA_ASSERT_EQ(static_cast(3), params.size()); // params are sorted OLA_ASSERT_EQ(static_cast(0x00aa), params[0]); OLA_ASSERT_EQ(static_cast(0x1234), params[1]); OLA_ASSERT_EQ(static_cast(0xabcd), params[2]); } void CheckParameterDescription( const ResponseStatus &status, const ola::rdm::ParameterDescriptor &description) { CheckResponseStatus(status); OLA_ASSERT_EQ(static_cast(0x1234), description.pid); OLA_ASSERT_EQ(static_cast(10), description.pdl_size); OLA_ASSERT_EQ(static_cast(ola::rdm::DS_UNSIGNED_DWORD), description.data_type); OLA_ASSERT_EQ(static_cast(ola::rdm::CC_GET), description.command_class); OLA_ASSERT_EQ(static_cast(ola::rdm::UNITS_METERS), description.unit); OLA_ASSERT_EQ(static_cast(ola::rdm::PREFIX_KILO), description.prefix); OLA_ASSERT_EQ(static_cast(0), description.min_value); OLA_ASSERT_EQ(static_cast(200000), description.max_value); OLA_ASSERT_EQ(static_cast(1000), description.default_value); OLA_ASSERT_EQ(string(TEST_DESCRIPTION).size(), description.description.size()); OLA_ASSERT_EQ(string(TEST_DESCRIPTION), description.description); } void CheckMalformedParameterDescription( const ResponseStatus &status, const ola::rdm::ParameterDescriptor &description) { OLA_ASSERT_EQ(ola::rdm::RDM_COMPLETED_OK, status.response_code); (void) description; } void CheckDeviceInfo(const ResponseStatus &status, const ola::rdm::DeviceDescriptor &descriptor) { CheckResponseStatus(status); OLA_ASSERT_EQ(static_cast(1), descriptor.protocol_version_high); OLA_ASSERT_EQ(static_cast(0), descriptor.protocol_version_low); OLA_ASSERT_EQ(static_cast(2), descriptor.device_model); OLA_ASSERT_EQ(static_cast(3), descriptor.product_category); OLA_ASSERT_EQ(static_cast(0x12345678), descriptor.software_version); OLA_ASSERT_EQ(static_cast(400), descriptor.dmx_footprint); OLA_ASSERT_EQ(static_cast(1), descriptor.current_personality); OLA_ASSERT_EQ(static_cast(2), descriptor.personality_count); OLA_ASSERT_EQ(static_cast(12), descriptor.dmx_start_address); OLA_ASSERT_EQ(static_cast(10), descriptor.sub_device_count); OLA_ASSERT_EQ(static_cast(4), descriptor.sensor_count); } void CheckProductDetailList(const ResponseStatus &status, const vector ¶ms) { CheckResponseStatus(status); OLA_ASSERT_EQ(static_cast(3), params.size()); OLA_ASSERT_EQ(static_cast(0x5678), params[0]); OLA_ASSERT_EQ(static_cast(0xfedc), params[1]); OLA_ASSERT_EQ(static_cast(0xaa00), params[2]); } void CheckDMXStartAddress(const ResponseStatus &status, uint16_t start_address) { CheckResponseStatus(status); OLA_ASSERT_EQ(static_cast(44), start_address); } }; const char RDMAPITest::BROADCAST_ERROR[] = "Cannot send to broadcast address"; const char RDMAPITest::DEVICE_RANGE_ERROR[] = "Sub device must be <= 0x0200"; const char RDMAPITest::DEVICE_RANGE_BCAST_ERROR[] = "Sub device must be <= 0x0200 or 0xffff"; const char RDMAPITest::TEST_DESCRIPTION[] = "This is a description"; void RDMAPITest::tearDown() { m_impl.Verify(); } CPPUNIT_TEST_SUITE_REGISTRATION(RDMAPITest); /* * Test the proxied commands work. */ void RDMAPITest::testProxyCommands() { string error; // get proxied device count OLA_ASSERT_FALSE(m_api.GetProxiedDeviceCount( UNIVERSE, m_bcast_uid, NewSingleCallback(this, &RDMAPITest::CheckProxiedDeviceCount), &error)); CheckForBroadcastError(&error); OLA_ASSERT_FALSE(m_api.GetProxiedDeviceCount( UNIVERSE, m_group_uid, NewSingleCallback(this, &RDMAPITest::CheckProxiedDeviceCount), &error)); CheckForBroadcastError(&error); struct { uint16_t count; uint8_t changed; } count_response; count_response.count = HostToNetwork(static_cast(2)); count_response.changed = 0; string s(reinterpret_cast(&count_response), sizeof(count_response)); m_impl.AddExpectedGet(s, UNIVERSE, m_uid, ola::rdm::ROOT_RDM_DEVICE, ola::rdm::PID_PROXIED_DEVICE_COUNT); OLA_ASSERT_TRUE(m_api.GetProxiedDeviceCount( UNIVERSE, m_uid, NewSingleCallback(this, &RDMAPITest::CheckProxiedDeviceCount), &error)); // get proxied devices OLA_ASSERT_FALSE(m_api.GetProxiedDevices( UNIVERSE, m_bcast_uid, NewSingleCallback(this, &RDMAPITest::CheckProxiedDevices), &error)); CheckForBroadcastError(&error); OLA_ASSERT_FALSE(m_api.GetProxiedDevices( UNIVERSE, m_group_uid, NewSingleCallback(this, &RDMAPITest::CheckProxiedDevices), &error)); CheckForBroadcastError(&error); struct { uint8_t uid1[UID::UID_SIZE]; uint8_t uid2[UID::UID_SIZE]; } uids_response; m_test_uid1.Pack(uids_response.uid1, UID::UID_SIZE); m_test_uid2.Pack(uids_response.uid2, UID::UID_SIZE); string s2(reinterpret_cast(&uids_response), sizeof(uids_response)); m_impl.AddExpectedGet(s2, UNIVERSE, m_uid, ola::rdm::ROOT_RDM_DEVICE, ola::rdm::PID_PROXIED_DEVICES); OLA_ASSERT_TRUE(m_api.GetProxiedDevices( UNIVERSE, m_uid, NewSingleCallback(this, &RDMAPITest::CheckProxiedDevices), &error)); } /* * test that network commands work */ void RDMAPITest::testNetworkCommands() { string error; // get comms status OLA_ASSERT_FALSE(m_api.GetCommStatus( UNIVERSE, m_bcast_uid, NewSingleCallback(this, &RDMAPITest::CheckCommsStatus), &error)); CheckForBroadcastError(&error); OLA_ASSERT_FALSE(m_api.GetCommStatus( UNIVERSE, m_group_uid, NewSingleCallback(this, &RDMAPITest::CheckCommsStatus), &error)); CheckForBroadcastError(&error); struct { uint16_t short_message; uint16_t length_mismatch; uint16_t checksum_fail; } comms_response; comms_response.short_message = HostToNetwork(static_cast(14)); comms_response.length_mismatch = HostToNetwork(static_cast(187)); comms_response.checksum_fail = HostToNetwork(static_cast(92)); string s(reinterpret_cast(&comms_response), sizeof(comms_response)); m_impl.AddExpectedGet(s, UNIVERSE, m_uid, ola::rdm::ROOT_RDM_DEVICE, ola::rdm::PID_COMMS_STATUS); OLA_ASSERT_TRUE(m_api.GetCommStatus( UNIVERSE, m_uid, NewSingleCallback(this, &RDMAPITest::CheckCommsStatus), &error)); // clear comms status m_impl.AddExpectedSet(UNIVERSE, m_bcast_uid, ola::rdm::ROOT_RDM_DEVICE, ola::rdm::PID_COMMS_STATUS); OLA_ASSERT_TRUE(m_api.ClearCommStatus( UNIVERSE, m_bcast_uid, NewSingleCallback(this, &RDMAPITest::CheckWasBroadcast), &error)); m_impl.AddExpectedSet(UNIVERSE, m_uid, ola::rdm::ROOT_RDM_DEVICE, ola::rdm::PID_COMMS_STATUS); OLA_ASSERT_TRUE(m_api.ClearCommStatus( UNIVERSE, m_uid, NewSingleCallback(this, &RDMAPITest::CheckResponseStatus), &error)); // TODO(simon): test status message here // status id description uint16_t status_id = 12; OLA_ASSERT_FALSE(m_api.GetStatusIdDescription( UNIVERSE, m_bcast_uid, status_id, NewSingleCallback(this, &RDMAPITest::CheckLabel), &error)); CheckForBroadcastError(&error); OLA_ASSERT_FALSE(m_api.GetStatusIdDescription( UNIVERSE, m_group_uid, status_id, NewSingleCallback(this, &RDMAPITest::CheckLabel), &error)); CheckForBroadcastError(&error); m_impl.AddExpectedGet(string(TEST_DESCRIPTION), UNIVERSE, m_uid, ola::rdm::ROOT_RDM_DEVICE, ola::rdm::PID_STATUS_ID_DESCRIPTION); OLA_ASSERT_TRUE(m_api.GetStatusIdDescription( UNIVERSE, m_uid, status_id, NewSingleCallback(this, &RDMAPITest::CheckLabel), &error)); // clear status id uint16_t sub_device = 3; m_impl.AddExpectedSet(UNIVERSE, m_bcast_uid, sub_device, ola::rdm::PID_CLEAR_STATUS_ID); OLA_ASSERT_TRUE(m_api.ClearStatusId( UNIVERSE, m_bcast_uid, sub_device, NewSingleCallback(this, &RDMAPITest::CheckWasBroadcast), &error)); m_impl.AddExpectedSet(UNIVERSE, m_uid, ola::rdm::ROOT_RDM_DEVICE, ola::rdm::PID_CLEAR_STATUS_ID); OLA_ASSERT_TRUE(m_api.ClearStatusId( UNIVERSE, m_uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMAPITest::CheckResponseStatus), &error)); // TODO(simon): add sub device reporting threshold here } /* * Test RDM Information commands work correctly */ void RDMAPITest::testRDMInformation() { string error; // supported params struct { uint16_t param1; uint16_t param2; uint16_t param3; } pid_list; pid_list.param1 = HostToNetwork(static_cast(0x1234)); pid_list.param2 = HostToNetwork(static_cast(0xabcd)); pid_list.param3 = HostToNetwork(static_cast(0x00aa)); uint16_t sub_device = 1; OLA_ASSERT_FALSE(m_api.GetSupportedParameters( UNIVERSE, m_bcast_uid, sub_device, NewSingleCallback(this, &RDMAPITest::CheckSupportedParams), &error)); CheckForBroadcastError(&error); OLA_ASSERT_FALSE(m_api.GetSupportedParameters( UNIVERSE, m_group_uid, sub_device, NewSingleCallback(this, &RDMAPITest::CheckSupportedParams), &error)); CheckForBroadcastError(&error); string s(reinterpret_cast(&pid_list), sizeof(pid_list)); m_impl.AddExpectedGet(s, UNIVERSE, m_uid, ola::rdm::ROOT_RDM_DEVICE, ola::rdm::PID_SUPPORTED_PARAMETERS); OLA_ASSERT_TRUE(m_api.GetSupportedParameters( UNIVERSE, m_uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMAPITest::CheckSupportedParams), &error)); // parameter description uint16_t pid = 16; OLA_ASSERT_FALSE(m_api.GetParameterDescription( UNIVERSE, m_bcast_uid, pid, NewSingleCallback(this, &RDMAPITest::CheckMalformedParameterDescription), &error)); CheckForBroadcastError(&error); OLA_ASSERT_FALSE(m_api.GetParameterDescription( UNIVERSE, m_group_uid, pid, NewSingleCallback(this, &RDMAPITest::CheckMalformedParameterDescription), &error)); CheckForBroadcastError(&error); s = ""; m_impl.AddExpectedGet(s, UNIVERSE, m_uid, ola::rdm::ROOT_RDM_DEVICE, ola::rdm::PID_PARAMETER_DESCRIPTION); OLA_ASSERT_TRUE(m_api.GetParameterDescription( UNIVERSE, m_uid, pid, NewSingleCallback(this, &RDMAPITest::CheckMalformedParameterDescription), &error)); PACK( struct param_info_s { uint16_t pid; uint8_t pdl_size; uint8_t data_type; uint8_t command_class; uint8_t type; uint8_t unit; uint8_t prefix; uint32_t min_value; uint32_t max_value; uint32_t default_value; char label[32]; }); STATIC_ASSERT(sizeof(param_info_s) == 52); struct param_info_s param_info; param_info.pid = HostToNetwork(static_cast(0x1234)); param_info.pdl_size = 10; param_info.data_type = ola::rdm::DS_UNSIGNED_DWORD; param_info.command_class = ola::rdm::CC_GET; param_info.type = 0; param_info.unit = ola::rdm::UNITS_METERS; param_info.prefix = ola::rdm::PREFIX_KILO; param_info.min_value = HostToNetwork(static_cast(0)); param_info.max_value = HostToNetwork(static_cast(200000)); param_info.default_value = HostToNetwork(static_cast(1000)); strncpy(param_info.label, TEST_DESCRIPTION, sizeof(param_info.label)); string s2(reinterpret_cast(¶m_info), sizeof(param_info) - sizeof(param_info.label) + strlen(TEST_DESCRIPTION)); m_impl.AddExpectedGet(s2, UNIVERSE, m_uid, ola::rdm::ROOT_RDM_DEVICE, ola::rdm::PID_PARAMETER_DESCRIPTION); OLA_ASSERT_TRUE(m_api.GetParameterDescription( UNIVERSE, m_uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMAPITest::CheckParameterDescription), &error)); } /* * Check that the product information commands work correctly */ void RDMAPITest::testProductInformation() { string error; uint16_t sub_device = 1; // device info PACK( struct device_info_s { uint8_t version_high; uint8_t version_low; uint16_t model; uint16_t product_category; uint32_t software_version; uint16_t dmx_footprint; uint8_t current_personality; uint8_t personality_count; uint16_t dmx_start_address; uint16_t sub_device_count; uint8_t sensor_count; }); STATIC_ASSERT(sizeof(device_info_s) == 19); struct device_info_s device_info; device_info.version_high = 1; device_info.version_low = 0; device_info.model = HostToNetwork(static_cast(2)); device_info.product_category = HostToNetwork(static_cast(3)); device_info.software_version = HostToNetwork( static_cast(0x12345678)); device_info.dmx_footprint = HostToNetwork(static_cast(400)); device_info.current_personality = 1; device_info.personality_count = 2; device_info.dmx_start_address = HostToNetwork(static_cast(12)); device_info.sub_device_count = HostToNetwork(static_cast(10)); device_info.sensor_count = 4; OLA_ASSERT_FALSE(m_api.GetDeviceInfo( UNIVERSE, m_bcast_uid, sub_device, NewSingleCallback(this, &RDMAPITest::CheckDeviceInfo), &error)); CheckForBroadcastError(&error); OLA_ASSERT_FALSE(m_api.GetDeviceInfo( UNIVERSE, m_group_uid, sub_device, NewSingleCallback(this, &RDMAPITest::CheckDeviceInfo), &error)); CheckForBroadcastError(&error); string s(reinterpret_cast(&device_info), sizeof(device_info)); m_impl.AddExpectedGet(s, UNIVERSE, m_uid, ola::rdm::ROOT_RDM_DEVICE, ola::rdm::PID_DEVICE_INFO); OLA_ASSERT_TRUE(m_api.GetDeviceInfo( UNIVERSE, m_uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMAPITest::CheckDeviceInfo), &error)); // product detail id list struct { uint16_t detail1; uint16_t detail2; uint16_t detail3; } detail_list; detail_list.detail1 = HostToNetwork(static_cast(0x5678)); detail_list.detail2 = HostToNetwork(static_cast(0xfedc)); detail_list.detail3 = HostToNetwork(static_cast(0xaa00)); OLA_ASSERT_FALSE(m_api.GetProductDetailIdList( UNIVERSE, m_bcast_uid, sub_device, NewSingleCallback(this, &RDMAPITest::CheckProductDetailList), &error)); CheckForBroadcastError(&error); OLA_ASSERT_FALSE(m_api.GetProductDetailIdList( UNIVERSE, m_group_uid, sub_device, NewSingleCallback(this, &RDMAPITest::CheckProductDetailList), &error)); CheckForBroadcastError(&error); string s2(reinterpret_cast(&detail_list), sizeof(detail_list)); m_impl.AddExpectedGet(s2, UNIVERSE, m_uid, ola::rdm::ROOT_RDM_DEVICE, ola::rdm::PID_PRODUCT_DETAIL_ID_LIST); OLA_ASSERT_TRUE(m_api.GetProductDetailIdList( UNIVERSE, m_uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMAPITest::CheckProductDetailList), &error)); // device model description OLA_ASSERT_FALSE(m_api.GetDeviceModelDescription( UNIVERSE, m_bcast_uid, sub_device, NewSingleCallback(this, &RDMAPITest::CheckLabel), &error)); CheckForBroadcastError(&error); OLA_ASSERT_FALSE(m_api.GetDeviceModelDescription( UNIVERSE, m_group_uid, sub_device, NewSingleCallback(this, &RDMAPITest::CheckLabel), &error)); CheckForBroadcastError(&error); m_impl.AddExpectedGet(string(TEST_DESCRIPTION), UNIVERSE, m_uid, sub_device, ola::rdm::PID_DEVICE_MODEL_DESCRIPTION); OLA_ASSERT_TRUE(m_api.GetDeviceModelDescription( UNIVERSE, m_uid, sub_device, NewSingleCallback(this, &RDMAPITest::CheckLabel), &error)); // manufacturer label OLA_ASSERT_FALSE(m_api.GetManufacturerLabel( UNIVERSE, m_bcast_uid, sub_device, NewSingleCallback(this, &RDMAPITest::CheckLabel), &error)); CheckForBroadcastError(&error); OLA_ASSERT_FALSE(m_api.GetManufacturerLabel( UNIVERSE, m_group_uid, sub_device, NewSingleCallback(this, &RDMAPITest::CheckLabel), &error)); CheckForBroadcastError(&error); m_impl.AddExpectedGet(string(TEST_DESCRIPTION), UNIVERSE, m_uid, sub_device, ola::rdm::PID_MANUFACTURER_LABEL); OLA_ASSERT_TRUE(m_api.GetManufacturerLabel( UNIVERSE, m_uid, sub_device, NewSingleCallback(this, &RDMAPITest::CheckLabel), &error)); // get device label OLA_ASSERT_FALSE(m_api.GetDeviceLabel( UNIVERSE, m_bcast_uid, sub_device, NewSingleCallback(this, &RDMAPITest::CheckLabel), &error)); CheckForBroadcastError(&error); OLA_ASSERT_FALSE(m_api.GetDeviceLabel( UNIVERSE, m_group_uid, sub_device, NewSingleCallback(this, &RDMAPITest::CheckLabel), &error)); CheckForBroadcastError(&error); m_impl.AddExpectedGet(string(TEST_DESCRIPTION), UNIVERSE, m_uid, sub_device, ola::rdm::PID_DEVICE_LABEL); OLA_ASSERT_TRUE(m_api.GetDeviceLabel( UNIVERSE, m_uid, sub_device, NewSingleCallback(this, &RDMAPITest::CheckLabel), &error)); // set device label s = TEST_DESCRIPTION; m_impl.AddExpectedSet(UNIVERSE, m_uid, sub_device, ola::rdm::PID_DEVICE_LABEL, reinterpret_cast(s.data()), s.size()); OLA_ASSERT_TRUE(m_api.SetDeviceLabel( UNIVERSE, m_uid, sub_device, s, NewSingleCallback(this, &RDMAPITest::CheckResponseStatus), &error)); // check we can bcast m_impl.AddExpectedSet(UNIVERSE, m_bcast_uid, ola::rdm::ALL_RDM_SUBDEVICES, ola::rdm::PID_DEVICE_LABEL, reinterpret_cast(s.data()), s.size()); OLA_ASSERT_TRUE(m_api.SetDeviceLabel( UNIVERSE, m_bcast_uid, ola::rdm::ALL_RDM_SUBDEVICES, s, NewSingleCallback(this, &RDMAPITest::CheckWasBroadcast), &error)); m_impl.AddExpectedSet(UNIVERSE, m_group_uid, ola::rdm::ALL_RDM_SUBDEVICES, ola::rdm::PID_DEVICE_LABEL, reinterpret_cast(s.data()), s.size()); OLA_ASSERT_TRUE(m_api.SetDeviceLabel( UNIVERSE, m_group_uid, ola::rdm::ALL_RDM_SUBDEVICES, s, NewSingleCallback(this, &RDMAPITest::CheckWasBroadcast), &error)); // check out of range sub devices fail OLA_ASSERT_FALSE(m_api.SetDeviceLabel( UNIVERSE, m_group_uid, 0x0201, s, NewSingleCallback(this, &RDMAPITest::CheckResponseStatus), &error)); CheckForDeviceRangeBcastError(&error); // software version label OLA_ASSERT_FALSE(m_api.GetSoftwareVersionLabel( UNIVERSE, m_bcast_uid, sub_device, NewSingleCallback(this, &RDMAPITest::CheckLabel), &error)); CheckForBroadcastError(&error); OLA_ASSERT_FALSE(m_api.GetSoftwareVersionLabel( UNIVERSE, m_group_uid, sub_device, NewSingleCallback(this, &RDMAPITest::CheckLabel), &error)); CheckForBroadcastError(&error); m_impl.AddExpectedGet(string(TEST_DESCRIPTION), UNIVERSE, m_uid, sub_device, ola::rdm::PID_SOFTWARE_VERSION_LABEL); OLA_ASSERT_TRUE(m_api.GetSoftwareVersionLabel( UNIVERSE, m_uid, sub_device, NewSingleCallback(this, &RDMAPITest::CheckLabel), &error)); // Boot software label OLA_ASSERT_FALSE(m_api.GetBootSoftwareVersionLabel( UNIVERSE, m_bcast_uid, sub_device, NewSingleCallback(this, &RDMAPITest::CheckLabel), &error)); CheckForBroadcastError(&error); OLA_ASSERT_FALSE(m_api.GetBootSoftwareVersionLabel( UNIVERSE, m_group_uid, sub_device, NewSingleCallback(this, &RDMAPITest::CheckLabel), &error)); CheckForBroadcastError(&error); m_impl.AddExpectedGet(string(TEST_DESCRIPTION), UNIVERSE, m_uid, sub_device, ola::rdm::PID_BOOT_SOFTWARE_VERSION_LABEL); OLA_ASSERT_TRUE(m_api.GetBootSoftwareVersionLabel( UNIVERSE, m_uid, sub_device, NewSingleCallback(this, &RDMAPITest::CheckLabel), &error)); } /* * Check that DMX commands work */ void RDMAPITest::testDmxSetup() { string error; uint16_t sub_device = 1; // Check get start address OLA_ASSERT_FALSE(m_api.GetDMXAddress( UNIVERSE, m_bcast_uid, sub_device, NewSingleCallback(this, &RDMAPITest::CheckDMXStartAddress), &error)); CheckForBroadcastError(&error); OLA_ASSERT_FALSE(m_api.GetDMXAddress( UNIVERSE, m_group_uid, sub_device, NewSingleCallback(this, &RDMAPITest::CheckDMXStartAddress), &error)); CheckForBroadcastError(&error); uint16_t start_address = HostToNetwork(static_cast(44)); string s(reinterpret_cast(&start_address), sizeof(start_address)); m_impl.AddExpectedGet(s, UNIVERSE, m_uid, sub_device, ola::rdm::PID_DMX_START_ADDRESS); OLA_ASSERT_TRUE(m_api.GetDMXAddress( UNIVERSE, m_uid, sub_device, NewSingleCallback(this, &RDMAPITest::CheckDMXStartAddress), &error)); // Check set start address start_address = 64; uint16_t address_data = HostToNetwork(start_address); m_impl.AddExpectedSet(UNIVERSE, m_uid, sub_device, ola::rdm::PID_DMX_START_ADDRESS, reinterpret_cast(&address_data), sizeof(address_data)); OLA_ASSERT_TRUE(m_api.SetDMXAddress( UNIVERSE, m_uid, sub_device, start_address, NewSingleCallback(this, &RDMAPITest::CheckResponseStatus), &error)); // check bcasts work m_impl.AddExpectedSet(UNIVERSE, m_bcast_uid, ola::rdm::ALL_RDM_SUBDEVICES, ola::rdm::PID_DMX_START_ADDRESS, reinterpret_cast(&address_data), sizeof(address_data)); OLA_ASSERT_TRUE(m_api.SetDMXAddress( UNIVERSE, m_bcast_uid, ola::rdm::ALL_RDM_SUBDEVICES, start_address, NewSingleCallback(this, &RDMAPITest::CheckWasBroadcast), &error)); m_impl.AddExpectedSet(UNIVERSE, m_group_uid, 0x0200, ola::rdm::PID_DMX_START_ADDRESS, reinterpret_cast(&address_data), sizeof(address_data)); OLA_ASSERT_TRUE(m_api.SetDMXAddress( UNIVERSE, m_group_uid, 0x0200, start_address, NewSingleCallback(this, &RDMAPITest::CheckWasBroadcast), &error)); OLA_ASSERT_FALSE(m_api.SetDMXAddress( UNIVERSE, m_group_uid, 0x0201, start_address, NewSingleCallback(this, &RDMAPITest::CheckWasBroadcast), &error)); CheckForDeviceRangeBcastError(&error); } ola-0.10.5.nojsmin/common/rdm/StringMessageBuilder.cpp0000644000175000017500000002223613023355232022323 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * StringMessageBuilder.cpp * Builds a Message object from a list of strings & a Descriptor. * Copyright (C) 2011 Simon Newton */ #include #include #include #include #include #include #include #include #include #include #include #include "common/rdm/GroupSizeCalculator.h" namespace ola { namespace rdm { using ola::messaging::MessageFieldInterface; using ola::rdm::UID; using std::auto_ptr; using std::string; using std::vector; StringMessageBuilder::StringMessageBuilder() : m_offset(0), m_input_size(0), m_group_instance_count(0), m_error(false) { } /** * @brief Clean up */ StringMessageBuilder::~StringMessageBuilder() { CleanUpVector(); } /** * @brief Get the Message object that this Builder created * * This method is *not* re-entrant. * @param inputs the string inputs provided to build the Message * @param descriptor the descriptor to use to build the Message * @returns a Message object, or NULL if the inputs failed. */ const ola::messaging::Message *StringMessageBuilder::GetMessage( const vector &inputs, const ola::messaging::Descriptor *descriptor) { InitVars(inputs); // first figure out if the number of inputs provided matches the number // expected by the descriptor. This accounts for repeating groups. GroupSizeCalculator calculator; GroupSizeCalculator::calculator_state state = calculator.CalculateGroupSize( inputs.size(), descriptor, &m_group_instance_count); switch (state) { case GroupSizeCalculator::INSUFFICIENT_TOKENS: SetError("Insufficient tokens"); return NULL; case GroupSizeCalculator::EXTRA_TOKENS: SetError("Extra tokens"); return NULL; case GroupSizeCalculator::MISMATCHED_TOKENS: SetError("Mismatched tokens"); return NULL; case GroupSizeCalculator::MULTIPLE_VARIABLE_GROUPS: SetError("Multiple variable groups"); return NULL; case GroupSizeCalculator::NESTED_VARIABLE_GROUPS: SetError("Nested variable groups"); return NULL; case GroupSizeCalculator::SINGLE_VARIABLE_GROUP: case GroupSizeCalculator::NO_VARIABLE_GROUPS: break; } // now we now that this list of inputs can be parsed, and we know the number // of instances of a repeating group if there is one. descriptor->Accept(this); if (m_error) { OLA_WARN << "Error building mesage, field is: " << m_error_string; return NULL; } if (m_groups.size() != 1) { OLA_WARN << "Mismatched stack, size was " << m_groups.size(); return NULL; } const ola::messaging::Message *message = new ola::messaging::Message( m_groups.top()); m_groups.top().clear(); return message; } /** * Bool values can be true,false,0,1 */ void StringMessageBuilder::Visit( const ola::messaging::BoolFieldDescriptor *descriptor) { if (StopParsing()) return; bool value = false; bool valid = false; string token = m_inputs[m_offset++]; ola::StringTrim(&token); ola::ToLower(&token); if (token == "true") { valid = value = true; } else if (token == "false") { value = false; valid = true; } if (!valid) { uint8_t int_value; if (ola::StringToInt(token, &int_value)) { if (int_value == 1) { valid = value = true; } else if (int_value == 0) { valid = true; value = false; } } } if (!valid) { SetError(descriptor->Name()); return; } m_groups.top().push_back( new ola::messaging::BoolMessageField(descriptor, value)); } /** * IPV4 Addresses */ void StringMessageBuilder::Visit( const ola::messaging::IPV4FieldDescriptor *descriptor) { if (StopParsing()) return; string token = m_inputs[m_offset++]; ola::network::IPV4Address ip_address; if (!ola::network::IPV4Address::FromString(token, &ip_address)) { SetError(descriptor->Name()); return; } m_groups.top().push_back( new ola::messaging::IPV4MessageField(descriptor, ip_address)); } /** * MAC Addresses */ void StringMessageBuilder::Visit( const ola::messaging::MACFieldDescriptor *descriptor) { if (StopParsing()) return; string token = m_inputs[m_offset++]; ola::network::MACAddress mac_address; if (!ola::network::MACAddress::FromString(token, &mac_address)) { SetError(descriptor->Name()); return; } m_groups.top().push_back( new ola::messaging::MACMessageField(descriptor, mac_address)); } /** * UIDs. */ void StringMessageBuilder::Visit( const ola::messaging::UIDFieldDescriptor *descriptor) { if (StopParsing()) return; string token = m_inputs[m_offset++]; auto_ptr uid(UID::FromString(token)); if (!uid.get()) { SetError(descriptor->Name()); return; } m_groups.top().push_back( new ola::messaging::UIDMessageField(descriptor, *uid)); } /** * Handle strings */ void StringMessageBuilder::Visit( const ola::messaging::StringFieldDescriptor *descriptor) { if (StopParsing()) return; const string &token = m_inputs[m_offset++]; if (descriptor->MaxSize() != 0 && token.size() > descriptor->MaxSize()) { SetError(descriptor->Name()); return; } m_groups.top().push_back( new ola::messaging::StringMessageField(descriptor, token)); } /** * uint8 */ void StringMessageBuilder::Visit( const ola::messaging::UInt8FieldDescriptor *descriptor) { VisitInt(descriptor); } void StringMessageBuilder::Visit( const ola::messaging::UInt16FieldDescriptor *descriptor) { VisitInt(descriptor); } void StringMessageBuilder::Visit( const ola::messaging::UInt32FieldDescriptor *descriptor) { VisitInt(descriptor); } void StringMessageBuilder::Visit( const ola::messaging::Int8FieldDescriptor *descriptor) { VisitInt(descriptor); } void StringMessageBuilder::Visit( const ola::messaging::Int16FieldDescriptor *descriptor) { VisitInt(descriptor); } void StringMessageBuilder::Visit( const ola::messaging::Int32FieldDescriptor *descriptor) { VisitInt(descriptor); } /** * Visit a group */ void StringMessageBuilder::Visit( const ola::messaging::FieldDescriptorGroup *descriptor) { unsigned int iterations = descriptor->FixedSize() ? descriptor->MinBlocks() : m_group_instance_count; for (unsigned int i = 0; i < iterations; ++i) { vector fields; m_groups.push(fields); for (unsigned int j = 0; j < descriptor->FieldCount(); ++j) { descriptor->GetField(j)->Accept(this); } const vector &populated_fields = m_groups.top(); const ola::messaging::MessageFieldInterface *message = new ola::messaging::GroupMessageField(descriptor, populated_fields); m_groups.pop(); m_groups.top().push_back(message); } } /** * This is a noop since we handle decending ourselfs in Visit() */ void StringMessageBuilder::PostVisit( const ola::messaging::FieldDescriptorGroup *descriptor) { (void) descriptor; } bool StringMessageBuilder::StopParsing() const { return m_error || m_offset >= m_input_size; } void StringMessageBuilder::SetError(const string &error) { m_error = true; m_error_string = error; } template void StringMessageBuilder::VisitInt( const ola::messaging::IntegerFieldDescriptor *descriptor) { if (StopParsing()) return; type int_value; string input = m_inputs[m_offset++]; if (descriptor->LookupLabel(input, &int_value) || ola::PrefixedHexStringToInt(input, &int_value) || ola::StringToInt(input, &int_value)) { m_groups.top().push_back( new ola::messaging::BasicMessageField(descriptor, int_value)); } else { SetError(descriptor->Name()); } } void StringMessageBuilder::InitVars(const vector &inputs) { CleanUpVector(); // add the first fields vector to the stack vector fields; m_groups.push(fields); m_inputs = inputs; m_input_size = inputs.size(); m_error = false; m_offset = 0; } void StringMessageBuilder::CleanUpVector() { while (!m_groups.empty()) { const vector &fields = m_groups.top(); vector::const_iterator iter = fields.begin(); for (; iter != fields.end(); ++iter) { delete *iter; } m_groups.pop(); } } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/RDMAPI.cpp0000644000175000017500000034776413023355232017235 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * RDMAPI.cpp * Provides a generic RDM API that can use different implementations. * Copyright (C) 2010 Simon Newton */ #include #include #include #include #include #include #include "ola/Callback.h" #include "ola/Logging.h" #include "ola/StringUtils.h" #include "ola/base/Macro.h" #include "ola/network/NetworkUtils.h" #include "ola/rdm/RDMAPI.h" #include "ola/rdm/RDMAPIImplInterface.h" #include "ola/rdm/RDMEnums.h" #include "ola/rdm/UID.h" namespace ola { namespace rdm { using std::map; using std::string; using std::vector; using ola::SingleUseCallback1; using ola::SingleUseCallback2; using ola::SingleUseCallback4; using ola::network::HostToNetwork; using ola::network::NetworkToHost; /* * Return the number of queues messages for a UID. Note that this is cached on * the client side so this number may not be correct. * @param uid the UID to fetch the outstanding message count for * @return the number of outstanding messages */ uint8_t RDMAPI::OutstandingMessagesCount(const UID &uid) { map::const_iterator iter = m_outstanding_messages.find(uid); if (iter == m_outstanding_messages.end()) return 0; return iter->second; } /* * Fetch a count of the proxied devices * @param uid the UID of the device to address this message to * @param callback the Callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return false if an error occurred, true otherwise */ bool RDMAPI::GetProxiedDeviceCount( unsigned int universe, const UID &uid, SingleUseCallback3 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleGetProxiedDeviceCount, callback); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, ROOT_RDM_DEVICE, PID_PROXIED_DEVICE_COUNT), error); } /* * Fetch a list of the proxied devices * @param uid the UID of the device to address this message to * @param callback the Callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return false if an error occurred, true otherwise */ bool RDMAPI::GetProxiedDevices( unsigned int universe, const UID &uid, SingleUseCallback2&> *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleGetProxiedDevices, callback); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, ROOT_RDM_DEVICE, PID_PROXIED_DEVICES), error); } /* * Get the communication status report * @param uid the UID of the device to address this message to * @param callback the Callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return false if an error occurred, true otherwise */ bool RDMAPI::GetCommStatus( unsigned int universe, const UID &uid, SingleUseCallback4 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleGetCommStatus, callback); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, ROOT_RDM_DEVICE, PID_COMMS_STATUS), error); } /* * Clear the Communication status * @param uid the UID of the device to address this message to * @param callback the Callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return false if an error occurred, true otherwise */ bool RDMAPI::ClearCommStatus( unsigned int universe, const UID &uid, SingleUseCallback1 *callback, string *error) { if (CheckCallback(error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleEmptyResponse, callback); return CheckReturnStatus( m_impl->RDMSet(cb, universe, uid, ROOT_RDM_DEVICE, PID_COMMS_STATUS), error); } /** * Send a queued message request. */ bool RDMAPI::GetQueuedMessage( unsigned int universe, const UID &uid, rdm_status_type status_type, QueuedMessageHandler *handler, string *error) { if (!handler) { if (error) *error = "Callback is null, this is a programming error"; return false; } RDMAPIImplInterface::rdm_pid_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleQueuedMessage, handler); uint8_t type = status_type; return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, ROOT_RDM_DEVICE, PID_QUEUED_MESSAGE, &type, sizeof(type)), error); } /** * Send a queued message request. When complete the callback will be run and * it's up to the caller to decode the message based on the PID. */ bool RDMAPI::GetQueuedMessage( unsigned int universe, const UID &uid, rdm_status_type status_type, SingleUseCallback3 *callback, string *error) { if (CheckCallback(error, callback)) return false; uint8_t type = status_type; return CheckReturnStatus( m_impl->RDMGet(callback, universe, uid, ROOT_RDM_DEVICE, PID_QUEUED_MESSAGE, &type, sizeof(type)), error); } /* * Get the status information from a device * @param uid the UID of the device to address this message to * @param status_type the Status Type requested * @param callback the Callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return false if an error occurred, true otherwise */ bool RDMAPI::GetStatusMessage( unsigned int universe, const UID &uid, rdm_status_type status_type, SingleUseCallback2&> *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleGetStatusMessage, callback); uint8_t type = static_cast(status_type); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, ROOT_RDM_DEVICE, PID_STATUS_MESSAGES, &type, sizeof(type)), error); } /* * Fetch the description for a status id * @param uid the UID of the device to address this message to * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetStatusIdDescription( unsigned int universe, const UID &uid, uint16_t status_id, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleLabelResponse, callback); status_id = HostToNetwork(status_id); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, ROOT_RDM_DEVICE, PID_STATUS_ID_DESCRIPTION, reinterpret_cast(&status_id), sizeof(status_id)), error); } /* * Clear the status message queue * @param uid the UID of the device to address this message to * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::ClearStatusId( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback1 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckValidSubDevice(sub_device, true, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleEmptyResponse, callback); return CheckReturnStatus( m_impl->RDMSet(cb, universe, uid, sub_device, PID_CLEAR_STATUS_ID), error); } /* * Get the reporting threshold for a device * @param uid the UID of the device to address this message to * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetSubDeviceReporting( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; if (CheckValidSubDevice(sub_device, false, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleGetSubDeviceReporting, callback); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, sub_device, PID_SUB_DEVICE_STATUS_REPORT_THRESHOLD), error); } /* * Set the reporting threshold for a device * @param uid the UID of the device to address this message to * @param sub_device the sub device to use * @param status_type the Status Type to set the threshold as * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::SetSubDeviceReporting( unsigned int universe, const UID &uid, uint16_t sub_device, rdm_status_type status_type, SingleUseCallback1 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; if (CheckValidSubDevice(sub_device, true, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleEmptyResponse, callback); uint8_t type = static_cast(status_type); return CheckReturnStatus( m_impl->RDMSet(cb, universe, uid, ROOT_RDM_DEVICE, PID_SUB_DEVICE_STATUS_REPORT_THRESHOLD, &type, sizeof(type)), error); } /* * Fetch the supported parameters list * @param uid the UID of the device to address this message to * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetSupportedParameters( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2&> *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; if (CheckValidSubDevice(sub_device, false, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleGetSupportedParameters, callback); return m_impl->RDMGet(cb, universe, uid, sub_device, PID_SUPPORTED_PARAMETERS); } /* * Fetch the description of a param ID * @param uid the UID of the device to address this message to * @param pid the parameter id to fetch the description for * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetParameterDescription( unsigned int universe, const UID &uid, uint16_t pid, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleGetParameterDescriptor, callback); pid = HostToNetwork(pid); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, ROOT_RDM_DEVICE, PID_PARAMETER_DESCRIPTION, reinterpret_cast(&pid), sizeof(pid)), error); } /* * Fetch the device information * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetDeviceInfo( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; if (CheckValidSubDevice(sub_device, false, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleGetDeviceDescriptor, callback); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, sub_device, PID_DEVICE_INFO), error); } /* * Fetch the product detail IDs. * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetProductDetailIdList( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2&> *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; if (CheckValidSubDevice(sub_device, false, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleGetProductDetailIdList, callback); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, sub_device, PID_PRODUCT_DETAIL_ID_LIST), error); } /* * Fetch the description for a device model. * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetDeviceModelDescription( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; if (CheckValidSubDevice(sub_device, false, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleLabelResponse, callback); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, sub_device, PID_DEVICE_MODEL_DESCRIPTION), error); } /* * Fetch the manufacturer label for a device * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetManufacturerLabel( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; if (CheckValidSubDevice(sub_device, false, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleLabelResponse, callback); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, sub_device, PID_MANUFACTURER_LABEL), error); } /* * Fetch the device label * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetDeviceLabel( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; if (CheckValidSubDevice(sub_device, false, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleLabelResponse, callback); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, sub_device, PID_DEVICE_LABEL), error); } /* * Set the device label * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::SetDeviceLabel( unsigned int universe, const UID &uid, uint16_t sub_device, const string &label, SingleUseCallback1 *callback, string *error) { if (CheckCallback(error, callback)) return false; // It doesn't really make sense to broadcast this but allow it anyway if (CheckValidSubDevice(sub_device, true, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleEmptyResponse, callback); return CheckReturnStatus( m_impl->RDMSet(cb, universe, uid, sub_device, PID_DEVICE_LABEL, reinterpret_cast(label.data()), label.size()), error); } /* * Check if a device is using the factory defaults * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetFactoryDefaults( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; if (CheckValidSubDevice(sub_device, false, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleBoolResponse, callback); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, sub_device, PID_FACTORY_DEFAULTS), error); } /* * Reset a device to factory defaults * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::ResetToFactoryDefaults( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback1 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; if (CheckValidSubDevice(sub_device, true, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleEmptyResponse, callback); return CheckReturnStatus( m_impl->RDMSet(cb, universe, uid, sub_device, PID_FACTORY_DEFAULTS), error); } /* * Get the list of languages this device supports * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetLanguageCapabilities( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2&> *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; if (CheckValidSubDevice(sub_device, false, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleGetLanguageCapabilities, callback); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, sub_device, PID_LANGUAGE_CAPABILITIES), error); } /* * Get the language for this device * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetLanguage( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; if (CheckValidSubDevice(sub_device, false, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleGetLanguage, callback); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, sub_device, PID_LANGUAGE), error); } /* * Set the language for this device * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param language the language code, only the first two characters are used * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::SetLanguage( unsigned int universe, const UID &uid, uint16_t sub_device, const string &language, SingleUseCallback1 *callback, string *error) { static const unsigned int DATA_SIZE = 2; if (CheckCallback(error, callback)) return false; if (CheckValidSubDevice(sub_device, true, error, callback)) return false; if (language.size() != DATA_SIZE) { if (error) *error = "Language must be a two letter code"; delete callback; return false; } RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleEmptyResponse, callback); return CheckReturnStatus( m_impl->RDMSet(cb, universe, uid, sub_device, PID_LANGUAGE, reinterpret_cast(language.data()), DATA_SIZE), error); } /* * Get the software version label * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetSoftwareVersionLabel( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; if (CheckValidSubDevice(sub_device, false, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleLabelResponse, callback); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, sub_device, PID_SOFTWARE_VERSION_LABEL), error); } /* * Get the boot software version. * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetBootSoftwareVersion( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; if (CheckValidSubDevice(sub_device, false, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleGetBootSoftwareVersion, callback); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, sub_device, PID_BOOT_SOFTWARE_VERSION_ID), error); } /* * Get the boot software version label * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetBootSoftwareVersionLabel( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; if (CheckValidSubDevice(sub_device, false, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleLabelResponse, callback); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, sub_device, PID_BOOT_SOFTWARE_VERSION_LABEL), error); } /* * Get the current DMX personality * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetDMXPersonality( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback3 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; if (CheckValidSubDevice(sub_device, false, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleGetDMXPersonality, callback); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, sub_device, PID_DMX_PERSONALITY), error); } /* * Set the DMX personality * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param personality the value of the personality to choose * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::SetDMXPersonality( unsigned int universe, const UID &uid, uint16_t sub_device, uint8_t personality, SingleUseCallback1 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckValidSubDevice(sub_device, true, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleEmptyResponse, callback); return CheckReturnStatus( m_impl->RDMSet(cb, universe, uid, sub_device, PID_DMX_PERSONALITY, &personality, sizeof(personality)), error); } /* * Get the description for a DMX personality * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param personality the value of the personality to get the description of * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetDMXPersonalityDescription( unsigned int universe, const UID &uid, uint16_t sub_device, uint8_t personality, SingleUseCallback4 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; if (CheckValidSubDevice(sub_device, false, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleGetDMXPersonalityDescription, callback); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, sub_device, PID_DMX_PERSONALITY_DESCRIPTION, &personality, sizeof(personality)), error); } /* * Get the DMX start address * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetDMXAddress( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; if (CheckValidSubDevice(sub_device, false, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleGetDMXAddress, callback); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, sub_device, PID_DMX_START_ADDRESS), error); } /* * Set the DMX start address * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param start_address the new start address * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::SetDMXAddress( unsigned int universe, const UID &uid, uint16_t sub_device, uint16_t start_address, SingleUseCallback1 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckValidSubDevice(sub_device, true, error, callback)) return false; start_address = HostToNetwork(start_address); RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleEmptyResponse, callback); return CheckReturnStatus( m_impl->RDMSet(cb, universe, uid, sub_device, PID_DMX_START_ADDRESS, reinterpret_cast(&start_address), sizeof(start_address)), error); } /* * Fetch the DMX slot info * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetSlotInfo( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2&> *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; if (CheckValidSubDevice(sub_device, false, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleGetSlotInfo, callback); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, sub_device, PID_SLOT_INFO), error); } /* * Fetch a DMX slot description * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param slot_offset the offset of the slot to get the description of * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetSlotDescription( unsigned int universe, const UID &uid, uint16_t sub_device, uint16_t slot_offset, SingleUseCallback3 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; if (CheckValidSubDevice(sub_device, false, error, callback)) return false; slot_offset = HostToNetwork(slot_offset); RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleGetSlotDescription, callback); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, sub_device, PID_SLOT_DESCRIPTION, reinterpret_cast(&slot_offset), sizeof(slot_offset)), error); } /* * Get the default value for a slot * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetSlotDefaultValues( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2&> *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; if (CheckValidSubDevice(sub_device, false, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleGetSlotDefaultValues, callback); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, sub_device, PID_DEFAULT_SLOT_VALUE), error); } /* * Get the definition for a sensor * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param sensor_number the sensor index to get the descriptor for * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetSensorDefinition( unsigned int universe, const UID &uid, uint16_t sub_device, uint8_t sensor_number, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; if (CheckValidSubDevice(sub_device, false, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleGetSensorDefinition, callback); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, sub_device, PID_SENSOR_DEFINITION, &sensor_number, sizeof(sensor_number)), error); } /* * Get the value of a sensor * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param sensor_number the sensor index to get the value of * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetSensorValue( unsigned int universe, const UID &uid, uint16_t sub_device, uint8_t sensor_number, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; if (CheckValidSubDevice(sub_device, false, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleSensorValue, callback); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, sub_device, PID_SENSOR_VALUE, &sensor_number, sizeof(sensor_number)), error); } /* * Reset a sensor * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param sensor_number the sensor index to reset * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::SetSensorValue( unsigned int universe, const UID &uid, uint16_t sub_device, uint8_t sensor_number, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckValidSubDevice(sub_device, true, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleSensorValue, callback); return CheckReturnStatus( m_impl->RDMSet(cb, universe, uid, sub_device, PID_SENSOR_VALUE, &sensor_number, sizeof(sensor_number)), error); } /* * Put a sensor into record mode * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param sensor_number the sensor index to record * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::RecordSensors( unsigned int universe, const UID &uid, uint16_t sub_device, uint8_t sensor_number, SingleUseCallback1 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckValidSubDevice(sub_device, true, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleEmptyResponse, callback); return CheckReturnStatus( m_impl->RDMSet(cb, universe, uid, sub_device, PID_RECORD_SENSORS, &sensor_number, sizeof(sensor_number)), error); } /* * Get the device hours * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetDeviceHours( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) return false; return GenericGetU32( universe, uid, sub_device, callback, PID_DEVICE_HOURS, error); } /* * Set the device hours * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param device_hours the number of device hours * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::SetDeviceHours( unsigned int universe, const UID &uid, uint16_t sub_device, uint32_t device_hours, SingleUseCallback1 *callback, string *error) { if (CheckCallback(error, callback)) return false; return GenericSetU32( universe, uid, sub_device, device_hours, callback, PID_DEVICE_HOURS, error); } /* * Get the lamp hours * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetLampHours( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) return false; return GenericGetU32( universe, uid, sub_device, callback, PID_LAMP_HOURS, error); } /* * Set the lamp hours * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param lamp_hours the number of lamp hours * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::SetLampHours( unsigned int universe, const UID &uid, uint16_t sub_device, uint32_t lamp_hours, SingleUseCallback1 *callback, string *error) { if (CheckCallback(error, callback)) return false; return GenericSetU32( universe, uid, sub_device, lamp_hours, callback, PID_LAMP_STRIKES, error); } /* * Get the number of lamp strikes * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetLampStrikes( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) return false; return GenericGetU32( universe, uid, sub_device, callback, PID_LAMP_STRIKES, error); } /* * Set the lamp strikes * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param lamp_strikes the number of lamp strikes * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::SetLampStrikes( unsigned int universe, const UID &uid, uint16_t sub_device, uint32_t lamp_strikes, SingleUseCallback1 *callback, string *error) { if (CheckCallback(error, callback)) return false; return GenericSetU32( universe, uid, sub_device, lamp_strikes, callback, PID_LAMP_STRIKES, error); } /* * Get the state of the lamp * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetLampState( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) return false; return GenericGetU8( universe, uid, sub_device, callback, PID_LAMP_STATE, error); } /* * Set the lamp state * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param lamp_state the new lamp state * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::SetLampState( unsigned int universe, const UID &uid, uint16_t sub_device, uint8_t lamp_state, SingleUseCallback1 *callback, string *error) { if (CheckCallback(error, callback)) return false; return GenericSetU8( universe, uid, sub_device, lamp_state, callback, PID_LAMP_STATE, error); } /* * Get the mode of the lamp * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetLampMode( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) return false; return GenericGetU8( universe, uid, sub_device, callback, PID_LAMP_ON_MODE, error); } /* * Set the lamp mode * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param lamp_mode the new lamp mode * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::SetLampMode( unsigned int universe, const UID &uid, uint16_t sub_device, uint8_t lamp_mode, SingleUseCallback1 *callback, string *error) { if (CheckCallback(error, callback)) return false; return GenericSetU8( universe, uid, sub_device, lamp_mode, callback, PID_LAMP_ON_MODE, error); } /* * Get the number of device power cycles * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetDevicePowerCycles( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) return false; return GenericGetU32( universe, uid, sub_device, callback, PID_DEVICE_POWER_CYCLES, error); } /* * Set the number of power cycles * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param power_cycles the number of power cycles * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::SetDevicePowerCycles( unsigned int universe, const UID &uid, uint16_t sub_device, uint32_t power_cycles, SingleUseCallback1 *callback, string *error) { if (CheckCallback(error, callback)) return false; return GenericSetU32( universe, uid, sub_device, power_cycles, callback, PID_DEVICE_POWER_CYCLES, error); } /* * Get the display invert setting * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetDisplayInvert( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) return false; return GenericGetU8( universe, uid, sub_device, callback, PID_DISPLAY_INVERT, error); } /* * Set the display invert setting * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param display_invert the new invert setting * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::SetDisplayInvert( unsigned int universe, const UID &uid, uint16_t sub_device, uint8_t display_invert, SingleUseCallback1 *callback, string *error) { if (CheckCallback(error, callback)) return false; return GenericSetU8( universe, uid, sub_device, display_invert, callback, PID_DISPLAY_INVERT, error); } /* * Get the display level * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetDisplayLevel( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) return false; return GenericGetU8( universe, uid, sub_device, callback, PID_DISPLAY_LEVEL, error); } /* * Set the display level * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param display_level the new setting * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::SetDisplayLevel( unsigned int universe, const UID &uid, uint16_t sub_device, uint8_t display_level, SingleUseCallback1 *callback, string *error) { if (CheckCallback(error, callback)) return false; return GenericSetU8( universe, uid, sub_device, display_level, callback, PID_DISPLAY_LEVEL, error); } /* * Get the pan invert parameter * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetPanInvert( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) return false; return GenericGetU8( universe, uid, sub_device, callback, PID_PAN_INVERT, error); } /* * Invert the pan parameter * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param invert set to true to invert * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::SetPanInvert( unsigned int universe, const UID &uid, uint16_t sub_device, uint8_t invert, SingleUseCallback1 *callback, string *error) { if (CheckCallback(error, callback)) return false; return GenericSetU8( universe, uid, sub_device, invert, callback, PID_PAN_INVERT, error); } /* * Get the tilt invert parameter * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetTiltInvert( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) return false; return GenericGetU8( universe, uid, sub_device, callback, PID_TILT_INVERT, error); } /* * Invert the tilt parameter * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param invert set to true to invert * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::SetTiltInvert( unsigned int universe, const UID &uid, uint16_t sub_device, uint8_t invert, SingleUseCallback1 *callback, string *error) { if (CheckCallback(error, callback)) return false; return GenericSetU8( universe, uid, sub_device, invert, callback, PID_TILT_INVERT, error); } /* * Get the pan/tilt swap parameter * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetPanTiltSwap( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) return false; return GenericGetU8( universe, uid, sub_device, callback, PID_PAN_TILT_SWAP, error); } /* * Swap the pan and tilt actions * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param swap, true to swap, false otherwise * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::SetPanTiltSwap( unsigned int universe, const UID &uid, uint16_t sub_device, uint8_t swap, SingleUseCallback1 *callback, string *error) { if (CheckCallback(error, callback)) return false; return GenericSetU8( universe, uid, sub_device, swap, callback, PID_PAN_TILT_SWAP, error); } /* * Get the clock value * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetClock( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleClock, callback); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, sub_device, PID_REAL_TIME_CLOCK), error); } /* * Set the clock value * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param clock, the new clock settings * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::SetClock( unsigned int universe, const UID &uid, uint16_t sub_device, const ClockValue &clock, SingleUseCallback1 *callback, string *error) { if (CheckCallback(error, callback)) return false; ClockValue clock_data; memcpy(&clock_data, &clock, sizeof(clock_data)); clock_data.year = HostToNetwork(clock_data.year); RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleEmptyResponse, callback); return CheckReturnStatus( m_impl->RDMSet(cb, universe, uid, sub_device, PID_REAL_TIME_CLOCK, reinterpret_cast(&clock_data), sizeof(struct clock_value_s)), error); } /* * Check the identify state for a device * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetIdentifyDevice( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; if (CheckValidSubDevice(sub_device, false, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleBoolResponse, callback); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, sub_device, PID_IDENTIFY_DEVICE), error); } /* * Change the identify state for a device * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param mode the identify mode to set * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::IdentifyDevice( unsigned int universe, const UID &uid, uint16_t sub_device, bool mode, SingleUseCallback1 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckValidSubDevice(sub_device, true, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleEmptyResponse, callback); uint8_t option = mode; return CheckReturnStatus( m_impl->RDMSet(cb, universe, uid, sub_device, PID_IDENTIFY_DEVICE, &option, sizeof(option)), error); } /* * Reset a device * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param warm_reset true for a warm reset, false for a cold reset * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::ResetDevice( unsigned int universe, const UID &uid, uint16_t sub_device, bool warm_reset, SingleUseCallback1 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckValidSubDevice(sub_device, true, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleEmptyResponse, callback); uint8_t option = warm_reset ? RESET_WARM : RESET_COLD; return CheckReturnStatus( m_impl->RDMSet(cb, universe, uid, sub_device, PID_RESET_DEVICE, &option, sizeof(option)), error); } /* * Get the power state for a device * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetPowerState( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; if (CheckValidSubDevice(sub_device, false, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleU8Response, callback); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, sub_device, PID_POWER_STATE), error); } /* * Set the power state for a device. * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param power_state the new power state * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::SetPowerState( unsigned int universe, const UID &uid, uint16_t sub_device, rdm_power_state power_state, SingleUseCallback1 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckValidSubDevice(sub_device, true, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleEmptyResponse, callback); uint8_t option = static_cast(power_state); return CheckReturnStatus( m_impl->RDMSet(cb, universe, uid, sub_device, PID_POWER_STATE, &option, sizeof(option)), error); } /* * Set the reset device for a device. * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param reset_device the new reset device * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::SetResetDevice( unsigned int universe, const UID &uid, uint16_t sub_device, rdm_reset_device_mode reset_device, SingleUseCallback1 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckValidSubDevice(sub_device, true, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleEmptyResponse, callback); uint8_t option = static_cast(reset_device); return CheckReturnStatus( m_impl->RDMSet(cb, universe, uid, sub_device, PID_RESET_DEVICE, &option, sizeof(option)), error); } /* * Fetch the DNS hostname * @param uid the UID to fetch the DNS hostname for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetDnsHostname( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) { return false; } if (CheckNotBroadcast(uid, error, callback)) { return false; } if (CheckValidSubDevice(sub_device, false, error, callback)) { return false; } RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleCustomLengthLabelResponse, callback, MAX_RDM_HOSTNAME_LENGTH); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, sub_device, PID_DNS_HOSTNAME), error); } /* * Set the DNS hostname * @param uid the UID to set the DNS hostname for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::SetDnsHostname( unsigned int universe, const UID &uid, uint16_t sub_device, const string &label, SingleUseCallback1 *callback, string *error) { if (CheckCallback(error, callback)) { return false; } // It doesn't really make sense to broadcast this but allow it anyway if (CheckValidSubDevice(sub_device, true, error, callback)) { return false; } RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleEmptyResponse, callback); return CheckReturnStatus( m_impl->RDMSet(cb, universe, uid, sub_device, PID_DNS_HOSTNAME, reinterpret_cast(label.data()), label.size()), error); } /* * Fetch the DNS domain name * @param uid the UID to fetch the DNS domain name for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::GetDnsDomainName( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) { return false; } if (CheckNotBroadcast(uid, error, callback)) { return false; } if (CheckValidSubDevice(sub_device, false, error, callback)) { return false; } RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleCustomLengthLabelResponse, callback, MAX_RDM_DOMAIN_NAME_LENGTH); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, sub_device, PID_DNS_DOMAIN_NAME), error); } /* * Set the DNS domain name * @param uid the UID to set the DNS domain name for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::SetDnsDomainName( unsigned int universe, const UID &uid, uint16_t sub_device, const string &label, SingleUseCallback1 *callback, string *error) { if (CheckCallback(error, callback)) { return false; } // It doesn't really make sense to broadcast this but allow it anyway if (CheckValidSubDevice(sub_device, true, error, callback)) { return false; } RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleEmptyResponse, callback); return CheckReturnStatus( m_impl->RDMSet(cb, universe, uid, sub_device, PID_DNS_DOMAIN_NAME, reinterpret_cast(label.data()), label.size()), error); } /* * Check if a device is in self test mode. * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::SelfTestEnabled( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; if (CheckValidSubDevice(sub_device, false, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleBoolResponse, callback); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, sub_device, PID_PERFORM_SELFTEST), error); } /* * Perform a self test on a device. * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param self_test_number the number of the self test to perform. * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::PerformSelfTest( unsigned int universe, const UID &uid, uint16_t sub_device, uint8_t self_test_number, SingleUseCallback1 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckValidSubDevice(sub_device, true, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleEmptyResponse, callback); return CheckReturnStatus( m_impl->RDMSet(cb, universe, uid, sub_device, PID_PERFORM_SELFTEST, &self_test_number, sizeof(self_test_number)), error); } /* * Fetch the description of a self test. * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param self_test_number the number of the self test to fetch the description * of. * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::SelfTestDescription( unsigned int universe, const UID &uid, uint16_t sub_device, uint8_t self_test_number, SingleUseCallback3 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; if (CheckValidSubDevice(sub_device, false, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleSelfTestDescription, callback); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, sub_device, PID_SELF_TEST_DESCRIPTION, &self_test_number, sizeof(self_test_number)), error); } /* * Capture the current state into a preset. * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param scene the number of the preset scene to store * @param fade_up_time the time in 10s of a second to fade up this scene. * @param fade_down_time the time in 10s of a second to fade down the previous * scene. * @param wait_time the time in 10s of a second to hold this scene when the * playback mode is PRESET_PLAYBACK_ALL * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::CapturePreset( unsigned int universe, const UID &uid, uint16_t sub_device, uint16_t scene, uint16_t fade_up_time, uint16_t fade_down_time, uint16_t wait_time, SingleUseCallback1 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckValidSubDevice(sub_device, true, error, callback)) return false; PACK( struct preset_config { uint16_t scene; uint16_t fade_up_time; uint16_t fade_down_time; uint16_t wait_time; }); STATIC_ASSERT(sizeof(preset_config) == 8); struct preset_config raw_config; raw_config.scene = HostToNetwork(scene); raw_config.fade_up_time = HostToNetwork(fade_up_time); raw_config.fade_down_time = HostToNetwork(fade_down_time); raw_config.wait_time = HostToNetwork(wait_time); RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleEmptyResponse, callback); return CheckReturnStatus( m_impl->RDMSet(cb, universe, uid, sub_device, PID_CAPTURE_PRESET, reinterpret_cast(&raw_config), sizeof(raw_config)), error); } /* * Fetch the current playback mode. * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::PresetPlaybackMode( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback3 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckNotBroadcast(uid, error, callback)) return false; if (CheckValidSubDevice(sub_device, false, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandlePlaybackMode, callback); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, sub_device, PID_PRESET_PLAYBACK, NULL, 0), error); } /* * Set the current playback mode. * @param uid the UID to fetch the outstanding message count for * @param sub_device the sub device to use * @param playback_mode the playback scene to use, PRESET_PLAYBACK_OFF or * PRESET_PLAYBACK_ALL. * @param level the level to use for the scene. * @param callback the callback to invoke when this request completes * @param error a pointer to a string which it set if an error occurs * @return true if the request is sent correctly, false otherwise */ bool RDMAPI::SetPresetPlaybackMode( unsigned int universe, const UID &uid, uint16_t sub_device, uint16_t playback_mode, uint8_t level, SingleUseCallback1 *callback, string *error) { if (CheckCallback(error, callback)) return false; if (CheckValidSubDevice(sub_device, true, error, callback)) return false; PACK( struct preset_config { uint16_t mode; uint8_t level; }); STATIC_ASSERT(sizeof(preset_config) == 3); struct preset_config raw_config; raw_config.mode = HostToNetwork(playback_mode); raw_config.level = level; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleEmptyResponse, callback); return CheckReturnStatus( m_impl->RDMSet(cb, universe, uid, sub_device, PID_PRESET_PLAYBACK, reinterpret_cast(&raw_config), sizeof(raw_config)), error); } // Handlers follow. These are invoked by the RDMAPIImpl when responses arrive // ---------------------------------------------------------------------------- /* * Handle a response that contains a custom length ASCII string */ void RDMAPI::_HandleCustomLengthLabelResponse( SingleUseCallback2 *callback, uint8_t max_length, const ResponseStatus &status, const string &data) { ResponseStatus response_status = status; if (status.WasAcked() && data.size() > max_length) { std::ostringstream str; str << "PDL needs to be <= " << static_cast(max_length) << ", was " << data.size(); response_status.error = str.str(); } string label = data; ShortenString(&label); callback->Run(response_status, label); } /* * Handle a response that contains a 32 byte ASCII string */ void RDMAPI::_HandleLabelResponse( SingleUseCallback2 *callback, const ResponseStatus &status, const string &data) { _HandleCustomLengthLabelResponse(callback, MAX_RDM_STRING_LENGTH, status, data); } /* * Handle a response that contains a bool */ void RDMAPI::_HandleBoolResponse( SingleUseCallback2 *callback, const ResponseStatus &status, const string &data) { static const unsigned int DATA_SIZE = 1; ResponseStatus response_status = status; bool option = false; if (response_status.WasAcked()) { if (data.size() == DATA_SIZE) { option = data.data()[0]; } else { SetIncorrectPDL(&response_status, data.size(), DATA_SIZE); } } callback->Run(response_status, option); } /* * Handle a response that contains a uint8_t */ void RDMAPI::_HandleU8Response( SingleUseCallback2 *callback, const ResponseStatus &status, const string &data) { ResponseStatus response_status = status; uint8_t value = 0; if (response_status.WasAcked()) { if (data.size() == sizeof(value)) { value = data.data()[0]; } else { SetIncorrectPDL(&response_status, data.size(), sizeof(value)); } } callback->Run(response_status, value); } /* * Handle a response that contains a uint32_t */ void RDMAPI::_HandleU32Response( SingleUseCallback2 *callback, const ResponseStatus &status, const string &data) { ResponseStatus response_status = status; uint32_t value = 0; if (response_status.WasAcked()) { if (data.size() == sizeof(value)) { const uint32_t *ptr = reinterpret_cast(data.data()); value = NetworkToHost(*ptr); } else { SetIncorrectPDL(&response_status, data.size(), sizeof(value)); } } callback->Run(response_status, value); } /* * Handle a response that doesn't contain any data */ void RDMAPI::_HandleEmptyResponse( SingleUseCallback1 *callback, const ResponseStatus &status, const string &data) { ResponseStatus response_status = status; if (response_status.WasAcked() && !data.empty()) SetIncorrectPDL(&response_status, data.size(), 0); callback->Run(response_status); } /* * Handle a PROXIED_DEVICE_COUNT get response */ void RDMAPI::_HandleGetProxiedDeviceCount( SingleUseCallback3 *callback, const ResponseStatus &status, const string &data) { static const unsigned int DATA_SIZE = 3; ResponseStatus response_status = status; uint16_t device_count = 0; bool list_change = false; if (response_status.WasAcked()) { if (data.size() >= DATA_SIZE) { struct { uint16_t device_count; uint8_t list_change; } unpacked_data; memcpy(&unpacked_data, data.data(), DATA_SIZE); device_count = NetworkToHost(unpacked_data.device_count); list_change = unpacked_data.list_change; } else { SetIncorrectPDL(&response_status, data.size(), DATA_SIZE); } } callback->Run(response_status, device_count, list_change); } /* * Handle a PROXIED_DEVICES get response */ void RDMAPI::_HandleGetProxiedDevices( SingleUseCallback2&> *callback, const ResponseStatus &status, const string &data) { ResponseStatus response_status = status; vector uids; unsigned int data_size = data.size(); if (response_status.WasAcked()) { if (data_size % UID::UID_SIZE == 0) { const uint8_t *start = reinterpret_cast(data.data()); for (const uint8_t *ptr = start; ptr < start + data_size; ptr += UID::UID_SIZE) { UID uid(ptr); uids.push_back(uid); } } else { response_status.error = ("PDL size not a multiple of " + IntToString(static_cast(UID::UID_SIZE)) + " : " + IntToString(static_cast(data_size))); } } callback->Run(response_status, uids); } /* * Handle a get COMMS_STATUS response */ void RDMAPI::_HandleGetCommStatus( SingleUseCallback4 *callback, const ResponseStatus &status, const string &data) { static const unsigned int DATA_SIZE = 6; ResponseStatus response_status = status; uint16_t short_message = 0, length_mismatch = 0, checksum_fail = 0; if (response_status.WasAcked()) { if (data.size() >= DATA_SIZE) { struct { uint16_t short_message; uint16_t length_mismatch; uint16_t checksum_fail; } unpacked_data; memcpy(&unpacked_data, data.data(), DATA_SIZE); short_message = NetworkToHost(unpacked_data.short_message); length_mismatch = NetworkToHost(unpacked_data.length_mismatch); checksum_fail = NetworkToHost(unpacked_data.checksum_fail); } else { SetIncorrectPDL(&response_status, data.size(), DATA_SIZE); } } callback->Run(response_status, short_message, length_mismatch, checksum_fail); } /* * Handle a QUEUED_MESSAGE response */ void RDMAPI::_HandleQueuedMessage( QueuedMessageHandler *handler, const ResponseStatus &status, uint16_t pid, const string &data) { // now we need to switch on pid, and dispatch to the handler // we should also pass the uid here handler->DefaultHandler(status, pid, data); } /* * Handle a STATUS_MESSAGES response */ void RDMAPI::_HandleGetStatusMessage( SingleUseCallback2&> *callback, const ResponseStatus &status, const string &data) { // Seriously WTF, learn how to align data structures struct status_message { uint8_t sub_device_hi; uint8_t sub_device_lo; uint8_t status_type; uint8_t message_id_hi; uint8_t message_id_lo; uint8_t value_1_hi; uint8_t value_1_lo; uint8_t value_2_hi; uint8_t value_2_lo; } message; ResponseStatus response_status = status; vector messages; unsigned int data_size = data.size(); if (response_status.WasAcked()) { if (data_size % sizeof(message) == 0) { const uint8_t *start = reinterpret_cast(data.data()); for (const uint8_t *ptr = start; ptr < start + data_size; ptr += sizeof(message)) { memcpy(&message, ptr, sizeof(message)); StatusMessage msg_object; msg_object.sub_device = (message.sub_device_hi << 8) + message.sub_device_lo; msg_object.status_message_id = (message.message_id_hi << 8) + message.message_id_lo; msg_object.value1 = (message.value_1_hi << 8) + message.value_1_lo; msg_object.value2 = (message.value_2_hi << 8) + message.value_2_lo; msg_object.status_type = message.status_type; messages.push_back(msg_object); } } else { response_status.error = ("PDL size not a multiple of " + IntToString(static_cast(sizeof(message))) + " : " + IntToString(static_cast(data_size))); } } callback->Run(response_status, messages); } /* * Handle a get SUB_DEVICE_STATUS_REPORT_THRESHOLD message */ void RDMAPI::_HandleGetSubDeviceReporting( SingleUseCallback2 *callback, const ResponseStatus &status, const string &data) { ResponseStatus response_status = status; uint8_t status_type = 0; if (response_status.WasAcked()) { if (data.size() == sizeof(status_type)) { status_type = data.data()[0]; } else { SetIncorrectPDL(&response_status, data.size(), sizeof(status_type)); } } callback->Run(response_status, status_type); } /* * Handle a SUPPORTED_PARAMETERS Get command */ void RDMAPI::_HandleGetSupportedParameters( SingleUseCallback2&> *callback, const ResponseStatus &status, const string &data) { ResponseStatus response_status = status; vector pids; unsigned int data_size = data.size(); if (response_status.WasAcked()) { if (data_size % 2 == 0) { const uint16_t *start = reinterpret_cast(data.data()); const uint16_t *end = start + (data_size / sizeof(*start)); for (const uint16_t *ptr = start; ptr < end; ptr++) { pids.push_back(NetworkToHost(*ptr)); } } else { response_status.error = ("PDL size not a multiple of 2 : " + IntToString(static_cast(data_size))); } sort(pids.begin(), pids.end()); } callback->Run(response_status, pids); } /* * Handle a PARAMETER_DESCRIPTION message */ void RDMAPI::_HandleGetParameterDescriptor( SingleUseCallback2 *callback, const ResponseStatus &status, const string &data) { ResponseStatus response_status = status; ParameterDescriptor description; if (response_status.WasAcked()) { PACK( struct param_description { uint16_t pid; uint8_t pdl_size; uint8_t data_type; uint8_t command_class; uint8_t type; uint8_t unit; uint8_t prefix; uint32_t min_value; uint32_t max_value; uint32_t default_value; // +1 for a null since it's not clear in the spec if this is null // terminated char description[MAX_RDM_STRING_LENGTH + 1]; }); STATIC_ASSERT(sizeof(param_description) == 53); struct param_description raw_description; unsigned int max = sizeof(raw_description) - 1; unsigned int min = max - MAX_RDM_STRING_LENGTH; unsigned int data_size = data.size(); if (data_size >= min && data_size <= max) { memcpy(&raw_description, data.data(), std::min(static_cast(data.size()), max)); raw_description.description[MAX_RDM_STRING_LENGTH] = 0; description.pid = NetworkToHost(raw_description.pid); description.pdl_size = raw_description.pdl_size; description.data_type = raw_description.data_type; description.command_class = raw_description.command_class; description.unit = raw_description.unit; description.prefix = raw_description.prefix; description.min_value = NetworkToHost(raw_description.min_value); description.default_value = NetworkToHost(raw_description.default_value); description.max_value = NetworkToHost(raw_description.max_value); unsigned int label_size = data_size - ( sizeof(raw_description) - MAX_RDM_STRING_LENGTH - 1); description.description = string(raw_description.description, label_size); ShortenString(&description.description); } else { std::ostringstream str; str << data_size << " needs to be between " << min << " and " << max; response_status.error = str.str(); } } callback->Run(response_status, description); } /* * Handle a DEVICE_INFO Get command */ void RDMAPI::_HandleGetDeviceDescriptor( SingleUseCallback2 *callback, const ResponseStatus &status, const string &data) { ResponseStatus response_status = status; DeviceDescriptor device_info; if (response_status.WasAcked()) { unsigned int data_size = data.size(); if (data_size == sizeof(device_info)) { memcpy(&device_info, data.data(), sizeof(device_info)); device_info.device_model = NetworkToHost(device_info.device_model); device_info.product_category = NetworkToHost(device_info.product_category); device_info.software_version = NetworkToHost(device_info.software_version); device_info.dmx_footprint = NetworkToHost(device_info.dmx_footprint); device_info.dmx_start_address = NetworkToHost(device_info.dmx_start_address); device_info.sub_device_count = NetworkToHost(device_info.sub_device_count); } else { SetIncorrectPDL(&response_status, data.size(), sizeof(device_info)); } } callback->Run(response_status, device_info); } /* * Handle a PRODUCT_DETAIL_ID_LIST response */ void RDMAPI::_HandleGetProductDetailIdList( SingleUseCallback2&> *callback, const ResponseStatus &status, const string &data) { static const unsigned int MAX_DETAIL_IDS = 6; ResponseStatus response_status = status; vector product_detail_ids; if (response_status.WasAcked()) { unsigned int data_size = data.size(); if (data_size > MAX_DETAIL_IDS * sizeof(uint16_t)) { std::ostringstream str; str << "PDL needs to be <= " << (MAX_DETAIL_IDS * sizeof(uint16_t)) << ", was " << data_size; response_status.error = str.str(); } else if (data_size % 2) { std::ostringstream str; str << "PDL needs to be a multiple of 2, was " << data_size; response_status.error = str.str(); } else { const uint16_t *start = reinterpret_cast(data.data()); const uint16_t *end = start + (data_size / sizeof(*start)); for (const uint16_t *ptr = start; ptr < end; ptr++) { product_detail_ids.push_back(NetworkToHost(*ptr)); } } } callback->Run(response_status, product_detail_ids); } /* * Handle a LANGUAGE_CAPABILITIES response */ void RDMAPI::_HandleGetLanguageCapabilities( SingleUseCallback2&> *callback, const ResponseStatus &status, const string &data) { ResponseStatus response_status = status; vector languages; if (response_status.WasAcked()) { unsigned int data_size = data.size(); if (data_size % 2) { std::ostringstream str; str << "PDL needs to be a multiple of 2, was " << data_size; response_status.error = str.str(); } else { const char *ptr = data.data(); const char *end = data.data() + data.size(); while (ptr < end) { languages.push_back(string(ptr, 2)); ptr+=2; } } } callback->Run(response_status, languages); } /* * Handle a LANGUAGE response */ void RDMAPI::_HandleGetLanguage( SingleUseCallback2 *callback, const ResponseStatus &status, const string &data) { ResponseStatus response_status = status; static const unsigned int DATA_SIZE = 2; if (response_status.WasAcked() && data.size() != DATA_SIZE) { SetIncorrectPDL(&response_status, data.size(), DATA_SIZE); } callback->Run(response_status, data); } /* * Handle a BOOT_SOFTWARE_VERSION_ID response */ void RDMAPI::_HandleGetBootSoftwareVersion( SingleUseCallback2 *callback, const ResponseStatus &status, const string &data) { ResponseStatus response_status = status; static const unsigned int DATA_SIZE = 4; uint32_t boot_version = 0; if (response_status.WasAcked()) { if (data.size() != DATA_SIZE) { SetIncorrectPDL(&response_status, data.size(), DATA_SIZE); } else { boot_version = *(reinterpret_cast(data.data())); boot_version = NetworkToHost(boot_version); } } callback->Run(response_status, boot_version); } /* * Handle a get DMX_PERSONALITY response */ void RDMAPI::_HandleGetDMXPersonality( SingleUseCallback3 *callback, const ResponseStatus &status, const string &data) { ResponseStatus response_status = status; static const unsigned int DATA_SIZE = 2; uint8_t current_personality = 0; uint8_t personality_count = 0; if (response_status.WasAcked()) { if (data.size() != DATA_SIZE) { SetIncorrectPDL(&response_status, data.size(), DATA_SIZE); } else { current_personality = data[0]; personality_count = data[1]; } } callback->Run(response_status, current_personality, personality_count); } /* * Handle a get DMX_PERSONALITY_DESCRIPTION response */ void RDMAPI::_HandleGetDMXPersonalityDescription( SingleUseCallback4 *callback, const ResponseStatus &status, const string &data) { ResponseStatus response_status = status; uint8_t personality = 0; uint16_t dmx_slots = 0; string description; if (response_status.WasAcked()) { PACK( struct personality_description { uint8_t personality; uint16_t dmx_slots; // +1 for a null since it's not clear in the spec if this is null // terminated char description[MAX_RDM_STRING_LENGTH + 1]; }); STATIC_ASSERT(sizeof(personality_description) == 36); struct personality_description raw_description; unsigned int max = sizeof(personality_description) - 1; unsigned int min = max - MAX_RDM_STRING_LENGTH; unsigned int data_size = data.size(); if (data_size >= min && data_size <= max) { memcpy(&raw_description, data.data(), std::min(static_cast(data.size()), max)); personality = raw_description.personality; dmx_slots = NetworkToHost(raw_description.dmx_slots); description = string(raw_description.description, data_size - min); ShortenString(&description); } else { std::ostringstream str; str << data_size << " needs to be between " << min << " and " << max; response_status.error = str.str(); } } callback->Run(response_status, personality, dmx_slots, description); } /* * Handle a get DMX_START_ADDRESS response */ void RDMAPI::_HandleGetDMXAddress( SingleUseCallback2 *callback, const ResponseStatus &status, const string &data) { ResponseStatus response_status = status; static const unsigned int DATA_SIZE = 2; uint16_t start_address = 0; if (response_status.WasAcked()) { if (data.size() != DATA_SIZE) { SetIncorrectPDL(&response_status, data.size(), DATA_SIZE); } else { start_address = *(reinterpret_cast(data.data())); start_address = NetworkToHost(start_address); } } callback->Run(response_status, start_address); } /* * Handle a get SLOT_INFO response */ void RDMAPI::_HandleGetSlotInfo( SingleUseCallback2&> *callback, const ResponseStatus &status, const string &data) { ResponseStatus response_status = status; vector slots; SlotDescriptor slot_info; unsigned int slot_info_size = sizeof(slot_info); unsigned int data_size = data.size(); if (response_status.WasAcked()) { if (data_size % slot_info_size) { response_status.error = ("PDL size not a multiple of " + IntToString(slot_info_size) + ", was " + IntToString(static_cast(data_size))); } else { const uint8_t *ptr = reinterpret_cast(data.data()); const uint8_t *end = ptr + data.size(); while (ptr < end) { memcpy(&slot_info, ptr, slot_info_size); slot_info.slot_offset = NetworkToHost(slot_info.slot_offset); slot_info.slot_label = NetworkToHost(slot_info.slot_label); slots.push_back(slot_info); } } } callback->Run(response_status, slots); } /* * Handle a get SLOT_DESCRIPTION response */ void RDMAPI::_HandleGetSlotDescription( SingleUseCallback3 *callback, const ResponseStatus &status, const string &data) { ResponseStatus response_status = status; uint16_t slot_index = 0; string description; if (response_status.WasAcked()) { PACK( struct slot_description { uint16_t slot_index; // +1 for a null since it's not clear in the spec if this is null // terminated char description[MAX_RDM_STRING_LENGTH + 1]; }); STATIC_ASSERT(sizeof(slot_description) == 35); struct slot_description raw_description; unsigned int max = sizeof(raw_description) - 1; unsigned int min = max - MAX_RDM_STRING_LENGTH; unsigned int data_size = data.size(); if (data_size >= min && data_size <= max) { raw_description.description[MAX_RDM_STRING_LENGTH] = 0; memcpy(&raw_description, data.data(), data.size()); slot_index = NetworkToHost(raw_description.slot_index); description = string(raw_description.description, data.size() - min); ShortenString(&description); } else { std::ostringstream str; str << data_size << " needs to be between " << min << " and " << max; response_status.error = str.str(); } } callback->Run(response_status, slot_index, description); } /* * Handle a get DEFAULT_SLOT_VALUE response */ void RDMAPI::_HandleGetSlotDefaultValues( SingleUseCallback2&> *callback, const ResponseStatus &status, const string &data) { ResponseStatus response_status = status; vector slots; SlotDefault slot_default; unsigned int slot_default_size = sizeof(slot_default); unsigned int data_size = data.size(); if (response_status.WasAcked()) { if (data_size % slot_default_size) { response_status.error = ("PDL size not a multiple of " + IntToString(slot_default_size) + ", was " + IntToString(static_cast(data_size))); } else { const uint8_t *ptr = reinterpret_cast(data.data()); const uint8_t *end = ptr + data.size(); while (ptr < end) { memcpy(&slot_default, ptr, slot_default_size); slot_default.slot_offset = NetworkToHost(slot_default.slot_offset); slots.push_back(slot_default); } } } callback->Run(response_status, slots); } /* * Handle a SENSOR_DEFINITION response */ void RDMAPI::_HandleGetSensorDefinition( SingleUseCallback2 *callback, const ResponseStatus &status, const string &data) { ResponseStatus response_status = status; SensorDescriptor sensor; if (response_status.WasAcked()) { PACK( struct sensor_definition_s { uint8_t sensor_number; uint8_t type; uint8_t unit; uint8_t prefix; int16_t range_min; int16_t range_max; int16_t normal_min; int16_t normal_max; uint8_t recorded_value_support; char description[MAX_RDM_STRING_LENGTH + 1]; }); STATIC_ASSERT(sizeof(sensor_definition_s) == 46); struct sensor_definition_s raw_description; unsigned int max = sizeof(raw_description) - 1; unsigned int min = max - MAX_RDM_STRING_LENGTH; unsigned int data_size = data.size(); if (data_size >= min && data_size <= max) { memcpy(&raw_description, data.data(), std::min(static_cast(data.size()), max)); sensor.sensor_number = raw_description.sensor_number; sensor.type = raw_description.type; sensor.unit = raw_description.unit; sensor.prefix = raw_description.prefix; sensor.range_min = NetworkToHost(raw_description.range_min); sensor.range_max = NetworkToHost(raw_description.range_max); sensor.normal_min = NetworkToHost(raw_description.normal_min); sensor.normal_max = NetworkToHost(raw_description.normal_max); sensor.recorded_value_support = raw_description.recorded_value_support; sensor.description = string(raw_description.description, data_size - min); ShortenString(&sensor.description); } else { std::ostringstream str; str << data_size << " needs to be between " << min << " and " << max; response_status.error = str.str(); } } callback->Run(response_status, sensor); } /* * Handle a SENSOR_VALUE response */ void RDMAPI::_HandleSensorValue( SingleUseCallback2 *callback, const ResponseStatus &status, const string &data) { ResponseStatus response_status = status; SensorValueDescriptor sensor; if (response_status.WasAcked()) { unsigned int data_size = data.size(); if (data_size == sizeof(sensor)) { memcpy(&sensor, data.data(), sizeof(sensor)); sensor.present_value = NetworkToHost(sensor.present_value); sensor.lowest = NetworkToHost(sensor.lowest); sensor.highest = NetworkToHost(sensor.highest); sensor.recorded = NetworkToHost(sensor.recorded); } else { SetIncorrectPDL(&response_status, data.size(), sizeof(sensor)); } } callback->Run(response_status, sensor); } /* * Handle a REAL_TIME_CLOCK response */ void RDMAPI::_HandleClock( SingleUseCallback2 *callback, const ResponseStatus &status, const string &data) { ResponseStatus response_status = status; ClockValue clock; if (response_status.WasAcked()) { unsigned int data_size = data.size(); if (data_size == sizeof(clock)) { memcpy(&clock, data.data(), sizeof(clock)); clock.year = NetworkToHost(clock.year); } else { SetIncorrectPDL(&response_status, data.size(), sizeof(clock)); } } callback->Run(response_status, clock); } /** * Handle a PID_SELF_TEST_DESCRIPTION response. */ void RDMAPI::_HandleSelfTestDescription( SingleUseCallback3 *callback, const ResponseStatus &status, const string &data) { ResponseStatus response_status = status; uint8_t self_test_number = 0; string description; if (response_status.WasAcked()) { PACK( struct self_test_description { uint8_t self_test_number; // +1 for a null since it's not clear in the spec if this is null // terminated char description[MAX_RDM_STRING_LENGTH + 1]; }); STATIC_ASSERT(sizeof(self_test_description) == 34); struct self_test_description raw_description; unsigned int max = sizeof(raw_description) - 1; unsigned int min = max - MAX_RDM_STRING_LENGTH; unsigned int data_size = data.size(); if (data_size >= min && data_size <= max) { raw_description.description[MAX_RDM_STRING_LENGTH] = 0; memcpy(&raw_description, data.data(), data.size()); self_test_number = raw_description.self_test_number; description = string(raw_description.description, data.size() - min); ShortenString(&description); } else { std::ostringstream str; str << data_size << " needs to be between " << min << " and " << max; response_status.error = str.str(); } } callback->Run(response_status, self_test_number, description); } /** * Handle a PID_PRESET_PLAYBACK response */ void RDMAPI::_HandlePlaybackMode( SingleUseCallback3 *callback, const ResponseStatus &status, const string &data) { ResponseStatus response_status = status; uint16_t mode = 0; uint8_t level = 0; if (response_status.WasAcked()) { PACK( struct preset_mode { uint16_t mode; uint8_t level; }); STATIC_ASSERT(sizeof(preset_mode) == 3); struct preset_mode raw_config; if (data.size() >= sizeof(raw_config)) { memcpy(&raw_config, data.data(), data.size()); mode = NetworkToHost(raw_config.mode); level = raw_config.level; } else { std::ostringstream str; str << data.size() << " needs to be more than " << sizeof(raw_config); response_status.error = str.str(); } } callback->Run(response_status, mode, level); } //----------------------------------------------------------------------------- // Private methods follow // get a 8 bit value bool RDMAPI::GenericGetU8( unsigned int universe, const UID &uid, uint8_t sub_device, SingleUseCallback2 *callback, uint16_t pid, string *error) { if (CheckNotBroadcast(uid, error, callback)) return false; if (CheckValidSubDevice(sub_device, false, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleU8Response, callback); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, sub_device, pid), error); } // set an 8 bit value bool RDMAPI::GenericSetU8( unsigned int universe, const UID &uid, uint16_t sub_device, uint8_t value, SingleUseCallback1 *callback, uint16_t pid, string *error) { if (CheckValidSubDevice(sub_device, true, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleEmptyResponse, callback); return CheckReturnStatus( m_impl->RDMSet(cb, universe, uid, sub_device, pid, &value, sizeof(value)), error); } // get a 32 bit value bool RDMAPI::GenericGetU32( unsigned int universe, const UID &uid, uint16_t sub_device, SingleUseCallback2 *callback, uint16_t pid, string *error) { if (CheckNotBroadcast(uid, error, callback)) return false; if (CheckValidSubDevice(sub_device, false, error, callback)) return false; RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleU32Response, callback); return CheckReturnStatus( m_impl->RDMGet(cb, universe, uid, sub_device, pid), error); } // set a 32 bit value bool RDMAPI::GenericSetU32( unsigned int universe, const UID &uid, uint16_t sub_device, uint32_t value, SingleUseCallback1 *callback, uint16_t pid, string *error) { if (CheckValidSubDevice(sub_device, true, error, callback)) return false; value = HostToNetwork(value); RDMAPIImplInterface::rdm_callback *cb = NewSingleCallback( this, &RDMAPI::_HandleEmptyResponse, callback); return CheckReturnStatus( m_impl->RDMSet(cb, universe, uid, sub_device, pid, reinterpret_cast(&value), sizeof(value)), error); } // Checks the status of a rdm command and sets error appropriately bool RDMAPI::CheckReturnStatus(bool status, string *error) { if (!status && error) *error = "Unable to send RDM command"; return status; } // Mark a ResponseStatus as malformed due to a length mismatch void RDMAPI::SetIncorrectPDL(ResponseStatus *status, unsigned int actual, unsigned int expected) { status->error = ("PDL mismatch, " + IntToString(actual) + " != " + IntToString(expected) + " (expected)"); } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/PidStoreLoader.cpp0000644000175000017500000004257613023355232021132 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * PidStoreLoader.cpp * The PidStoreLoader and helper code. * Copyright (C) 2011 Simon Newton */ #include #include #include #include #include #include #include #include #include "common/rdm/DescriptorConsistencyChecker.h" #include "common/rdm/PidStoreLoader.h" #include "common/rdm/Pids.pb.h" #include "ola/Logging.h" #include "ola/StringUtils.h" #include "ola/file/Util.h" #include "ola/rdm/PidStore.h" #include "ola/rdm/RDMEnums.h" #include "ola/stl/STLUtils.h" #include "ola/strings/Format.h" namespace ola { namespace rdm { using ola::messaging::Descriptor; using ola::messaging::FieldDescriptor; using std::auto_ptr; using std::map; using std::ostringstream; using std::set; using std::string; using std::vector; const char PidStoreLoader::OVERRIDE_FILE_NAME[] = "overrides.proto"; const uint16_t PidStoreLoader::ESTA_MANUFACTURER_ID = 0; const uint16_t PidStoreLoader::MANUFACTURER_PID_MIN = 0x8000; const uint16_t PidStoreLoader::MANUFACTURER_PID_MAX = 0xffe0; const RootPidStore *PidStoreLoader::LoadFromFile(const string &file, bool validate) { std::ifstream proto_file(file.data()); if (!proto_file.is_open()) { OLA_WARN << "Missing " << file << ": " << strerror(errno); return NULL; } const RootPidStore *store = LoadFromStream(&proto_file, validate); proto_file.close(); return store; } const RootPidStore *PidStoreLoader::LoadFromDirectory( const string &directory, bool validate) { vector files; string override_file; vector all_files; ola::file::ListDirectory(directory, &all_files); vector::const_iterator file_iter = all_files.begin(); for (; file_iter != all_files.end(); ++file_iter) { if (ola::file::FilenameFromPath(*file_iter) == OVERRIDE_FILE_NAME) { override_file = *file_iter; } else if (StringEndsWith(*file_iter, ".proto")) { files.push_back(*file_iter); } } ola::rdm::pid::PidStore pid_store_pb; vector::const_iterator iter = files.begin(); for (; iter != files.end(); ++iter) { std::ifstream proto_file(iter->data()); if (!proto_file.is_open()) { OLA_WARN << "Failed to open " << *iter << ": " << strerror(errno); return NULL; } google::protobuf::io::IstreamInputStream input_stream(&proto_file); bool ok = google::protobuf::TextFormat::Merge(&input_stream, &pid_store_pb); proto_file.close(); if (!ok) { OLA_WARN << "Failed to load " << *iter; return NULL; } } ola::rdm::pid::PidStore override_pb; if (!override_file.empty()) { if (!ReadFile(override_file, &override_pb)) { return NULL; } } return BuildStore(pid_store_pb, override_pb, validate); } const RootPidStore *PidStoreLoader::LoadFromStream(std::istream *data, bool validate) { ola::rdm::pid::PidStore pid_store_pb; google::protobuf::io::IstreamInputStream input_stream(data); bool ok = google::protobuf::TextFormat::Parse(&input_stream, &pid_store_pb); if (!ok) return NULL; ola::rdm::pid::PidStore override_pb; return BuildStore(pid_store_pb, override_pb, validate); } bool PidStoreLoader::ReadFile(const std::string &file_path, ola::rdm::pid::PidStore *proto) { std::ifstream proto_file(file_path.c_str()); if (!proto_file.is_open()) { OLA_WARN << "Failed to open " << file_path << ": " << strerror(errno); return false; } google::protobuf::io::IstreamInputStream input_stream(&proto_file); bool ok = google::protobuf::TextFormat::Merge(&input_stream, proto); proto_file.close(); if (!ok) { OLA_WARN << "Failed to load " << file_path; } return ok; } /* * Build the RootPidStore from a protocol buffer. */ const RootPidStore *PidStoreLoader::BuildStore( const ola::rdm::pid::PidStore &store_pb, const ola::rdm::pid::PidStore &override_pb, bool validate) { ManufacturerMap pid_data; // Load the overrides first so they get first dibs on each PID. if (!LoadFromProto(&pid_data, override_pb, validate)) { FreeManufacturerMap(&pid_data); return NULL; } // Load the main data if (!LoadFromProto(&pid_data, store_pb, validate)) { FreeManufacturerMap(&pid_data); return NULL; } // Now we need to convert the data structure into a format that the PidStore // understands. auto_ptr esta_store; RootPidStore::ManufacturerMap manufacturer_map; ManufacturerMap::iterator iter = pid_data.begin(); for (; iter != pid_data.end(); ++iter) { // Ownership of the Descriptors is transferred to the vector vector pids; STLValues(*iter->second, &pids); delete iter->second; if (iter->first == ESTA_MANUFACTURER_ID) { esta_store.reset(new PidStore(pids)); } else { STLReplaceAndDelete(&manufacturer_map, iter->first, new PidStore(pids)); } } pid_data.clear(); OLA_DEBUG << "Load Complete"; return new RootPidStore(esta_store.release(), manufacturer_map, store_pb.version()); } /* * @brief Load the data from the PidStore proto into the ManufacturerMap. * @param[out] pid_data the ManufacturerMap to populate. * @param proto the Protobuf data. * @param validate Enables strict validation mode. * * If a collision occurs, the data in the map is not replaced. */ bool PidStoreLoader::LoadFromProto(ManufacturerMap *pid_data, const ola::rdm::pid::PidStore &proto, bool validate) { set seen_manufacturer_ids; ManufacturerMap::iterator iter = STLLookupOrInsertNew( pid_data, ESTA_MANUFACTURER_ID); if (!GetPidList(iter->second, proto, validate, true)) { return false; } for (int i = 0; i < proto.manufacturer_size(); ++i) { const ola::rdm::pid::Manufacturer &manufacturer = proto.manufacturer(i); if (STLContains(seen_manufacturer_ids, manufacturer.manufacturer_id())) { OLA_WARN << "Manufacturer id " << manufacturer.manufacturer_id() << "(" << manufacturer.manufacturer_name() << ") listed more than once in the PIDs file"; return false; } seen_manufacturer_ids.insert(manufacturer.manufacturer_id()); ManufacturerMap::iterator iter = STLLookupOrInsertNew( pid_data, manufacturer.manufacturer_id()); if (!GetPidList(iter->second, manufacturer, validate, false)) { return false; } } return true; } /* * @brief Populate a PidMap from a protobuf object that has a set of repeated * PIDs. */ template bool PidStoreLoader::GetPidList(PidMap *pid_map, const pb_object &store, bool validate, bool limit_pid_values) { set seen_pids; set seen_names; for (int i = 0; i < store.pid_size(); ++i) { const ola::rdm::pid::Pid &pid = store.pid(i); OLA_DEBUG << "Loading " << pid.name(); if (validate) { if (STLContains(seen_pids, pid.value())) { OLA_WARN << "PID " << pid.value() << " exists multiple times in the pid file"; return false; } seen_pids.insert(pid.value()); if (STLContains(seen_names, pid.name())) { OLA_WARN << "PID " << pid.name() << " exists multiple times in the pid file"; return false; } seen_names.insert(pid.name()); if (limit_pid_values && pid.value() > MANUFACTURER_PID_MIN && pid.value() < MANUFACTURER_PID_MAX) { OLA_WARN << "ESTA PID " << pid.name() << " (" << pid.value() << ")" << " is outside acceptable range"; return false; } } PidMap::iterator iter = STLLookupOrInsertNull(pid_map, pid.value()); if (iter->second) { OLA_INFO << "Using " << OVERRIDE_FILE_NAME << " for " << pid.name() << "( " << strings::ToHex(pid.value()) << ")"; continue; } const PidDescriptor *descriptor = PidToDescriptor(pid, validate); if (!descriptor) { return false; } iter->second = descriptor; } return true; } /* * Build a PidDescriptor from a Pid protobuf object */ PidDescriptor *PidStoreLoader::PidToDescriptor(const ola::rdm::pid::Pid &pid, bool validate) { // populate sub device validators PidDescriptor::sub_device_validator get_validator = PidDescriptor::ANY_SUB_DEVICE; if (pid.has_get_sub_device_range()) get_validator = ConvertSubDeviceValidator(pid.get_sub_device_range()); PidDescriptor::sub_device_validator set_validator = PidDescriptor::ANY_SUB_DEVICE; if (pid.has_set_sub_device_range()) set_validator = ConvertSubDeviceValidator(pid.set_sub_device_range()); // yuck, code smell. This should use protobuf reflections instead. const Descriptor *get_request = NULL; if (pid.has_get_request()) { get_request = FrameFormatToDescriptor(pid.get_request(), validate); if (!get_request) return NULL; } const Descriptor *get_response = NULL; if (pid.has_get_response()) { get_response = FrameFormatToDescriptor(pid.get_response(), validate); if (!get_response) { delete get_request; return NULL; } } const Descriptor *set_request = NULL; if (pid.has_set_request()) { set_request = FrameFormatToDescriptor(pid.set_request(), validate); if (!set_request) { delete get_request; delete get_response; return NULL; } } const Descriptor *set_response = NULL; if (pid.has_set_response()) { set_response = FrameFormatToDescriptor(pid.set_response(), validate); if (!set_response) { delete get_request; delete get_response; delete set_request; return NULL; } } PidDescriptor *descriptor = new PidDescriptor( pid.name(), pid.value(), get_request, get_response, set_request, set_response, get_validator, set_validator); return descriptor; } /* * Convert a protobuf frame format to a Descriptor object */ const Descriptor* PidStoreLoader::FrameFormatToDescriptor( const ola::rdm::pid::FrameFormat &format, bool validate) { bool ok = true; vector fields; for (int i = 0; i < format.field_size(); ++i) { const FieldDescriptor *field = FieldToFieldDescriptor(format.field(i)); if (!field) { ok = false; break; } fields.push_back(field); } if (!ok) { vector::iterator iter = fields.begin(); for (; iter != fields.end(); ++iter) { delete *iter; } return NULL; } // we don't give these descriptors names const Descriptor *descriptor = new Descriptor("", fields); if (validate) { if (!m_checker.CheckConsistency(descriptor)) { OLA_WARN << "Invalid frame format"; delete descriptor; return NULL; } } return descriptor; } /* * Convert a protobuf field object to a FieldDescriptor. */ const FieldDescriptor *PidStoreLoader::FieldToFieldDescriptor( const ola::rdm::pid::Field &field) { const FieldDescriptor *descriptor = NULL; switch (field.type()) { case ola::rdm::pid::BOOL: descriptor = new ola::messaging::BoolFieldDescriptor(field.name()); break; case ola::rdm::pid::UINT8: descriptor = IntegerFieldToFieldDescriptor( field); break; case ola::rdm::pid::UINT16: descriptor = IntegerFieldToFieldDescriptor( field); break; case ola::rdm::pid::UINT32: descriptor = IntegerFieldToFieldDescriptor( field); break; case ola::rdm::pid::INT8: descriptor = IntegerFieldToFieldDescriptor( field); break; case ola::rdm::pid::INT16: descriptor = IntegerFieldToFieldDescriptor( field); break; case ola::rdm::pid::INT32: descriptor = IntegerFieldToFieldDescriptor( field); break; case ola::rdm::pid::STRING: descriptor = StringFieldToFieldDescriptor(field); break; case ola::rdm::pid::GROUP: descriptor = GroupFieldToFieldDescriptor(field); break; case ola::rdm::pid::IPV4: descriptor = new ola::messaging::IPV4FieldDescriptor(field.name()); break; case ola::rdm::pid::MAC: descriptor = new ola::messaging::MACFieldDescriptor(field.name()); break; case ola::rdm::pid::UID: descriptor = new ola::messaging::UIDFieldDescriptor(field.name()); break; default: OLA_WARN << "Unknown field type: " << field.type(); } return descriptor; } /* * Convert a integer protobuf field to a FieldDescriptor. */ template const FieldDescriptor *PidStoreLoader::IntegerFieldToFieldDescriptor( const ola::rdm::pid::Field &field) { typename descriptor_class::IntervalVector intervals; typename descriptor_class::LabeledValues labels; for (int i = 0; i < field.range_size(); ++i) { const ola::rdm::pid::Range &range_value = field.range(i); typename descriptor_class::Interval interval(range_value.min(), range_value.max()); intervals.push_back(interval); } // if not intervals were specified, we automatically add all the labels bool intervals_empty = intervals.empty(); for (int i = 0; i < field.label_size(); ++i) { const ola::rdm::pid::LabeledValue &labeled_value = field.label(i); labels[labeled_value.label()] = labeled_value.value(); if (intervals_empty) { typename descriptor_class::Interval interval(labeled_value.value(), labeled_value.value()); intervals.push_back(interval); } } int8_t multipler = 0; if (field.has_multiplier()) multipler = field.multiplier(); return new descriptor_class( field.name(), intervals, labels, false, multipler); } /* * Convert a string protobuf field to a FieldDescriptor. */ const FieldDescriptor *PidStoreLoader::StringFieldToFieldDescriptor( const ola::rdm::pid::Field &field) { uint8_t min = 0; if (field.has_min_size()) min = field.min_size(); if (!field.has_max_size()) { OLA_WARN << "String field failed to specify max size"; return NULL; } return new ola::messaging::StringFieldDescriptor( field.name(), min, field.max_size()); } /* * Convert a group protobuf field to a FieldDescriptor. */ const FieldDescriptor *PidStoreLoader::GroupFieldToFieldDescriptor( const ola::rdm::pid::Field &field) { vector fields; bool ok = true; uint16_t min = 0; int16_t max = ola::messaging::FieldDescriptorGroup::UNLIMITED_BLOCKS; if (field.has_min_size()) min = field.min_size(); if (field.has_max_size()) max = field.max_size(); for (int i = 0; i < field.field_size(); ++i) { const FieldDescriptor *descriptor = FieldToFieldDescriptor(field.field(i)); if (!descriptor) { ok = false; break; } fields.push_back(descriptor); } if (!ok) { vector::iterator iter = fields.begin(); for (; iter != fields.end(); ++iter) { delete *iter; } return NULL; } return new ola::messaging::FieldDescriptorGroup( field.name(), fields, min, max); } /* * Convert a protobuf sub device enum to a PidDescriptor one. */ PidDescriptor::sub_device_validator PidStoreLoader::ConvertSubDeviceValidator( const ola::rdm::pid::SubDeviceRange &sub_device_range) { switch (sub_device_range) { case ola::rdm::pid::ROOT_DEVICE: return PidDescriptor::ROOT_DEVICE; case ola::rdm::pid::ROOT_OR_ALL_SUBDEVICE: return PidDescriptor::ANY_SUB_DEVICE; case ola::rdm::pid::ROOT_OR_SUBDEVICE: return PidDescriptor::NON_BROADCAST_SUB_DEVICE; case ola::rdm::pid::ONLY_SUBDEVICES: return PidDescriptor::SPECIFIC_SUB_DEVICE; default: OLA_WARN << "Unknown sub device validator: " << sub_device_range << ", defaulting to all"; return PidDescriptor::ANY_SUB_DEVICE; } } void PidStoreLoader::FreeManufacturerMap(ManufacturerMap *data) { ManufacturerMap::iterator iter = data->begin(); for (; iter != data->end(); ++iter) { STLDeleteValues(iter->second); delete iter->second; } data->clear(); } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/VariableFieldSizeCalculatorTest.cpp0000644000175000017500000002752413023355232024444 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * VariableFieldSizeCalculatorTest.cpp * Test fixture for the VariableFieldSizeCalculator. * Copyright (C) 2011 Simon Newton */ #include #include #include "ola/testing/TestUtils.h" #include "ola/Logging.h" #include "ola/messaging/Descriptor.h" #include "common/rdm/VariableFieldSizeCalculator.h" using ola::messaging::BoolFieldDescriptor; using ola::messaging::IPV4FieldDescriptor; using ola::messaging::Descriptor; using ola::messaging::FieldDescriptor; using ola::messaging::FieldDescriptorGroup; using ola::messaging::Int16FieldDescriptor; using ola::messaging::Int32FieldDescriptor; using ola::messaging::Int8FieldDescriptor; using ola::messaging::StringFieldDescriptor; using ola::messaging::UInt16FieldDescriptor; using ola::messaging::UInt32FieldDescriptor; using ola::messaging::UInt8FieldDescriptor; using ola::messaging::UIDFieldDescriptor; using ola::rdm::VariableFieldSizeCalculator; using std::vector; class VariableFieldSizeCalculatorTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(VariableFieldSizeCalculatorTest); CPPUNIT_TEST(testFixedFields); CPPUNIT_TEST(testStringFields); CPPUNIT_TEST(testWithFixedGroups); CPPUNIT_TEST(testSingleVariableSizedGroup); CPPUNIT_TEST(testMultipleVariableSizedFields); CPPUNIT_TEST(testNestedVariableSizedGroups); CPPUNIT_TEST_SUITE_END(); public: void testFixedFields(); void testStringFields(); void testWithFixedGroups(); void testSingleVariableSizedGroup(); void testMultipleVariableSizedFields(); void testNestedVariableSizedGroups(); private: ola::rdm::VariableFieldSizeCalculator m_calculator; }; CPPUNIT_TEST_SUITE_REGISTRATION(VariableFieldSizeCalculatorTest); /** * Test that we can determine the token count for descriptors that contain only * fixed fields. */ void VariableFieldSizeCalculatorTest::testFixedFields() { vector fields; fields.push_back(new BoolFieldDescriptor("bool1")); fields.push_back(new IPV4FieldDescriptor("ip1")); fields.push_back(new UIDFieldDescriptor("ip1")); fields.push_back(new UInt8FieldDescriptor("uint8")); fields.push_back(new UInt16FieldDescriptor("uint16")); fields.push_back(new UInt32FieldDescriptor("uint32")); fields.push_back(new Int8FieldDescriptor("int8")); fields.push_back(new Int16FieldDescriptor("int16")); fields.push_back(new Int32FieldDescriptor("int32")); Descriptor descriptor("Test Descriptor", fields); unsigned int variable_field_size; OLA_ASSERT_EQ( VariableFieldSizeCalculator::TOO_SMALL, m_calculator.CalculateFieldSize( 0, &descriptor, &variable_field_size)); OLA_ASSERT_EQ( VariableFieldSizeCalculator::TOO_SMALL, m_calculator.CalculateFieldSize( 1, &descriptor, &variable_field_size)); OLA_ASSERT_EQ( VariableFieldSizeCalculator::TOO_SMALL, m_calculator.CalculateFieldSize( 14, &descriptor, &variable_field_size)); OLA_ASSERT_EQ( VariableFieldSizeCalculator::FIXED_SIZE, m_calculator.CalculateFieldSize( 25, &descriptor, &variable_field_size)); OLA_ASSERT_EQ( VariableFieldSizeCalculator::TOO_LARGE, m_calculator.CalculateFieldSize( 26, &descriptor, &variable_field_size)); } /** * Check that we can work out the size for variable sized string fields */ void VariableFieldSizeCalculatorTest::testStringFields() { vector fields; fields.push_back(new UInt8FieldDescriptor("uint8")); fields.push_back(new UInt16FieldDescriptor("uint16")); fields.push_back(new StringFieldDescriptor("str1", 0, 32)); Descriptor descriptor("Test Descriptor", fields); // set this to something large so we can verify it's set correctly unsigned int variable_field_size = 2000; OLA_ASSERT_EQ( VariableFieldSizeCalculator::TOO_SMALL, m_calculator.CalculateFieldSize( 0, &descriptor, &variable_field_size)); OLA_ASSERT_EQ( VariableFieldSizeCalculator::TOO_SMALL, m_calculator.CalculateFieldSize( 2, &descriptor, &variable_field_size)); OLA_ASSERT_EQ( VariableFieldSizeCalculator::VARIABLE_STRING, m_calculator.CalculateFieldSize( 3, &descriptor, &variable_field_size)); OLA_ASSERT_EQ(0u, variable_field_size); OLA_ASSERT_EQ( VariableFieldSizeCalculator::VARIABLE_STRING, m_calculator.CalculateFieldSize( 4, &descriptor, &variable_field_size)); OLA_ASSERT_EQ(1u, variable_field_size); OLA_ASSERT_EQ( VariableFieldSizeCalculator::VARIABLE_STRING, m_calculator.CalculateFieldSize( 34, &descriptor, &variable_field_size)); OLA_ASSERT_EQ(31u, variable_field_size); OLA_ASSERT_EQ( VariableFieldSizeCalculator::VARIABLE_STRING, m_calculator.CalculateFieldSize( 35, &descriptor, &variable_field_size)); OLA_ASSERT_EQ(32u, variable_field_size); OLA_ASSERT_EQ( VariableFieldSizeCalculator::TOO_LARGE, m_calculator.CalculateFieldSize( 36, &descriptor, &variable_field_size)); } /** * Check the calculators work with fixed groups. */ void VariableFieldSizeCalculatorTest::testWithFixedGroups() { vector group_fields, group_fields2; group_fields.push_back(new BoolFieldDescriptor("bool")); group_fields.push_back(new UInt8FieldDescriptor("uint8")); group_fields2.push_back(new Int16FieldDescriptor("int16")); group_fields2.push_back(new UInt16FieldDescriptor("uint16")); vector fields; fields.push_back(new FieldDescriptorGroup("", group_fields, 2, 2)); fields.push_back(new FieldDescriptorGroup("", group_fields2, 2, 2)); Descriptor descriptor("Test Descriptor", fields); unsigned int variable_field_size; OLA_ASSERT_EQ( VariableFieldSizeCalculator::TOO_SMALL, m_calculator.CalculateFieldSize( 11, &descriptor, &variable_field_size)); OLA_ASSERT_EQ( VariableFieldSizeCalculator::FIXED_SIZE, m_calculator.CalculateFieldSize( 12, &descriptor, &variable_field_size)); OLA_ASSERT_EQ( VariableFieldSizeCalculator::TOO_LARGE, m_calculator.CalculateFieldSize( 13, &descriptor, &variable_field_size)); } /* * Test that a single variable-sized group passes */ void VariableFieldSizeCalculatorTest::testSingleVariableSizedGroup() { vector group_fields; group_fields.push_back(new BoolFieldDescriptor("bool")); group_fields.push_back(new UInt8FieldDescriptor("uint8")); vector fields; fields.push_back(new UInt8FieldDescriptor("uint8")); fields.push_back(new UInt16FieldDescriptor("uint16")); fields.push_back(new FieldDescriptorGroup("", group_fields, 0, 2)); Descriptor descriptor("Test Descriptor", fields); unsigned int variable_field_size; OLA_ASSERT_EQ( VariableFieldSizeCalculator::TOO_SMALL, m_calculator.CalculateFieldSize( 2, &descriptor, &variable_field_size)); OLA_ASSERT_EQ( VariableFieldSizeCalculator::VARIABLE_GROUP, m_calculator.CalculateFieldSize( 3, &descriptor, &variable_field_size)); OLA_ASSERT_EQ(0u, variable_field_size); OLA_ASSERT_EQ( VariableFieldSizeCalculator::MISMATCHED_SIZE, m_calculator.CalculateFieldSize( 4, &descriptor, &variable_field_size)); OLA_ASSERT_EQ( VariableFieldSizeCalculator::VARIABLE_GROUP, m_calculator.CalculateFieldSize( 5, &descriptor, &variable_field_size)); OLA_ASSERT_EQ(1u, variable_field_size); OLA_ASSERT_EQ( VariableFieldSizeCalculator::MISMATCHED_SIZE, m_calculator.CalculateFieldSize( 6, &descriptor, &variable_field_size)); OLA_ASSERT_EQ( VariableFieldSizeCalculator::VARIABLE_GROUP, m_calculator.CalculateFieldSize( 7, &descriptor, &variable_field_size)); OLA_ASSERT_EQ(2u, variable_field_size); OLA_ASSERT_EQ( VariableFieldSizeCalculator::TOO_LARGE, m_calculator.CalculateFieldSize( 8, &descriptor, &variable_field_size)); } /* * Test that multiple variable-sized groups fail */ void VariableFieldSizeCalculatorTest::testMultipleVariableSizedFields() { // first try a descriptor with two strings vector fields; fields.push_back(new StringFieldDescriptor("str1", 0, 10)); fields.push_back(new StringFieldDescriptor("str2", 0 , 10)); Descriptor string_descriptor("Test Descriptor", fields); unsigned int variable_field_size; OLA_ASSERT_EQ( VariableFieldSizeCalculator::MULTIPLE_VARIABLE_FIELDS, m_calculator.CalculateFieldSize( 0, &string_descriptor, &variable_field_size)); // now try a variable group and a variable string vector group_fields, fields2; group_fields.push_back(new BoolFieldDescriptor("bool")); group_fields.push_back(new UInt8FieldDescriptor("uint8")); fields2.push_back(new StringFieldDescriptor("str1", 0, 10)); fields2.push_back(new FieldDescriptorGroup("", group_fields, 0, 2)); Descriptor string_group_descriptor("Test Descriptor", fields2); OLA_ASSERT_EQ( VariableFieldSizeCalculator::MULTIPLE_VARIABLE_FIELDS, m_calculator.CalculateFieldSize( 0, &string_group_descriptor, &variable_field_size)); // now do multiple variable sized groups vector group_fields1, group_fields2, fields3; group_fields1.push_back(new BoolFieldDescriptor("bool")); group_fields1.push_back(new UInt8FieldDescriptor("uint8")); group_fields2.push_back(new BoolFieldDescriptor("bool")); group_fields2.push_back(new UInt8FieldDescriptor("uint8")); fields3.push_back(new FieldDescriptorGroup("", group_fields1, 0, 2)); fields3.push_back(new FieldDescriptorGroup("", group_fields2, 0, 2)); Descriptor multi_group_descriptor("Test Descriptor", fields3); OLA_ASSERT_EQ( VariableFieldSizeCalculator::MULTIPLE_VARIABLE_FIELDS, m_calculator.CalculateFieldSize( 0, &multi_group_descriptor, &variable_field_size)); } /* * Test that a nested, variable sized groups fail */ void VariableFieldSizeCalculatorTest::testNestedVariableSizedGroups() { vector fields, group_fields, group_fields2; group_fields.push_back(new BoolFieldDescriptor("bool")); group_fields.push_back(new UInt8FieldDescriptor("uint8")); group_fields2.push_back(new Int16FieldDescriptor("int16")); group_fields2.push_back(new FieldDescriptorGroup("", group_fields, 0, 2)); const FieldDescriptorGroup *nested_variable_group = new FieldDescriptorGroup( "", group_fields2, 0, 4); fields.push_back(new Int16FieldDescriptor("int16")); fields.push_back(nested_variable_group); Descriptor descriptor("Test Descriptor", fields); unsigned int variable_field_size; // now check the main calculator. OLA_ASSERT_EQ( VariableFieldSizeCalculator::NESTED_VARIABLE_GROUPS, m_calculator.CalculateFieldSize( 10, &descriptor, &variable_field_size)); } ola-0.10.5.nojsmin/common/rdm/FakeNetworkManager.cpp0000644000175000017500000000500513023355232021747 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * FakeNetworkManager.cpp * A NetworkManager which uses a simulated network config. * Copyright (C) 2014 Simon Newton */ #include "common/rdm/FakeNetworkManager.h" #include #include namespace ola { namespace rdm { using ola::network::Interface; using ola::network::InterfacePicker; using ola::network::IPV4Address; using std::string; using std::vector; FakeNetworkManager::FakeNetworkManager( const vector &interfaces, const int32_t ipv4_default_route_if_index, const IPV4Address ipv4_default_route, const string &hostname, const string &domain_name, const vector &name_servers) : NetworkManagerInterface(), m_interface_picker(interfaces), m_ipv4_default_route_if_index(ipv4_default_route_if_index), m_ipv4_default_route(ipv4_default_route), m_hostname(hostname), m_domain_name(domain_name), m_name_servers(name_servers) { } const InterfacePicker *FakeNetworkManager::GetInterfacePicker() const { return &m_interface_picker; } rdm_dhcp_status FakeNetworkManager::GetDHCPStatus( const Interface &iface) const { // Mix things up a bit. The status depends on the index. return static_cast(iface.index % DHCP_STATUS_MAX); } bool FakeNetworkManager::GetIPV4DefaultRoute( int32_t *if_index, IPV4Address *default_route) const { *if_index = m_ipv4_default_route_if_index; *default_route = m_ipv4_default_route; return true; } const string FakeNetworkManager::GetHostname() const { return m_hostname; } const string FakeNetworkManager::GetDomainName() const { return m_domain_name; } bool FakeNetworkManager::GetNameServers( vector *name_servers) const { *name_servers = m_name_servers; return true; } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/OpenLightingEnums.cpp0000644000175000017500000000173213023355232021636 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * OpenLightingEnums.cpp * Copyright (C) 2013 Peter Newman */ #include "ola/rdm/OpenLightingEnums.h" namespace ola { namespace rdm { const char OLA_MANUFACTURER_LABEL[] = "Open Lighting Project"; } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/rdm/GroupSizeCalculator.h0000644000175000017500000001051213023355232021641 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * GroupSizeCalculator.h * Calculate the number of items in a group, given a fixed number of tokens. * Copyright (C) 2011 Simon Newton */ #ifndef COMMON_RDM_GROUPSIZECALCULATOR_H_ #define COMMON_RDM_GROUPSIZECALCULATOR_H_ #include #include #include namespace ola { namespace messaging { class Descriptor; } namespace rdm { /** * This calculates the required nmuber of tokens for a group which contains no * variable-sized groups. */ class StaticGroupTokenCalculator : public ola::messaging::FieldDescriptorVisitor { public: StaticGroupTokenCalculator() : m_variable_sized_group_encountered(false) { } ~StaticGroupTokenCalculator() {} bool Descend() const { return true; } bool CalculateTokensRequired( const class ola::messaging::FieldDescriptorGroup*, unsigned int *token_count); void Visit(const ola::messaging::BoolFieldDescriptor*); void Visit(const ola::messaging::IPV4FieldDescriptor*); void Visit(const ola::messaging::MACFieldDescriptor*); void Visit(const ola::messaging::UIDFieldDescriptor*); void Visit(const ola::messaging::StringFieldDescriptor*); void Visit(const ola::messaging::UInt8FieldDescriptor*); void Visit(const ola::messaging::UInt16FieldDescriptor*); void Visit(const ola::messaging::UInt32FieldDescriptor*); void Visit(const ola::messaging::Int8FieldDescriptor*); void Visit(const ola::messaging::Int16FieldDescriptor*); void Visit(const ola::messaging::Int32FieldDescriptor*); void Visit(const ola::messaging::FieldDescriptorGroup*); void PostVisit(const ola::messaging::FieldDescriptorGroup*); private: std::stack m_token_count; bool m_variable_sized_group_encountered; }; /** * Calculate the number of repeats of a group required, given a certain number * of tokens. */ class GroupSizeCalculator: public ola::messaging::FieldDescriptorVisitor { public: typedef enum { INSUFFICIENT_TOKENS, EXTRA_TOKENS, NO_VARIABLE_GROUPS, SINGLE_VARIABLE_GROUP, MULTIPLE_VARIABLE_GROUPS, NESTED_VARIABLE_GROUPS, MISMATCHED_TOKENS, } calculator_state; GroupSizeCalculator() {} ~GroupSizeCalculator() {} bool Descend() const { return false; } calculator_state CalculateGroupSize( unsigned int token_count, const class ola::messaging::Descriptor *descriptor, unsigned int *group_repeat_count); void Visit(const ola::messaging::BoolFieldDescriptor*); void Visit(const ola::messaging::IPV4FieldDescriptor*); void Visit(const ola::messaging::MACFieldDescriptor*); void Visit(const ola::messaging::UIDFieldDescriptor*); void Visit(const ola::messaging::StringFieldDescriptor*); void Visit(const ola::messaging::UInt8FieldDescriptor*); void Visit(const ola::messaging::UInt16FieldDescriptor*); void Visit(const ola::messaging::UInt32FieldDescriptor*); void Visit(const ola::messaging::Int8FieldDescriptor*); void Visit(const ola::messaging::Int16FieldDescriptor*); void Visit(const ola::messaging::Int32FieldDescriptor*); void Visit(const ola::messaging::FieldDescriptorGroup*); void PostVisit(const ola::messaging::FieldDescriptorGroup*); private: std::vector m_groups; std::vector m_non_groups; StaticGroupTokenCalculator m_simple_calculator; unsigned int DetermineGroupSize(const ola::messaging::FieldDescriptorGroup*); }; } // namespace rdm } // namespace ola #endif // COMMON_RDM_GROUPSIZECALCULATOR_H_ ola-0.10.5.nojsmin/common/rdm/TestHelper.h0000644000175000017500000000234713023355232017766 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * TestHelper.h * Helper classes for the RDM tests. * Copyright (C) 2015 Simon Newton */ #ifndef COMMON_RDM_TESTHELPER_H_ #define COMMON_RDM_TESTHELPER_H_ #include "ola/network/NetworkUtils.h" #include "ola/rdm/RDMCommand.h" inline uint16_t NackReasonFromResponse(const ola::rdm::RDMResponse *response) { uint16_t reason; memcpy(reinterpret_cast(&reason), response->ParamData(), sizeof(reason)); return ola::network::NetworkToHost(reason); } #endif // COMMON_RDM_TESTHELPER_H_ ola-0.10.5.nojsmin/common/rdm/PidStoreTest.cpp0000644000175000017500000004254513023355232020637 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * PidStoreTest.cpp * Test fixture for the PidStore & Pid classes * Copyright (C) 2011 Simon Newton */ #include #include #include #include #include #include #include "common/rdm/PidStoreLoader.h" #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/messaging/Descriptor.h" #include "ola/messaging/SchemaPrinter.h" #include "ola/rdm/PidStore.h" #include "ola/rdm/RDMEnums.h" #include "ola/testing/TestUtils.h" using ola::messaging::Descriptor; using ola::messaging::FieldDescriptor; using ola::messaging::FieldDescriptorGroup; using ola::rdm::PidDescriptor; using ola::rdm::PidStore; using ola::rdm::PidStoreLoader; using ola::rdm::RootPidStore; using std::auto_ptr; using std::endl; using std::string; using std::stringstream; using std::vector; class PidStoreTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(PidStoreTest); CPPUNIT_TEST(testPidDescriptor); CPPUNIT_TEST(testPidStore); CPPUNIT_TEST(testPidStoreLoad); CPPUNIT_TEST(testPidStoreFileLoad); CPPUNIT_TEST(testPidStoreDirectoryLoad); CPPUNIT_TEST(testPidStoreLoadMissingFile); CPPUNIT_TEST(testPidStoreLoadDuplicateManufacturer); CPPUNIT_TEST(testPidStoreLoadDuplicateValue); CPPUNIT_TEST(testPidStoreLoadDuplicateName); CPPUNIT_TEST(testPidStoreLoadInvalidEstaPid); CPPUNIT_TEST(testInconsistentData); CPPUNIT_TEST_SUITE_END(); public: void testPidDescriptor(); void testPidStore(); void testPidStoreLoad(); void testPidStoreFileLoad(); void testPidStoreDirectoryLoad(); void testPidStoreLoadMissingFile(); void testPidStoreLoadDuplicateManufacturer(); void testPidStoreLoadDuplicateValue(); void testPidStoreLoadDuplicateName(); void testPidStoreLoadInvalidEstaPid(); void testInconsistentData(); private: string GetTestDataFile(const string &filename) { string path = TEST_SRC_DIR; path.append("/common/rdm/testdata/"); path.append(filename); return path; } }; CPPUNIT_TEST_SUITE_REGISTRATION(PidStoreTest); /* * Test that the PidDescriptor works. */ void PidStoreTest::testPidDescriptor() { // just use empty fields for now vector fields; const Descriptor *get_request_descriptor = new Descriptor("GET Request", fields); const Descriptor *get_response_descriptor = new Descriptor("GET Response", fields); const Descriptor *set_request_descriptor = new Descriptor("SET Request", fields); const Descriptor *set_response_descriptor = new Descriptor("SET Response", fields); PidDescriptor pid("foo", 10, get_request_descriptor, get_response_descriptor, set_request_descriptor, set_response_descriptor, PidDescriptor::NON_BROADCAST_SUB_DEVICE, PidDescriptor::ANY_SUB_DEVICE); // basic checks OLA_ASSERT_EQ(string("foo"), pid.Name()); OLA_ASSERT_EQ(static_cast(10), pid.Value()); OLA_ASSERT_EQ(get_request_descriptor, pid.GetRequest()); OLA_ASSERT_EQ(get_response_descriptor, pid.GetResponse()); OLA_ASSERT_EQ(set_request_descriptor, pid.SetRequest()); OLA_ASSERT_EQ(set_response_descriptor, pid.SetResponse()); // check sub device constraints OLA_ASSERT_TRUE(pid.IsGetValid(0)); OLA_ASSERT_TRUE(pid.IsGetValid(1)); OLA_ASSERT_TRUE(pid.IsGetValid(2)); OLA_ASSERT_TRUE(pid.IsGetValid(511)); OLA_ASSERT_TRUE(pid.IsGetValid(512)); OLA_ASSERT_FALSE(pid.IsGetValid(513)); OLA_ASSERT_FALSE(pid.IsGetValid(0xffff)); OLA_ASSERT_TRUE(pid.IsSetValid(0)); OLA_ASSERT_TRUE(pid.IsSetValid(1)); OLA_ASSERT_TRUE(pid.IsSetValid(2)); OLA_ASSERT_TRUE(pid.IsSetValid(511)); OLA_ASSERT_TRUE(pid.IsSetValid(512)); OLA_ASSERT_FALSE(pid.IsSetValid(513)); OLA_ASSERT_TRUE(pid.IsSetValid(0xffff)); } /** * Check the PidStore works. */ void PidStoreTest::testPidStore() { const PidDescriptor *foo_pid = new PidDescriptor( "foo", 0, NULL, NULL, NULL, NULL, PidDescriptor::NON_BROADCAST_SUB_DEVICE, PidDescriptor::ANY_SUB_DEVICE); const PidDescriptor *bar_pid = new PidDescriptor( "bar", 1, NULL, NULL, NULL, NULL, PidDescriptor::NON_BROADCAST_SUB_DEVICE, PidDescriptor::ANY_SUB_DEVICE); vector pids; pids.push_back(foo_pid); pids.push_back(bar_pid); PidStore store(pids); // check value lookups OLA_ASSERT_EQ(foo_pid, store.LookupPID(0)); OLA_ASSERT_EQ(bar_pid, store.LookupPID(1)); OLA_ASSERT_EQ(static_cast(NULL), store.LookupPID(2)); // check name lookups OLA_ASSERT_EQ(foo_pid, store.LookupPID("foo")); OLA_ASSERT_EQ(bar_pid, store.LookupPID("bar")); OLA_ASSERT_EQ(static_cast(NULL), store.LookupPID("baz")); // check all pids; vector all_pids; store.AllPids(&all_pids); OLA_ASSERT_EQ(static_cast(2), all_pids.size()); OLA_ASSERT_EQ(foo_pid, all_pids[0]); OLA_ASSERT_EQ(bar_pid, all_pids[1]); } /** * Check we can load a PidStore from a string */ void PidStoreTest::testPidStoreLoad() { PidStoreLoader loader; // This is a stringstream not a ostringstream as the other end needs an // istream stringstream str; // check that this fails to load const RootPidStore *empty_root_store = loader.LoadFromStream(&str); OLA_ASSERT_EQ(static_cast(NULL), empty_root_store); // now try a simple pid store config str.clear(); str << "pid {" << endl << " name: \"PROXIED_DEVICES\"" << endl << " value: 16" << endl << " get_request {" << endl << " }" << endl << " get_response {" << endl << " field {" << endl << " type: GROUP" << endl << " name: \"uids\"" << endl << " field {" << endl << " type: UINT16" << endl << " name: \"manufacturer_id\"" << endl << " }" << endl << " field {" << endl << " type: UINT32" << endl << " name: \"device_id\"" << endl << " }" << endl << " }" << endl << " }" << endl << " get_sub_device_range: ROOT_DEVICE" << endl << "}" << endl << "manufacturer {" << endl << " manufacturer_id: 31344" << endl << " manufacturer_name: \"Open Lighting\"" << endl << "}" << endl << "version: 1" << endl; auto_ptr root_store(loader.LoadFromStream(&str)); OLA_ASSERT_TRUE(root_store.get()); // check version OLA_ASSERT_EQ(static_cast(1), root_store->Version()); // check manufacturer pids const PidStore *open_lighting_store = root_store->ManufacturerStore(ola::OPEN_LIGHTING_ESTA_CODE); OLA_ASSERT_TRUE(open_lighting_store); OLA_ASSERT_EQ(0u, open_lighting_store->PidCount()); // lookup by value OLA_ASSERT_TRUE(root_store->GetDescriptor(16)); OLA_ASSERT_FALSE(root_store->GetDescriptor(17)); OLA_ASSERT_TRUE(root_store->GetDescriptor(16, ola::OPEN_LIGHTING_ESTA_CODE)); OLA_ASSERT_FALSE(root_store->GetDescriptor(17, ola::OPEN_LIGHTING_ESTA_CODE)); // lookup by name OLA_ASSERT_TRUE(root_store->GetDescriptor("PROXIED_DEVICES")); OLA_ASSERT_FALSE(root_store->GetDescriptor("DEVICE_INFO")); OLA_ASSERT_TRUE(root_store->GetDescriptor("PROXIED_DEVICES", ola::OPEN_LIGHTING_ESTA_CODE)); OLA_ASSERT_FALSE(root_store->GetDescriptor("DEVICE_INFO", ola::OPEN_LIGHTING_ESTA_CODE)); // check lookups const PidStore *esta_store = root_store->EstaStore(); OLA_ASSERT_TRUE(esta_store); const PidDescriptor *pid_descriptor = esta_store->LookupPID(16); OLA_ASSERT_TRUE(pid_descriptor); const PidDescriptor *pid_descriptor2 = esta_store->LookupPID( "PROXIED_DEVICES"); OLA_ASSERT_TRUE(pid_descriptor2); OLA_ASSERT_EQ(pid_descriptor, pid_descriptor2); // check name and value OLA_ASSERT_EQ(static_cast(16), pid_descriptor->Value()); OLA_ASSERT_EQ(string("PROXIED_DEVICES"), pid_descriptor->Name()); // check descriptors OLA_ASSERT_TRUE(pid_descriptor->GetRequest()); OLA_ASSERT_TRUE(pid_descriptor->GetResponse()); OLA_ASSERT_EQ(static_cast(NULL), pid_descriptor->SetRequest()); OLA_ASSERT_EQ(static_cast(NULL), pid_descriptor->SetResponse()); // check GET descriptors const Descriptor *get_request = pid_descriptor->GetRequest(); OLA_ASSERT_EQ(0u, get_request->FieldCount()); const Descriptor *get_response = pid_descriptor->GetResponse(); OLA_ASSERT_EQ(1u, get_response->FieldCount()); const FieldDescriptor *proxied_group = get_response->GetField(0); OLA_ASSERT_TRUE(proxied_group); // this is ugly but it's a test const FieldDescriptorGroup *group_descriptor = dynamic_cast(proxied_group); OLA_ASSERT_TRUE(group_descriptor); // check all the group properties OLA_ASSERT_FALSE(group_descriptor->FixedSize()); OLA_ASSERT_FALSE(group_descriptor->LimitedSize()); OLA_ASSERT_EQ(0u, group_descriptor->MaxSize()); OLA_ASSERT_EQ(2u, group_descriptor->FieldCount()); OLA_ASSERT_TRUE(group_descriptor->FixedBlockSize()); OLA_ASSERT_EQ(6u, group_descriptor->BlockSize()); OLA_ASSERT_EQ(6u, group_descriptor->MaxBlockSize()); OLA_ASSERT_EQ(static_cast(0), group_descriptor->MinBlocks()); OLA_ASSERT_EQ(FieldDescriptorGroup::UNLIMITED_BLOCKS, group_descriptor->MaxBlocks()); OLA_ASSERT_FALSE(group_descriptor->FixedBlockCount()); // Check this prints correctly ola::messaging::SchemaPrinter printer; get_response->Accept(&printer); string expected = ( "uids {\n manufacturer_id: uint16\n device_id: uint32\n}\n"); OLA_ASSERT_EQ(expected, printer.AsString()); // check sub device ranges OLA_ASSERT_TRUE(pid_descriptor->IsGetValid(0)); OLA_ASSERT_FALSE(pid_descriptor->IsGetValid(1)); OLA_ASSERT_FALSE(pid_descriptor->IsGetValid(512)); OLA_ASSERT_FALSE(pid_descriptor->IsGetValid(ola::rdm::ALL_RDM_SUBDEVICES)); OLA_ASSERT_FALSE(pid_descriptor->IsSetValid(0)); OLA_ASSERT_FALSE(pid_descriptor->IsSetValid(1)); OLA_ASSERT_FALSE(pid_descriptor->IsSetValid(512)); OLA_ASSERT_FALSE(pid_descriptor->IsSetValid(ola::rdm::ALL_RDM_SUBDEVICES)); } /** * Check that loading from a file works */ void PidStoreTest::testPidStoreFileLoad() { PidStoreLoader loader; auto_ptr root_store( loader.LoadFromFile(GetTestDataFile("test_pids.proto"))); OLA_ASSERT_NOT_NULL(root_store.get()); // check version OLA_ASSERT_EQ(static_cast(1302986774), root_store->Version()); // Check all the esta pids are there const PidStore *esta_store = root_store->EstaStore(); OLA_ASSERT_NOT_NULL(esta_store); vector all_pids; esta_store->AllPids(&all_pids); OLA_ASSERT_EQ(static_cast(70), all_pids.size()); // check for device info const PidDescriptor *device_info = esta_store->LookupPID("DEVICE_INFO"); OLA_ASSERT_NOT_NULL(device_info); OLA_ASSERT_EQ(static_cast(96), device_info->Value()); OLA_ASSERT_EQ(string("DEVICE_INFO"), device_info->Name()); // check descriptors OLA_ASSERT_TRUE(device_info->GetRequest()); OLA_ASSERT_TRUE(device_info->GetResponse()); OLA_ASSERT_EQ(static_cast(NULL), device_info->SetRequest()); OLA_ASSERT_EQ(static_cast(NULL), device_info->SetResponse()); ola::messaging::SchemaPrinter printer; device_info->GetResponse()->Accept(&printer); string expected = ( "protocol_major: uint8\nprotocol_minor: uint8\ndevice_model: uint16\n" "product_category: uint16\nsoftware_version: uint32\n" "dmx_footprint: uint16\ncurrent_personality: uint8\n" "personality_count: uint8\ndmx_start_address: uint16\n" "sub_device_count: uint16\nsensor_count: uint8\n"); OLA_ASSERT_EQ(expected, printer.AsString()); // check manufacturer pids const PidStore *open_lighting_store = root_store->ManufacturerStore(ola::OPEN_LIGHTING_ESTA_CODE); OLA_ASSERT_NOT_NULL(open_lighting_store); OLA_ASSERT_EQ(1u, open_lighting_store->PidCount()); const PidDescriptor *serial_number = open_lighting_store->LookupPID( "SERIAL_NUMBER"); OLA_ASSERT_NOT_NULL(serial_number); OLA_ASSERT_EQ(static_cast(32768), serial_number->Value()); OLA_ASSERT_EQ(string("SERIAL_NUMBER"), serial_number->Name()); // check descriptors OLA_ASSERT_EQ(static_cast(NULL), serial_number->GetRequest()); OLA_ASSERT_EQ(static_cast(NULL), serial_number->GetResponse()); OLA_ASSERT_TRUE(serial_number->SetRequest()); OLA_ASSERT_TRUE(serial_number->SetResponse()); printer.Reset(); serial_number->SetRequest()->Accept(&printer); string expected2 = "serial_number: uint32\n"; OLA_ASSERT_EQ(expected2, printer.AsString()); } /** * Check that loading from a directory works. This also tests the override * mechanism. */ void PidStoreTest::testPidStoreDirectoryLoad() { PidStoreLoader loader; auto_ptr root_store(loader.LoadFromDirectory( GetTestDataFile("pids"))); OLA_ASSERT_NOT_NULL(root_store.get()); // check version OLA_ASSERT_EQ(static_cast(1302986774), root_store->Version()); // Check all the esta pids are there const PidStore *esta_store = root_store->EstaStore(); OLA_ASSERT_NOT_NULL(esta_store); vector all_pids; esta_store->AllPids(&all_pids); OLA_ASSERT_EQ(static_cast(4), all_pids.size()); // check manufacturer pids const PidStore *open_lighting_store = root_store->ManufacturerStore(ola::OPEN_LIGHTING_ESTA_CODE); OLA_ASSERT_NOT_NULL(open_lighting_store); OLA_ASSERT_EQ(1u, open_lighting_store->PidCount()); // FOO_BAR in the overrides file replaces SERIAL_NUMBER. const PidDescriptor *serial_number = open_lighting_store->LookupPID( "SERIAL_NUMBER"); OLA_ASSERT_NULL(serial_number); const PidDescriptor *foo_bar = open_lighting_store->LookupPID( "FOO_BAR"); OLA_ASSERT_NOT_NULL(foo_bar); OLA_ASSERT_EQ(static_cast(32768), foo_bar->Value()); OLA_ASSERT_EQ(string("FOO_BAR"), foo_bar->Name()); // check descriptors OLA_ASSERT_TRUE(foo_bar->GetRequest()); OLA_ASSERT_TRUE(foo_bar->GetResponse()); OLA_ASSERT_EQ(static_cast(NULL), foo_bar->SetRequest()); OLA_ASSERT_EQ(static_cast(NULL), foo_bar->SetResponse()); ola::messaging::SchemaPrinter printer; foo_bar->GetResponse()->Accept(&printer); string expected2 = "baz: uint32\n"; OLA_ASSERT_EQ(expected2, printer.AsString()); } /** * Check that loading a missing file fails. */ void PidStoreTest::testPidStoreLoadMissingFile() { PidStoreLoader loader; const RootPidStore *root_store = loader.LoadFromFile( GetTestDataFile("missing_file_pids.proto")); OLA_ASSERT_NULL(root_store); } /** * Check that loading a file with duplicate manufacturers fails. */ void PidStoreTest::testPidStoreLoadDuplicateManufacturer() { PidStoreLoader loader; const RootPidStore *root_store = loader.LoadFromFile( GetTestDataFile("duplicate_manufacturer.proto")); OLA_ASSERT_NULL(root_store); } /** * Check that loading file with duplicate pid values fails. */ void PidStoreTest::testPidStoreLoadDuplicateValue() { PidStoreLoader loader; const RootPidStore *root_store = loader.LoadFromFile( GetTestDataFile("duplicate_pid_value.proto")); OLA_ASSERT_NULL(root_store); } /** * Check that loading a file with duplicate pid names fails. */ void PidStoreTest::testPidStoreLoadDuplicateName() { PidStoreLoader loader; const RootPidStore *root_store = loader.LoadFromFile( GetTestDataFile("duplicate_pid_name.proto")); OLA_ASSERT_NULL(root_store); } /** * Check that loading a file with an out-of-range ESTA pid fails. */ void PidStoreTest::testPidStoreLoadInvalidEstaPid() { PidStoreLoader loader; const RootPidStore *root_store = loader.LoadFromFile( GetTestDataFile("invalid_esta_pid.proto")); OLA_ASSERT_NULL(root_store); } /** * Check that loading a file with an inconsistent descriptor fails. */ void PidStoreTest::testInconsistentData() { PidStoreLoader loader; const RootPidStore *root_store = loader.LoadFromFile( GetTestDataFile("inconsistent_pid.proto")); OLA_ASSERT_NULL(root_store); } ola-0.10.5.nojsmin/common/rdm/FakeNetworkManager.h0000644000175000017500000000555413023355232021425 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * FakeNetworkManager.h * Talks to the machine's network systems to get/set data. * Copyright (C) 2013 Peter Newman */ #ifndef COMMON_RDM_FAKENETWORKMANAGER_H_ #define COMMON_RDM_FAKENETWORKMANAGER_H_ #include #include #include "common/network/FakeInterfacePicker.h" #include "ola/network/IPV4Address.h" #include "ola/network/Interface.h" #include "ola/network/InterfacePicker.h" #include "ola/rdm/NetworkManagerInterface.h" namespace ola { namespace rdm { /** * @brief An implementation of NetworkManagerInterface which simulates a * network configuration. */ class FakeNetworkManager : public NetworkManagerInterface { public: /** * @brief Create a new FakeNetworkManager * @param interfaces the interfaces to return * @param ipv4_default_route_if_index the interface that has the default gateway * @param ipv4_default_route the default gateway * @param hostname the hostname * @param domain_name the domain name * @param name_servers the name servers to return. */ FakeNetworkManager( const std::vector &interfaces, const int32_t ipv4_default_route_if_index, const ola::network::IPV4Address ipv4_default_route, const std::string &hostname, const std::string &domain_name, const std::vector &name_servers); ~FakeNetworkManager() {} const ola::network::InterfacePicker *GetInterfacePicker() const; rdm_dhcp_status GetDHCPStatus(const ola::network::Interface &iface) const; bool GetIPV4DefaultRoute( int32_t *if_index, ola::network::IPV4Address *default_route) const; const std::string GetHostname() const; const std::string GetDomainName() const; bool GetNameServers( std::vector *name_servers) const; private: ola::network::FakeInterfacePicker m_interface_picker; int32_t m_ipv4_default_route_if_index; ola::network::IPV4Address m_ipv4_default_route; std::string m_hostname; std::string m_domain_name; std::vector m_name_servers; }; } // namespace rdm } // namespace ola #endif // COMMON_RDM_FAKENETWORKMANAGER_H_ ola-0.10.5.nojsmin/common/rdm/RDMReplyTest.cpp0000644000175000017500000001602413023355232020535 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * RDMReplyTest.cpp * Test fixture for the RDMReply. * Copyright (C) 2015 Simon Newton */ #include #include #include "ola/base/Array.h" #include "ola/io/ByteString.h" #include "ola/rdm/RDMFrame.h" #include "ola/rdm/RDMReply.h" #include "ola/rdm/RDMResponseCodes.h" #include "ola/rdm/UID.h" #include "ola/testing/TestUtils.h" using ola::io::ByteString; using ola::rdm::RDMFrame; using ola::rdm::RDMFrames; using ola::rdm::RDMGetResponse; using ola::rdm::RDMReply; using ola::rdm::RDMResponse; using ola::rdm::UID; using std::auto_ptr; class RDMReplyTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(RDMReplyTest); CPPUNIT_TEST(testReplyFromCode); CPPUNIT_TEST(testReplyWithResponse); CPPUNIT_TEST(testReplyWithFrames); CPPUNIT_TEST(testFromFrameHelper); CPPUNIT_TEST(testDUBHelper); CPPUNIT_TEST_SUITE_END(); public: RDMReplyTest() : m_source(1, 2), m_destination(3, 4) { } void testReplyFromCode(); void testReplyWithResponse(); void testReplyWithFrames(); void testFromFrameHelper(); void testDUBHelper(); private: UID m_source; UID m_destination; }; CPPUNIT_TEST_SUITE_REGISTRATION(RDMReplyTest); void RDMReplyTest::testReplyFromCode() { RDMReply reply(ola::rdm::RDM_WAS_BROADCAST); OLA_ASSERT_EQ(ola::rdm::RDM_WAS_BROADCAST, reply.StatusCode()); OLA_ASSERT_NULL(reply.Response()); OLA_ASSERT_NULL(reply.MutableResponse()); OLA_ASSERT_TRUE(reply.Frames().empty()); } void RDMReplyTest::testReplyWithResponse() { RDMResponse *response = new RDMGetResponse(m_source, m_destination, 0, // transaction # 0, // response type 0, // message count 10, // sub device 100, // param id NULL, // data 0); // Ownership is transferred. RDMReply reply(ola::rdm::RDM_COMPLETED_OK, response); OLA_ASSERT_EQ(ola::rdm::RDM_COMPLETED_OK, reply.StatusCode()); OLA_ASSERT_EQ(static_cast(response), reply.Response()); OLA_ASSERT_EQ(response, reply.MutableResponse()); OLA_ASSERT_TRUE(reply.Frames().empty()); } void RDMReplyTest::testReplyWithFrames() { const uint8_t response_data[] = { 0xcc, 1, 28, // start code, sub code & length 0, 3, 0, 0, 0, 4, // dst uid 0, 1, 0, 0, 0, 2, // src uid 0, 1, 0, 0, 10, // transaction, port id, msg count & sub device 0x21, 1, 40, 4, // command, param id, param data length 0x5a, 0x5a, 0x5a, 0x5a, // param data 0, 0 // checksum, anoything is fine. }; RDMFrame frame(response_data, arraysize(response_data)); frame.timing.response_time = 10000; frame.timing.mark_time = 32000; frame.timing.break_time = 8000; frame.timing.data_time = 45000; RDMFrames frames; frames.push_back(frame); RDMResponse *response = new RDMGetResponse(m_source, m_destination, 0, // transaction # 0, // response type 0, // message count 10, // sub device 100, // param id NULL, // data 0); RDMReply reply(ola::rdm::RDM_COMPLETED_OK, response, frames); OLA_ASSERT_EQ(ola::rdm::RDM_COMPLETED_OK, reply.StatusCode()); OLA_ASSERT_EQ(static_cast(response), reply.Response()); OLA_ASSERT_EQ(response, reply.MutableResponse()); OLA_ASSERT_EQ(static_cast(1), reply.Frames().size()); OLA_ASSERT_TRUE(frame == reply.Frames()[0]); } void RDMReplyTest::testFromFrameHelper() { const uint8_t response_data[] = { 0xcc, 1, 28, // start code, sub code & length 0, 3, 0, 0, 0, 4, // dst uid 0, 1, 0, 0, 0, 2, // src uid 0, 1, 0, 0, 10, // transaction, port id, msg count & sub device 0x21, 1, 40, 4, // command, param id, param data length 0x5a, 0x5a, 0x5a, 0x5a, // param data 2, 0xb4 // checksum, anoything is fine. }; RDMFrame frame(response_data, arraysize(response_data)); frame.timing.response_time = 10000; frame.timing.mark_time = 32000; frame.timing.break_time = 8000; frame.timing.data_time = 45000; auto_ptr reply(RDMReply::FromFrame(frame)); OLA_ASSERT_NOT_NULL(reply.get()); OLA_ASSERT_EQ(ola::rdm::RDM_COMPLETED_OK, reply->StatusCode()); OLA_ASSERT_NOT_NULL(reply->Response()); OLA_ASSERT_NOT_NULL(reply->MutableResponse()); OLA_ASSERT_EQ(static_cast(1), reply->Frames().size()); OLA_ASSERT_TRUE(frame == reply->Frames()[0]); const RDMResponse *response = reply->Response(); OLA_ASSERT_EQ(ola::rdm::SUB_START_CODE, response->SubStartCode()); OLA_ASSERT_EQ((uint8_t) 28, response->MessageLength()); OLA_ASSERT_EQ(m_source, response->SourceUID()); OLA_ASSERT_EQ(m_destination, response->DestinationUID()); OLA_ASSERT_EQ((uint8_t) 0, response->TransactionNumber()); OLA_ASSERT_EQ((uint8_t) 1, response->PortIdResponseType()); OLA_ASSERT_EQ((uint8_t) 0, response->MessageCount()); OLA_ASSERT_EQ((uint16_t) 10, response->SubDevice()); OLA_ASSERT_EQ(ola::rdm::RDMCommand::GET_COMMAND_RESPONSE, response->CommandClass()); OLA_ASSERT_EQ((uint16_t) 296, response->ParamId()); OLA_ASSERT_NOT_NULL(response->ParamData()); OLA_ASSERT_EQ(4u, response->ParamDataSize()); } void RDMReplyTest::testDUBHelper() { const uint8_t data[] = {1, 2, 3, 4}; RDMFrame frame(data, arraysize(data)); frame.timing.response_time = 10000; frame.timing.data_time = 45000; auto_ptr reply(RDMReply::DUBReply(frame)); OLA_ASSERT_NOT_NULL(reply.get()); OLA_ASSERT_EQ(ola::rdm::RDM_DUB_RESPONSE, reply->StatusCode()); OLA_ASSERT_NULL(reply->Response()); OLA_ASSERT_NULL(reply->MutableResponse()); OLA_ASSERT_EQ(static_cast(1), reply->Frames().size()); OLA_ASSERT_TRUE(frame == reply->Frames()[0]); OLA_ASSERT_EQ(10000u, reply->Frames()[0].timing.response_time); OLA_ASSERT_EQ(45000u, reply->Frames()[0].timing.data_time); } ola-0.10.5.nojsmin/common/rdm/UIDTest.cpp0000644000175000017500000002256213023355232017524 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * UIDTest.cpp * Test fixture for the UID classes * Copyright (C) 2005 Simon Newton */ #include #include #include #include "ola/StringUtils.h" #include "ola/rdm/UID.h" #include "ola/rdm/UIDSet.h" #include "ola/testing/TestUtils.h" using std::string; using ola::rdm::UID; using ola::rdm::UIDSet; class UIDTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(UIDTest); CPPUNIT_TEST(testUID); CPPUNIT_TEST(testUIDInequalities); CPPUNIT_TEST(testUIDSet); CPPUNIT_TEST(testUIDSetUnion); CPPUNIT_TEST(testUIDParse); CPPUNIT_TEST(testDirectedToUID); CPPUNIT_TEST_SUITE_END(); public: void testUID(); void testUIDInequalities(); void testUIDSet(); void testUIDSetUnion(); void testUIDParse(); void testDirectedToUID(); }; CPPUNIT_TEST_SUITE_REGISTRATION(UIDTest); /* * Test the UIDs work. */ void UIDTest::testUID() { UID uid(1, 2); UID uid2 = uid; OLA_ASSERT_EQ(uid, uid2); OLA_ASSERT_FALSE(uid != uid2); OLA_ASSERT_EQ((uint16_t) 1, uid.ManufacturerId()); OLA_ASSERT_EQ((uint32_t) 2, uid.DeviceId()); UID uid3(2, 10); OLA_ASSERT_NE(uid, uid3); OLA_ASSERT_LT(uid, uid3); OLA_ASSERT_EQ((uint16_t) 2, uid3.ManufacturerId()); OLA_ASSERT_EQ((uint32_t) 10, uid3.DeviceId()); // ToString OLA_ASSERT_EQ(string("0001:00000002"), uid.ToString()); OLA_ASSERT_EQ(string("0002:0000000a"), uid3.ToString()); UID all_devices = UID::AllDevices(); UID manufacturer_devices = UID::VendorcastAddress(0x52); OLA_ASSERT_EQ(string("ffff:ffffffff"), all_devices.ToString()); OLA_ASSERT_EQ(string("0052:ffffffff"), manufacturer_devices.ToString()); OLA_ASSERT_EQ(all_devices.ManufacturerId(), static_cast(0xffff)); OLA_ASSERT_EQ(all_devices.DeviceId(), static_cast(0xffffffff)); OLA_ASSERT_EQ(manufacturer_devices.ManufacturerId(), static_cast(0x0052)); OLA_ASSERT_EQ(manufacturer_devices.DeviceId(), static_cast(0xffffffff)); OLA_ASSERT_TRUE(all_devices.IsBroadcast()); OLA_ASSERT_TRUE(manufacturer_devices.IsBroadcast()); // now test the packing & unpacking unsigned int buffer_size = UID::UID_SIZE; uint8_t *buffer = new uint8_t[buffer_size]; OLA_ASSERT_TRUE(uid.Pack(buffer, buffer_size)); uint8_t expected[] = {0, 1, 0, 0, 0, 2}; OLA_ASSERT_EQ(0, memcmp(expected, buffer, buffer_size)); UID unpacked_uid1(buffer); OLA_ASSERT_EQ(uid, unpacked_uid1); OLA_ASSERT_TRUE(uid3.Pack(buffer, buffer_size)); uint8_t expected2[] = {0, 2, 0, 0, 0, 0x0a}; OLA_ASSERT_EQ(0, memcmp(expected2, buffer, buffer_size)); UID unpacked_uid2(buffer); OLA_ASSERT_EQ(uid3, unpacked_uid2); delete[] buffer; } /* * Test the UIDs inequalities work */ void UIDTest::testUIDInequalities() { uint16_t MOCK_ESTA_ID = 0x7a70; // check comparisons on the device id UID uid1(MOCK_ESTA_ID, 0); UID uid2(MOCK_ESTA_ID, 1); UID uid3(MOCK_ESTA_ID, 2); OLA_ASSERT_TRUE(uid1 < uid2); OLA_ASSERT_TRUE(uid1 < uid3); OLA_ASSERT_TRUE(uid2 < uid3); OLA_ASSERT_TRUE(uid3 > uid1); OLA_ASSERT_TRUE(uid2 > uid1); OLA_ASSERT_TRUE(uid3 > uid2); // check we're using unsigned ints for the device id UID uid4(MOCK_ESTA_ID, 0x80000000); UID uid5(MOCK_ESTA_ID, 0xffffffff); OLA_ASSERT_LT(uid1, uid4); OLA_ASSERT_LT(uid2, uid4); OLA_ASSERT_LT(uid3, uid4); OLA_ASSERT_LT(uid1, uid5); OLA_ASSERT_LT(uid2, uid5); OLA_ASSERT_LT(uid3, uid5); OLA_ASSERT_LT(uid4, uid5); OLA_ASSERT_GT(uid4, uid1); OLA_ASSERT_GT(uid4, uid2); OLA_ASSERT_GT(uid4, uid3); OLA_ASSERT_GT(uid5, uid1); OLA_ASSERT_GT(uid5, uid2); OLA_ASSERT_GT(uid5, uid3); OLA_ASSERT_GT(uid5, uid4); // test the manufacturer ID UID uid6(MOCK_ESTA_ID - 1, 0xffffffff); OLA_ASSERT_LT(uid6, uid1); OLA_ASSERT_LT(uid6, uid4); OLA_ASSERT_LT(uid6, uid5); OLA_ASSERT_GT(uid1, uid6); OLA_ASSERT_GT(uid4, uid6); OLA_ASSERT_GT(uid5, uid6); UID uid7(MOCK_ESTA_ID + 1, 0); OLA_ASSERT_LT(uid1, uid7); OLA_ASSERT_LT(uid4, uid7); OLA_ASSERT_LT(uid5, uid7); OLA_ASSERT_LT(uid6, uid7); OLA_ASSERT_GT(uid7, uid1); OLA_ASSERT_GT(uid7, uid4); OLA_ASSERT_GT(uid7, uid5); OLA_ASSERT_GT(uid7, uid6); // now some tests that would expose problems if we used signed ints UID uid8(0x8000, 0); OLA_ASSERT_LT(uid1, uid8); OLA_ASSERT_LT(uid2, uid8); OLA_ASSERT_LT(uid3, uid8); OLA_ASSERT_LT(uid4, uid8); OLA_ASSERT_LT(uid5, uid8); OLA_ASSERT_LT(uid6, uid8); OLA_ASSERT_GT(uid8, uid1); OLA_ASSERT_GT(uid8, uid4); OLA_ASSERT_GT(uid8, uid5); OLA_ASSERT_GT(uid8, uid6); OLA_ASSERT_GT(uid8, uid7); } /* * Test the UIDSet */ void UIDTest::testUIDSet() { UIDSet set1; OLA_ASSERT_EQ(0u, set1.Size()); UID uid(1, 2); UID uid2(2, 10); set1.AddUID(uid); OLA_ASSERT_EQ(1u, set1.Size()); OLA_ASSERT_EQ(string("0001:00000002"), set1.ToString()); OLA_ASSERT_TRUE(set1.Contains(uid)); OLA_ASSERT_FALSE(set1.Contains(uid2)); set1.AddUID(uid); OLA_ASSERT_EQ(1u, set1.Size()); set1.AddUID(uid2); OLA_ASSERT_EQ(2u, set1.Size()); OLA_ASSERT_EQ(string("0001:00000002,0002:0000000a"), set1.ToString()); OLA_ASSERT_TRUE(set1.Contains(uid)); OLA_ASSERT_TRUE(set1.Contains(uid2)); UIDSet set2(set1); OLA_ASSERT_EQ(set1, set2); UIDSet set3; OLA_ASSERT_EQ(0u, set3.Size()); set3 = set2; OLA_ASSERT_EQ(set1, set2); set3.RemoveUID(uid2); OLA_ASSERT_EQ(1u, set3.Size()); OLA_ASSERT_EQ(string("0001:00000002"), set3.ToString()); UIDSet difference = set1.SetDifference(set3); OLA_ASSERT_EQ(1u, difference.Size()); OLA_ASSERT_TRUE(set1.Contains(uid)); OLA_ASSERT_TRUE(set1.Contains(uid2)); difference = set3.SetDifference(set1); OLA_ASSERT_EQ(0u, difference.Size()); } /* * Test the UIDSet Union method. */ void UIDTest::testUIDSetUnion() { UIDSet set1, set2, expected; UID uid(1, 2); UID uid2(2, 10); UID uid3(3, 10); UID uid4(4, 10); set1.AddUID(uid); set2.AddUID(uid2); set2.AddUID(uid3); set2.AddUID(uid4); UIDSet union_set = set1.Union(set2); OLA_ASSERT_EQ(4u, union_set.Size()); OLA_ASSERT_TRUE(union_set.Contains(uid)); OLA_ASSERT_TRUE(union_set.Contains(uid2)); OLA_ASSERT_TRUE(union_set.Contains(uid3)); OLA_ASSERT_TRUE(union_set.Contains(uid4)); } /* * Test UID parsing */ void UIDTest::testUIDParse() { UID *uid = UID::FromString("ffff:00000000"); OLA_ASSERT_NOT_NULL(uid); OLA_ASSERT_EQ(uid->ManufacturerId(), static_cast(0xffff)); OLA_ASSERT_EQ(uid->DeviceId(), static_cast(0x00)); OLA_ASSERT_EQ(uid->ToString(), string("ffff:00000000")); delete uid; uid = UID::FromString("1234:567890ab"); OLA_ASSERT_NOT_NULL(uid); OLA_ASSERT_EQ(uid->ManufacturerId(), static_cast(0x1234)); OLA_ASSERT_EQ(uid->DeviceId(), static_cast(0x567890ab)); OLA_ASSERT_EQ(uid->ToString(), string("1234:567890ab")); delete uid; uid = UID::FromString("abcd:ef123456"); OLA_ASSERT_NOT_NULL(uid); OLA_ASSERT_EQ(uid->ManufacturerId(), static_cast(0xabcd)); OLA_ASSERT_EQ(uid->DeviceId(), static_cast(0xef123456)); OLA_ASSERT_EQ(uid->ToString(), string("abcd:ef123456")); delete uid; OLA_ASSERT_FALSE(UID::FromString("")); OLA_ASSERT_FALSE(UID::FromString(":")); OLA_ASSERT_FALSE(UID::FromString("0:0")); OLA_ASSERT_FALSE(UID::FromString(":123456")); OLA_ASSERT_FALSE(UID::FromString(":123456")); OLA_ASSERT_FALSE(UID::FromString("abcd:123456")); } /** * Test DirectedToUID() */ void UIDTest::testDirectedToUID() { const uint16_t MANUFACTURER_ID = 0x7a70; UID device_uid(MANUFACTURER_ID, 10); // test a direct match OLA_ASSERT_TRUE(device_uid.DirectedToUID(device_uid)); // test a different device UID other_device(MANUFACTURER_ID, 9); OLA_ASSERT_FALSE(other_device.DirectedToUID(device_uid)); // test broadcast UID broadcast_uid = UID::AllDevices(); OLA_ASSERT_TRUE(broadcast_uid.DirectedToUID(device_uid)); // test vendorcast passing manufacturer ID UID vendorcast_uid = UID::VendorcastAddress(MANUFACTURER_ID); OLA_ASSERT_TRUE(vendorcast_uid.DirectedToUID(device_uid)); // test vendorcast passing UID UID other_device_uid(MANUFACTURER_ID, 11); UID vendorcast_uid_2 = UID::VendorcastAddress(other_device_uid); OLA_ASSERT_TRUE(vendorcast_uid_2.DirectedToUID(device_uid)); // test another vendor passing manufacturer ID UID other_vendorcast_uid = UID::VendorcastAddress(MANUFACTURER_ID - 1); OLA_ASSERT_FALSE(other_vendorcast_uid.DirectedToUID(device_uid)); // test another vendor passing UID UID other_manufacturer_uid(MANUFACTURER_ID - 1, 10); UID other_vendorcast_uid_2 = UID::VendorcastAddress(other_manufacturer_uid); OLA_ASSERT_FALSE(other_vendorcast_uid_2.DirectedToUID(device_uid)); } ola-0.10.5.nojsmin/common/rdm/VariableFieldSizeCalculator.h0000644000175000017500000000605213023355232023242 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * VariableFieldSizeCalculator.h * Calculate the number of items in a group, given a fixed number of tokens. * Copyright (C) 2011 Simon Newton */ #ifndef COMMON_RDM_VARIABLEFIELDSIZECALCULATOR_H_ #define COMMON_RDM_VARIABLEFIELDSIZECALCULATOR_H_ #include #include #include namespace ola { namespace messaging { class Descriptor; } namespace rdm { /** * Calculate the size of a variable field when unpacking a Message from a raw * data stream. */ class VariableFieldSizeCalculator : public ola::messaging::FieldDescriptorVisitor { public: typedef enum { TOO_SMALL, TOO_LARGE, FIXED_SIZE, VARIABLE_STRING, VARIABLE_GROUP, MULTIPLE_VARIABLE_FIELDS, NESTED_VARIABLE_GROUPS, MISMATCHED_SIZE, } calculator_state; VariableFieldSizeCalculator() : m_fixed_size_sum(0) {} ~VariableFieldSizeCalculator() {} bool Descend() const { return false; } calculator_state CalculateFieldSize( unsigned int data_size, const class ola::messaging::Descriptor*, unsigned int *variable_field_repeat_count); void Visit(const ola::messaging::BoolFieldDescriptor*); void Visit(const ola::messaging::IPV4FieldDescriptor*); void Visit(const ola::messaging::MACFieldDescriptor*); void Visit(const ola::messaging::UIDFieldDescriptor*); void Visit(const ola::messaging::StringFieldDescriptor*); void Visit(const ola::messaging::UInt8FieldDescriptor*); void Visit(const ola::messaging::UInt16FieldDescriptor*); void Visit(const ola::messaging::UInt32FieldDescriptor*); void Visit(const ola::messaging::Int8FieldDescriptor*); void Visit(const ola::messaging::Int16FieldDescriptor*); void Visit(const ola::messaging::Int32FieldDescriptor*); void Visit(const ola::messaging::FieldDescriptorGroup*); void PostVisit(const ola::messaging::FieldDescriptorGroup*) {} private: unsigned int m_fixed_size_sum; std::vector m_variable_string_fields; std::vector m_variable_group_fields; unsigned int DetermineGroupSize(const ola::messaging::FieldDescriptorGroup*); }; } // namespace rdm } // namespace ola #endif // COMMON_RDM_VARIABLEFIELDSIZECALCULATOR_H_ ola-0.10.5.nojsmin/common/rdm/DummyResponder.cpp0000644000175000017500000003343213023355232021216 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * DummyResponder.cpp * Copyright (C) 2005 Simon Newton */ #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #include #include #include "ola/base/Array.h" #include "ola/Clock.h" #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/network/NetworkUtils.h" #include "ola/rdm/DummyResponder.h" #include "common/rdm/NetworkManager.h" #include "ola/rdm/OpenLightingEnums.h" #include "ola/rdm/RDMEnums.h" #include "ola/rdm/ResponderHelper.h" #include "ola/rdm/ResponderLoadSensor.h" #include "ola/rdm/ResponderSensor.h" #include "ola/stl/STLUtils.h" namespace ola { namespace rdm { using ola::network::HostToNetwork; using ola::network::NetworkToHost; using std::string; using std::vector; DummyResponder::RDMOps *DummyResponder::RDMOps::instance = NULL; const DummyResponder::Personalities * DummyResponder::Personalities::Instance() { if (!instance) { SlotDataCollection::SlotDataList p2_slot_data; p2_slot_data.push_back(SlotData::PrimarySlot(SD_INTENSITY, 0)); p2_slot_data.push_back(SlotData::SecondarySlot(ST_SEC_FINE, 0, 0)); p2_slot_data.push_back(SlotData::PrimarySlot(SD_PAN, 127)); p2_slot_data.push_back(SlotData::PrimarySlot(SD_TILT, 127)); p2_slot_data.push_back(SlotData::PrimarySlot(SD_UNDEFINED, 0, "Foo")); PersonalityList personalities; personalities.push_back(Personality(0, "Personality 1")); personalities.push_back(Personality(5, "Personality 2", SlotDataCollection(p2_slot_data))); personalities.push_back(Personality(10, "Personality 3")); personalities.push_back(Personality(20, "Personality 4")); instance = new Personalities(personalities); } return instance; } DummyResponder::Personalities * DummyResponder::Personalities::instance = NULL; const ResponderOps::ParamHandler DummyResponder::PARAM_HANDLERS[] = { { PID_PARAMETER_DESCRIPTION, &DummyResponder::GetParamDescription, NULL}, { PID_DEVICE_INFO, &DummyResponder::GetDeviceInfo, NULL}, { PID_PRODUCT_DETAIL_ID_LIST, &DummyResponder::GetProductDetailList, NULL}, { PID_DEVICE_MODEL_DESCRIPTION, &DummyResponder::GetDeviceModelDescription, NULL}, { PID_MANUFACTURER_LABEL, &DummyResponder::GetManufacturerLabel, NULL}, { PID_DEVICE_LABEL, &DummyResponder::GetDeviceLabel, NULL}, { PID_FACTORY_DEFAULTS, &DummyResponder::GetFactoryDefaults, &DummyResponder::SetFactoryDefaults}, { PID_SOFTWARE_VERSION_LABEL, &DummyResponder::GetSoftwareVersionLabel, NULL}, { PID_DMX_PERSONALITY, &DummyResponder::GetPersonality, &DummyResponder::SetPersonality}, { PID_DMX_PERSONALITY_DESCRIPTION, &DummyResponder::GetPersonalityDescription, NULL}, { PID_SLOT_INFO, &DummyResponder::GetSlotInfo, NULL}, { PID_SLOT_DESCRIPTION, &DummyResponder::GetSlotDescription, NULL}, { PID_DEFAULT_SLOT_VALUE, &DummyResponder::GetSlotDefaultValues, NULL}, { PID_DMX_START_ADDRESS, &DummyResponder::GetDmxStartAddress, &DummyResponder::SetDmxStartAddress}, { PID_LAMP_STRIKES, &DummyResponder::GetLampStrikes, &DummyResponder::SetLampStrikes}, { PID_IDENTIFY_DEVICE, &DummyResponder::GetIdentify, &DummyResponder::SetIdentify}, { PID_REAL_TIME_CLOCK, &DummyResponder::GetRealTimeClock, NULL}, #ifdef HAVE_GETLOADAVG { PID_SENSOR_DEFINITION, &DummyResponder::GetSensorDefinition, NULL}, { PID_SENSOR_VALUE, &DummyResponder::GetSensorValue, &DummyResponder::SetSensorValue}, { PID_RECORD_SENSORS, NULL, &DummyResponder::RecordSensor}, #endif // HAVE_GETLOADAVG { PID_LIST_INTERFACES, &DummyResponder::GetListInterfaces, NULL}, { PID_INTERFACE_LABEL, &DummyResponder::GetInterfaceLabel, NULL}, { PID_INTERFACE_HARDWARE_ADDRESS_TYPE1, &DummyResponder::GetInterfaceHardwareAddressType1, NULL}, { PID_IPV4_CURRENT_ADDRESS, &DummyResponder::GetIPV4CurrentAddress, NULL}, { PID_IPV4_DEFAULT_ROUTE, &DummyResponder::GetIPV4DefaultRoute, NULL}, { PID_DNS_HOSTNAME, &DummyResponder::GetDNSHostname, NULL}, { PID_DNS_DOMAIN_NAME, &DummyResponder::GetDNSDomainName, NULL}, { PID_DNS_NAME_SERVER, &DummyResponder::GetDNSNameServer, NULL}, { OLA_MANUFACTURER_PID_CODE_VERSION, &DummyResponder::GetOlaCodeVersion, NULL}, { 0, NULL, NULL}, }; DummyResponder::DummyResponder(const UID &uid) : m_uid(uid), m_start_address(1), m_identify_mode(0), m_lamp_strikes(0), m_personality_manager(Personalities::Instance()) { // default to a personality with a non-0 footprint. m_personality_manager.SetActivePersonality(DEFAULT_PERSONALITY); #ifdef HAVE_GETLOADAVG m_sensors.push_back(new LoadSensor(ola::system::LOAD_AVERAGE_1_MIN, "Load Average 1 minute")); m_sensors.push_back(new LoadSensor(ola::system::LOAD_AVERAGE_5_MINS, "Load Average 5 minutes")); m_sensors.push_back(new LoadSensor(ola::system::LOAD_AVERAGE_15_MINS, "Load Average 15 minutes")); #endif // HAVE_GETLOADAVG m_network_manager.reset(new NetworkManager()); } DummyResponder::~DummyResponder() { STLDeleteElements(&m_sensors); } /* * Handle an RDM Request */ void DummyResponder::SendRDMRequest(RDMRequest *request, RDMCallback *callback) { RDMOps::Instance()->HandleRDMRequest(this, m_uid, ola::rdm::ROOT_RDM_DEVICE, request, callback); } RDMResponse *DummyResponder::GetParamDescription( const RDMRequest *request) { // Check that it's OLA_MANUFACTURER_PID_CODE_VERSION being requested uint16_t parameter_id; if (!ResponderHelper::ExtractUInt16(request, ¶meter_id)) { return NackWithReason(request, NR_FORMAT_ERROR); } if (parameter_id != OLA_MANUFACTURER_PID_CODE_VERSION) { OLA_WARN << "Dummy responder received param description request with " "unknown PID, expected " << OLA_MANUFACTURER_PID_CODE_VERSION << ", got " << parameter_id; return NackWithReason(request, NR_DATA_OUT_OF_RANGE); } else { return ResponderHelper::GetASCIIParamDescription( request, OLA_MANUFACTURER_PID_CODE_VERSION, CC_GET, "Code Version"); } } RDMResponse *DummyResponder::GetDeviceInfo(const RDMRequest *request) { return ResponderHelper::GetDeviceInfo( request, OLA_DUMMY_DEVICE_MODEL, PRODUCT_CATEGORY_OTHER, 3, &m_personality_manager, m_start_address, 0, m_sensors.size()); } /** * Reset to factory defaults */ RDMResponse *DummyResponder::GetFactoryDefaults( const RDMRequest *request) { if (request->ParamDataSize()) { return NackWithReason(request, NR_FORMAT_ERROR); } uint8_t using_defaults = ( m_start_address == 1 && m_personality_manager.ActivePersonalityNumber() == DEFAULT_PERSONALITY && m_identify_mode == false); return GetResponseFromData(request, &using_defaults, sizeof(using_defaults)); } RDMResponse *DummyResponder::SetFactoryDefaults( const RDMRequest *request) { if (request->ParamDataSize()) { return NackWithReason(request, NR_FORMAT_ERROR); } m_start_address = 1; m_personality_manager.SetActivePersonality(DEFAULT_PERSONALITY); m_identify_mode = 0; return ResponderHelper::EmptySetResponse(request); } RDMResponse *DummyResponder::GetProductDetailList( const RDMRequest *request) { vector product_details; product_details.push_back(PRODUCT_DETAIL_TEST); product_details.push_back(PRODUCT_DETAIL_OTHER); return ResponderHelper::GetProductDetailList(request, product_details); } RDMResponse *DummyResponder::GetPersonality( const RDMRequest *request) { return ResponderHelper::GetPersonality(request, &m_personality_manager); } RDMResponse *DummyResponder::SetPersonality( const RDMRequest *request) { return ResponderHelper::SetPersonality(request, &m_personality_manager, m_start_address); } RDMResponse *DummyResponder::GetPersonalityDescription( const RDMRequest *request) { return ResponderHelper::GetPersonalityDescription( request, &m_personality_manager); } RDMResponse *DummyResponder::GetSlotInfo(const RDMRequest *request) { return ResponderHelper::GetSlotInfo(request, &m_personality_manager); } RDMResponse *DummyResponder::GetSlotDescription( const RDMRequest *request) { return ResponderHelper::GetSlotDescription(request, &m_personality_manager); } RDMResponse *DummyResponder::GetSlotDefaultValues( const RDMRequest *request) { return ResponderHelper::GetSlotDefaultValues(request, &m_personality_manager); } RDMResponse *DummyResponder::GetDmxStartAddress( const RDMRequest *request) { return ResponderHelper::GetDmxAddress(request, &m_personality_manager, m_start_address); } RDMResponse *DummyResponder::SetDmxStartAddress( const RDMRequest *request) { return ResponderHelper::SetDmxAddress(request, &m_personality_manager, &m_start_address); } RDMResponse *DummyResponder::GetLampStrikes(const RDMRequest *request) { return ResponderHelper::GetUInt32Value(request, m_lamp_strikes); } RDMResponse *DummyResponder::SetLampStrikes(const RDMRequest *request) { return ResponderHelper::SetUInt32Value(request, &m_lamp_strikes); } RDMResponse *DummyResponder::GetIdentify(const RDMRequest *request) { return ResponderHelper::GetBoolValue(request, m_identify_mode); } RDMResponse *DummyResponder::SetIdentify(const RDMRequest *request) { bool old_value = m_identify_mode; RDMResponse *response = ResponderHelper::SetBoolValue( request, &m_identify_mode); if (m_identify_mode != old_value) { OLA_INFO << "Dummy device, identify mode " << (m_identify_mode ? "on" : "off"); } return response; } RDMResponse *DummyResponder::GetRealTimeClock(const RDMRequest *request) { return ResponderHelper::GetRealTimeClock(request); } RDMResponse *DummyResponder::GetManufacturerLabel( const RDMRequest *request) { return ResponderHelper::GetString(request, OLA_MANUFACTURER_LABEL); } RDMResponse *DummyResponder::GetDeviceLabel(const RDMRequest *request) { return ResponderHelper::GetString(request, "Dummy RDM Device"); } RDMResponse *DummyResponder::GetDeviceModelDescription( const RDMRequest *request) { return ResponderHelper::GetString(request, "Dummy Model"); } RDMResponse *DummyResponder::GetSoftwareVersionLabel( const RDMRequest *request) { return ResponderHelper::GetString(request, "Dummy Software Version"); } /** * PID_SENSOR_DEFINITION */ RDMResponse *DummyResponder::GetSensorDefinition( const RDMRequest *request) { return ResponderHelper::GetSensorDefinition(request, m_sensors); } /** * PID_SENSOR_VALUE */ RDMResponse *DummyResponder::GetSensorValue(const RDMRequest *request) { return ResponderHelper::GetSensorValue(request, m_sensors); } RDMResponse *DummyResponder::SetSensorValue(const RDMRequest *request) { return ResponderHelper::SetSensorValue(request, m_sensors); } /** * PID_RECORD_SENSORS */ RDMResponse *DummyResponder::RecordSensor(const RDMRequest *request) { return ResponderHelper::RecordSensor(request, m_sensors); } /** * E1.37-2 PIDs */ RDMResponse *DummyResponder::GetListInterfaces( const RDMRequest *request) { return ResponderHelper::GetListInterfaces(request, m_network_manager.get()); } RDMResponse *DummyResponder::GetInterfaceLabel( const RDMRequest *request) { return ResponderHelper::GetInterfaceLabel(request, m_network_manager.get()); } RDMResponse *DummyResponder::GetInterfaceHardwareAddressType1( const RDMRequest *request) { return ResponderHelper::GetInterfaceHardwareAddressType1( request, m_network_manager.get()); } RDMResponse *DummyResponder::GetIPV4CurrentAddress( const RDMRequest *request) { return ResponderHelper::GetIPV4CurrentAddress(request, m_network_manager.get()); } RDMResponse *DummyResponder::GetIPV4DefaultRoute( const RDMRequest *request) { return ResponderHelper::GetIPV4DefaultRoute(request, m_network_manager.get()); } RDMResponse *DummyResponder::GetDNSHostname( const RDMRequest *request) { return ResponderHelper::GetDNSHostname(request, m_network_manager.get()); } RDMResponse *DummyResponder::GetDNSDomainName( const RDMRequest *request) { return ResponderHelper::GetDNSDomainName(request, m_network_manager.get()); } RDMResponse *DummyResponder::GetDNSNameServer( const RDMRequest *request) { return ResponderHelper::GetDNSNameServer(request, m_network_manager.get()); } RDMResponse *DummyResponder::GetOlaCodeVersion( const RDMRequest *request) { return ResponderHelper::GetString(request, VERSION); } } // namespace rdm } // namespace ola ola-0.10.5.nojsmin/common/messaging/0000755000175000017500000000000013155164170016730 5ustar wouterwouterola-0.10.5.nojsmin/common/messaging/SchemaPrinter.cpp0000644000175000017500000000726513023355232022205 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SchemaPrinter.cpp * Prints the text representation of a schema. * Copyright (C) 2011 Simon Newton */ #include #include #include #include namespace ola { namespace messaging { using std::string; using std::endl; void SchemaPrinter::Visit(const BoolFieldDescriptor *descriptor) { m_str << string(m_indent, ' ') << descriptor->Name() << ": bool" << endl; } void SchemaPrinter::Visit(const IPV4FieldDescriptor *descriptor) { m_str << string(m_indent, ' ') << descriptor->Name() << ": IPv4 address" << endl; } void SchemaPrinter::Visit(const MACFieldDescriptor *descriptor) { m_str << string(m_indent, ' ') << descriptor->Name() << ": MAC" << endl; } void SchemaPrinter::Visit(const UIDFieldDescriptor *descriptor) { m_str << string(m_indent, ' ') << descriptor->Name() << ": UID" << endl; } void SchemaPrinter::Visit(const StringFieldDescriptor *descriptor) { m_str << string(m_indent, ' ') << descriptor->Name() << ": string [" << descriptor->MinSize() << ", " << descriptor->MaxSize() << "]" << endl; } void SchemaPrinter::Visit(const UInt8FieldDescriptor *descriptor) { AppendHeading(descriptor->Name(), "uint8"); MaybeAppendIntervals(descriptor->Intervals()); MaybeAppendLabels(descriptor->Labels()); m_str << endl; } void SchemaPrinter::Visit(const UInt16FieldDescriptor *descriptor) { AppendHeading(descriptor->Name(), "uint16"); MaybeAppendIntervals(descriptor->Intervals()); MaybeAppendLabels(descriptor->Labels()); m_str << endl; } void SchemaPrinter::Visit(const UInt32FieldDescriptor *descriptor) { AppendHeading(descriptor->Name(), "uint32"); MaybeAppendIntervals(descriptor->Intervals()); MaybeAppendLabels(descriptor->Labels()); m_str << endl; } void SchemaPrinter::Visit(const Int8FieldDescriptor *descriptor) { AppendHeading(descriptor->Name(), "int8"); MaybeAppendIntervals(descriptor->Intervals()); MaybeAppendLabels(descriptor->Labels()); m_str << endl; } void SchemaPrinter::Visit(const Int16FieldDescriptor *descriptor) { AppendHeading(descriptor->Name(), "int16"); MaybeAppendIntervals(descriptor->Intervals()); MaybeAppendLabels(descriptor->Labels()); m_str << endl; } void SchemaPrinter::Visit(const Int32FieldDescriptor *descriptor) { AppendHeading(descriptor->Name(), "int32"); MaybeAppendIntervals(descriptor->Intervals()); MaybeAppendLabels(descriptor->Labels()); m_str << endl; } void SchemaPrinter::Visit(const FieldDescriptorGroup *descriptor) { m_str << string(m_indent, ' ') << descriptor->Name() << " {" << endl; m_indent += m_indent_size; } void SchemaPrinter::PostVisit(const FieldDescriptorGroup *descriptor) { m_indent -= m_indent_size; m_str << string(m_indent, ' ') << "}" << endl; (void) descriptor; } void SchemaPrinter::AppendHeading(const string &name, const string &type) { m_str << string(m_indent, ' ') << name << ": " << type; } } // namespace messaging } // namespace ola ola-0.10.5.nojsmin/common/messaging/Makefile.mk0000644000175000017500000000124513023355232020773 0ustar wouterwouter# LIBRARIES ################################################## common_libolacommon_la_SOURCES += \ common/messaging/Descriptor.cpp \ common/messaging/Message.cpp \ common/messaging/MessagePrinter.cpp \ common/messaging/SchemaPrinter.cpp # TESTS ################################################## test_programs += common/messaging/DescriptorTester common_messaging_DescriptorTester_SOURCES = \ common/messaging/DescriptorTest.cpp \ common/messaging/SchemaPrinterTest.cpp \ common/messaging/MessagePrinterTest.cpp common_messaging_DescriptorTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_messaging_DescriptorTester_LDADD = $(COMMON_TESTING_LIBS) ola-0.10.5.nojsmin/common/messaging/SchemaPrinterTest.cpp0000644000175000017500000002031713023355232023036 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SchemaPrinterTest.cpp * Test fixture for the SchemaPrinter class. * Copyright (C) 2011 Simon Newton */ #include #include #include #include "ola/messaging/Descriptor.h" #include "ola/messaging/SchemaPrinter.h" #include "ola/testing/TestUtils.h" using std::string; using std::vector; using ola::messaging::BoolFieldDescriptor; using ola::messaging::IPV4FieldDescriptor; using ola::messaging::MACFieldDescriptor; using ola::messaging::Descriptor; using ola::messaging::FieldDescriptor; using ola::messaging::FieldDescriptorGroup; using ola::messaging::SchemaPrinter; using ola::messaging::StringFieldDescriptor; using ola::messaging::UInt16FieldDescriptor; using ola::messaging::UInt32FieldDescriptor; using ola::messaging::UInt8FieldDescriptor; using ola::messaging::Int16FieldDescriptor; using ola::messaging::Int32FieldDescriptor; using ola::messaging::Int8FieldDescriptor; using ola::messaging::UIDFieldDescriptor; class SchemaPrinterTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(SchemaPrinterTest); CPPUNIT_TEST(testPrinter); CPPUNIT_TEST(testGroupPrinter); CPPUNIT_TEST(testLabels); CPPUNIT_TEST(testIntervalsAndLabels); CPPUNIT_TEST(testIntervalTypes); CPPUNIT_TEST_SUITE_END(); public: SchemaPrinterTest() {} void testPrinter(); void testGroupPrinter(); void testLabels(); void testIntervalsAndLabels(); void testIntervalTypes(); private: template string GenerateIntervalString(int_type min, int_type max); }; CPPUNIT_TEST_SUITE_REGISTRATION(SchemaPrinterTest); /* * Test the SchemaPrinter */ void SchemaPrinterTest::testPrinter() { // setup some fields BoolFieldDescriptor *bool_descriptor = new BoolFieldDescriptor("On/Off"); StringFieldDescriptor *string_descriptor = new StringFieldDescriptor( "Name", 0, 32); UInt8FieldDescriptor *uint8_descriptor = new UInt8FieldDescriptor( "Count", false, 10); IPV4FieldDescriptor *ipv4_descriptor = new IPV4FieldDescriptor( "Address"); MACFieldDescriptor *mac_descriptor = new MACFieldDescriptor( "MAC Address"); UIDFieldDescriptor *uid_descriptor = new UIDFieldDescriptor("Device"); // try a simple print first vector fields; fields.push_back(bool_descriptor); fields.push_back(string_descriptor); fields.push_back(uint8_descriptor); fields.push_back(ipv4_descriptor); fields.push_back(mac_descriptor); fields.push_back(uid_descriptor); Descriptor test_descriptor("Test Descriptor", fields); SchemaPrinter printer(false, false); test_descriptor.Accept(&printer); string expected = ( "On/Off: bool\nName: string [0, 32]\nCount: uint8\n" "Address: IPv4 address\nMAC Address: MAC\nDevice: UID\n"); OLA_ASSERT_EQ(expected, printer.AsString()); } void SchemaPrinterTest::testGroupPrinter() { BoolFieldDescriptor *bool_descriptor = new BoolFieldDescriptor("On/Off"); StringFieldDescriptor *string_descriptor = new StringFieldDescriptor( "Name", 0, 32); StringFieldDescriptor *string_descriptor2 = new StringFieldDescriptor( "Device", 0, 32); UInt8FieldDescriptor *uint8_descriptor = new UInt8FieldDescriptor( "Count", false, 10); UInt32FieldDescriptor *uint32_descriptor = new UInt32FieldDescriptor("Id"); vector fields; fields.push_back(bool_descriptor); fields.push_back(string_descriptor); fields.push_back(uint8_descriptor); // now do a descriptor which contains a GroupDescriptor FieldDescriptorGroup *group_descriptor = new FieldDescriptorGroup( "Group 1", fields, 0, 2); vector fields2; fields2.push_back(string_descriptor2); fields2.push_back(uint32_descriptor); fields2.push_back(group_descriptor); Descriptor test_descriptor("Test Descriptor2", fields2); SchemaPrinter printer(false, false); test_descriptor.Accept(&printer); string expected = "Device: string [0, 32]\nId: uint32\nGroup 1 {\n" " On/Off: bool\n Name: string [0, 32]\n Count: uint8\n}\n"; OLA_ASSERT_EQ(expected, printer.AsString()); } void SchemaPrinterTest::testLabels() { UInt16FieldDescriptor::IntervalVector intervals; intervals.push_back(UInt16FieldDescriptor::Interval(12, 12)); intervals.push_back(UInt16FieldDescriptor::Interval(13, 13)); UInt16FieldDescriptor::LabeledValues labels; labels["dozen"] = 12; labels["bakers_dozen"] = 13; UInt16FieldDescriptor *uint16_descriptor = new UInt16FieldDescriptor( "Count", intervals, labels); vector fields; fields.push_back(uint16_descriptor); Descriptor test_descriptor("Test Descriptor", fields); SchemaPrinter interval_printer(true, false); test_descriptor.Accept(&interval_printer); string expected = "Count: uint16: 12, 13\n"; OLA_ASSERT_EQ(expected, interval_printer.AsString()); } void SchemaPrinterTest::testIntervalsAndLabels() { UInt16FieldDescriptor::IntervalVector intervals; intervals.push_back(UInt16FieldDescriptor::Interval(2, 8)); intervals.push_back(UInt16FieldDescriptor::Interval(12, 14)); UInt16FieldDescriptor::LabeledValues labels; labels["dozen"] = 12; labels["bakers_dozen"] = 13; UInt16FieldDescriptor *uint16_descriptor = new UInt16FieldDescriptor( "Count", intervals, labels); vector fields; fields.push_back(uint16_descriptor); Descriptor test_descriptor("Test Descriptor", fields); SchemaPrinter interval_printer(true, false); test_descriptor.Accept(&interval_printer); string expected = "Count: uint16: (2, 8), (12, 14)\n"; OLA_ASSERT_EQ(expected, interval_printer.AsString()); SchemaPrinter label_printer(false, true); test_descriptor.Accept(&label_printer); string expected2 = "Count: uint16\n bakers_dozen: 13\n dozen: 12\n"; OLA_ASSERT_EQ(expected2, label_printer.AsString()); SchemaPrinter interval_label_printer(true, true); test_descriptor.Accept(&interval_label_printer); string expected3 = ( "Count: uint16: (2, 8), (12, 14)\n bakers_dozen: 13\n dozen: 12\n"); OLA_ASSERT_EQ(expected3, interval_label_printer.AsString()); } template string SchemaPrinterTest::GenerateIntervalString(int_type min, int_type max) { typename field_descriptor_class::IntervalVector intervals; intervals.push_back(typename field_descriptor_class::Interval(min, max)); typename field_descriptor_class::LabeledValues labels; vector fields; fields.push_back(new field_descriptor_class("Count", intervals, labels)); Descriptor test_descriptor("Test Descriptor", fields); SchemaPrinter interval_printer(true, false); test_descriptor.Accept(&interval_printer); return interval_printer.AsString(); } void SchemaPrinterTest::testIntervalTypes() { OLA_ASSERT_EQ(string("Count: uint8: (2, 8)\n"), GenerateIntervalString(2, 8)); OLA_ASSERT_EQ(string("Count: uint16: (2, 8256)\n"), GenerateIntervalString(2, 8256)); OLA_ASSERT_EQ( string("Count: uint32: (2, 82560)\n"), GenerateIntervalString(2, 82560)); OLA_ASSERT_EQ(string("Count: int8: (-2, 8)\n"), GenerateIntervalString(-2, 8)); OLA_ASSERT_EQ( string("Count: int16: (-300, 8256)\n"), GenerateIntervalString(-300, 8256)); OLA_ASSERT_EQ( string("Count: int32: (-70000, 82560)\n"), GenerateIntervalString(-70000, 82560)); } ola-0.10.5.nojsmin/common/messaging/MessagePrinter.cpp0000644000175000017500000001307513023355232022365 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * MessagePrinter.cpp * Prints the test representation of a Message. * Copyright (C) 2011 Simon Newton */ #include #include #include #include #include namespace ola { namespace messaging { using std::string; using std::endl; /** * Build the string representation of a message object */ string MessagePrinter::AsString(const Message *message) { m_str.str(""); message->Accept(this); PostStringHook(); return m_str.str(); } void GenericMessagePrinter::Visit(const BoolMessageField *message) { Stream() << string(m_indent, ' ') << TransformLabel(message->GetDescriptor()->Name()) << ": " << (message->Value() ? "true" : "false") << endl; } void GenericMessagePrinter::Visit(const IPV4MessageField *message) { Stream() << string(m_indent, ' ') << TransformLabel(message->GetDescriptor()->Name()) << ": " << message->Value() << endl; } void GenericMessagePrinter::Visit(const MACMessageField *message) { Stream() << string(m_indent, ' ') << TransformLabel(message->GetDescriptor()->Name()) << ": " << message->Value().ToString() << endl; } void GenericMessagePrinter::Visit(const UIDMessageField *message) { Stream() << string(m_indent, ' ') << TransformLabel(message->GetDescriptor()->Name()) << ": " << message->Value().ToString() << endl; } void GenericMessagePrinter::Visit(const StringMessageField *message) { Stream() << string(m_indent, ' ') << TransformLabel(message->GetDescriptor()->Name()) << ": " << EncodeString(message->Value()) << endl; } void GenericMessagePrinter::Visit(const BasicMessageField *message) { const UInt8FieldDescriptor *descriptor = message->GetDescriptor(); AppendUInt(descriptor->Name(), message->Value(), descriptor->LookupValue(message->Value()), descriptor->Multiplier()); } void GenericMessagePrinter::Visit(const BasicMessageField *message) { const UInt16FieldDescriptor *descriptor = message->GetDescriptor(); AppendUInt(descriptor->Name(), message->Value(), descriptor->LookupValue(message->Value()), descriptor->Multiplier()); } void GenericMessagePrinter::Visit(const BasicMessageField *message) { const UInt32FieldDescriptor *descriptor = message->GetDescriptor(); AppendUInt(descriptor->Name(), message->Value(), descriptor->LookupValue(message->Value()), descriptor->Multiplier()); } void GenericMessagePrinter::Visit(const BasicMessageField *message) { const Int8FieldDescriptor *descriptor = message->GetDescriptor(); AppendInt(descriptor->Name(), message->Value(), descriptor->LookupValue(message->Value()), descriptor->Multiplier()); } void GenericMessagePrinter::Visit(const BasicMessageField *message) { const Int16FieldDescriptor *descriptor = message->GetDescriptor(); AppendInt(descriptor->Name(), message->Value(), descriptor->LookupValue(message->Value()), descriptor->Multiplier()); } void GenericMessagePrinter::Visit(const BasicMessageField *message) { const Int32FieldDescriptor *descriptor = message->GetDescriptor(); AppendInt(descriptor->Name(), message->Value(), descriptor->LookupValue(message->Value()), descriptor->Multiplier()); } void GenericMessagePrinter::Visit(const GroupMessageField *message) { Stream() << string(m_indent, ' ') << TransformLabel(message->GetDescriptor()->Name()) << " {" << endl; m_indent += m_indent_size; } void GenericMessagePrinter::PostVisit(const GroupMessageField *message) { m_indent -= m_indent_size; Stream() << string(m_indent, ' ') << "}" << endl; (void) message; } void GenericMessagePrinter::AppendUInt(const string &name, unsigned int value, const string &label, int8_t multipler) { Stream() << string(m_indent, ' ') << TransformLabel(name) << ": "; if (label.empty()) { Stream() << value; AppendMultipler(multipler); } else { Stream() << label; } Stream() << endl; } void GenericMessagePrinter::AppendInt(const string &name, int value, const string &label, int8_t multipler) { Stream() << string(m_indent, ' ') << TransformLabel(name) << ": "; if (label.empty()) { Stream() << value; AppendMultipler(multipler); } else { Stream() << label; } Stream() << endl; } void GenericMessagePrinter::AppendMultipler(int8_t multipler) { if (multipler) Stream() << " x 10 ^ " << static_cast(multipler); } } // namespace messaging } // namespace ola ola-0.10.5.nojsmin/common/messaging/Descriptor.cpp0000644000175000017500000000572313023355232021554 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Descriptor.cpp * Holds the metadata (schema) for a Message. * Copyright (C) 2011 Simon Newton */ #include #include namespace ola { namespace messaging { using std::vector; const int16_t FieldDescriptorGroup::UNLIMITED_BLOCKS = -1; FieldDescriptorGroup::~FieldDescriptorGroup() { vector::const_iterator iter = m_fields.begin(); for (; iter != m_fields.end(); ++iter) delete *iter; } bool FieldDescriptorGroup::LimitedSize() const { if (m_max_blocks == UNLIMITED_BLOCKS) return false; PopulateIfRequired(); return m_limited_size; } bool FieldDescriptorGroup::FixedBlockSize() const { PopulateIfRequired(); return m_fixed_size; } unsigned int FieldDescriptorGroup::BlockSize() const { PopulateIfRequired(); return m_block_size; } unsigned int FieldDescriptorGroup::MaxBlockSize() const { PopulateIfRequired(); return m_max_block_size; } unsigned int FieldDescriptorGroup::MaxSize() const { if (!LimitedSize()) return 0; return MaxBlockSize() * m_max_blocks; } void FieldDescriptorGroup::Accept(FieldDescriptorVisitor *visitor) const { visitor->Visit(this); vector::const_iterator iter = m_fields.begin(); if (visitor->Descend()) { for (; iter != m_fields.end(); ++iter) (*iter)->Accept(visitor); } visitor->PostVisit(this); } /** * We cache all the information that requires iterating over the fields * This method populates the cache if required. */ void FieldDescriptorGroup::PopulateIfRequired() const { if (m_populated) return; unsigned int size = 0; vector::const_iterator iter = m_fields.begin(); for (; iter != m_fields.end(); ++iter) { if (!(*iter)->LimitedSize()) m_limited_size = false; if (!(*iter)->FixedSize()) m_fixed_size = false; size += (*iter)->MaxSize(); } m_populated = true; m_block_size = m_fixed_size ? size : 0; m_max_block_size = m_limited_size ? size : 0; } void Descriptor::Accept(FieldDescriptorVisitor *visitor) const { vector::const_iterator iter = m_fields.begin(); for (; iter != m_fields.end(); ++iter) (*iter)->Accept(visitor); } } // namespace messaging } // namespace ola ola-0.10.5.nojsmin/common/messaging/MessagePrinterTest.cpp0000644000175000017500000001462513023355232023227 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * MessagePrinterTest.cpp * Test fixture for the MessagePrinter class. * Copyright (C) 2011 Simon Newton */ #include #include #include #include "ola/messaging/Descriptor.h" #include "ola/messaging/Message.h" #include "ola/messaging/MessagePrinter.h" #include "ola/network/NetworkUtils.h" #include "ola/rdm/UID.h" #include "ola/testing/TestUtils.h" using std::string; using std::vector; using ola::rdm::UID; using ola::messaging::BoolFieldDescriptor; using ola::messaging::BoolMessageField; using ola::messaging::FieldDescriptor; using ola::messaging::FieldDescriptorGroup; using ola::messaging::GroupMessageField; using ola::messaging::IPV4FieldDescriptor; using ola::messaging::GenericMessagePrinter; using ola::messaging::IPV4MessageField; using ola::messaging::Int16FieldDescriptor; using ola::messaging::Int16MessageField; using ola::messaging::Int8FieldDescriptor; using ola::messaging::Int8MessageField; using ola::messaging::Message; using ola::messaging::MessageFieldInterface; using ola::messaging::StringFieldDescriptor; using ola::messaging::StringMessageField; using ola::messaging::UIDFieldDescriptor; using ola::messaging::UIDMessageField; using ola::messaging::UInt32FieldDescriptor; using ola::messaging::UInt32MessageField; using ola::messaging::UInt8FieldDescriptor; using ola::messaging::UInt8MessageField; class GenericMessagePrinterTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(GenericMessagePrinterTest); CPPUNIT_TEST(testSimplePrinter); CPPUNIT_TEST(testLabeledPrinter); CPPUNIT_TEST(testNestedPrinter); CPPUNIT_TEST_SUITE_END(); public: GenericMessagePrinterTest() {} void testSimplePrinter(); void testLabeledPrinter(); void testNestedPrinter(); private: GenericMessagePrinter m_printer; }; CPPUNIT_TEST_SUITE_REGISTRATION(GenericMessagePrinterTest); /* * Test the MessagePrinter */ void GenericMessagePrinterTest::testSimplePrinter() { // setup some fields BoolFieldDescriptor bool_descriptor("On/Off"); IPV4FieldDescriptor ipv4_descriptor("ip"); UIDFieldDescriptor uid_descriptor("uid"); StringFieldDescriptor string_descriptor("Name", 0, 32); UInt32FieldDescriptor uint32_descriptor("Id"); UInt8FieldDescriptor uint8_descriptor("Count", false, -3); Int8FieldDescriptor int8_descriptor("Delta", false, 1); Int16FieldDescriptor int16_descriptor("Rate", false, -1); // try a simple print first vector fields; fields.push_back(new BoolMessageField(&bool_descriptor, false)); fields.push_back( new IPV4MessageField(&ipv4_descriptor, ola::network::HostToNetwork(0x0a000001))); fields.push_back(new UIDMessageField(&uid_descriptor, UID(0x7a70, 1))); fields.push_back(new StringMessageField(&string_descriptor, "foobar")); fields.push_back(new UInt32MessageField(&uint32_descriptor, 42)); fields.push_back(new UInt8MessageField(&uint8_descriptor, 4)); fields.push_back(new Int8MessageField(&int8_descriptor, 10)); fields.push_back(new Int16MessageField(&int16_descriptor, 10)); Message message(fields); string expected = ( "On/Off: false\nip: 10.0.0.1\nuid: 7a70:00000001\nName: foobar\nId: 42\n" "Count: 4 x 10 ^ -3\nDelta: 10 x 10 ^ 1\nRate: 10 x 10 ^ -1\n"); OLA_ASSERT_EQ(expected, m_printer.AsString(&message)); } /** * Check that labels are added */ void GenericMessagePrinterTest::testLabeledPrinter() { UInt8FieldDescriptor::IntervalVector intervals; intervals.push_back(UInt8FieldDescriptor::Interval(0, 2)); UInt8FieldDescriptor::LabeledValues labels; labels["off"] = 0; labels["on"] = 1; labels["auto"] = 2; UInt8FieldDescriptor uint8_descriptor("State", intervals, labels); vector fields; fields.push_back(new UInt8MessageField(&uint8_descriptor, 0)); fields.push_back(new UInt8MessageField(&uint8_descriptor, 1)); fields.push_back(new UInt8MessageField(&uint8_descriptor, 2)); Message message(fields); string expected = "State: off\nState: on\nState: auto\n"; OLA_ASSERT_EQ(expected, m_printer.AsString(&message)); } void GenericMessagePrinterTest::testNestedPrinter() { // this holds some information on people StringFieldDescriptor *string_descriptor = new StringFieldDescriptor( "Name", 0, 32); BoolFieldDescriptor *bool_descriptor = new BoolFieldDescriptor("Female"); UInt8FieldDescriptor *uint8_descriptor = new UInt8FieldDescriptor("Age"); vector person_fields; person_fields.push_back(string_descriptor); person_fields.push_back(bool_descriptor); person_fields.push_back(uint8_descriptor); FieldDescriptorGroup group_descriptor("Person", person_fields, 0, 10); // setup the first person vector person1; person1.push_back(new StringMessageField(string_descriptor, "Lisa")); person1.push_back(new BoolMessageField(bool_descriptor, true)); person1.push_back(new UInt8MessageField(uint8_descriptor, 21)); // setup the second person vector person2; person2.push_back(new StringMessageField(string_descriptor, "Simon")); person2.push_back(new BoolMessageField(bool_descriptor, false)); person2.push_back(new UInt8MessageField(uint8_descriptor, 26)); vector messages; messages.push_back(new GroupMessageField(&group_descriptor, person1)); messages.push_back(new GroupMessageField(&group_descriptor, person2)); Message message(messages); string expected = ( "Person {\n Name: Lisa\n Female: true\n Age: 21\n}\n" "Person {\n Name: Simon\n Female: false\n Age: 26\n}\n"); OLA_ASSERT_EQ(expected, m_printer.AsString(&message)); } ola-0.10.5.nojsmin/common/messaging/Message.cpp0000644000175000017500000000345213023355232021017 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Message.cpp * Holds the metadata (schema) for a Message. * Copyright (C) 2011 Simon Newton */ #include #include namespace ola { namespace messaging { using std::vector; Message::~Message() { vector::const_iterator iter = m_fields.begin(); for (; iter != m_fields.end(); ++iter) delete *iter; } void Message::Accept(MessageVisitor *visitor) const { vector::const_iterator iter = m_fields.begin(); for (; iter != m_fields.end(); ++iter) (*iter)->Accept(visitor); } GroupMessageField::~GroupMessageField() { vector::const_iterator iter = m_fields.begin(); for (; iter != m_fields.end(); ++iter) delete *iter; } void GroupMessageField::Accept(MessageVisitor *visitor) const { visitor->Visit(this); vector::const_iterator iter = m_fields.begin(); for (; iter != m_fields.end(); ++iter) (*iter)->Accept(visitor); visitor->PostVisit(this); } } // namespace messaging } // namespace ola ola-0.10.5.nojsmin/common/messaging/DescriptorTest.cpp0000644000175000017500000003425013023355232022411 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * DescriptorTest.cpp * Test fixture for the Descriptor classes * Copyright (C) 2011 Simon Newton */ #include #include #include #include "ola/messaging/Descriptor.h" #include "ola/testing/TestUtils.h" using std::string; using std::vector; using ola::messaging::BoolFieldDescriptor; using ola::messaging::FieldDescriptor; using ola::messaging::FieldDescriptorGroup; using ola::messaging::IPV4FieldDescriptor; using ola::messaging::StringFieldDescriptor; using ola::messaging::UIDFieldDescriptor; using ola::messaging::UInt16FieldDescriptor; using ola::messaging::UInt32FieldDescriptor; using ola::messaging::UInt8FieldDescriptor; class DescriptorTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(DescriptorTest); CPPUNIT_TEST(testFieldDescriptors); CPPUNIT_TEST(testFieldDescriptorGroup); CPPUNIT_TEST(testIntervalsAndLabels); CPPUNIT_TEST_SUITE_END(); public: DescriptorTest() {} void testFieldDescriptors(); void testFieldDescriptorGroup(); void testIntervalsAndLabels(); }; CPPUNIT_TEST_SUITE_REGISTRATION(DescriptorTest); /* * Test the FieldDescriptors */ void DescriptorTest::testFieldDescriptors() { // bool BoolFieldDescriptor bool_descriptor("bool"); OLA_ASSERT_EQ(string("bool"), bool_descriptor.Name()); OLA_ASSERT_TRUE(bool_descriptor.FixedSize()); OLA_ASSERT_TRUE(bool_descriptor.LimitedSize()); OLA_ASSERT_EQ(1u, bool_descriptor.MaxSize()); // IPv4 address IPV4FieldDescriptor ipv4_descriptor("ipv4"); OLA_ASSERT_EQ(string("ipv4"), ipv4_descriptor.Name()); OLA_ASSERT_TRUE(ipv4_descriptor.FixedSize()); OLA_ASSERT_TRUE(ipv4_descriptor.LimitedSize()); OLA_ASSERT_EQ(4u, ipv4_descriptor.MaxSize()); // UID UIDFieldDescriptor uid_descriptor("uid"); OLA_ASSERT_EQ(string("uid"), uid_descriptor.Name()); OLA_ASSERT_TRUE(uid_descriptor.FixedSize()); OLA_ASSERT_TRUE(uid_descriptor.LimitedSize()); OLA_ASSERT_EQ(6u, uid_descriptor.MaxSize()); // string StringFieldDescriptor string_descriptor("string", 10, 32); OLA_ASSERT_EQ(string("string"), string_descriptor.Name()); OLA_ASSERT_EQ(10u, string_descriptor.MinSize()); OLA_ASSERT_EQ(32u, string_descriptor.MaxSize()); OLA_ASSERT_FALSE(string_descriptor.FixedSize()); OLA_ASSERT_TRUE(string_descriptor.LimitedSize()); // uint8_t UInt8FieldDescriptor uint8_descriptor("uint8", false, 10); OLA_ASSERT_EQ(string("uint8"), uint8_descriptor.Name()); OLA_ASSERT_EQ(1u, uint8_descriptor.MaxSize()); OLA_ASSERT_FALSE(uint8_descriptor.IsLittleEndian()); OLA_ASSERT_EQ(static_cast(10), uint8_descriptor.Multiplier()); OLA_ASSERT_TRUE(uint8_descriptor.FixedSize()); OLA_ASSERT_TRUE(uint8_descriptor.LimitedSize()); UInt8FieldDescriptor uint8_descriptor2("uint8", true, -1); OLA_ASSERT_EQ(string("uint8"), uint8_descriptor2.Name()); OLA_ASSERT_EQ(1u, uint8_descriptor2.MaxSize()); OLA_ASSERT_TRUE(uint8_descriptor2.IsLittleEndian()); OLA_ASSERT_EQ(static_cast(-1), uint8_descriptor2.Multiplier()); OLA_ASSERT_TRUE(uint8_descriptor2.FixedSize()); OLA_ASSERT_TRUE(uint8_descriptor2.LimitedSize()); // uint16_t UInt16FieldDescriptor uint16_descriptor("uint16", false, 10); OLA_ASSERT_EQ(string("uint16"), uint16_descriptor.Name()); OLA_ASSERT_EQ(2u, uint16_descriptor.MaxSize()); OLA_ASSERT_FALSE(uint16_descriptor.IsLittleEndian()); OLA_ASSERT_EQ(static_cast(10), uint16_descriptor.Multiplier()); OLA_ASSERT_TRUE(uint16_descriptor.FixedSize()); OLA_ASSERT_TRUE(uint16_descriptor.LimitedSize()); UInt16FieldDescriptor uint16_descriptor2("uint16", true, -1); OLA_ASSERT_EQ(string("uint16"), uint16_descriptor2.Name()); OLA_ASSERT_EQ(2u, uint16_descriptor2.MaxSize()); OLA_ASSERT_TRUE(uint16_descriptor2.IsLittleEndian()); OLA_ASSERT_EQ(static_cast(-1), uint16_descriptor2.Multiplier()); OLA_ASSERT_TRUE(uint16_descriptor2.FixedSize()); OLA_ASSERT_TRUE(uint16_descriptor2.LimitedSize()); // uint32_t UInt32FieldDescriptor uint32_descriptor("uint32", false, 10); OLA_ASSERT_EQ(string("uint32"), uint32_descriptor.Name()); OLA_ASSERT_EQ(4u, uint32_descriptor.MaxSize()); OLA_ASSERT_FALSE(uint32_descriptor.IsLittleEndian()); OLA_ASSERT_EQ(static_cast(10), uint32_descriptor.Multiplier()); OLA_ASSERT_TRUE(uint32_descriptor.FixedSize()); OLA_ASSERT_TRUE(uint32_descriptor.LimitedSize()); UInt32FieldDescriptor uint32_descriptor2("uint32", true, -1); OLA_ASSERT_EQ(string("uint32"), uint32_descriptor2.Name()); OLA_ASSERT_EQ(4u, uint32_descriptor2.MaxSize()); OLA_ASSERT_TRUE(uint32_descriptor2.IsLittleEndian()); OLA_ASSERT_EQ(static_cast(-1), uint32_descriptor2.Multiplier()); OLA_ASSERT_TRUE(uint32_descriptor2.FixedSize()); OLA_ASSERT_TRUE(uint32_descriptor2.LimitedSize()); } /** * Check FieldDescriptorGroup */ void DescriptorTest::testFieldDescriptorGroup() { // first try a group where the fields are all a fixed size BoolFieldDescriptor *bool_descriptor = new BoolFieldDescriptor("bool"); UInt8FieldDescriptor *uint8_descriptor = new UInt8FieldDescriptor( "uint8", false, 10); // group with a variable number of repeats vector fields; fields.push_back(bool_descriptor); fields.push_back(uint8_descriptor); FieldDescriptorGroup group_descriptor("group", fields, 0, 3); OLA_ASSERT_FALSE(group_descriptor.FixedSize()); OLA_ASSERT_TRUE(group_descriptor.LimitedSize()); OLA_ASSERT_EQ(6u, group_descriptor.MaxSize()); OLA_ASSERT_EQ(2u, group_descriptor.FieldCount()); OLA_ASSERT_TRUE(group_descriptor.FixedBlockSize()); OLA_ASSERT_EQ(2u, group_descriptor.BlockSize()); OLA_ASSERT_EQ(2u, group_descriptor.MaxBlockSize()); OLA_ASSERT_EQ(static_cast(0), group_descriptor.MinBlocks()); OLA_ASSERT_EQ(static_cast(3), group_descriptor.MaxBlocks()); OLA_ASSERT_FALSE(group_descriptor.FixedBlockCount()); OLA_ASSERT_EQ(static_cast(bool_descriptor), group_descriptor.GetField(0)); OLA_ASSERT_EQ(static_cast(uint8_descriptor), group_descriptor.GetField(1)); // A group with a fixed number of repeats and fixed size fields BoolFieldDescriptor *bool_descriptor2 = new BoolFieldDescriptor("bool"); UInt8FieldDescriptor *uint8_descriptor2 = new UInt8FieldDescriptor( "uint8", false, 10); UInt16FieldDescriptor *uint16_descriptor2 = new UInt16FieldDescriptor( "uint16", false, 10); vector fields2; fields2.push_back(bool_descriptor2); fields2.push_back(uint8_descriptor2); fields2.push_back(uint16_descriptor2); FieldDescriptorGroup group_descriptor2("group", fields2, 2, 2); OLA_ASSERT_TRUE(group_descriptor2.FixedSize()); OLA_ASSERT_TRUE(group_descriptor2.LimitedSize()); OLA_ASSERT_EQ(8u, group_descriptor2.MaxSize()); OLA_ASSERT_EQ(3u, group_descriptor2.FieldCount()); OLA_ASSERT_TRUE(group_descriptor2.FixedBlockSize()); OLA_ASSERT_EQ(4u, group_descriptor2.BlockSize()); OLA_ASSERT_EQ(4u, group_descriptor2.MaxBlockSize()); OLA_ASSERT_EQ(static_cast(2), group_descriptor2.MinBlocks()); OLA_ASSERT_EQ(static_cast(2), group_descriptor2.MaxBlocks()); OLA_ASSERT_TRUE(group_descriptor2.FixedBlockCount()); OLA_ASSERT_EQ(static_cast(bool_descriptor2), group_descriptor2.GetField(0)); OLA_ASSERT_EQ(static_cast(uint8_descriptor2), group_descriptor2.GetField(1)); OLA_ASSERT_EQ(static_cast(uint16_descriptor2), group_descriptor2.GetField(2)); // now check a group with variable sized fields BoolFieldDescriptor *bool_descriptor3 = new BoolFieldDescriptor("bool"); StringFieldDescriptor *string_descriptor2 = new StringFieldDescriptor("string", 0, 32); vector fields3; fields3.push_back(bool_descriptor3); fields3.push_back(string_descriptor2); FieldDescriptorGroup group_descriptor3("group", fields3, 0, 2); OLA_ASSERT_FALSE(group_descriptor3.FixedSize()); OLA_ASSERT_TRUE(group_descriptor3.LimitedSize()); OLA_ASSERT_EQ(66u, group_descriptor3.MaxSize()); OLA_ASSERT_EQ(2u, group_descriptor3.FieldCount()); OLA_ASSERT_FALSE(group_descriptor3.FixedBlockSize()); OLA_ASSERT_EQ(0u, group_descriptor3.BlockSize()); OLA_ASSERT_EQ(33u, group_descriptor3.MaxBlockSize()); OLA_ASSERT_EQ(static_cast(0), group_descriptor3.MinBlocks()); OLA_ASSERT_EQ(static_cast(2), group_descriptor3.MaxBlocks()); OLA_ASSERT_FALSE(group_descriptor3.FixedBlockCount()); OLA_ASSERT_EQ(static_cast(bool_descriptor3), group_descriptor3.GetField(0)); OLA_ASSERT_EQ(static_cast(string_descriptor2), group_descriptor3.GetField(1)); // now check a group with variable sized fields but a fixed block count BoolFieldDescriptor *bool_descriptor4 = new BoolFieldDescriptor("bool"); StringFieldDescriptor *string_descriptor3 = new StringFieldDescriptor("string", 0, 32); vector fields4; fields4.push_back(bool_descriptor4); fields4.push_back(string_descriptor3); FieldDescriptorGroup group_descriptor4("group", fields4, 2, 2); OLA_ASSERT_FALSE(group_descriptor4.FixedSize()); OLA_ASSERT_TRUE(group_descriptor4.LimitedSize()); OLA_ASSERT_EQ(66u, group_descriptor4.MaxSize()); OLA_ASSERT_EQ(2u, group_descriptor4.FieldCount()); OLA_ASSERT_FALSE(group_descriptor4.FixedBlockSize()); OLA_ASSERT_EQ(0u, group_descriptor4.BlockSize()); OLA_ASSERT_EQ(33u, group_descriptor4.MaxBlockSize()); OLA_ASSERT_EQ(static_cast(2), group_descriptor4.MinBlocks()); OLA_ASSERT_EQ(static_cast(2), group_descriptor4.MaxBlocks()); OLA_ASSERT_TRUE(group_descriptor4.FixedBlockCount()); OLA_ASSERT_EQ(static_cast(bool_descriptor4), group_descriptor4.GetField(0)); OLA_ASSERT_EQ(static_cast(string_descriptor3), group_descriptor4.GetField(1)); // now check a group with an unlimited block count BoolFieldDescriptor *bool_descriptor5 = new BoolFieldDescriptor("bool"); vector fields5; fields5.push_back(bool_descriptor5); FieldDescriptorGroup group_descriptor5( "group", fields5, 0, FieldDescriptorGroup::UNLIMITED_BLOCKS); OLA_ASSERT_FALSE(group_descriptor5.FixedSize()); OLA_ASSERT_FALSE(group_descriptor5.LimitedSize()); OLA_ASSERT_EQ(0u, group_descriptor5.MaxSize()); OLA_ASSERT_EQ(1u, group_descriptor5.FieldCount()); OLA_ASSERT_TRUE(group_descriptor5.FixedBlockSize()); OLA_ASSERT_EQ(1u, group_descriptor5.BlockSize()); OLA_ASSERT_EQ(1u, group_descriptor5.MaxBlockSize()); OLA_ASSERT_EQ(static_cast(0), group_descriptor5.MinBlocks()); OLA_ASSERT_EQ( static_cast(FieldDescriptorGroup::UNLIMITED_BLOCKS), group_descriptor5.MaxBlocks()); OLA_ASSERT_FALSE(group_descriptor5.FixedBlockCount()); OLA_ASSERT_EQ(static_cast(bool_descriptor5), group_descriptor5.GetField(0)); } /** * Check that intervals and labels work */ void DescriptorTest::testIntervalsAndLabels() { UInt16FieldDescriptor::IntervalVector intervals; intervals.push_back(UInt16FieldDescriptor::Interval(2, 8)); intervals.push_back(UInt16FieldDescriptor::Interval(12, 14)); UInt16FieldDescriptor::LabeledValues labels; labels["dozen"] = 12; labels["bakers_dozen"] = 13; UInt16FieldDescriptor uint16_descriptor("uint16", intervals, labels); // check IsValid() OLA_ASSERT_FALSE(uint16_descriptor.IsValid(0)); OLA_ASSERT_FALSE(uint16_descriptor.IsValid(1)); OLA_ASSERT_TRUE(uint16_descriptor.IsValid(2)); OLA_ASSERT_TRUE(uint16_descriptor.IsValid(8)); OLA_ASSERT_FALSE(uint16_descriptor.IsValid(9)); OLA_ASSERT_FALSE(uint16_descriptor.IsValid(11)); OLA_ASSERT_TRUE(uint16_descriptor.IsValid(12)); OLA_ASSERT_TRUE(uint16_descriptor.IsValid(13)); OLA_ASSERT_TRUE(uint16_descriptor.IsValid(14)); OLA_ASSERT_FALSE(uint16_descriptor.IsValid(15)); OLA_ASSERT_FALSE(uint16_descriptor.IsValid(255)); OLA_ASSERT_FALSE(uint16_descriptor.IsValid(65535)); // check LookupLabel() uint16_t value; OLA_ASSERT_FALSE(uint16_descriptor.LookupLabel("one", &value)); OLA_ASSERT_TRUE(uint16_descriptor.LookupLabel("dozen", &value)); OLA_ASSERT_EQ(static_cast(12), value); OLA_ASSERT_TRUE(uint16_descriptor.LookupLabel("bakers_dozen", &value)); OLA_ASSERT_EQ(static_cast(13), value); OLA_ASSERT_FALSE(uint16_descriptor.LookupLabel("twenty", &value)); // check LookupValue OLA_ASSERT_EQ(string(""), uint16_descriptor.LookupValue(0)); OLA_ASSERT_EQ(string("dozen"), uint16_descriptor.LookupValue(12)); OLA_ASSERT_EQ(string("bakers_dozen"), uint16_descriptor.LookupValue(13)); // a Descriptor with no labels or intervals UInt16FieldDescriptor::IntervalVector intervals2; UInt16FieldDescriptor::LabeledValues labels2; UInt16FieldDescriptor uint16_descriptor2("uint16", intervals2, labels2); OLA_ASSERT_TRUE(uint16_descriptor2.IsValid(0)); OLA_ASSERT_TRUE(uint16_descriptor2.IsValid(255)); OLA_ASSERT_TRUE(uint16_descriptor2.IsValid(65535)); } ola-0.10.5.nojsmin/common/network/0000755000175000017500000000000013155164170016444 5ustar wouterwouterola-0.10.5.nojsmin/common/network/SocketHelper.h0000644000175000017500000000223513023355232021202 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SocketHelper.h * Various functions to operate on sockets. * Copyright (C) 2013 Simon Newton */ #ifndef COMMON_NETWORK_SOCKETHELPER_H_ #define COMMON_NETWORK_SOCKETHELPER_H_ #include namespace ola { namespace network { GenericSocketAddress GetLocalAddress(int sd); GenericSocketAddress GetPeerAddress(int sd); } // namespace network } // namespace ola #endif // COMMON_NETWORK_SOCKETHELPER_H_ ola-0.10.5.nojsmin/common/network/InterfacePickerTest.cpp0000644000175000017500000001231613134123277023051 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * InterfacePickerTest.cpp * Test fixture for the InterfacePicker class * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include #include #include "common/network/FakeInterfacePicker.h" #include "ola/network/InterfacePicker.h" #include "ola/Logging.h" #include "ola/testing/TestUtils.h" using ola::network::FakeInterfacePicker; using ola::network::IPV4Address; using ola::network::Interface; using ola::network::InterfacePicker; using ola::network::MACAddress; using std::auto_ptr; using std::cout; using std::endl; using std::string; using std::vector; class InterfacePickerTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(InterfacePickerTest); CPPUNIT_TEST(testGetInterfaces); CPPUNIT_TEST(testGetLoopbackInterfaces); CPPUNIT_TEST(testChooseInterface); CPPUNIT_TEST_SUITE_END(); public: void testGetInterfaces(); void testGetLoopbackInterfaces(); void testChooseInterface(); }; CPPUNIT_TEST_SUITE_REGISTRATION(InterfacePickerTest); /* * Check that we find at least one candidate interface. */ void InterfacePickerTest::testGetInterfaces() { auto_ptr picker(InterfacePicker::NewPicker()); vector interfaces = picker->GetInterfaces(true); #ifndef _WIN32 // If a Windows box is not on a network, and doesn't have it's loopback, there // may be zero interfaces present so we skip this check OLA_ASSERT_GT(interfaces.size(), 0); #else OLA_WARN << "Windows found " << interfaces.size() << " interfaces"; #endif // _WIN32 vector::iterator iter; cout << endl; for (iter = interfaces.begin(); iter != interfaces.end(); ++iter) { cout << iter->name << endl; cout << " index: " << iter->index << endl; cout << " ip: " << iter->ip_address << endl; cout << " bcast: " << iter->bcast_address << endl; cout << " subnet: " << iter->subnet_mask << endl; cout << " type: " << iter->type << endl; cout << " hw_addr: " << iter->hw_address << endl; cout << endl; cout << "---------------" << endl; } } /* * Check that we find a loopback interface. */ void InterfacePickerTest::testGetLoopbackInterfaces() { auto_ptr picker(InterfacePicker::NewPicker()); vector interfaces = picker->GetInterfaces(true); #ifndef _WIN32 // If a Windows box is not on a network, and doesn't have it's loopback, there // may be zero interfaces present so we skip this check OLA_ASSERT_GT(interfaces.size(), 0); #else OLA_WARN << "Windows found " << interfaces.size() << " interfaces"; #endif // _WIN32 vector::iterator iter; unsigned int loopback_count = 0; for (iter = interfaces.begin(); iter != interfaces.end(); ++iter) { if (iter->loopback) loopback_count++; } #ifndef _WIN32 OLA_ASSERT_GT(loopback_count, 0); #endif // _WIN32 } void InterfacePickerTest::testChooseInterface() { vector interfaces; FakeInterfacePicker picker(interfaces); // no interfaces Interface iface; OLA_ASSERT_FALSE(picker.ChooseInterface(&iface, "")); // no interfaces, by index OLA_ASSERT_FALSE(picker.ChooseInterface(&iface, 0)); // now with one iface that doesn't match Interface iface1; iface1.name = "eth0"; iface1.index = 1; OLA_ASSERT_TRUE(IPV4Address::FromString("10.0.0.1", &iface1.ip_address)); interfaces.push_back(iface1); FakeInterfacePicker picker2(interfaces); OLA_ASSERT_TRUE(picker2.ChooseInterface(&iface, "192.168.1.1")); OLA_ASSERT_TRUE(iface1 == iface); // check that preferred works Interface iface2; iface2.name = "eth1"; iface2.index = 2; OLA_ASSERT_TRUE(IPV4Address::FromString("192.168.1.1", &iface2.ip_address)); interfaces.push_back(iface2); FakeInterfacePicker picker3(interfaces); OLA_ASSERT_TRUE(picker3.ChooseInterface(&iface, "192.168.1.1")); OLA_ASSERT_TRUE(iface2 == iface); // now check for iface name OLA_ASSERT_TRUE(picker3.ChooseInterface(&iface, "eth0")); OLA_ASSERT_TRUE(iface1 == iface); OLA_ASSERT_TRUE(picker3.ChooseInterface(&iface, "eth1")); OLA_ASSERT_TRUE(iface2 == iface); // a invalid address should return the first one OLA_ASSERT_TRUE(picker3.ChooseInterface(&iface, "foo")); OLA_ASSERT_TRUE(iface1 == iface); // now check by iface index OLA_ASSERT_TRUE(picker3.ChooseInterface(&iface, 2)); OLA_ASSERT_TRUE(iface2 == iface); // an invalid index should return the first one OLA_ASSERT_TRUE(picker3.ChooseInterface(&iface, 3)); OLA_ASSERT_TRUE(iface1 == iface); } ola-0.10.5.nojsmin/common/network/SocketAddress.cpp0000644000175000017500000000720613023355232021706 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SocketAddress.cpp * Represents a sockaddr structure. * Copyright (C) 2012 Simon Newton */ #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #ifdef HAVE_ARPA_INET_H #include #endif // HAVE_ARPA_INET_H #ifdef HAVE_NETINET_IN_H #include // Required by FreeBSD #endif // HAVE_NETINET_IN_H #include #include #include #include #include #include #include namespace ola { namespace network { using std::string; string IPV4SocketAddress::ToString() const { std::ostringstream str; str << Host() << ":" << Port(); return str.str(); } /** * Copy this IPV4SocketAddress into a sockaddr. */ bool IPV4SocketAddress::ToSockAddr(struct sockaddr *addr, unsigned int size) const { if (size < sizeof(struct sockaddr_in)) { OLA_FATAL << "Length passed to ToSockAddr is too small."; return false; } struct sockaddr_in *v4_addr = reinterpret_cast(addr); memset(v4_addr, 0, size); v4_addr->sin_family = AF_INET; v4_addr->sin_port = HostToNetwork(m_port); v4_addr->sin_addr.s_addr = m_host.AsInt(); return true; } /** * Extract a IPV4SocketAddress from a string. */ bool IPV4SocketAddress::FromString(const string &input, IPV4SocketAddress *socket_address) { size_t pos = input.find_first_of(":"); if (pos == string::npos) return false; IPV4Address address; if (!IPV4Address::FromString(input.substr(0, pos), &address)) return false; uint16_t port; if (!StringToInt(input.substr(pos + 1), &port)) return false; *socket_address = IPV4SocketAddress(address, port); return true; } IPV4SocketAddress IPV4SocketAddress::FromStringOrDie( const string &address) { IPV4SocketAddress socket_address; assert(FromString(address, &socket_address)); return socket_address; } bool GenericSocketAddress::IsValid() const { return Family() != AF_UNSPEC; } string GenericSocketAddress::ToString() const { switch (Family()) { case AF_INET: return V4Addr().ToString(); case AF_INET6: default: std::ostringstream str; str << "Generic sockaddr of type: " << m_addr.sa_family; return str.str(); } } /** * Convert the sockaddr to a sockaddr_in. * The caller should check that Family() is AF_INET before calling this. */ IPV4SocketAddress GenericSocketAddress::V4Addr() const { if (Family() == AF_INET) { const struct sockaddr_in *v4_addr = reinterpret_cast(&m_addr); return IPV4SocketAddress(IPV4Address(v4_addr->sin_addr.s_addr), NetworkToHost(v4_addr->sin_port)); } else { OLA_FATAL << "Invalid conversion of socket family " << Family(); return IPV4SocketAddress(IPV4Address(), 0); } } } // namespace network } // namespace ola ola-0.10.5.nojsmin/common/network/Makefile.mk0000644000175000017500000000455213023355232020513 0ustar wouterwouter# LIBRARIES ################################################## common_libolacommon_la_SOURCES += \ common/network/AdvancedTCPConnector.cpp \ common/network/FakeInterfacePicker.h \ common/network/HealthCheckedConnection.cpp \ common/network/IPV4Address.cpp \ common/network/Interface.cpp \ common/network/InterfacePicker.cpp \ common/network/MACAddress.cpp \ common/network/NetworkUtils.cpp \ common/network/NetworkUtilsInternal.h \ common/network/Socket.cpp \ common/network/SocketAddress.cpp \ common/network/SocketCloser.cpp \ common/network/SocketHelper.cpp \ common/network/SocketHelper.h \ common/network/TCPConnector.cpp \ common/network/TCPSocket.cpp common_libolacommon_la_LIBADD += $(RESOLV_LIBS) if USING_WIN32 common_libolacommon_la_SOURCES += \ common/network/WindowsInterfacePicker.h \ common/network/WindowsInterfacePicker.cpp else common_libolacommon_la_SOURCES += \ common/network/PosixInterfacePicker.h \ common/network/PosixInterfacePicker.cpp endif # TESTS ################################################## test_programs += \ common/network/HealthCheckedConnectionTester \ common/network/NetworkTester \ common/network/TCPConnectorTester common_network_HealthCheckedConnectionTester_SOURCES = \ common/network/HealthCheckedConnectionTest.cpp common_network_HealthCheckedConnectionTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_network_HealthCheckedConnectionTester_LDADD = $(COMMON_TESTING_LIBS) common_network_NetworkTester_SOURCES = \ common/network/IPV4AddressTest.cpp \ common/network/InterfacePickerTest.cpp \ common/network/InterfaceTest.cpp \ common/network/MACAddressTest.cpp \ common/network/NetworkUtilsTest.cpp \ common/network/SocketAddressTest.cpp \ common/network/SocketTest.cpp common_network_NetworkTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_network_NetworkTester_LDADD = $(COMMON_TESTING_LIBS) if USING_WIN32 common_network_NetworkTester_LDFLAGS = -no-undefined -liphlpapi -lnetapi32 \ -lcap -lws2_32 -ldpnet -lwsock32 endif common_network_TCPConnectorTester_SOURCES = \ common/network/AdvancedTCPConnectorTest.cpp \ common/network/TCPConnectorTest.cpp common_network_TCPConnectorTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_network_TCPConnectorTester_LDADD = $(COMMON_TESTING_LIBS) ola-0.10.5.nojsmin/common/network/HealthCheckedConnectionTest.cpp0000644000175000017500000001732613023355232024510 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * HealthCheckedConnectionTest.cpp * Test fixture for the HealthCheckedConnection class. * Copyright (C) 2012 Simon Newton */ #include #include "ola/Callback.h" #include "ola/Clock.h" #include "ola/Logging.h" #include "ola/io/SelectServer.h" #include "ola/network/HealthCheckedConnection.h" #include "ola/network/Socket.h" #include "ola/testing/TestUtils.h" using ola::MockClock; using ola::NewCallback; using ola::NewSingleCallback; using ola::TimeInterval; using ola::network::HealthCheckedConnection; using ola::io::LoopbackDescriptor; using ola::io::SelectServer; class MockHealthCheckedConnection: public HealthCheckedConnection { public: struct Options { uint8_t end_after; // terminate after this many heartbeats uint8_t send_every; // don't send every N heartbeats bool validate_heartbeat; // check the heartbeat is what we expect bool abort_on_failure; // fail if the channel goes down }; static void InitOptions(Options *options) { options->end_after = 8; options->send_every = 0; options->validate_heartbeat = false; options->abort_on_failure = true; } MockHealthCheckedConnection(ola::io::ConnectedDescriptor *descriptor, SelectServer *scheduler, const ola::TimeInterval timeout_interval, const Options &options, MockClock *clock) : HealthCheckedConnection(scheduler, timeout_interval), m_descriptor(descriptor), m_ss(scheduler), m_options(options), m_next_heartbeat(0), m_expected_heartbeat(0), m_channel_ok(true), m_clock(clock) { } void SendHeartbeat() { if (m_options.send_every == 0 || m_next_heartbeat % m_options.send_every == 0) { m_descriptor->Send(&m_next_heartbeat, sizeof(m_next_heartbeat)); } m_clock->AdvanceTime(0, 180000); m_next_heartbeat++; } void HeartbeatTimeout() { if (m_options.abort_on_failure) CPPUNIT_FAIL("Channel went down"); m_channel_ok = false; m_ss->Terminate(); } void ReadData() { uint8_t data; unsigned int data_read; m_descriptor->Receive(&data, sizeof(data), data_read); if (m_options.validate_heartbeat) OLA_ASSERT_EQ(m_expected_heartbeat++, data); HeartbeatReceived(); if (data >= m_options.end_after) m_ss->Terminate(); } bool ChannelOk() const { return m_channel_ok; } private: ola::io::ConnectedDescriptor *m_descriptor; SelectServer *m_ss; Options m_options; uint8_t m_next_heartbeat; uint8_t m_expected_heartbeat; bool m_channel_ok; MockClock *m_clock; }; class HealthCheckedConnectionTest: public CppUnit::TestFixture { public: HealthCheckedConnectionTest() : CppUnit::TestFixture(), m_ss(NULL, &m_clock), heartbeat_interval(0, 200000) { } CPPUNIT_TEST_SUITE(HealthCheckedConnectionTest); CPPUNIT_TEST(testSimpleChannel); CPPUNIT_TEST(testChannelWithPacketLoss); CPPUNIT_TEST(testChannelWithHeavyPacketLoss); CPPUNIT_TEST(testPauseAndResume); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void tearDown() {} void testSimpleChannel(); void testChannelWithPacketLoss(); void testChannelWithHeavyPacketLoss(); void testPauseAndResume(); void PauseReading(MockHealthCheckedConnection *connection) { connection->PauseTimer(); m_ss.RemoveReadDescriptor(&socket); } void ResumeReading(MockHealthCheckedConnection *connection) { connection->ResumeTimer(); m_ss.AddReadDescriptor(&socket); } private: MockClock m_clock; SelectServer m_ss; LoopbackDescriptor socket; TimeInterval heartbeat_interval; MockHealthCheckedConnection::Options options; }; CPPUNIT_TEST_SUITE_REGISTRATION(HealthCheckedConnectionTest); void HealthCheckedConnectionTest::setUp() { socket.Init(); MockHealthCheckedConnection::InitOptions(&options); } /* * Check that the channel stays up when all heartbeats are received. */ void HealthCheckedConnectionTest::testSimpleChannel() { options.validate_heartbeat = true; MockHealthCheckedConnection connection(&socket, &m_ss, heartbeat_interval, options, &m_clock); socket.SetOnData( NewCallback(&connection, &MockHealthCheckedConnection::ReadData)); connection.Setup(); m_ss.AddReadDescriptor(&socket); connection.Setup(); m_ss.Run(); OLA_ASSERT_TRUE(connection.ChannelOk()); } /** * Check the channel works when every 2nd heartbeat is lost */ void HealthCheckedConnectionTest::testChannelWithPacketLoss() { options.send_every = 2; MockHealthCheckedConnection connection(&socket, &m_ss, heartbeat_interval, options, &m_clock); socket.SetOnData( NewCallback(&connection, &MockHealthCheckedConnection::ReadData)); connection.Setup(); m_ss.AddReadDescriptor(&socket); connection.Setup(); m_ss.Run(); OLA_ASSERT_TRUE(connection.ChannelOk()); } /** * Check the channel works when every 2nd heartbeat is lost */ void HealthCheckedConnectionTest::testChannelWithHeavyPacketLoss() { options.send_every = 3; options.abort_on_failure = false; MockHealthCheckedConnection connection(&socket, &m_ss, heartbeat_interval, options, &m_clock); socket.SetOnData( NewCallback(&connection, &MockHealthCheckedConnection::ReadData)); connection.Setup(); m_ss.AddReadDescriptor(&socket); connection.Setup(); m_ss.Run(); OLA_ASSERT_FALSE(connection.ChannelOk()); } /** * Check pausing doesn't mark the channel as bad. */ void HealthCheckedConnectionTest::testPauseAndResume() { MockHealthCheckedConnection connection(&socket, &m_ss, heartbeat_interval, options, &m_clock); socket.SetOnData( NewCallback(&connection, &MockHealthCheckedConnection::ReadData)); connection.Setup(); m_ss.AddReadDescriptor(&socket); connection.Setup(); m_ss.RegisterSingleTimeout( TimeInterval(1, 0), NewSingleCallback(this, &HealthCheckedConnectionTest::PauseReading, &connection)); m_ss.RegisterSingleTimeout( TimeInterval(3, 0), NewSingleCallback(this, &HealthCheckedConnectionTest::ResumeReading, &connection)); m_ss.Run(); OLA_ASSERT_TRUE(connection.ChannelOk()); } ola-0.10.5.nojsmin/common/network/PosixInterfacePicker.h0000644000175000017500000000272213023355232022674 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * PosixInterfacePicker.h * Choose an interface to listen on * Copyright (C) 2005 Simon Newton */ #ifndef COMMON_NETWORK_POSIXINTERFACEPICKER_H_ #define COMMON_NETWORK_POSIXINTERFACEPICKER_H_ #include #include "ola/network/InterfacePicker.h" namespace ola { namespace network { /* * The InterfacePicker for posix systems */ class PosixInterfacePicker: public InterfacePicker { public: std::vector GetInterfaces(bool include_loopback) const; private: static const unsigned int INITIAL_IFACE_COUNT = 10; static const unsigned int IFACE_COUNT_INC = 5; unsigned int GetIfReqSize(const char *data) const; }; } // namespace network } // namespace ola #endif // COMMON_NETWORK_POSIXINTERFACEPICKER_H_ ola-0.10.5.nojsmin/common/network/InterfaceTest.cpp0000644000175000017500000001215413023355232021706 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * InterfaceTest.cpp * Test fixture for the Interface & InterfaceBuilder classes. * Copyright (C) 2011 Simon Newton */ #include #include #include "ola/Logging.h" #include "ola/network/Interface.h" #include "ola/network/IPV4Address.h" #include "ola/network/MACAddress.h" #include "ola/network/NetworkUtils.h" #include "ola/testing/TestUtils.h" using ola::network::IPV4Address; using ola::network::Interface; using ola::network::InterfaceBuilder; using ola::network::MACAddress; using std::string; class InterfaceTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(InterfaceTest); CPPUNIT_TEST(testBuilder); CPPUNIT_TEST_SUITE_END(); public: void testBuilder(); }; CPPUNIT_TEST_SUITE_REGISTRATION(InterfaceTest); /* * Check that we find at least one candidate interface. */ void InterfaceTest::testBuilder() { InterfaceBuilder builder; Interface interface = builder.Construct(); OLA_ASSERT_EQ(string(""), interface.name); OLA_ASSERT_EQ(string("0.0.0.0"), interface.ip_address.ToString()); OLA_ASSERT_EQ(string("0.0.0.0"), interface.bcast_address.ToString()); OLA_ASSERT_EQ(string("0.0.0.0"), interface.subnet_mask.ToString()); OLA_ASSERT_EQ(string("00:00:00:00:00:00"), interface.hw_address.ToString()); // set & build an interface (mostly) from strings builder.SetName("eth0"); OLA_ASSERT_TRUE(builder.SetAddress("192.168.1.1")); OLA_ASSERT_TRUE(builder.SetBroadcast("192.168.1.255")); OLA_ASSERT_TRUE(builder.SetSubnetMask("255.255.255.0")); builder.SetHardwareAddress(MACAddress::FromStringOrDie("e4:ff:29:36:74:12")); interface = builder.Construct(); OLA_ASSERT_EQ(string("eth0"), interface.name); OLA_ASSERT_EQ(string("192.168.1.1"), interface.ip_address.ToString()); OLA_ASSERT_EQ(string("192.168.1.255"), interface.bcast_address.ToString()); OLA_ASSERT_EQ(string("255.255.255.0"), interface.subnet_mask.ToString()); OLA_ASSERT_EQ(string("e4:ff:29:36:74:12"), interface.hw_address.ToString()); // check the alternate form of mac address builder.SetHardwareAddress(MACAddress::FromStringOrDie("12.34.56.78.90.ab")); interface = builder.Construct(); OLA_ASSERT_EQ(string("12:34:56:78:90:ab"), interface.hw_address.ToString()); // reset the builder builder.Reset(); interface = builder.Construct(); OLA_ASSERT_EQ(string(""), interface.name); OLA_ASSERT_EQ(string("0.0.0.0"), interface.ip_address.ToString()); OLA_ASSERT_EQ(string("0.0.0.0"), interface.bcast_address.ToString()); OLA_ASSERT_EQ(string("0.0.0.0"), interface.subnet_mask.ToString()); OLA_ASSERT_EQ(string("00:00:00:00:00:00"), interface.hw_address.ToString()); // now check we can't use bad data OLA_ASSERT_FALSE(builder.SetAddress("192.168.1.")); OLA_ASSERT_FALSE(builder.SetBroadcast("192.168.1.255.255")); OLA_ASSERT_FALSE(builder.SetSubnetMask("foobarbaz")); MACAddress addr3, addr4; OLA_ASSERT_FALSE(MACAddress::FromString(string("e4:ff:29:36:74:12:ac"), &addr3)); builder.SetHardwareAddress(addr3); OLA_ASSERT_FALSE(MACAddress::FromString(string("e4:ff:29:36:74:hh"), &addr4)); builder.SetHardwareAddress(addr4); // none of this should have changed. interface = builder.Construct(); OLA_ASSERT_EQ(string(""), interface.name); OLA_ASSERT_EQ(string("0.0.0.0"), interface.ip_address.ToString()); OLA_ASSERT_EQ(string("0.0.0.0"), interface.bcast_address.ToString()); OLA_ASSERT_EQ(string("0.0.0.0"), interface.subnet_mask.ToString()); OLA_ASSERT_EQ(string("00:00:00:00:00:00"), interface.hw_address.ToString()); // now build from IPV4Address and MACAddress objects IPV4Address ip_address, netmask, broadcast_address; IPV4Address::FromString("10.0.0.1", &ip_address); IPV4Address::FromString("10.0.255.255", &netmask); IPV4Address::FromString("10.0.255.255", &broadcast_address); MACAddress mac_address; MACAddress::FromString("ba:98:76:54:32:10", &mac_address); builder.SetName("eth1"); builder.SetAddress(ip_address); builder.SetBroadcast(broadcast_address); builder.SetSubnetMask(netmask); builder.SetHardwareAddress(mac_address); interface = builder.Construct(); OLA_ASSERT_EQ(string("eth1"), interface.name); OLA_ASSERT_EQ(ip_address, interface.ip_address); OLA_ASSERT_EQ(broadcast_address, interface.bcast_address); OLA_ASSERT_EQ(netmask, interface.subnet_mask); OLA_ASSERT_EQ(mac_address, interface.hw_address); } ola-0.10.5.nojsmin/common/network/NetworkUtils.cpp0000644000175000017500000004210013023355232021612 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * NetworkUtils.cpp * Abstract various network functions. * Copyright (C) 2005 Simon Newton */ #include "ola/network/NetworkUtils.h" #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #ifdef _WIN32 typedef uint32_t in_addr_t; // Iphlpapi.h depends on Winsock2.h #define WIN_32_LEAN_AND_MEAN #include #include #else #include #endif // _WIN32 #ifdef HAVE_RESOLV_H #include #endif // HAVE_RESOLV_H #if defined(HAVE_LINUX_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H) #define USE_NETLINK_FOR_DEFAULT_ROUTE 1 #include #include #elif defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_NET_ROUTE_H) && \ defined(HAVE_DECL_PF_ROUTE) && defined(HAVE_DECL_NET_RT_DUMP) #define USE_SYSCTL_FOR_DEFAULT_ROUTE 1 #include #ifdef HAVE_SYS_PARAM_H #include #endif // HAVE_SYS_PARAM_H #include #else // TODO(Peter): Do something else if we don't have Netlink/on Windows #endif // defined(HAVE_LINUX_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H) #ifdef HAVE_ENDIAN_H #include #endif // HAVE_ENDIAN_H #include #include #include #include #include #include #include #include #include #include #include "common/network/NetworkUtilsInternal.h" #include "ola/Callback.h" #include "ola/Logging.h" #include "ola/StringUtils.h" #include "ola/math/Random.h" #include "ola/network/Interface.h" #include "ola/network/MACAddress.h" #include "ola/network/SocketCloser.h" namespace ola { namespace network { using std::string; using std::vector; using ola::network::Interface; namespace { inline bool IsBigEndian() { #ifdef HAVE_ENDIAN_H return BYTE_ORDER == __BIG_ENDIAN; #else #ifdef _WIN32 // Windows currently only runs in little-endian mode, but that might change // on future devices. Since there is no BYTE_ORDER define, we use this // little trick from http://esr.ibiblio.org/?p=5095 return (*(uint16_t*)"\0\xff" < 0x100); // NOLINT(readability/casting) #else return BYTE_ORDER == BIG_ENDIAN; #endif // _WIN32 #endif // HAVE_ENDIAN_H } inline uint32_t ByteSwap32(uint32_t value) { return ((value & 0x000000ff) << 24) | ((value & 0x0000ff00) << 8) | ((value & 0x00ff0000) >> 8) | ((value & 0xff000000) >> 24); } inline uint32_t ByteSwap16(uint16_t value) { return ((value & 0xff) << 8) | ((value & 0xff00) >> 8); } } // namespace unsigned int SockAddrLen(const struct sockaddr &sa) { #ifdef HAVE_SOCKADDR_SA_LEN return sa.sa_len; #else switch (sa.sa_family) { case AF_INET: return sizeof(struct sockaddr_in); #ifdef IPV6 case AF_INET6: return sizeof(struct sockaddr_in6); #endif // IPV6 #ifdef HAVE_SOCKADDR_DL_STRUCT case AF_LINK: return sizeof(struct sockaddr_dl); #endif // HAVE_SOCKADDR_DL_STRUCT default: OLA_WARN << "Can't determine size of sockaddr: " << sa.sa_family; return sizeof(struct sockaddr); } #endif // HAVE_SOCKADDR_SA_LEN } uint16_t NetworkToHost(uint16_t value) { return ntohs(value); } uint32_t NetworkToHost(uint32_t value) { return ntohl(value); } int16_t NetworkToHost(int16_t value) { return ntohs(value); } int32_t NetworkToHost(int32_t value) { return ntohl(value); } uint16_t HostToNetwork(uint16_t value) { return htons(value); } int16_t HostToNetwork(int16_t value) { return htons(value); } uint32_t HostToNetwork(uint32_t value) { return htonl(value); } int32_t HostToNetwork(int32_t value) { return htonl(value); } uint16_t HostToLittleEndian(uint16_t value) { if (IsBigEndian()) { return ByteSwap16(value); } else { return value; } } int16_t HostToLittleEndian(int16_t value) { if (IsBigEndian()) { return ByteSwap16(value); } else { return value; } } uint32_t HostToLittleEndian(uint32_t value) { if (IsBigEndian()) { return ByteSwap32(value); } else { return value; } } int32_t HostToLittleEndian(int32_t value) { if (IsBigEndian()) { return ByteSwap32(value); } else { return value; } } uint16_t LittleEndianToHost(uint16_t value) { if (IsBigEndian()) { return ByteSwap16(value); } else { return value; } } int16_t LittleEndianToHost(int16_t value) { if (IsBigEndian()) { return ByteSwap16(value); } else { return value; } } uint32_t LittleEndianToHost(uint32_t value) { if (IsBigEndian()) { return ByteSwap32(value); } else { return value; } } int32_t LittleEndianToHost(int32_t value) { if (IsBigEndian()) { return ByteSwap32(value); } else { return value; } } string HostnameFromFQDN(const string &fqdn) { string::size_type first_dot = fqdn.find_first_of("."); if (first_dot == string::npos) { return fqdn; } return fqdn.substr(0, first_dot); // Don't return the dot itself } string DomainNameFromFQDN(const string &fqdn) { string::size_type first_dot = string::npos; first_dot = fqdn.find_first_of("."); if (first_dot == string::npos) { return ""; } return fqdn.substr(first_dot + 1); // Don't return the dot itself } string DomainName() { return DomainNameFromFQDN(FQDN()); } string FQDN() { #ifdef _POSIX_HOST_NAME_MAX char hostname[_POSIX_HOST_NAME_MAX]; #else char hostname[256]; #endif // _POSIX_HOST_NAME_MAX int ret = gethostname(hostname, sizeof(hostname)); if (ret) { OLA_WARN << "gethostname failed: " << strerror(errno); return ""; } return hostname; } string FullHostname() { return FQDN(); } string Hostname() { return HostnameFromFQDN(FQDN()); } bool NameServers(vector *name_servers) { #if HAVE_DECL_RES_NINIT struct __res_state res; memset(&res, 0, sizeof(struct __res_state)); // Init the resolver info each time so it's always current for the RDM // responders in case we've set it via RDM too if (res_ninit(&res) != 0) { OLA_WARN << "Error getting nameservers via res_ninit"; return false; } for (int32_t i = 0; i < res.nscount; i++) { IPV4Address addr = IPV4Address(res.nsaddr_list[i].sin_addr.s_addr); OLA_DEBUG << "Found Nameserver " << i << ": " << addr; name_servers->push_back(addr); } res_nclose(&res); #elif defined(_WIN32) ULONG size = sizeof(FIXED_INFO); PFIXED_INFO fixed_info = NULL; while (1) { fixed_info = reinterpret_cast(new uint8_t[size]); DWORD result = GetNetworkParams(fixed_info, &size); if (result == ERROR_SUCCESS) { break; } if (result != ERROR_BUFFER_OVERFLOW) { OLA_WARN << "GetNetworkParams failed with: " << GetLastError(); return false; } delete[] fixed_info; } IP_ADDR_STRING* addr = &(fixed_info->DnsServerList); for (; addr; addr = addr->Next) { IPV4Address ipv4addr = IPV4Address(inet_addr(addr->IpAddress.String)); OLA_DEBUG << "Found nameserver: " << ipv4addr; name_servers->push_back(ipv4addr); } delete[] fixed_info; #else // Init the resolver info each time so it's always current for the RDM // responders in case we've set it via RDM too if (res_init() != 0) { OLA_WARN << "Error getting nameservers via res_init"; return false; } for (int32_t i = 0; i < _res.nscount; i++) { IPV4Address addr = IPV4Address(_res.nsaddr_list[i].sin_addr.s_addr); OLA_DEBUG << "Found Nameserver " << i << ": " << addr; name_servers->push_back(addr); } #endif // HAVE_DECL_RES_NINIT return true; } #ifdef USE_SYSCTL_FOR_DEFAULT_ROUTE /** * Try to extract an AF_INET address from a sockaddr. If successful, sa points * to the next sockaddr and true is returned. */ bool ExtractIPV4AddressFromSockAddr(const uint8_t **data, IPV4Address *ip) { const struct sockaddr *sa = reinterpret_cast(*data); if (sa->sa_family != AF_INET) { return false; } *ip = IPV4Address( reinterpret_cast(*data)->sin_addr.s_addr); *data += SockAddrLen(*sa); return true; } /** * Use sysctl() to get the default route */ static bool GetDefaultRouteWithSysctl(int32_t *if_index, IPV4Address *default_gateway) { int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_DUMP, 0}; size_t space_required; uint8_t *buffer = NULL; // loop until we know we've read all the data. while (1) { int ret = sysctl(mib, 6, NULL, &space_required, NULL, 0); if (ret < 0) { OLA_WARN << "sysctl({CTL_NET, PF_ROUTE, 0, 0, NET_RT_DUMP, 0}, 6, NULL) " << "failed: " << strerror(errno); return false; } buffer = new uint8_t[space_required]; ret = sysctl(mib, 6, buffer, &space_required, NULL, 0); if (ret < 0) { delete[] buffer; if (errno == ENOMEM) { continue; } else { OLA_WARN << "sysctl({CTL_NET, PF_ROUTE, 0, 0, NET_RT_DUMP, 0}, 6, !NULL)" << " failed: " << strerror(errno); return false; } } else { break; } } const struct rt_msghdr *rtm = NULL; const uint8_t *end = buffer + space_required; for (const uint8_t *next = buffer; next < end; next += rtm->rtm_msglen) { rtm = reinterpret_cast(next); if (rtm->rtm_version != RTM_VERSION) { OLA_WARN << "Old RTM_VERSION, was " << rtm->rtm_version << ", expected " << RTM_VERSION; continue; } const uint8_t *data_start = reinterpret_cast(rtm + 1); IPV4Address dest, gateway, netmask; if (rtm->rtm_flags & RTA_DST) { if (!ExtractIPV4AddressFromSockAddr(&data_start, &dest)) { continue; } } if (rtm->rtm_flags & RTA_GATEWAY) { if (!ExtractIPV4AddressFromSockAddr(&data_start, &gateway)) { continue; } } if (rtm->rtm_flags & RTA_NETMASK) { if (!ExtractIPV4AddressFromSockAddr(&data_start, &netmask)) { continue; } } if (dest.IsWildcard() && netmask.IsWildcard()) { *default_gateway = gateway; *if_index = rtm->rtm_index; delete[] buffer; OLA_INFO << "Default gateway: " << *default_gateway << ", if_index: " << *if_index; return true; } } delete[] buffer; OLA_WARN << "No default route found"; return true; } #elif defined(USE_NETLINK_FOR_DEFAULT_ROUTE) /** * Handle a netlink message. If this message is a routing table message and it * contains the default route, then either: * i) default_gateway is updated with the address of the gateway. * ii) if_index is updated with the interface index for the default route. * @param if_index[out] possibly updated with interface index for the default * route. * @param default_gateway[out] possibly updated with the default gateway. * @param nl_hdr the netlink message. */ void MessageHandler(int32_t *if_index, IPV4Address *default_gateway, const struct nlmsghdr *nl_hdr) { // Unless RTA_DST is provided, an RTA_GATEWAY or RTA_OIF attribute implies // it's the default route. IPV4Address gateway; int32_t index = Interface::DEFAULT_INDEX; bool is_default_route = true; // Loop over the attributes looking for RTA_GATEWAY and/or RTA_DST const rtmsg *rt_msg = reinterpret_cast(NLMSG_DATA(nl_hdr)); if (rt_msg->rtm_family == AF_INET && rt_msg->rtm_table == RT_TABLE_MAIN) { int rt_len = RTM_PAYLOAD(nl_hdr); for (const rtattr* rt_attr = reinterpret_cast( RTM_RTA(rt_msg)); RTA_OK(rt_attr, rt_len); rt_attr = RTA_NEXT(rt_attr, rt_len)) { switch (rt_attr->rta_type) { case RTA_OIF: index = *(reinterpret_cast(RTA_DATA(rt_attr))); break; case RTA_GATEWAY: gateway = IPV4Address( reinterpret_cast(RTA_DATA(rt_attr))->s_addr); break; case RTA_DST: IPV4Address dest( reinterpret_cast(RTA_DATA(rt_attr))->s_addr); is_default_route = dest.IsWildcard(); break; } } } if (is_default_route && (!gateway.IsWildcard() || index != Interface::DEFAULT_INDEX)) { *default_gateway = gateway; *if_index = index; } } typedef ola::Callback1 NetlinkCallback; /** * Read a message from the netlink socket. This continues to read until the * expected sequence number is seend. Returns true if the desired message was * seen, false if there was an error reading from the netlink socket. */ bool ReadNetlinkSocket(int sd, uint8_t *buffer, int bufsize, unsigned int seq, NetlinkCallback *handler) { OLA_DEBUG << "Looking for netlink response with seq: " << seq; while (true) { int len = recv(sd, buffer, bufsize, 0); if (len < 0) { return false; } if (len == static_cast(bufsize)) { OLA_WARN << "Number of bytes fetched == buffer size (" << bufsize << "), Netlink data may be truncated"; } struct nlmsghdr* nl_hdr; for (nl_hdr = reinterpret_cast(buffer); NLMSG_OK(nl_hdr, static_cast(len)); nl_hdr = NLMSG_NEXT(nl_hdr, len)) { OLA_DEBUG << "Read seq " << nl_hdr->nlmsg_seq << ", pid " << nl_hdr->nlmsg_pid << ", type " << nl_hdr->nlmsg_type << ", from netlink socket"; if (static_cast(nl_hdr->nlmsg_seq) != seq) { continue; } if (nl_hdr->nlmsg_type == NLMSG_ERROR) { struct nlmsgerr* err = reinterpret_cast( NLMSG_DATA(nl_hdr)); OLA_WARN << "Netlink returned error: " << err->error; return false; } handler->Run(nl_hdr); if ((nl_hdr->nlmsg_flags & NLM_F_MULTI) == 0 || nl_hdr->nlmsg_type == NLMSG_DONE) { return true; } } } } /** * Get the default route using a netlink socket */ static bool GetDefaultRouteWithNetlink(int32_t *if_index, IPV4Address *default_gateway) { int sd = socket(PF_ROUTE, SOCK_DGRAM, NETLINK_ROUTE); if (sd < 0) { OLA_WARN << "Could not create Netlink socket " << strerror(errno); return false; } SocketCloser closer(sd); int seq = ola::math::Random(0, INT_MAX); const unsigned int BUFSIZE = 8192; uint8_t msg[BUFSIZE]; memset(msg, 0, BUFSIZE); nlmsghdr* nl_msg = reinterpret_cast(msg); nl_msg->nlmsg_len = NLMSG_LENGTH(sizeof(rtmsg)); nl_msg->nlmsg_type = RTM_GETROUTE; nl_msg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; nl_msg->nlmsg_seq = seq++; nl_msg->nlmsg_pid = 0; if (send(sd, nl_msg, nl_msg->nlmsg_len, 0) < 0) { OLA_WARN << "Could not send data to Netlink " << strerror(errno); return false; } std::auto_ptr cb( ola::NewCallback(MessageHandler, if_index, default_gateway)); if (!ReadNetlinkSocket(sd, msg, BUFSIZE, nl_msg->nlmsg_seq, cb.get())) { return false; } if (default_gateway->IsWildcard() && *if_index == Interface::DEFAULT_INDEX) { OLA_WARN << "No default route found"; } OLA_INFO << "Default gateway: " << *default_gateway << ", if_index: " << *if_index; return true; } #endif // USE_SYSCTL_FOR_DEFAULT_ROUTE bool DefaultRoute(int32_t *if_index, IPV4Address *default_gateway) { *default_gateway = IPV4Address(); *if_index = Interface::DEFAULT_INDEX; #ifdef USE_SYSCTL_FOR_DEFAULT_ROUTE return GetDefaultRouteWithSysctl(if_index, default_gateway); #elif defined(USE_NETLINK_FOR_DEFAULT_ROUTE) return GetDefaultRouteWithNetlink(if_index, default_gateway); #elif defined(_WIN32) ULONG size = 4096; PMIB_IPFORWARDTABLE forward_table = reinterpret_cast(malloc(size)); DWORD result = GetIpForwardTable(forward_table, &size, TRUE); if (result == NO_ERROR) { for (unsigned int i = 0; i < forward_table->dwNumEntries; ++i) { if (forward_table->table[i].dwForwardDest == 0) { *default_gateway = IPV4Address(forward_table->table[i].dwForwardNextHop); *if_index = forward_table->table[i].dwForwardIfIndex; } } free(forward_table); return true; } else { OLA_WARN << "GetIpForwardTable failed with " << GetLastError(); return false; } #else #error "DefaultRoute not implemented for this platform, please report this." // TODO(Peter): Do something else on machines without Netlink // No Netlink, can't do anything return false; #endif // USE_SYSCTL_FOR_DEFAULT_ROUTE } } // namespace network } // namespace ola ola-0.10.5.nojsmin/common/network/MACAddress.cpp0000644000175000017500000001170413023355232021054 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * MACAddress.cpp * A MAC address * Copyright (C) 2013 Peter Newman */ #include "ola/network/MACAddress.h" #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #ifdef _WIN32 #include struct ether_addr { unsigned char octet[ola::network::MACAddress::LENGTH]; }; #define ether_addr_octet octet #else #include // required for FreeBSD uchar - doesn't hurt others #ifdef HAVE_NET_ETHERNET_H #include #endif // HAVE_NET_ETHERNET_H // NetBSD and OpenBSD don't have net/ethernet.h #ifdef HAVE_SYS_SOCKET_H #include #endif // HAVE_SYS_SOCKET_H #ifdef HAVE_NET_IF_H #include #endif // HAVE_NET_IF_H #ifdef HAVE_NET_IF_ETHER_H #include #endif // HAVE_NET_IF_ETHER_H #ifdef HAVE_NETINET_IN_H #include #endif // HAVE_NETINET_IN_H #ifdef HAVE_NET_IF_ARP_H #include #endif // HAVE_NET_IF_ARP_H #ifdef HAVE_NETINET_IF_ETHER_H #include #endif // HAVE_NETINET_IF_ETHER_H #endif // _WIN32 #ifdef __FreeBSD__ // In the FreeBSD struct ether_addr, the single field is named octet, instead // of ether_addr_octet. // OS X does this too, but avoids it by adding the following line to its // header, for compatibility with linux and others: // http://www.opensource.apple.com/source/xnu/xnu-1456.1.26/bsd/net/ethernet.h #define ether_addr_octet octet #endif // __FreeBSD__ #include #include #include #include #include #include "ola/network/NetworkUtils.h" #include "ola/StringUtils.h" namespace ola { namespace network { using std::string; using std::vector; MACAddress::MACAddress() { memset(m_address, 0, LENGTH); } MACAddress::MACAddress(const uint8_t *address) { memcpy(m_address, address, LENGTH); } MACAddress::MACAddress(const MACAddress &other) { memcpy(m_address, other.m_address, LENGTH); } MACAddress& MACAddress::operator=(const MACAddress &other) { if (this != &other) { memcpy(m_address, other.m_address, LENGTH); } return *this; } bool MACAddress::operator==(const MACAddress &other) const { return (memcmp(m_address, other.m_address, LENGTH) == 0); } bool MACAddress::operator<(const MACAddress &other) const { return (memcmp(m_address, other.m_address, LENGTH) < 0); } bool MACAddress::operator>(const MACAddress &other) const { return (memcmp(m_address, other.m_address, LENGTH) > 0); } void MACAddress::Get(uint8_t ptr[LENGTH]) const { memcpy(ptr, m_address, LENGTH); } string MACAddress::ToString() const { /** * ether_ntoa_r doesn't exist on Mac, so can't use it; ether_ntoa isn't * thread safe */ std::ostringstream str; for (unsigned int i = 0 ; i < MACAddress::LENGTH; i++) { if (i != 0) str << ":"; str << std::hex << std::setfill('0') << std::setw(2) << static_cast(m_address[i]); } return str.str(); } /** * Convert a string to a ether_addr struct * @param address a string in the form 'nn:nn:nn:nn:nn:nn' or * 'nn.nn.nn.nn.nn.nn' * @param target a pointer to a ether_addr struct * @return true if it worked, false otherwise */ bool StringToEther(const string &address, ether_addr *target) { /** * ether_aton_r doesn't exist on Mac, so can't use it (it also might not * handle dots as well as colons as seperators) */ vector tokens; ola::StringSplit(address, &tokens, ":."); if (tokens.size() != MACAddress::LENGTH) { return false; } for (unsigned int i = 0; i < MACAddress::LENGTH; i++) { if (!ola::HexStringToInt(tokens[i], target->ether_addr_octet + i)) { return false; } } return true; } MACAddress* MACAddress::FromString(const string &address) { struct ether_addr addr; if (!StringToEther(address, &addr)) { return NULL; } return new MACAddress(addr.ether_addr_octet); } bool MACAddress::FromString(const string &address, MACAddress *target) { struct ether_addr addr; if (!StringToEther(address, &addr)) { return false; } *target = MACAddress(addr.ether_addr_octet); return true; } MACAddress MACAddress::FromStringOrDie(const string &address) { struct ether_addr addr; assert(StringToEther(address, &addr)); return MACAddress(addr.ether_addr_octet); } } // namespace network } // namespace ola ola-0.10.5.nojsmin/common/network/TCPConnectorTest.cpp0000644000175000017500000002360513023355232022312 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * TCPConnectorTest.cpp * Test fixture for the TCPConnector class * Copyright (C) 2012 Simon Newton */ #include #include #include #include #include "ola/Callback.h" #include "ola/Clock.h" #include "ola/Logging.h" #include "ola/io/SelectServer.h" #include "ola/network/IPV4Address.h" #include "ola/network/NetworkUtils.h" #include "ola/network/SocketAddress.h" #include "ola/network/Socket.h" #include "ola/network/TCPConnector.h" #include "ola/network/TCPSocketFactory.h" #include "ola/testing/TestUtils.h" using ola::TimeInterval; using ola::io::ConnectedDescriptor; using ola::network::GenericSocketAddress; using ola::network::IPV4Address; using ola::network::IPV4SocketAddress; using ola::io::SelectServer; using ola::network::TCPConnector; using ola::network::TCPAcceptingSocket; using ola::network::TCPSocket; using std::auto_ptr; using std::string; // used to set a timeout which aborts the tests static const int CONNECT_TIMEOUT_IN_MS = 500; static const int ABORT_TIMEOUT_IN_MS = 1000; class TCPConnectorTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(TCPConnectorTest); CPPUNIT_TEST(testNonBlockingConnect); CPPUNIT_TEST(testNonBlockingConnectFailure); CPPUNIT_TEST(testNonBlockingConnectError); CPPUNIT_TEST(testNonBlockingCancel); CPPUNIT_TEST(testEarlyDestruction); CPPUNIT_TEST_SUITE_END(); public: TCPConnectorTest() : CppUnit::TestFixture(), m_localhost(IPV4Address::Loopback()) { } void setUp(); void tearDown(); void testNonBlockingConnect(); void testNonBlockingConnectFailure(); void testNonBlockingConnectError(); void testNonBlockingCancel(); void testEarlyDestruction(); // timing out indicates something went wrong void Timeout() { m_timeout_closure = NULL; OLA_FAIL("timeout"); } // Socket close actions void TerminateOnClose() { m_ss->Terminate(); } private: SelectServer *m_ss; IPV4Address m_localhost; ola::SingleUseCallback0 *m_timeout_closure; unsigned int m_sucessfull_calls; unsigned int m_failure_calls; void AcceptedConnection(TCPSocket *socket); void OnConnect(int fd, int error); void OnConnectFailure(int fd, int error); uint16_t ReservePort(); }; CPPUNIT_TEST_SUITE_REGISTRATION(TCPConnectorTest); /* * Setup the select server */ void TCPConnectorTest::setUp() { m_ss = new SelectServer(); m_timeout_closure = ola::NewSingleCallback(this, &TCPConnectorTest::Timeout); m_sucessfull_calls = 0; m_failure_calls = 0; OLA_ASSERT_TRUE(m_ss->RegisterSingleTimeout(ABORT_TIMEOUT_IN_MS, m_timeout_closure)); #if _WIN32 WSADATA wsa_data; int result = WSAStartup(MAKEWORD(2, 0), &wsa_data); OLA_ASSERT_EQ(result, 0); #endif // _WIN32 } /* * Cleanup the select server */ void TCPConnectorTest::tearDown() { delete m_ss; #ifdef _WIN32 WSACleanup(); #endif // _WIN32 } /* * Test non-blocking TCP connects work correctly. */ void TCPConnectorTest::testNonBlockingConnect() { ola::network::TCPSocketFactory socket_factory( ola::NewCallback(this, &TCPConnectorTest::AcceptedConnection)); TCPAcceptingSocket listening_socket(&socket_factory); IPV4SocketAddress listen_address(m_localhost, 0); OLA_ASSERT_TRUE_MSG(listening_socket.Listen(listen_address), "Failed to listen"); GenericSocketAddress addr = listening_socket.GetLocalAddress(); OLA_ASSERT_TRUE(addr.IsValid()); // calling listen a second time should fail OLA_ASSERT_FALSE(listening_socket.Listen(listen_address)); OLA_ASSERT_TRUE(m_ss->AddReadDescriptor(&listening_socket)); // Attempt a non-blocking connect TCPConnector connector(m_ss); TimeInterval connect_timeout(0, CONNECT_TIMEOUT_IN_MS * 1000); TCPConnector::TCPConnectionID id = connector.Connect( addr.V4Addr(), connect_timeout, ola::NewSingleCallback(this, &TCPConnectorTest::OnConnect)); if (id) { OLA_ASSERT_EQ(1u, connector.ConnectionsPending()); m_ss->Run(); OLA_ASSERT_EQ(0u, connector.ConnectionsPending()); } OLA_ASSERT_EQ(1u, m_sucessfull_calls); OLA_ASSERT_EQ(0u, m_failure_calls); m_ss->RemoveReadDescriptor(&listening_socket); } /* * Test a non-blocking TCP connect fails. */ void TCPConnectorTest::testNonBlockingConnectFailure() { uint16_t port = ReservePort(); OLA_ASSERT_NE(0, port); IPV4SocketAddress target(m_localhost, port); // attempt a non-blocking connect, hopefully nothing is running on port 9010 TCPConnector connector(m_ss); TimeInterval connect_timeout(0, CONNECT_TIMEOUT_IN_MS * 1000); TCPConnector::TCPConnectionID id = connector.Connect( target, connect_timeout, ola::NewSingleCallback(this, &TCPConnectorTest::OnConnectFailure)); // On platforms where connect() doesn't return EINPROGRESS, it's hard to // actually test this without knowing a non-local address. if (id) { m_ss->Run(); OLA_ASSERT_EQ(0u, connector.ConnectionsPending()); } OLA_ASSERT_EQ(0u, m_sucessfull_calls); OLA_ASSERT_EQ(1u, m_failure_calls); } /* * Test a non-blocking TCP connect for an invalid port. */ void TCPConnectorTest::testNonBlockingConnectError() { IPV4Address bcast_address; OLA_ASSERT_TRUE(IPV4Address::FromString("255.255.255.255", &bcast_address)); TCPConnector connector(m_ss); TimeInterval connect_timeout(0, CONNECT_TIMEOUT_IN_MS * 1000); TCPConnector::TCPConnectionID id = connector.Connect( IPV4SocketAddress(bcast_address, 0), connect_timeout, ola::NewSingleCallback(this, &TCPConnectorTest::OnConnectFailure)); OLA_ASSERT_FALSE(id); OLA_ASSERT_EQ(0u, connector.ConnectionsPending()); OLA_ASSERT_EQ(0u, m_sucessfull_calls); OLA_ASSERT_EQ(1u, m_failure_calls); } /* * Test that cancelling a connect works. */ void TCPConnectorTest::testNonBlockingCancel() { uint16_t port = ReservePort(); OLA_ASSERT_NE(0, port); IPV4SocketAddress target(m_localhost, port); TCPConnector connector(m_ss); TimeInterval connect_timeout(0, CONNECT_TIMEOUT_IN_MS * 1000); TCPConnector::TCPConnectionID id = connector.Connect( target, connect_timeout, ola::NewSingleCallback(this, &TCPConnectorTest::OnConnectFailure)); // On platforms where connect() doesn't return EINPROGRESS, it's hard to // actually test this without knowing a non-local address. if (id) { OLA_ASSERT_EQ(1u, connector.ConnectionsPending()); OLA_ASSERT_TRUE(connector.Cancel(id)); OLA_ASSERT_EQ(0u, connector.ConnectionsPending()); } OLA_ASSERT_EQ(0u, m_sucessfull_calls); OLA_ASSERT_EQ(1u, m_failure_calls); } /* * Test that we can destroy the Connector and everything will work. */ void TCPConnectorTest::testEarlyDestruction() { uint16_t port = ReservePort(); OLA_ASSERT_NE(0, port); IPV4SocketAddress target(m_localhost, port); // attempt a non-blocking connect. TimeInterval connect_timeout(0, CONNECT_TIMEOUT_IN_MS * 1000); { TCPConnector connector(m_ss); TCPConnector::TCPConnectionID id = connector.Connect( target, connect_timeout, ola::NewSingleCallback(this, &TCPConnectorTest::OnConnectFailure)); if (id != 0) { // The callback hasn't run yet. OLA_ASSERT_EQ(1u, connector.ConnectionsPending()); m_ss->RunOnce(TimeInterval(1, 0)); } OLA_ASSERT_EQ(0u, m_sucessfull_calls); OLA_ASSERT_EQ(1u, m_failure_calls); } } /* * Accept a new TCP connection. */ void TCPConnectorTest::AcceptedConnection(TCPSocket *new_socket) { OLA_ASSERT_NOT_NULL(new_socket); GenericSocketAddress address = new_socket->GetPeerAddress(); OLA_ASSERT_TRUE(address.Family() == AF_INET); OLA_INFO << "Connection from " << address; // terminate the ss when this connection is closed new_socket->SetOnClose( ola::NewSingleCallback(this, &TCPConnectorTest::TerminateOnClose)); m_ss->AddReadDescriptor(new_socket, true); } /** * Called when a connection completes or times out. */ void TCPConnectorTest::OnConnect(int fd, int error) { if (error) { std::ostringstream str; str << "Failed to connect: " << strerror(error); OLA_ASSERT_EQ_MSG(0, error, str.str()); m_ss->Terminate(); } else { OLA_ASSERT_TRUE(fd >= 0); #ifdef _WIN32 closesocket(fd); #else close(fd); #endif // _WIN32 } m_sucessfull_calls++; } /** * Called when a connection completes or times out. */ void TCPConnectorTest::OnConnectFailure(int fd, int error) { // The error could be one of many things, right now we just check it's non-0 OLA_ASSERT_NE(0, error); OLA_ASSERT_EQ(-1, fd); m_ss->Terminate(); m_failure_calls++; } /** * For certain tests we need to ensure there isn't something listening on a TCP * port. The best way I've come up with doing this is to bind to port 0, then * close the socket. REUSE_ADDR means that the port shouldn't be allocated * again for a while. */ uint16_t TCPConnectorTest::ReservePort() { TCPAcceptingSocket listening_socket(NULL); IPV4SocketAddress listen_address(m_localhost, 0); OLA_ASSERT_TRUE_MSG(listening_socket.Listen(listen_address), "Failed to listen"); GenericSocketAddress addr = listening_socket.GetLocalAddress(); OLA_ASSERT_TRUE(addr.IsValid()); return addr.V4Addr().Port(); } ola-0.10.5.nojsmin/common/network/TCPConnector.cpp0000644000175000017500000001710313023355232021446 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * TCPConnector.cpp * Copyright (C) 2012 Simon Newton */ #include #ifdef _WIN32 #include #ifndef ETIMEDOUT #define ETIMEDOUT WSAETIMEDOUT #endif // !ETIMEDOUT #endif // _WIN32 #include "ola/Logging.h" #include "ola/network/NetworkUtils.h" #include "ola/network/TCPConnector.h" #include "ola/stl/STLUtils.h" namespace ola { namespace network { /* * A TCP socket waiting to connect. */ class PendingTCPConnection: public ola::io::WriteFileDescriptor { public: PendingTCPConnection(TCPConnector *connector, const IPV4Address &ip, int fd, TCPConnector::TCPConnectCallback *callback); ola::io::DescriptorHandle WriteDescriptor() const { return m_handle; } void PerformWrite(); void Close(); const IPV4Address ip_address; TCPConnector::TCPConnectCallback *callback; ola::thread::timeout_id timeout_id; private: TCPConnector *m_connector; ola::io::DescriptorHandle m_handle; }; PendingTCPConnection::PendingTCPConnection( TCPConnector *connector, const IPV4Address &ip, int fd, TCPConnector::TCPConnectCallback *callback) : WriteFileDescriptor(), ip_address(ip), callback(callback), timeout_id(ola::thread::INVALID_TIMEOUT), m_connector(connector) { #ifdef _WIN32 m_handle.m_handle.m_fd = fd; m_handle.m_type = ola::io::SOCKET_DESCRIPTOR; #else m_handle = fd; #endif // _WIN32 } /* * Close this connection */ void PendingTCPConnection::Close() { #ifdef _WIN32 close(m_handle.m_handle.m_fd); #else close(m_handle); #endif // _WIN32 } /* * Called when the socket becomes writeable */ void PendingTCPConnection::PerformWrite() { m_connector->SocketWritable(this); } void DeleteConnection(PendingTCPConnection *connection) { delete connection; } TCPConnector::TCPConnector(ola::io::SelectServerInterface *ss) : m_ss(ss) { } TCPConnector::~TCPConnector() { CancelAll(); } TCPConnector::TCPConnectionID TCPConnector::Connect( const IPV4SocketAddress &endpoint, const ola::TimeInterval &timeout, TCPConnectCallback *callback) { struct sockaddr server_address; if (!endpoint.ToSockAddr(&server_address, sizeof(server_address))) { callback->Run(-1, 0); return 0; } int sd = socket(endpoint.Family(), SOCK_STREAM, 0); if (sd < 0) { int error = errno; OLA_WARN << "socket() failed, " << strerror(error); callback->Run(-1, error); return 0; } #ifdef _WIN32 ola::io::DescriptorHandle descriptor; descriptor.m_handle.m_fd = sd; descriptor.m_type = ola::io::SOCKET_DESCRIPTOR; #else ola::io::DescriptorHandle descriptor = sd; #endif // _WIN32 ola::io::ConnectedDescriptor::SetNonBlocking(descriptor); int r = connect(sd, &server_address, sizeof(server_address)); if (r) { #ifdef _WIN32 if (WSAGetLastError() != WSAEWOULDBLOCK) { #else if (errno != EINPROGRESS) { #endif // _WIN32 int error = errno; OLA_WARN << "connect() to " << endpoint << " returned, " << strerror(error); close(sd); callback->Run(-1, error); return 0; } } else { // Connect returned immediately // The callback takes ownership of the socket descriptor. callback->Run(sd, 0); // coverity[RESOURCE_LEAK] return 0; } PendingTCPConnection *connection = new PendingTCPConnection( this, endpoint.Host(), sd, callback); m_connections.insert(connection); connection->timeout_id = m_ss->RegisterSingleTimeout( timeout, ola::NewSingleCallback(this, &TCPConnector::TimeoutEvent, connection)); m_ss->AddWriteDescriptor(connection); return connection; } bool TCPConnector::Cancel(TCPConnectionID id) { PendingTCPConnection *connection = const_cast( reinterpret_cast(id)); ConnectionSet::iterator iter = m_connections.find(connection); if (iter == m_connections.end()) return false; if (connection->timeout_id != ola::thread::INVALID_TIMEOUT) { m_ss->RemoveTimeout(connection->timeout_id); connection->timeout_id = ola::thread::INVALID_TIMEOUT; } Timeout(iter); m_connections.erase(iter); return true; } void TCPConnector::CancelAll() { ConnectionSet::iterator iter = m_connections.begin(); for (; iter != m_connections.end(); ++iter) { PendingTCPConnection *connection = *iter; if (connection->timeout_id != ola::thread::INVALID_TIMEOUT) { m_ss->RemoveTimeout(connection->timeout_id); connection->timeout_id = ola::thread::INVALID_TIMEOUT; } Timeout(iter); } m_connections.clear(); } /* * Called when a socket becomes writeable. */ void TCPConnector::SocketWritable(PendingTCPConnection *connection) { // Cancel the timeout m_ss->RemoveTimeout(connection->timeout_id); connection->timeout_id = ola::thread::INVALID_TIMEOUT; m_ss->RemoveWriteDescriptor(connection); // fetch the error code #ifdef _WIN32 int sd = connection->WriteDescriptor().m_handle.m_fd; #else int sd = connection->WriteDescriptor(); #endif // _WIN32 int error = 0; socklen_t len; len = sizeof(error); #ifdef _WIN32 int r = getsockopt(sd, SOL_SOCKET, SO_ERROR, reinterpret_cast(&error), &len); #else int r = getsockopt(sd, SOL_SOCKET, SO_ERROR, &error, &len); #endif // _WIN32 if (r < 0) { error = errno; } ConnectionSet::iterator iter = m_connections.find(connection); if (iter != m_connections.end()) { m_connections.erase(iter); } // we're already within the PendingTCPConnection's call stack here // schedule the deletion to run later m_ss->Execute(ola::NewSingleCallback(DeleteConnection, connection)); if (error) { OLA_WARN << "connect() to " << connection->ip_address << " returned: " << strerror(error); connection->Close(); connection->callback->Run(-1, error); } else { #ifdef _WIN32 connection->callback->Run(connection->WriteDescriptor().m_handle.m_fd, 0); #else connection->callback->Run(connection->WriteDescriptor(), 0); #endif // _WIN32 } } /** * Delete this pending connection */ void TCPConnector::FreePendingConnection(PendingTCPConnection *connection) { delete connection; } void TCPConnector::Timeout(const ConnectionSet::iterator &iter) { PendingTCPConnection *connection = *iter; m_ss->RemoveWriteDescriptor(connection); connection->Close(); TCPConnectCallback *callback = connection->callback; delete connection; callback->Run(-1, ETIMEDOUT); } /** * Called when the connect() times out. */ void TCPConnector::TimeoutEvent(PendingTCPConnection *connection) { ConnectionSet::iterator iter = m_connections.find(connection); if (iter == m_connections.end()) { OLA_FATAL << "Timeout triggered but couldn't find the connection this refers to"; } connection->timeout_id = ola::thread::INVALID_TIMEOUT; Timeout(iter); m_connections.erase(iter); } } // namespace network } // namespace ola ola-0.10.5.nojsmin/common/network/IPV4Address.cpp0000644000175000017500000001077313023355232021203 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * IPV4Address.cpp * A IPV4 address * Copyright (C) 2011 Simon Newton */ #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #ifdef HAVE_WINSOCK2_H #include #ifndef in_addr_t #define in_addr_t uint32_t #endif // !in_addr_t #endif // HAVE_WINSOCK2_H #ifdef HAVE_SYS_SOCKET_H #include // Required by FreeBSD #endif // HAVE_SYS_SOCKET_H #ifdef HAVE_ARPA_INET_H #include #endif // HAVE_ARPA_INET_H #ifdef HAVE_NETINET_IN_H #include // Required by FreeBSD #endif // HAVE_NETINET_IN_H #include #include #include #include #include #include "common/network/NetworkUtilsInternal.h" #include "ola/Logging.h" #include "ola/network/IPV4Address.h" #include "ola/network/NetworkUtils.h" namespace ola { namespace network { using std::string; bool IPV4Address::operator<(const IPV4Address &other) const { // Stored in network byte order, so convert to sort appropriately return NetworkToHost(m_address) < NetworkToHost(other.m_address); } bool IPV4Address::operator>(const IPV4Address &other) const { // Stored in network byte order, so convert to sort appropriately return NetworkToHost(m_address) > NetworkToHost(other.m_address); } bool IPV4StringToAddress(const string &address, struct in_addr *addr) { bool ok; // TODO(Peter): This currently allows some rather quirky values as per // inet_aton, we may want to restrict that in future to match IPV4Validator if (address.empty()) { // Don't bother trying to extract an address if we weren't given one return false; } #ifdef HAVE_INET_PTON ok = (1 == inet_pton(AF_INET, address.data(), addr)); #elif HAVE_INET_ATON ok = (1 == inet_aton(address.data(), addr)); #else in_addr_t ip_addr4 = inet_addr(address.c_str()); ok = (INADDR_NONE != ip_addr4 || address == "255.255.255.255"); addr->s_addr = ip_addr4; #endif // HAVE_INET_PTON if (!ok) { OLA_WARN << "Could not convert address " << address; } return ok; } bool IPV4Address::IsWildcard() const { return m_address == INADDR_ANY; } string IPV4Address::ToString() const { struct in_addr addr; addr.s_addr = m_address; #ifdef HAVE_INET_NTOP char str[INET_ADDRSTRLEN]; if (inet_ntop(AF_INET, &addr, str, INET_ADDRSTRLEN) == NULL) { OLA_WARN << "Failed to convert address to string using inet_ntop, failing " << "back to inet_ntoa"; return inet_ntoa(addr); } return str; #else return inet_ntoa(addr); #endif // HAVE_INET_NTOP } IPV4Address* IPV4Address::FromString(const string &address) { struct in_addr addr; if (!IPV4StringToAddress(address, &addr)) { return NULL; } return new IPV4Address(addr.s_addr); } bool IPV4Address::FromString(const string &address, IPV4Address *target) { struct in_addr addr; if (!IPV4StringToAddress(address, &addr)) { return false; } *target = IPV4Address(addr.s_addr); return true; } IPV4Address IPV4Address::FromStringOrDie(const string &address) { struct in_addr addr; assert(IPV4StringToAddress(address, &addr)); return IPV4Address(addr.s_addr); } bool IPV4Address::ToCIDRMask(IPV4Address address, uint8_t *mask) { uint32_t netmask = NetworkToHost(address.AsInt()); uint8_t bits = 0; bool seen_one = false; for (uint8_t i = 0; i < std::numeric_limits::digits; i++) { if (netmask & 1) { bits++; seen_one = true; } else { if (seen_one) { return false; } } netmask = netmask >> 1; } *mask = bits; return true; } IPV4Address IPV4Address::WildCard() { return IPV4Address(INADDR_ANY); } IPV4Address IPV4Address::Broadcast() { return IPV4Address(INADDR_NONE); } IPV4Address IPV4Address::Loopback() { return IPV4Address(HostToNetwork(0x7f000001)); } } // namespace network } // namespace ola ola-0.10.5.nojsmin/common/network/WindowsInterfacePicker.cpp0000644000175000017500000000761413134123277023571 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * WindowsInterfacePicker.cpp * Chooses an interface to listen on * Copyright (C) 2005 Simon Newton */ typedef int socklen_t; #include #include #include #include #include #include "ola/network/IPV4Address.h" #include "common/network/WindowsInterfacePicker.h" #include "ola/Logging.h" namespace ola { namespace network { using std::vector; /* * Return a vector of interfaces on the system. */ vector WindowsInterfacePicker::GetInterfaces( bool include_loopback) const { vector interfaces; PIP_ADAPTER_INFO pAdapter = NULL; PIP_ADAPTER_INFO pAdapterInfo; IP_ADDR_STRING *ipAddress; ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO); uint32_t net, mask; if (include_loopback) { OLA_WARN << "Loopback interface inclusion requested. Loopback might not " << "exist on Windows"; } while (1) { pAdapterInfo = reinterpret_cast(new uint8_t[ulOutBufLen]); if (!pAdapterInfo) { OLA_WARN << "Error allocating memory needed for GetAdaptersInfo"; return interfaces; } // if ulOutBufLen isn't long enough it will be set to the size of the // buffer required DWORD status = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen); if (status == NO_ERROR) { break; } delete[] pAdapterInfo; if (status != ERROR_BUFFER_OVERFLOW) { OLA_WARN << "GetAdaptersInfo failed with error: " << static_cast(status); return interfaces; } } for (pAdapter = pAdapterInfo; pAdapter && pAdapter < pAdapterInfo + ulOutBufLen; pAdapter = pAdapter->Next) { // Since Vista, wireless interfaces return a different type // See https://msdn.microsoft.com/en-us/library/windows/desktop/aa366062(v=vs.85).aspx if ((pAdapter->Type != MIB_IF_TYPE_ETHERNET) && (pAdapter->Type != IF_TYPE_IEEE80211)) { OLA_INFO << "Skipping " << pAdapter->AdapterName << " (" << pAdapter->Description << ")" << " as it's not MIB_IF_TYPE_ETHERNET" << " or IF_TYPE_IEEE80211, got " << pAdapter->Type << " instead"; continue; } for (ipAddress = &pAdapter->IpAddressList; ipAddress; ipAddress = ipAddress->Next) { net = inet_addr(ipAddress->IpAddress.String); // Windows doesn't seem to have the notion of an interface being 'up' // so we check if this interface has an address assigned. if (net) { Interface iface; iface.name = pAdapter->AdapterName; // IFNAME_SIZE iface.index = pAdapter->Index; uint8_t macaddr[MACAddress::LENGTH]; memcpy(macaddr, pAdapter->Address, MACAddress::LENGTH); iface.hw_address = MACAddress(macaddr); iface.ip_address = IPV4Address(net); mask = inet_addr(ipAddress->IpMask.String); iface.subnet_mask = IPV4Address(mask); iface.bcast_address = IPV4Address((iface.ip_address.AsInt() & mask) | (0xFFFFFFFF ^ mask)); interfaces.push_back(iface); } } } delete[] pAdapterInfo; return interfaces; } } // namespace network } // namespace ola ola-0.10.5.nojsmin/common/network/IPV4AddressTest.cpp0000644000175000017500000001342713023355232022042 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * IPV4AddressTest.cpp * Test fixture for the IPV4Address class * Copyright (C) 2011 Simon Newton */ #include #include #include #include #include #include #include #ifdef _WIN32 #include #ifndef in_addr_t #define in_addr_t uint32_t #endif // !in_addr_t #endif // _WIN32 #include "common/network/NetworkUtilsInternal.h" #include "ola/network/IPV4Address.h" #include "ola/network/NetworkUtils.h" #include "ola/testing/TestUtils.h" using ola::network::IPV4Address; using ola::network::HostToNetwork; using std::auto_ptr; using std::string; using std::vector; class IPAddressTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(IPAddressTest); CPPUNIT_TEST(testIPV4Address); CPPUNIT_TEST(testWildcard); CPPUNIT_TEST(testBroadcast); CPPUNIT_TEST(testLoopback); CPPUNIT_TEST_SUITE_END(); public: void testIPV4Address(); void testWildcard(); void testBroadcast(); void testLoopback(); }; CPPUNIT_TEST_SUITE_REGISTRATION(IPAddressTest); /* * Test the IPV4 Address class works */ void IPAddressTest::testIPV4Address() { IPV4Address wildcard_address; OLA_ASSERT_EQ(string("0.0.0.0"), wildcard_address.ToString()); OLA_ASSERT_EQ(static_cast(0), wildcard_address.AsInt()); OLA_ASSERT_TRUE(wildcard_address.IsWildcard()); IPV4Address address1 = IPV4Address::FromStringOrDie("192.168.1.1"); int ip_as_int = address1.AsInt(); OLA_ASSERT_NE(wildcard_address, address1); OLA_ASSERT_NE(HostToNetwork(0xc0a811), ip_as_int); // Test Get() uint8_t addr[IPV4Address::LENGTH]; address1.Get(addr); OLA_ASSERT_EQ( 0, memcmp(addr, reinterpret_cast(&ip_as_int), sizeof(ip_as_int))); // test copy and assignment IPV4Address address2(address1); OLA_ASSERT_EQ(address1, address2); IPV4Address address3 = address1; OLA_ASSERT_EQ(address1, address3); // test stringification OLA_ASSERT_EQ(string("192.168.1.1"), address1.ToString()); std::ostringstream str; str << address1; OLA_ASSERT_EQ(string("192.168.1.1"), str.str()); // test from string auto_ptr string_address(IPV4Address::FromString("10.0.0.1")); OLA_ASSERT_NOT_NULL(string_address.get()); OLA_ASSERT_EQ(string("10.0.0.1"), string_address->ToString()); auto_ptr string_address2(IPV4Address::FromString("foo")); OLA_ASSERT_NULL(string_address2.get()); // and the second form IPV4Address string_address3; OLA_ASSERT_TRUE(IPV4Address::FromString("172.16.4.1", &string_address3)); OLA_ASSERT_EQ(string("172.16.4.1"), string_address3.ToString()); IPV4Address string_address4; OLA_ASSERT_FALSE(IPV4Address::FromString("", &string_address4)); // make sure sorting works vector addresses; addresses.push_back(address1); addresses.push_back(*string_address); addresses.push_back(string_address3); std::sort(addresses.begin(), addresses.end()); // The comparisons take into account network byte order automagically. OLA_ASSERT_EQ(string("10.0.0.1"), addresses[0].ToString()); OLA_ASSERT_EQ(string("172.16.4.1"), addresses[1].ToString()); OLA_ASSERT_EQ(string("192.168.1.1"), addresses[2].ToString()); uint8_t mask = 255; // UINT8_MAX; OLA_ASSERT_TRUE( IPV4Address::ToCIDRMask(IPV4Address::FromStringOrDie("0.0.0.0"), &mask)); OLA_ASSERT_EQ(0, static_cast(mask)); OLA_ASSERT_TRUE( IPV4Address::ToCIDRMask(IPV4Address::FromStringOrDie("255.0.0.0"), &mask)); OLA_ASSERT_EQ(8, static_cast(mask)); OLA_ASSERT_TRUE( IPV4Address::ToCIDRMask(IPV4Address::FromStringOrDie("255.255.255.0"), &mask)); OLA_ASSERT_EQ(24, static_cast(mask)); OLA_ASSERT_TRUE( IPV4Address::ToCIDRMask(IPV4Address::FromStringOrDie("255.255.255.252"), &mask)); OLA_ASSERT_EQ(30, static_cast(mask)); OLA_ASSERT_TRUE( IPV4Address::ToCIDRMask(IPV4Address::FromStringOrDie("255.255.255.255"), &mask)); OLA_ASSERT_EQ(32, static_cast(mask)); OLA_ASSERT_FALSE( IPV4Address::ToCIDRMask(IPV4Address::FromStringOrDie("255.0.0.255"), &mask)); } /* * Test the wildcard address works. */ void IPAddressTest::testWildcard() { IPV4Address wildcard_address; OLA_ASSERT_EQ(string("0.0.0.0"), wildcard_address.ToString()); OLA_ASSERT_EQ(static_cast(0), wildcard_address.AsInt()); OLA_ASSERT_TRUE(wildcard_address.IsWildcard()); IPV4Address wildcard_address2 = IPV4Address::WildCard(); OLA_ASSERT_EQ(wildcard_address, wildcard_address2); } /* * Test the broadcast address works. */ void IPAddressTest::testBroadcast() { IPV4Address broadcast_address = IPV4Address::Broadcast(); OLA_ASSERT_EQ(string("255.255.255.255"), broadcast_address.ToString()); } /* * Test the loopback address works. */ void IPAddressTest::testLoopback() { IPV4Address loopback_address = IPV4Address::Loopback(); OLA_ASSERT_EQ(string("127.0.0.1"), loopback_address.ToString()); } ola-0.10.5.nojsmin/common/network/Socket.cpp0000644000175000017500000003176013023355232020402 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Socket.cpp * Implementation of the UDP Socket classes * Copyright (C) 2005 Simon Newton */ #include "ola/network/Socket.h" #include #include #include #include #include #include #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #ifdef _WIN32 #include #include #include #include #else #include #endif // _WIN32 #ifdef HAVE_SYS_SOCKET_H #include #endif // HAVE_SYS_SOCKET_H #ifdef HAVE_NETINET_IN_H #include #endif // HAVE_NETINET_IN_H #include #include "common/network/SocketHelper.h" #include "ola/Logging.h" #include "ola/network/NetworkUtils.h" #include "ola/network/TCPSocketFactory.h" namespace ola { namespace network { namespace { bool ReceiveFrom(int fd, uint8_t *buffer, ssize_t *data_read, struct sockaddr_in *source, socklen_t *src_size) { *data_read = recvfrom( fd, reinterpret_cast(buffer), *data_read, 0, reinterpret_cast(source), source ? src_size : NULL); if (*data_read < 0) { #ifdef _WIN32 OLA_WARN << "recvfrom fd: " << fd << " failed: " << WSAGetLastError(); #else OLA_WARN << "recvfrom fd: " << fd << " failed: " << strerror(errno); #endif // _WIN32 return false; } return true; } } // namespace // UDPSocket // ------------------------------------------------ bool UDPSocket::Init() { if (m_handle != ola::io::INVALID_DESCRIPTOR) return false; int sd = socket(PF_INET, SOCK_DGRAM, 0); if (sd < 0) { OLA_WARN << "Could not create socket " << strerror(errno); return false; } #ifdef _WIN32 m_handle.m_handle.m_fd = sd; m_handle.m_type = ola::io::SOCKET_DESCRIPTOR; // Set socket to nonblocking to enable WSAEventSelect u_long mode = 1; ioctlsocket(sd, FIONBIO, &mode); #else m_handle = sd; #endif // _WIN32 return true; } bool UDPSocket::Bind(const IPV4SocketAddress &endpoint) { if (m_handle == ola::io::INVALID_DESCRIPTOR) return false; struct sockaddr server_address; if (!endpoint.ToSockAddr(&server_address, sizeof(server_address))) return false; #if HAVE_DECL_SO_REUSEADDR int reuse_addr_flag = 1; int addr_ok = setsockopt(m_handle, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&reuse_addr_flag), sizeof(reuse_addr_flag)); if (addr_ok < 0) { OLA_WARN << "can't set SO_REUSEADDR for " << m_handle << ", " << strerror(errno); return false; } #endif // HAVE_DECL_SO_REUSEADDR #if HAVE_DECL_SO_REUSEPORT // turn on REUSEPORT if we can int reuse_port_flag = 1; int ok = setsockopt(m_handle, SOL_SOCKET, SO_REUSEPORT, reinterpret_cast(&reuse_port_flag), sizeof(reuse_port_flag)); if (ok < 0) { OLA_WARN << "can't set SO_REUSEPORT for " << m_handle << ", " << strerror(errno); // This is non fatal, since Linux introduced this option in the 3.9 series. } #endif // HAVE_DECL_SO_REUSEPORT OLA_DEBUG << "Binding to " << endpoint; #ifdef _WIN32 if (bind(m_handle.m_handle.m_fd, &server_address, sizeof(server_address)) == -1) { #else if (bind(m_handle, &server_address, sizeof(server_address)) == -1) { #endif // _WIN32 OLA_WARN << "bind(" << endpoint << "): " << strerror(errno); return false; } m_bound_to_port = true; return true; } bool UDPSocket::GetSocketAddress(IPV4SocketAddress *address) const { #ifdef _WIN32 GenericSocketAddress addr = GetLocalAddress(m_handle.m_handle.m_fd); #else GenericSocketAddress addr = GetLocalAddress(m_handle); #endif // _WIN32 if (!addr.IsValid()) { return false; } *address = addr.V4Addr(); return true; } bool UDPSocket::Close() { if (m_handle == ola::io::INVALID_DESCRIPTOR) return false; #ifdef _WIN32 int fd = m_handle.m_handle.m_fd; #else int fd = m_handle; #endif // _WIN32 m_handle = ola::io::INVALID_DESCRIPTOR; m_bound_to_port = false; #ifdef _WIN32 if (closesocket(fd)) { #else if (close(fd)) { #endif // _WIN32 OLA_WARN << "close() failed, " << strerror(errno); return false; } return true; } ssize_t UDPSocket::SendTo(const uint8_t *buffer, unsigned int size, const IPV4Address &ip, unsigned short port) const { return SendTo(buffer, size, IPV4SocketAddress(ip, port)); } ssize_t UDPSocket::SendTo(const uint8_t *buffer, unsigned int size, const IPV4SocketAddress &dest) const { if (!ValidWriteDescriptor()) return 0; struct sockaddr_in destination; if (!dest.ToSockAddr(reinterpret_cast(&destination), sizeof(destination))) { return 0; } ssize_t bytes_sent = sendto( #ifdef _WIN32 m_handle.m_handle.m_fd, #else m_handle, #endif // _WIN32 reinterpret_cast(buffer), size, 0, reinterpret_cast(&destination), sizeof(struct sockaddr)); if (bytes_sent < 0 || static_cast(bytes_sent) != size) OLA_INFO << "sendto failed: " << dest << " : " << strerror(errno); return bytes_sent; } ssize_t UDPSocket::SendTo(ola::io::IOVecInterface *data, const IPV4Address &ip, unsigned short port) const { return SendTo(data, IPV4SocketAddress(ip, port)); } ssize_t UDPSocket::SendTo(ola::io::IOVecInterface *data, const IPV4SocketAddress &dest) const { if (!ValidWriteDescriptor()) return 0; struct sockaddr_in destination; if (!dest.ToSockAddr(reinterpret_cast(&destination), sizeof(destination))) { return 0; } int io_len; const struct ola::io::IOVec *iov = data->AsIOVec(&io_len); if (iov == NULL) return 0; #ifdef _WIN32 ssize_t bytes_sent = 0; for (int buffer = 0; buffer < io_len; ++buffer) { bytes_sent += SendTo(reinterpret_cast(iov[buffer].iov_base), iov[buffer].iov_len, dest); } #else struct msghdr message; message.msg_name = &destination; message.msg_namelen = sizeof(destination); message.msg_iov = reinterpret_cast(const_cast(iov)); message.msg_iovlen = io_len; message.msg_control = NULL; message.msg_controllen = 0; message.msg_flags = 0; ssize_t bytes_sent = sendmsg(WriteDescriptor(), &message, 0); #endif // _WIN32 data->FreeIOVec(iov); if (bytes_sent < 0) { OLA_INFO << "Failed to send on " << WriteDescriptor() << ": to " << dest << " : " << strerror(errno); } else { data->Pop(bytes_sent); } return bytes_sent; } bool UDPSocket::RecvFrom(uint8_t *buffer, ssize_t *data_read) const { socklen_t length = 0; #ifdef _WIN32 return ReceiveFrom(m_handle.m_handle.m_fd, buffer, data_read, NULL, &length); #else return ReceiveFrom(m_handle, buffer, data_read, NULL, &length); #endif // _WIN32 } bool UDPSocket::RecvFrom( uint8_t *buffer, ssize_t *data_read, IPV4Address &source) const { // NOLINT(runtime/references) struct sockaddr_in src_sockaddr; socklen_t src_size = sizeof(src_sockaddr); #ifdef _WIN32 bool ok = ReceiveFrom(m_handle.m_handle.m_fd, buffer, data_read, &src_sockaddr, &src_size); #else bool ok = ReceiveFrom(m_handle, buffer, data_read, &src_sockaddr, &src_size); #endif // _WIN32 if (ok) source = IPV4Address(src_sockaddr.sin_addr.s_addr); return ok; } bool UDPSocket::RecvFrom(uint8_t *buffer, ssize_t *data_read, IPV4Address &source, // NOLINT(runtime/references) uint16_t &port) const { // NOLINT(runtime/references) struct sockaddr_in src_sockaddr; socklen_t src_size = sizeof(src_sockaddr); #ifdef _WIN32 bool ok = ReceiveFrom(m_handle.m_handle.m_fd, buffer, data_read, &src_sockaddr, &src_size); #else bool ok = ReceiveFrom(m_handle, buffer, data_read, &src_sockaddr, &src_size); #endif // _WIN32 if (ok) { source = IPV4Address(src_sockaddr.sin_addr.s_addr); port = NetworkToHost(src_sockaddr.sin_port); } return ok; } bool UDPSocket::RecvFrom(uint8_t *buffer, ssize_t *data_read, IPV4SocketAddress *source) { struct sockaddr_in src_sockaddr; socklen_t src_size = sizeof(src_sockaddr); #ifdef _WIN32 bool ok = ReceiveFrom(m_handle.m_handle.m_fd, buffer, data_read, &src_sockaddr, &src_size); #else bool ok = ReceiveFrom(m_handle, buffer, data_read, &src_sockaddr, &src_size); #endif // _WIN32 if (ok) { *source = IPV4SocketAddress(IPV4Address(src_sockaddr.sin_addr.s_addr), NetworkToHost(src_sockaddr.sin_port)); } return ok; } bool UDPSocket::EnableBroadcast() { if (m_handle == ola::io::INVALID_DESCRIPTOR) return false; int broadcast_flag = 1; #ifdef _WIN32 int ok = setsockopt(m_handle.m_handle.m_fd, #else int ok = setsockopt(m_handle, #endif // _WIN32 SOL_SOCKET, SO_BROADCAST, reinterpret_cast(&broadcast_flag), sizeof(broadcast_flag)); if (ok == -1) { OLA_WARN << "Failed to enable broadcasting: " << strerror(errno); return false; } return true; } bool UDPSocket::SetMulticastInterface(const IPV4Address &iface) { struct in_addr addr; addr.s_addr = iface.AsInt(); #ifdef _WIN32 int ok = setsockopt(m_handle.m_handle.m_fd, #else int ok = setsockopt(m_handle, #endif // _WIN32 IPPROTO_IP, IP_MULTICAST_IF, reinterpret_cast(&addr), sizeof(addr)); if (ok < 0) { OLA_WARN << "Failed to set outgoing multicast interface to " << iface << ": " << strerror(errno); return false; } return true; } bool UDPSocket::JoinMulticast(const IPV4Address &iface, const IPV4Address &group, bool multicast_loop) { char loop = multicast_loop; struct ip_mreq mreq; mreq.imr_interface.s_addr = iface.AsInt(); mreq.imr_multiaddr.s_addr = group.AsInt(); #ifdef _WIN32 int ok = setsockopt(m_handle.m_handle.m_fd, #else int ok = setsockopt(m_handle, #endif // _WIN32 IPPROTO_IP, IP_ADD_MEMBERSHIP, reinterpret_cast(&mreq), sizeof(mreq)); if (ok < 0) { OLA_WARN << "Failed to join multicast group " << group << ": " << strerror(errno); return false; } if (!multicast_loop) { #ifdef _WIN32 ok = setsockopt(m_handle.m_handle.m_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)); #else ok = setsockopt(m_handle, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)); #endif // _WIN32 if (ok < 0) { OLA_WARN << "Failed to disable looping for " << m_handle << ":" << strerror(errno); return false; } } return true; } bool UDPSocket::LeaveMulticast(const IPV4Address &iface, const IPV4Address &group) { struct ip_mreq mreq; mreq.imr_interface.s_addr = iface.AsInt(); mreq.imr_multiaddr.s_addr = group.AsInt(); #ifdef _WIN32 int ok = setsockopt(m_handle.m_handle.m_fd, #else int ok = setsockopt(m_handle, #endif // _WIN32 IPPROTO_IP, IP_DROP_MEMBERSHIP, reinterpret_cast(&mreq), sizeof(mreq)); if (ok < 0) { OLA_WARN << "Failed to leave multicast group " << group << ": " << strerror(errno); return false; } return true; } bool UDPSocket::SetTos(uint8_t tos) { unsigned int value = tos & 0xFC; // zero the ECN fields #ifdef _WIN32 int ok = setsockopt(m_handle.m_handle.m_fd, #else int ok = setsockopt(m_handle, #endif // _WIN32 IPPROTO_IP, IP_TOS, reinterpret_cast(&value), sizeof(value)); if (ok < 0) { OLA_WARN << "Failed to set tos for " << m_handle << ", " << strerror(errno); return false; } return true; } } // namespace network } // namespace ola ola-0.10.5.nojsmin/common/network/FakeInterfacePicker.h0000644000175000017500000000323513023355232022440 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * FakeInterfacePicker.h * A fake interface picker * Copyright (C) 2005 Simon Newton */ #ifndef COMMON_NETWORK_FAKEINTERFACEPICKER_H_ #define COMMON_NETWORK_FAKEINTERFACEPICKER_H_ #include #include "ola/Logging.h" #include "ola/network/InterfacePicker.h" namespace ola { namespace network { /* * The InterfacePicker for dummy systems and testing */ class FakeInterfacePicker: public InterfacePicker { public: explicit FakeInterfacePicker(const std::vector &interfaces) : InterfacePicker(), m_interfaces(interfaces) { } std::vector GetInterfaces(bool include_loopback) const { if (include_loopback) { return m_interfaces; } else { // Todo(Peter): Filter out loopback interfaces return m_interfaces; } } private: const std::vector m_interfaces; }; } // namespace network } // namespace ola #endif // COMMON_NETWORK_FAKEINTERFACEPICKER_H_ ola-0.10.5.nojsmin/common/network/AdvancedTCPConnectorTest.cpp0000644000175000017500000003202613023355232023735 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * AdvancedTCPConnectorTest.cpp * Test fixture for the TCPConnector class * Copyright (C) 2012 Simon Newton */ #include #include #include #include #include #include "ola/Callback.h" #include "ola/Clock.h" #include "ola/Logging.h" #include "ola/io/SelectServer.h" #include "ola/network/AdvancedTCPConnector.h" #include "ola/network/IPV4Address.h" #include "ola/network/NetworkUtils.h" #include "ola/network/SocketAddress.h" #include "ola/network/Socket.h" #include "ola/network/TCPSocketFactory.h" #include "ola/testing/TestUtils.h" using ola::ExponentialBackoffPolicy; using ola::LinearBackoffPolicy; using ola::TimeInterval; using ola::io::SelectServer; using ola::network::AdvancedTCPConnector; using ola::network::GenericSocketAddress; using ola::network::IPV4Address; using ola::network::IPV4SocketAddress; using ola::network::TCPAcceptingSocket; using ola::network::TCPSocket; using std::auto_ptr; using std::string; // used to set a timeout which aborts the tests static const int CONNECT_TIMEOUT_IN_MS = 500; static const int ABORT_TIMEOUT_IN_MS = 2000; class AdvancedTCPConnectorTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(AdvancedTCPConnectorTest); CPPUNIT_TEST(testConnect); CPPUNIT_TEST(testPause); CPPUNIT_TEST(testBackoff); CPPUNIT_TEST(testEarlyDestruction); CPPUNIT_TEST_SUITE_END(); public: AdvancedTCPConnectorTest() : CppUnit::TestFixture(), m_localhost(IPV4Address::Loopback()), m_server_address(m_localhost, 0) { } void setUp(); void tearDown(); void testConnect(); void testPause(); void testBackoff(); void testEarlyDestruction(); // timing out indicates something went wrong void Timeout() { OLA_FAIL("timeout"); } // Socket close actions void TerminateOnClose() { m_ss->Terminate(); } private: ola::MockClock m_clock; SelectServer *m_ss; auto_ptr m_tcp_socket_factory; IPV4Address m_localhost; IPV4SocketAddress m_server_address; ola::thread::timeout_id m_timeout_id; TCPSocket *m_connected_socket; void ConfirmState(const ola::testing::SourceLine &source_line, const AdvancedTCPConnector &connector, const IPV4SocketAddress &endpoint, AdvancedTCPConnector::ConnectionState state, unsigned int failed_attempts); void SetupListeningSocket(TCPAcceptingSocket *socket); uint16_t ReservePort(); void AcceptedConnection(TCPSocket *socket); void OnConnect(TCPSocket *socket); }; CPPUNIT_TEST_SUITE_REGISTRATION(AdvancedTCPConnectorTest); /* * Setup the select server */ void AdvancedTCPConnectorTest::setUp() { m_tcp_socket_factory.reset(new ola::network::TCPSocketFactory( ola::NewCallback(this, &AdvancedTCPConnectorTest::OnConnect))); m_connected_socket = NULL; m_ss = new SelectServer(NULL, &m_clock); m_timeout_id = m_ss->RegisterSingleTimeout( ABORT_TIMEOUT_IN_MS, ola::NewSingleCallback(this, &AdvancedTCPConnectorTest::Timeout)); OLA_ASSERT_TRUE(m_timeout_id); #if _WIN32 WSADATA wsa_data; int result = WSAStartup(MAKEWORD(2, 0), &wsa_data); OLA_ASSERT_EQ(result, 0); #endif // _WIN32 } /* * Cleanup the select server */ void AdvancedTCPConnectorTest::tearDown() { delete m_ss; #ifdef _WIN32 WSACleanup(); #endif // _WIN32 } /* * Test that a TCP Connect works. */ void AdvancedTCPConnectorTest::testConnect() { ola::network::TCPSocketFactory socket_factory( ola::NewCallback(this, &AdvancedTCPConnectorTest::AcceptedConnection)); TCPAcceptingSocket listening_socket(&socket_factory); SetupListeningSocket(&listening_socket); AdvancedTCPConnector connector( m_ss, m_tcp_socket_factory.get(), TimeInterval(0, CONNECT_TIMEOUT_IN_MS * 1000)); // 5 per attempt, up to a max of 30 LinearBackoffPolicy policy(TimeInterval(5, 0), TimeInterval(30, 0)); connector.AddEndpoint(m_server_address, &policy); OLA_ASSERT_EQ(1u, connector.EndpointCount()); // The socket may be connected immediately depending on the platform. AdvancedTCPConnector::ConnectionState state; unsigned int failed_attempts; connector.GetEndpointState(m_server_address, &state, &failed_attempts); if (state == AdvancedTCPConnector::DISCONNECTED) { m_ss->Run(); } OLA_ASSERT_EQ(1u, connector.EndpointCount()); // confirm the status is correct ConfirmState(OLA_SOURCELINE(), connector, m_server_address, AdvancedTCPConnector::CONNECTED, 0); // check our socket exists OLA_ASSERT_TRUE(m_connected_socket); m_connected_socket->Close(); delete m_connected_socket; connector.Disconnect(m_server_address, true); // state should be updated ConfirmState(OLA_SOURCELINE(), connector, m_server_address, AdvancedTCPConnector::PAUSED, 0); // remove & shutdown connector.RemoveEndpoint(m_server_address); OLA_ASSERT_EQ(0u, connector.EndpointCount()); m_ss->RemoveReadDescriptor(&listening_socket); } /** * Test that pausing a connection works. */ void AdvancedTCPConnectorTest::testPause() { ola::network::TCPSocketFactory socket_factory( ola::NewCallback(this, &AdvancedTCPConnectorTest::AcceptedConnection)); TCPAcceptingSocket listening_socket(&socket_factory); SetupListeningSocket(&listening_socket); AdvancedTCPConnector connector( m_ss, m_tcp_socket_factory.get(), TimeInterval(0, CONNECT_TIMEOUT_IN_MS * 1000)); // 5 per attempt, up to a max of 30 LinearBackoffPolicy policy(TimeInterval(5, 0), TimeInterval(30, 0)); // add endpoint, but make sure it's paused connector.AddEndpoint(m_server_address, &policy, true); OLA_ASSERT_EQ(1u, connector.EndpointCount()); ConfirmState(OLA_SOURCELINE(), connector, m_server_address, AdvancedTCPConnector::PAUSED, 0); m_ss->RunOnce(TimeInterval(0, 500000)); // now unpause connector.Resume(m_server_address); // The socket may be connected immediately depending on the platform. AdvancedTCPConnector::ConnectionState state; unsigned int failed_attempts; connector.GetEndpointState(m_server_address, &state, &failed_attempts); if (state == AdvancedTCPConnector::DISCONNECTED) { m_ss->Run(); } OLA_ASSERT_EQ(1u, connector.EndpointCount()); ConfirmState(OLA_SOURCELINE(), connector, m_server_address, AdvancedTCPConnector::CONNECTED, 0); // check our socket exists OLA_ASSERT_TRUE(m_connected_socket); m_connected_socket->Close(); delete m_connected_socket; connector.Disconnect(m_server_address, true); // state should be updated ConfirmState(OLA_SOURCELINE(), connector, m_server_address, AdvancedTCPConnector::PAUSED, 0); // clean up connector.RemoveEndpoint(m_server_address); OLA_ASSERT_EQ(0u, connector.EndpointCount()); m_ss->RemoveReadDescriptor(&listening_socket); } /** * Test that backoff works. * This is quite brittle and should be fixed at some stage. */ void AdvancedTCPConnectorTest::testBackoff() { uint16_t port = ReservePort(); OLA_ASSERT_NE(0, port); IPV4SocketAddress target(m_localhost, port); // we advance the clock so remove the timeout closure m_ss->RemoveTimeout(m_timeout_id); m_timeout_id = ola::thread::INVALID_TIMEOUT; AdvancedTCPConnector connector( m_ss, m_tcp_socket_factory.get(), TimeInterval(0, CONNECT_TIMEOUT_IN_MS * 1000)); // 5s per attempt, up to a max of 30 LinearBackoffPolicy policy(TimeInterval(5, 0), TimeInterval(30, 0)); connector.AddEndpoint(target, &policy); OLA_ASSERT_EQ(1u, connector.EndpointCount()); // failed_attempts may be 0 or 1, depending on the platform. AdvancedTCPConnector::ConnectionState state; unsigned int failed_attempts; connector.GetEndpointState(target, &state, &failed_attempts); OLA_ASSERT_EQ(AdvancedTCPConnector::DISCONNECTED, state); OLA_ASSERT_TRUE(failed_attempts == 0 || failed_attempts == 1); // the timeout is 500ms, so we advance by 490 and set a 200ms timeout m_clock.AdvanceTime(0, 490000); m_ss->RunOnce(TimeInterval(0, 200000)); // should have one failure at this point ConfirmState(OLA_SOURCELINE(), connector, target, AdvancedTCPConnector::DISCONNECTED, 1); // the next attempt should be in 5 seconds m_clock.AdvanceTime(4, 900000); m_ss->RunOnce(TimeInterval(1, 0)); // wait for the timeout m_clock.AdvanceTime(0, 490000); m_ss->RunOnce(TimeInterval(0, 200000)); ConfirmState(OLA_SOURCELINE(), connector, target, AdvancedTCPConnector::DISCONNECTED, 2); // run once more to clean up m_ss->RunOnce(TimeInterval(0, 10000)); // clean up connector.RemoveEndpoint(target); OLA_ASSERT_EQ(0u, connector.EndpointCount()); } /* * Test that we don't leak memory when the AdvancedTCPConnector is destored * while a connecting is pending. */ void AdvancedTCPConnectorTest::testEarlyDestruction() { uint16_t port = ReservePort(); OLA_ASSERT_NE(0, port); IPV4SocketAddress target(m_localhost, port); // 5 per attempt, up to a max of 30 LinearBackoffPolicy policy(TimeInterval(5, 0), TimeInterval(30, 0)); { AdvancedTCPConnector connector( m_ss, m_tcp_socket_factory.get(), TimeInterval(0, CONNECT_TIMEOUT_IN_MS * 1000)); connector.AddEndpoint(target, &policy); OLA_ASSERT_EQ(1u, connector.EndpointCount()); } } /** * Confirm the state & failed attempts matches what we expected */ void AdvancedTCPConnectorTest::ConfirmState( const ola::testing::SourceLine &source_line, const AdvancedTCPConnector &connector, const IPV4SocketAddress &endpoint, AdvancedTCPConnector::ConnectionState expected_state, unsigned int expected_attempts) { AdvancedTCPConnector::ConnectionState state; unsigned int failed_attempts; ola::testing::_FailIf( source_line, !connector.GetEndpointState(endpoint, &state, &failed_attempts), "Incorrect endpoint state"); ola::testing::_AssertEquals(source_line, expected_state, state, "States differ"); ola::testing::_AssertEquals(source_line, expected_attempts, failed_attempts, "Attempts differ"); } /** * Setup a TCP socket that accepts connections */ void AdvancedTCPConnectorTest::SetupListeningSocket( TCPAcceptingSocket *listening_socket) { IPV4SocketAddress listen_address(m_localhost, 0); OLA_ASSERT_TRUE_MSG(listening_socket->Listen(listen_address), "Failed to listen"); // calling listen a second time should fail OLA_ASSERT_FALSE(listening_socket->Listen(listen_address)); GenericSocketAddress addr = listening_socket->GetLocalAddress(); OLA_ASSERT_TRUE(addr.IsValid()); m_server_address = addr.V4Addr(); OLA_INFO << "listening on " << m_server_address; OLA_ASSERT_TRUE(m_ss->AddReadDescriptor(listening_socket)); } /** * For certain tests we need to ensure there isn't something listening on a TCP * port. The best way I've come up with doing this is to bind to port 0, then * close the socket. REUSE_ADDR means that the port shouldn't be allocated * again for a while. */ uint16_t AdvancedTCPConnectorTest::ReservePort() { TCPAcceptingSocket listening_socket(NULL); IPV4SocketAddress listen_address(m_localhost, 0); OLA_ASSERT_TRUE_MSG(listening_socket.Listen(listen_address), "Failed to listen"); GenericSocketAddress addr = listening_socket.GetLocalAddress(); OLA_ASSERT_TRUE(addr.IsValid()); return addr.V4Addr().Port(); } /* * Accept a new TCP connection. */ void AdvancedTCPConnectorTest::AcceptedConnection(TCPSocket *new_socket) { OLA_ASSERT_NOT_NULL(new_socket); GenericSocketAddress address = new_socket->GetPeerAddress(); OLA_ASSERT_TRUE(address.Family() == AF_INET); OLA_INFO << "Connection from " << address; // terminate the ss when this connection is closed new_socket->SetOnClose( ola::NewSingleCallback(this, &AdvancedTCPConnectorTest::TerminateOnClose)); m_ss->AddReadDescriptor(new_socket, true); } /* * Called when a connection completes or times out. */ void AdvancedTCPConnectorTest::OnConnect(TCPSocket *socket) { OLA_ASSERT_NOT_NULL(socket); GenericSocketAddress address = socket->GetPeerAddress(); OLA_ASSERT_TRUE(address.Family() == AF_INET); OLA_ASSERT_EQ(m_localhost, address.V4Addr().Host()); m_connected_socket = socket; m_ss->Terminate(); } ola-0.10.5.nojsmin/common/network/SocketAddressTest.cpp0000644000175000017500000001046113023355232022543 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SocketAddressTest.cpp * Test fixture for the SocketAddress class * Copyright (C) 2012 Simon Newton */ #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #ifdef HAVE_ARPA_INET_H #include #endif // HAVE_ARPA_INET_H #ifdef HAVE_NETINET_IN_H #include // Required by FreeBSD #endif // HAVE_NETINET_IN_H #include #include #include "ola/network/IPV4Address.h" #include "ola/network/NetworkUtils.h" #include "ola/network/SocketAddress.h" #include "ola/testing/TestUtils.h" using ola::network::IPV4Address; using ola::network::IPV4SocketAddress; using std::string; class SocketAddressTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(SocketAddressTest); CPPUNIT_TEST(testIPV4SocketAddress); CPPUNIT_TEST(testIPV4SocketAddressFromString); CPPUNIT_TEST_SUITE_END(); public: void testIPV4SocketAddress(); void testIPV4SocketAddressFromString(); }; CPPUNIT_TEST_SUITE_REGISTRATION(SocketAddressTest); /* * Test the IPV4 SocketAddress class works */ void SocketAddressTest::testIPV4SocketAddress() { IPV4Address ip_address; OLA_ASSERT_TRUE(IPV4Address::FromString("192.168.1.1", &ip_address)); IPV4SocketAddress socket_address(ip_address, 8080); OLA_ASSERT_EQ(ip_address, socket_address.Host()); OLA_ASSERT_EQ(static_cast(8080), socket_address.Port()); struct sockaddr sock_addr; OLA_ASSERT_FALSE(socket_address.ToSockAddr(&sock_addr, 0)); OLA_ASSERT_TRUE(socket_address.ToSockAddr(&sock_addr, sizeof(sock_addr))); OLA_ASSERT_EQ(static_cast(AF_INET), static_cast(sock_addr.sa_family)); struct sockaddr_in *sock_addr_in = reinterpret_cast(&sock_addr); OLA_ASSERT_EQ(ola::network::HostToNetwork(static_cast(8080)), sock_addr_in->sin_port); IPV4Address actual_ip(sock_addr_in->sin_addr.s_addr); OLA_ASSERT_EQ(ip_address, actual_ip); // test comparison operators IPV4SocketAddress socket_address2(ip_address, 8079); IPV4SocketAddress socket_address3(ip_address, 8081); IPV4Address ip_address2; OLA_ASSERT_TRUE(IPV4Address::FromString("182.168.1.2", &ip_address2)); IPV4SocketAddress socket_address4(ip_address2, 8080); OLA_ASSERT_EQ(socket_address, socket_address); OLA_ASSERT_NE(socket_address, socket_address2); OLA_ASSERT_NE(socket_address, socket_address3); OLA_ASSERT_LT(socket_address2, socket_address); OLA_ASSERT_LT(socket_address, socket_address3); OLA_ASSERT_LT(socket_address4, socket_address); OLA_ASSERT_LT(socket_address4, socket_address3); OLA_ASSERT_GT(socket_address, socket_address2); OLA_ASSERT_GT(socket_address3, socket_address); OLA_ASSERT_GT(socket_address, socket_address4); OLA_ASSERT_GT(socket_address3, socket_address4); // test assignment & copy constructor IPV4SocketAddress copy_address(socket_address); socket_address4 = socket_address; OLA_ASSERT_EQ(socket_address, copy_address); OLA_ASSERT_EQ(socket_address, socket_address4); } /** * Test that FromString() works */ void SocketAddressTest::testIPV4SocketAddressFromString() { IPV4SocketAddress socket_address; OLA_ASSERT_TRUE( IPV4SocketAddress::FromString("127.0.0.1:80", &socket_address)); OLA_ASSERT_EQ(string("127.0.0.1"), socket_address.Host().ToString()); OLA_ASSERT_EQ(static_cast(80), socket_address.Port()); OLA_ASSERT_FALSE( IPV4SocketAddress::FromString("127.0.0.1", &socket_address)); OLA_ASSERT_FALSE(IPV4SocketAddress::FromString("foo", &socket_address)); OLA_ASSERT_FALSE(IPV4SocketAddress::FromString(":80", &socket_address)); } ola-0.10.5.nojsmin/common/network/SocketTest.cpp0000644000175000017500000003544613023355232021247 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SocketTest.cpp * Test fixture for the Socket classes * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include "ola/Callback.h" #include "ola/Logging.h" #include "ola/io/Descriptor.h" #include "ola/io/IOQueue.h" #include "ola/io/SelectServer.h" #include "ola/network/IPV4Address.h" #include "ola/network/NetworkUtils.h" #include "ola/network/Socket.h" #include "ola/network/TCPSocketFactory.h" #include "ola/testing/TestUtils.h" using ola::io::ConnectedDescriptor; using ola::io::IOQueue; using ola::io::SelectServer; using ola::network::IPV4Address; using ola::network::GenericSocketAddress; using ola::network::IPV4SocketAddress; using ola::network::TCPAcceptingSocket; using ola::network::TCPSocket; using ola::network::UDPSocket; using std::string; static const unsigned char test_cstring[] = "Foo"; // used to set a timeout which aborts the tests static const int ABORT_TIMEOUT_IN_MS = 1000; class SocketTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(SocketTest); CPPUNIT_TEST(testTCPSocketClientClose); CPPUNIT_TEST(testTCPSocketServerClose); CPPUNIT_TEST(testUDPSocket); CPPUNIT_TEST(testIOQueueUDPSend); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void tearDown(); void testTCPSocketClientClose(); void testTCPSocketServerClose(); void testUDPSocket(); void testIOQueueUDPSend(); // timing out indicates something went wrong void Timeout() { OLA_FAIL("timeout"); m_timeout_closure = NULL; } // Socket data actions void ReceiveAndClose(ConnectedDescriptor *socket); void ReceiveAndTerminate(ConnectedDescriptor *socket); void Receive(ConnectedDescriptor *socket); void ReceiveAndSend(ConnectedDescriptor *socket); void ReceiveSendAndClose(ConnectedDescriptor *socket); void NewConnectionSend(TCPSocket *socket); void NewConnectionSendAndClose(TCPSocket *socket); void UDPReceiveAndTerminate(UDPSocket *socket); void UDPReceiveAndSend(UDPSocket *socket); // Socket close actions void TerminateOnClose() { m_ss->Terminate(); } private: SelectServer *m_ss; ola::SingleUseCallback0 *m_timeout_closure; void SocketClientClose(ConnectedDescriptor *socket, ConnectedDescriptor *socket2); void SocketServerClose(ConnectedDescriptor *socket, ConnectedDescriptor *socket2); }; CPPUNIT_TEST_SUITE_REGISTRATION(SocketTest); /* * Setup the select server */ void SocketTest::setUp() { m_ss = new SelectServer(); m_timeout_closure = ola::NewSingleCallback(this, &SocketTest::Timeout); OLA_ASSERT_TRUE(m_ss->RegisterSingleTimeout(ABORT_TIMEOUT_IN_MS, m_timeout_closure)); #if _WIN32 WSADATA wsa_data; int result = WSAStartup(MAKEWORD(2, 0), &wsa_data); OLA_ASSERT_EQ(result, 0); #endif // _WIN32 } /* * Cleanup the select server */ void SocketTest::tearDown() { delete m_ss; #ifdef _WIN32 WSACleanup(); #endif // _WIN32 } /* * Test TCP sockets work correctly. * The client connects and the server sends some data. The client checks the * data matches and then closes the connection. */ void SocketTest::testTCPSocketClientClose() { IPV4SocketAddress socket_address(IPV4Address::Loopback(), 0); ola::network::TCPSocketFactory socket_factory( ola::NewCallback(this, &SocketTest::NewConnectionSend)); TCPAcceptingSocket socket(&socket_factory); OLA_ASSERT_TRUE_MSG(socket.Listen(socket_address), "Check for another instance of olad running"); OLA_ASSERT_FALSE(socket.Listen(socket_address)); GenericSocketAddress local_address = socket.GetLocalAddress(); OLA_ASSERT_EQ(static_cast(AF_INET), local_address.Family()); OLA_ASSERT_TRUE(m_ss->AddReadDescriptor(&socket)); TCPSocket *client_socket = TCPSocket::Connect(local_address); OLA_ASSERT_NOT_NULL(client_socket); client_socket->SetOnData(ola::NewCallback( this, &SocketTest::ReceiveAndClose, static_cast(client_socket))); OLA_ASSERT_TRUE(m_ss->AddReadDescriptor(client_socket)); m_ss->Run(); m_ss->RemoveReadDescriptor(&socket); m_ss->RemoveReadDescriptor(client_socket); delete client_socket; } /* * Test TCP sockets work correctly. * The client connects and the server then sends some data and closes the * connection. */ void SocketTest::testTCPSocketServerClose() { IPV4SocketAddress socket_address(IPV4Address::Loopback(), 0); ola::network::TCPSocketFactory socket_factory( ola::NewCallback(this, &SocketTest::NewConnectionSendAndClose)); TCPAcceptingSocket socket(&socket_factory); OLA_ASSERT_TRUE_MSG(socket.Listen(socket_address), "Check for another instance of olad running"); OLA_ASSERT_FALSE(socket.Listen(socket_address)); GenericSocketAddress local_address = socket.GetLocalAddress(); OLA_ASSERT_EQ(static_cast(AF_INET), local_address.Family()); OLA_ASSERT_TRUE(m_ss->AddReadDescriptor(&socket)); // The client socket checks the response and terminates on close TCPSocket *client_socket = TCPSocket::Connect(local_address); OLA_ASSERT_NOT_NULL(client_socket); client_socket->SetOnData(ola::NewCallback( this, &SocketTest::Receive, static_cast(client_socket))); client_socket->SetOnClose( ola::NewSingleCallback(this, &SocketTest::TerminateOnClose)); OLA_ASSERT_TRUE(m_ss->AddReadDescriptor(client_socket)); m_ss->Run(); m_ss->RemoveReadDescriptor(&socket); m_ss->RemoveReadDescriptor(client_socket); delete client_socket; } /* * Test UDP sockets work correctly. * The client connects and the server sends some data. The client checks the * data matches and then closes the connection. */ void SocketTest::testUDPSocket() { IPV4SocketAddress socket_address(IPV4Address::Loopback(), 0); UDPSocket socket; OLA_ASSERT_TRUE(socket.Init()); OLA_ASSERT_FALSE(socket.Init()); OLA_ASSERT_TRUE(socket.Bind(socket_address)); OLA_ASSERT_FALSE(socket.Bind(socket_address)); IPV4SocketAddress local_address; OLA_ASSERT_TRUE(socket.GetSocketAddress(&local_address)); OLA_ASSERT_EQ(static_cast(AF_INET), local_address.Family()); socket.SetOnData( ola::NewCallback(this, &SocketTest::UDPReceiveAndSend, &socket)); OLA_ASSERT_TRUE(m_ss->AddReadDescriptor(&socket)); UDPSocket client_socket; OLA_ASSERT_TRUE(client_socket.Init()); OLA_ASSERT_FALSE(client_socket.Init()); client_socket.SetOnData( ola::NewCallback( this, &SocketTest::UDPReceiveAndTerminate, static_cast(&client_socket))); OLA_ASSERT_TRUE(m_ss->AddReadDescriptor(&client_socket)); ssize_t bytes_sent = client_socket.SendTo( static_cast(test_cstring), sizeof(test_cstring), local_address); OLA_ASSERT_EQ(static_cast(sizeof(test_cstring)), bytes_sent); m_ss->Run(); m_ss->RemoveReadDescriptor(&socket); m_ss->RemoveReadDescriptor(&client_socket); } /* * Test UDP sockets with an IOQueue work correctly. * The client connects and the server sends some data. The client checks the * data matches and then closes the connection. */ void SocketTest::testIOQueueUDPSend() { IPV4SocketAddress socket_address(IPV4Address::Loopback(), 9010); UDPSocket socket; OLA_ASSERT_TRUE(socket.Init()); OLA_ASSERT_FALSE(socket.Init()); OLA_ASSERT_TRUE(socket.Bind(socket_address)); OLA_ASSERT_FALSE(socket.Bind(socket_address)); socket.SetOnData( ola::NewCallback(this, &SocketTest::UDPReceiveAndSend, &socket)); OLA_ASSERT_TRUE(m_ss->AddReadDescriptor(&socket)); UDPSocket client_socket; OLA_ASSERT_TRUE(client_socket.Init()); OLA_ASSERT_FALSE(client_socket.Init()); client_socket.SetOnData( ola::NewCallback( this, &SocketTest::UDPReceiveAndTerminate, static_cast(&client_socket))); OLA_ASSERT_TRUE(m_ss->AddReadDescriptor(&client_socket)); IOQueue output; output.Write(static_cast(test_cstring), sizeof(test_cstring)); ssize_t bytes_sent = client_socket.SendTo(&output, socket_address); OLA_ASSERT_EQ(static_cast(sizeof(test_cstring)), bytes_sent); m_ss->Run(); m_ss->RemoveReadDescriptor(&socket); m_ss->RemoveReadDescriptor(&client_socket); } /* * Receive some data and close the socket */ void SocketTest::ReceiveAndClose(ConnectedDescriptor *socket) { Receive(socket); m_ss->RemoveReadDescriptor(socket); socket->Close(); } /* * Receive some data and terminate */ void SocketTest::ReceiveAndTerminate(ConnectedDescriptor *socket) { Receive(socket); m_ss->Terminate(); } /* * Receive some data and check it's what we expected. */ void SocketTest::Receive(ConnectedDescriptor *socket) { // try to read more than what we sent to test non-blocking uint8_t buffer[sizeof(test_cstring) + 10]; unsigned int data_read; OLA_ASSERT_FALSE(socket->Receive(buffer, sizeof(buffer), data_read)); OLA_ASSERT_EQ(static_cast(sizeof(test_cstring)), data_read); OLA_ASSERT_EQ(0, memcmp(test_cstring, buffer, data_read)); } /* * Receive some data and send it back */ void SocketTest::ReceiveAndSend(ConnectedDescriptor *socket) { uint8_t buffer[sizeof(test_cstring) + 10]; unsigned int data_read; socket->Receive(buffer, sizeof(buffer), data_read); OLA_ASSERT_EQ(static_cast(sizeof(test_cstring)), data_read); ssize_t bytes_sent = socket->Send(buffer, data_read); OLA_ASSERT_EQ(static_cast(sizeof(test_cstring)), bytes_sent); } /* * Receive some data, send the same data and close */ void SocketTest::ReceiveSendAndClose(ConnectedDescriptor *socket) { ReceiveAndSend(socket); m_ss->RemoveReadDescriptor(socket); socket->Close(); } /* * Accept a new connection and send some test data */ void SocketTest::NewConnectionSend(TCPSocket *new_socket) { OLA_ASSERT_TRUE(new_socket); GenericSocketAddress address = new_socket->GetPeerAddress(); OLA_ASSERT_TRUE(address.Family() == AF_INET); OLA_INFO << "Connection from " << address; ssize_t bytes_sent = new_socket->Send( static_cast(test_cstring), sizeof(test_cstring)); OLA_ASSERT_EQ(static_cast(sizeof(test_cstring)), bytes_sent); new_socket->SetOnClose(ola::NewSingleCallback(this, &SocketTest::TerminateOnClose)); m_ss->AddReadDescriptor(new_socket, true); } /* * Accept a new connect, send some data and close */ void SocketTest::NewConnectionSendAndClose(TCPSocket *new_socket) { OLA_ASSERT_NOT_NULL(new_socket); GenericSocketAddress address = new_socket->GetPeerAddress(); OLA_ASSERT_TRUE(address.Family() == AF_INET); OLA_INFO << "Connection from " << address; ssize_t bytes_sent = new_socket->Send( static_cast(test_cstring), sizeof(test_cstring)); OLA_ASSERT_EQ(static_cast(sizeof(test_cstring)), bytes_sent); new_socket->Close(); delete new_socket; } /* * Receive some data and check it. */ void SocketTest::UDPReceiveAndTerminate(UDPSocket *socket) { IPV4Address expected_address; OLA_ASSERT_TRUE(IPV4Address::FromString("127.0.0.1", &expected_address)); IPV4SocketAddress source; uint8_t buffer[sizeof(test_cstring) + 10]; ssize_t data_read = sizeof(buffer); socket->RecvFrom(buffer, &data_read, &source); OLA_ASSERT_EQ(static_cast(sizeof(test_cstring)), data_read); OLA_ASSERT_EQ(expected_address, source.Host()); m_ss->Terminate(); } /* * Receive some data and echo it back. */ void SocketTest::UDPReceiveAndSend(UDPSocket *socket) { IPV4Address expected_address; OLA_ASSERT_TRUE(IPV4Address::FromString("127.0.0.1", &expected_address)); IPV4SocketAddress source; uint8_t buffer[sizeof(test_cstring) + 10]; ssize_t data_read = sizeof(buffer); socket->RecvFrom(buffer, &data_read, &source); OLA_ASSERT_EQ(static_cast(sizeof(test_cstring)), data_read); OLA_ASSERT_EQ(expected_address, source.Host()); ssize_t data_sent = socket->SendTo(buffer, data_read, source); OLA_ASSERT_EQ(data_read, data_sent); } /** * Generic method to test client initiated close */ void SocketTest::SocketClientClose(ConnectedDescriptor *socket, ConnectedDescriptor *socket2) { OLA_ASSERT_NOT_NULL(socket); socket->SetOnData( ola::NewCallback(this, &SocketTest::ReceiveAndClose, static_cast(socket))); OLA_ASSERT_TRUE(m_ss->AddReadDescriptor(socket)); OLA_ASSERT_NOT_NULL(socket2); socket2->SetOnData( ola::NewCallback(this, &SocketTest::ReceiveAndSend, static_cast(socket2))); socket2->SetOnClose(ola::NewSingleCallback(this, &SocketTest::TerminateOnClose)); OLA_ASSERT_TRUE(m_ss->AddReadDescriptor(socket2)); ssize_t bytes_sent = socket->Send( static_cast(test_cstring), sizeof(test_cstring)); OLA_ASSERT_EQ(static_cast(sizeof(test_cstring)), bytes_sent); m_ss->Run(); m_ss->RemoveReadDescriptor(socket); m_ss->RemoveReadDescriptor(socket2); delete socket2; } /** * Generic method to test server initiated close */ void SocketTest::SocketServerClose(ConnectedDescriptor *socket, ConnectedDescriptor *socket2) { OLA_ASSERT_NOT_NULL(socket); socket->SetOnData(ola::NewCallback( this, &SocketTest::Receive, static_cast(socket))); socket->SetOnClose( ola::NewSingleCallback(this, &SocketTest::TerminateOnClose)); OLA_ASSERT_TRUE(m_ss->AddReadDescriptor(socket)); OLA_ASSERT_TRUE(socket2); socket2->SetOnData(ola::NewCallback( this, &SocketTest::ReceiveSendAndClose, static_cast(socket2))); OLA_ASSERT_TRUE(m_ss->AddReadDescriptor(socket2)); ssize_t bytes_sent = socket->Send( static_cast(test_cstring), sizeof(test_cstring)); OLA_ASSERT_EQ(static_cast(sizeof(test_cstring)), bytes_sent); m_ss->Run(); m_ss->RemoveReadDescriptor(socket); m_ss->RemoveReadDescriptor(socket2); delete socket2; } ola-0.10.5.nojsmin/common/network/InterfacePicker.cpp0000644000175000017500000001014313023355232022200 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * InterfacePicker.cpp * Chooses an interface to listen on * Copyright (C) 2005 Simon Newton */ #include #include #include #include "ola/Logging.h" #include "ola/network/InterfacePicker.h" #include "ola/network/NetworkUtils.h" #ifdef _WIN32 #include "common/network/WindowsInterfacePicker.h" #else #include "common/network/PosixInterfacePicker.h" #endif // _WIN32 namespace ola { namespace network { using std::string; using std::vector; /* * Select an interface to use * @param iface, the interface to populate * @param ip_or_name the IP address or interface name of the local interface * we'd prefer to use. * @param options a Options struct configuring ChooseInterface * @return true if we found an interface, false otherwise */ // TODO(Simon): Change these to callback based code to reduce duplication. bool InterfacePicker::ChooseInterface( Interface *iface, const string &ip_or_name, const Options &options) const { bool found = false; vector interfaces = GetInterfaces(options.include_loopback); if (interfaces.empty()) { OLA_INFO << "No interfaces found"; return false; } vector::const_iterator iter; if (!ip_or_name.empty()) { IPV4Address wanted_ip; if (IPV4Address::FromString(ip_or_name, &wanted_ip)) { // search by IP for (iter = interfaces.begin(); iter != interfaces.end(); ++iter) { if (iter->ip_address == wanted_ip) { *iface = *iter; found = true; break; } } } else { // search by interface name for (iter = interfaces.begin(); iter != interfaces.end(); ++iter) { if (iter->name == ip_or_name) { *iface = *iter; found = true; break; } } } } if (!found && options.specific_only) return false; // No match and being fussy if (!found) *iface = interfaces[0]; OLA_DEBUG << "Using interface " << iface->name << " (" << iface->ip_address << ")"; return true; } /* * Select an interface to use by index * @param iface, the interface to populate * @param index the index of the local interface we'd prefer to use. * @param options a Options struct configuring ChooseInterface * @return true if we found an interface, false otherwise */ // TODO(Simon): Change these to callback based code to reduce duplication. bool InterfacePicker::ChooseInterface( Interface *iface, int32_t index, const Options &options) const { bool found = false; vector interfaces = GetInterfaces(options.include_loopback); if (interfaces.empty()) { OLA_INFO << "No interfaces found"; return false; } vector::const_iterator iter; // search by index for (iter = interfaces.begin(); iter != interfaces.end(); ++iter) { if (iter->index == index) { *iface = *iter; found = true; break; } } if (!found && options.specific_only) return false; // No match and being fussy if (!found) *iface = interfaces[0]; OLA_DEBUG << "Using interface " << iface->name << " (" << iface->ip_address << ") with index " << iface->index; return true; } /* * Create the appropriate picker */ InterfacePicker *InterfacePicker::NewPicker() { #ifdef _WIN32 return new WindowsInterfacePicker(); #else return new PosixInterfacePicker(); #endif // _WIN32 } } // namespace network } // namespace ola ola-0.10.5.nojsmin/common/network/HealthCheckedConnection.cpp0000644000175000017500000000636213023355232023646 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * HealthCheckedConnection.cpp * Copyright (C) 2012 Simon Newton */ #include "ola/Logging.h" #include "ola/network/HealthCheckedConnection.h" #include "ola/thread/SchedulerInterface.h" namespace ola { namespace network { HealthCheckedConnection::HealthCheckedConnection( ola::thread::SchedulerInterface *scheduler, const ola::TimeInterval timeout_interval) : m_scheduler(scheduler), m_heartbeat_interval(timeout_interval), m_send_timeout_id(ola::thread::INVALID_TIMEOUT), m_receive_timeout_id(ola::thread::INVALID_TIMEOUT) { } HealthCheckedConnection::~HealthCheckedConnection() { if (m_send_timeout_id != ola::thread::INVALID_TIMEOUT) m_scheduler->RemoveTimeout(m_send_timeout_id); if (m_receive_timeout_id != ola::thread::INVALID_TIMEOUT) m_scheduler->RemoveTimeout(m_receive_timeout_id); } bool HealthCheckedConnection::Setup() { // setup the RX timeout ResumeTimer(); // send a heartbeat now and setup the TX timer SendHeartbeat(); HeartbeatSent(); return true; } /** * Reset the send timer */ void HealthCheckedConnection::HeartbeatSent() { if (m_send_timeout_id != ola::thread::INVALID_TIMEOUT) m_scheduler->RemoveTimeout(m_send_timeout_id); m_send_timeout_id = m_scheduler->RegisterRepeatingTimeout( m_heartbeat_interval, NewCallback(this, &HealthCheckedConnection::SendNextHeartbeat)); } /** * Reset the RX timer */ void HealthCheckedConnection::HeartbeatReceived() { m_scheduler->RemoveTimeout(m_receive_timeout_id); UpdateReceiveTimer(); } /** * Pause the receive timer */ void HealthCheckedConnection::PauseTimer() { if (m_receive_timeout_id != ola::thread::INVALID_TIMEOUT) { m_scheduler->RemoveTimeout(m_receive_timeout_id); m_receive_timeout_id = ola::thread::INVALID_TIMEOUT; } } /** * Resume the receive timer */ void HealthCheckedConnection::ResumeTimer() { if (m_receive_timeout_id == ola::thread::INVALID_TIMEOUT) UpdateReceiveTimer(); } bool HealthCheckedConnection::SendNextHeartbeat() { SendHeartbeat(); return true; } void HealthCheckedConnection::UpdateReceiveTimer() { TimeInterval timeout_interval(static_cast( 2.5 * m_heartbeat_interval.AsInt())); m_receive_timeout_id = m_scheduler->RegisterSingleTimeout( timeout_interval, NewSingleCallback( this, &HealthCheckedConnection::InternalHeartbeatTimeout)); } void HealthCheckedConnection::InternalHeartbeatTimeout() { m_receive_timeout_id = ola::thread::INVALID_TIMEOUT; HeartbeatTimeout(); } } // namespace network } // namespace ola ola-0.10.5.nojsmin/common/network/PosixInterfacePicker.cpp0000644000175000017500000002021113023355232023220 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * PosixInterfacePicker.cpp * Chooses an interface to listen on * Copyright (C) 2005 Simon Newton */ #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #ifdef HAVE_GETIFADDRS #ifdef HAVE_LINUX_IF_PACKET_H #include #include #include #endif // HAVE_LINUX_IF_PACKET_H #endif // HAVE_GETIFADDRS #ifdef HAVE_SYS_TYPES_H #include // Required by OpenBSD #endif // HAVE_SYS_TYPES_H #ifdef HAVE_SYS_SOCKET_H #include // order is important for FreeBSD #endif // HAVE_SYS_SOCKET_H #include #ifdef HAVE_NETINET_IN_H #include // Required by FreeBSD #endif // HAVE_NETINET_IN_H #include #include #ifdef HAVE_SOCKADDR_DL_STRUCT #include #endif // HAVE_SOCKADDR_DL_STRUCT #include #include #include #include #include #include #include "common/network/NetworkUtilsInternal.h" #include "common/network/PosixInterfacePicker.h" #include "ola/Logging.h" #include "ola/network/IPV4Address.h" #include "ola/network/MACAddress.h" #include "ola/network/NetworkUtils.h" #include "ola/network/SocketCloser.h" namespace ola { namespace network { using std::string; using std::vector; /* * Return a vector of interfaces on the system. */ vector PosixInterfacePicker::GetInterfaces( bool include_loopback) const { vector interfaces; #ifdef HAVE_SOCKADDR_DL_STRUCT string last_dl_iface_name; uint8_t hwlen = 0; char *hwaddr = NULL; #endif // HAVE_SOCKADDR_DL_STRUCT // create socket to get iface config int sd = socket(PF_INET, SOCK_DGRAM, 0); if (sd < 0) { OLA_WARN << "Could not create socket " << strerror(errno); return interfaces; } SocketCloser closer(sd); // use ioctl to get a listing of interfaces char *buffer; // holds the iface data unsigned int lastlen = 0; // the amount of data returned by the last ioctl unsigned int len = INITIAL_IFACE_COUNT; while (true) { struct ifconf ifc; ifc.ifc_len = len * sizeof(struct ifreq); buffer = new char[ifc.ifc_len]; ifc.ifc_buf = buffer; if (ioctl(sd, SIOCGIFCONF, &ifc) < 0) { if (errno != EINVAL || lastlen != 0) { OLA_WARN << "ioctl error " << strerror(errno); delete[] buffer; return interfaces; } } else { if (static_cast(ifc.ifc_len) == lastlen) { lastlen = ifc.ifc_len; break; } lastlen = ifc.ifc_len; } len += IFACE_COUNT_INC; delete[] buffer; } // loop through each iface for (char *ptr = buffer; ptr < buffer + lastlen;) { struct ifreq *iface = (struct ifreq*) ptr; ptr += GetIfReqSize(ptr); #ifdef HAVE_SOCKADDR_DL_STRUCT if (iface->ifr_addr.sa_family == AF_LINK) { struct sockaddr_dl *sdl = (struct sockaddr_dl*) &iface->ifr_addr; last_dl_iface_name.assign(sdl->sdl_data, sdl->sdl_nlen); hwaddr = sdl->sdl_data + sdl->sdl_nlen; hwlen = sdl->sdl_alen; } #endif // HAVE_SOCKADDR_DL_STRUCT // look for AF_INET interfaces only if (iface->ifr_addr.sa_family != AF_INET) { OLA_DEBUG << "Skipping " << iface->ifr_name << " because it's not af_inet"; continue; } struct ifreq ifrcopy = *iface; if (ioctl(sd, SIOCGIFFLAGS, &ifrcopy) < 0) { OLA_WARN << "ioctl error for " << iface->ifr_name << ":" << strerror(errno); continue; } if (!(ifrcopy.ifr_flags & IFF_UP)) { OLA_DEBUG << "Skipping " << iface->ifr_name << " because it's down"; continue; } Interface interface; interface.name = iface->ifr_name; if (ifrcopy.ifr_flags & IFF_LOOPBACK) { if (include_loopback) { interface.loopback = true; } else { OLA_DEBUG << "Skipping " << iface->ifr_name << " because it's a loopback"; continue; } } #ifdef HAVE_SOCKADDR_DL_STRUCT // The only way hwaddr is non-null is if HAVE_SOCKADDR_DL_STRUCT is defined. if ((interface.name == last_dl_iface_name) && hwaddr) { if (hwlen == MACAddress::LENGTH) { interface.hw_address = MACAddress(reinterpret_cast(hwaddr)); } else { OLA_WARN << "hwlen was not expected length, so didn't obtain MAC " << "address; got " << static_cast(hwlen) << ", expecting " << MACAddress::LENGTH; } } #endif // HAVE_SOCKADDR_DL_STRUCT struct sockaddr_in *sin = (struct sockaddr_in *) &iface->ifr_addr; interface.ip_address = IPV4Address(sin->sin_addr.s_addr); // fetch bcast address #ifdef SIOCGIFBRDADDR if (ifrcopy.ifr_flags & IFF_BROADCAST) { if (ioctl(sd, SIOCGIFBRDADDR, &ifrcopy) < 0) { OLA_WARN << "ioctl error " << strerror(errno); } else { sin = (struct sockaddr_in *) &ifrcopy.ifr_broadaddr; interface.bcast_address = IPV4Address(sin->sin_addr.s_addr); } } #endif // SIOCGIFBRDADDR // fetch subnet address #ifdef SIOCGIFNETMASK if (ioctl(sd, SIOCGIFNETMASK, &ifrcopy) < 0) { OLA_WARN << "ioctl error " << strerror(errno); } else { sin = (struct sockaddr_in *) &ifrcopy.ifr_broadaddr; interface.subnet_mask = IPV4Address(sin->sin_addr.s_addr); } #endif // SIOCGIFNETMASK // fetch hardware address #ifdef SIOCGIFHWADDR if (ifrcopy.ifr_flags & SIOCGIFHWADDR) { if (ioctl(sd, SIOCGIFHWADDR, &ifrcopy) < 0) { OLA_WARN << "ioctl error " << strerror(errno); } else { interface.type = ifrcopy.ifr_hwaddr.sa_family; // TODO(Peter): We probably shouldn't do this if it's not ARPHRD_ETHER interface.hw_address = MACAddress( reinterpret_cast(ifrcopy.ifr_hwaddr.sa_data)); } } #endif // SIOCGIFHWADDR // fetch index #ifdef SIOCGIFINDEX if (ifrcopy.ifr_flags & SIOCGIFINDEX) { if (ioctl(sd, SIOCGIFINDEX, &ifrcopy) < 0) { OLA_WARN << "ioctl error " << strerror(errno); } else { #ifdef __FreeBSD__ interface.index = ifrcopy.ifr_index; #else interface.index = ifrcopy.ifr_ifindex; #endif // SIOCGIFINDEX } } #elif defined(HAVE_IF_NAMETOINDEX) // fetch index on NetBSD and other platforms without SIOCGIFINDEX unsigned int index = if_nametoindex(iface->ifr_name); if (index != 0) { interface.index = index; } #endif // defined(HAVE_IF_NAMETOINDEX) /* ok, if that all failed we should prob try and use sysctl to work out the * broadcast and hardware addresses * I'll leave that for another day */ OLA_DEBUG << "Found: " << interface.name << ", " << interface.ip_address << ", " << interface.hw_address; interfaces.push_back(interface); } delete[] buffer; return interfaces; } /* * Return the size of an ifreq structure in a cross platform manner. * @param data a pointer to an ifreq structure * @return the size of the ifreq structure */ unsigned int PosixInterfacePicker::GetIfReqSize(const char *data) const { const struct ifreq *iface = (struct ifreq*) data; unsigned int socket_len = SockAddrLen(iface->ifr_addr); // We can't assume sizeof(ifreq) = IFNAMSIZ + sizeof(sockaddr), this isn't // the case on some 64bit linux systems. if (socket_len > sizeof(struct ifreq) - IFNAMSIZ) { return IFNAMSIZ + socket_len; } else { return sizeof(struct ifreq); } } } // namespace network } // namespace ola ola-0.10.5.nojsmin/common/network/WindowsInterfacePicker.h0000644000175000017500000000245213023355232023224 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * WindowsInterfacePicker.h * Choose an interface to listen on * Copyright (C) 2005 Simon Newton */ #ifndef COMMON_NETWORK_WINDOWSINTERFACEPICKER_H_ #define COMMON_NETWORK_WINDOWSINTERFACEPICKER_H_ #include #include "ola/network/InterfacePicker.h" namespace ola { namespace network { /* * The InterfacePicker for windows */ class WindowsInterfacePicker: public InterfacePicker { public: std::vector GetInterfaces(bool include_loopback) const; }; } // namespace network } // namespace ola #endif // COMMON_NETWORK_WINDOWSINTERFACEPICKER_H_ ola-0.10.5.nojsmin/common/network/NetworkUtilsInternal.h0000644000175000017500000000263713023355232022767 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * NetworkUtilsInternal.h * Abstract various network functions. * Copyright (C) 2005 Simon Newton */ #ifndef COMMON_NETWORK_NETWORKUTILSINTERNAL_H_ #define COMMON_NETWORK_NETWORKUTILSINTERNAL_H_ #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #ifdef HAVE_WINSOCK2_H #define VC_EXTRALEAN #include #endif // HAVE_WINSOCK2_H #ifdef HAVE_ARPA_INET_H #include #endif // HAVE_ARPA_INET_H #include namespace ola { namespace network { /** * Return the length of a sockaddr */ unsigned int SockAddrLen(const struct sockaddr &sa); } // namespace network } // namespace ola #endif // COMMON_NETWORK_NETWORKUTILSINTERNAL_H_ ola-0.10.5.nojsmin/common/network/TCPSocket.cpp0000644000175000017500000001755413023355232020756 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * TCPSocket.cpp * Implementation of the TCP Socket classes * Copyright (C) 2005 Simon Newton */ #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #include /* FreeBSD needs types.h before tcp.h */ #include #ifndef _WIN32 #include #endif // !_WIN32 #include #include #include #ifdef _WIN32 #include #include #include #else #include #endif // _WIN32 #ifdef HAVE_ARPA_INET_H #include #endif // HAVE_ARPA_INET_H #ifdef HAVE_NETINET_IN_H #include // Required by FreeBSD #endif // HAVE_NETINET_IN_H #include #include "common/network/SocketHelper.h" #include "ola/Logging.h" #include "ola/io/Descriptor.h" #include "ola/network/NetworkUtils.h" #include "ola/network/Socket.h" #include "ola/network/SocketCloser.h" #include "ola/network/TCPSocketFactory.h" namespace ola { namespace network { // TCPSocket // ------------------------------------------------ /** * Get the remote IPAddress and port for this socket */ GenericSocketAddress TCPSocket::GetPeerAddress() const { #ifdef _WIN32 return ola::network::GetPeerAddress(m_handle.m_handle.m_fd); #else return ola::network::GetPeerAddress(m_handle); #endif // _WIN32 } GenericSocketAddress TCPSocket::GetLocalAddress() const { #ifdef _WIN32 return ola::network::GetLocalAddress(m_handle.m_handle.m_fd); #else return ola::network::GetLocalAddress(m_handle); #endif // _WIN32 } TCPSocket::TCPSocket(int sd) { #ifdef _WIN32 m_handle.m_handle.m_fd = sd; m_handle.m_type = ola::io::SOCKET_DESCRIPTOR; #else m_handle = sd; #endif // _WIN32 SetNoSigPipe(m_handle); } /* * Close this TCPSocket */ bool TCPSocket::Close() { if (m_handle != ola::io::INVALID_DESCRIPTOR) { #ifdef _WIN32 closesocket(m_handle.m_handle.m_fd); #else close(m_handle); #endif // _WIN32 m_handle = ola::io::INVALID_DESCRIPTOR; } return true; } /* * Set the TCP_NODELAY option */ bool TCPSocket::SetNoDelay() { int flag = 1; #ifdef _WIN32 int sd = m_handle.m_handle.m_fd; #else int sd = m_handle; #endif // _WIN32 int result = setsockopt(sd, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&flag), sizeof(flag)); if (result < 0) { OLA_WARN << "Can't set TCP_NODELAY for " << sd << ", " << strerror(errno); return false; } return true; } /* * Connect * @param ip_address the IP to connect to * @param port the port to connect to * @param blocking whether to block on connect or not */ TCPSocket* TCPSocket::Connect(const SocketAddress &endpoint) { struct sockaddr server_address; if (!endpoint.ToSockAddr(&server_address, sizeof(server_address))) return NULL; int sd = socket(endpoint.Family(), SOCK_STREAM, 0); if (sd < 0) { OLA_WARN << "socket() failed, " << strerror(errno); return NULL; } SocketCloser closer(sd); int r = connect(sd, &server_address, sizeof(server_address)); if (r) { OLA_WARN << "connect(" << endpoint << "): " << strerror(errno); return NULL; } TCPSocket *socket = new TCPSocket(closer.Release()); socket->SetReadNonBlocking(); return socket; } // TCPAcceptingSocket // ------------------------------------------------ /* * Create a new TCPListeningSocket */ TCPAcceptingSocket::TCPAcceptingSocket(TCPSocketFactoryInterface *factory) : ReadFileDescriptor(), m_handle(ola::io::INVALID_DESCRIPTOR), m_factory(factory) { } /** * Clean up */ TCPAcceptingSocket::~TCPAcceptingSocket() { Close(); } /* * Start listening * @param endpoint the SocketAddress to listen on * @param backlog the backlog * @return true if it succeeded, false otherwise */ bool TCPAcceptingSocket::Listen(const SocketAddress &endpoint, int backlog) { struct sockaddr server_address; int reuse_flag = 1; if (m_handle != ola::io::INVALID_DESCRIPTOR) return false; if (!endpoint.ToSockAddr(&server_address, sizeof(server_address))) return false; int sd = socket(endpoint.Family(), SOCK_STREAM, 0); if (sd < 0) { OLA_WARN << "socket() failed: " << strerror(errno); return false; } SocketCloser closer(sd); #ifdef _WIN32 ola::io::DescriptorHandle temp_handle; temp_handle.m_handle.m_fd = sd; temp_handle.m_type = ola::io::SOCKET_DESCRIPTOR; if (!ola::io::ConnectedDescriptor::SetNonBlocking(temp_handle)) { #else if (!ola::io::ConnectedDescriptor::SetNonBlocking(sd)) { #endif // _WIN32 OLA_WARN << "Failed to mark TCP accept socket as non-blocking"; return false; } int ok = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&reuse_flag), sizeof(reuse_flag)); if (ok < 0) { OLA_WARN << "can't set reuse for " << sd << ", " << strerror(errno); return false; } if (bind(sd, &server_address, sizeof(server_address)) == -1) { OLA_WARN << "bind to " << endpoint << " failed, " << strerror(errno); return false; } if (listen(sd, backlog)) { OLA_WARN << "listen on " << endpoint << " failed, " << strerror(errno); return false; } #ifdef _WIN32 m_handle.m_handle.m_fd = closer.Release(); m_handle.m_type = ola::io::SOCKET_DESCRIPTOR; #else m_handle = closer.Release(); #endif // _WIN32 return true; } /* * Stop listening & close this socket * @return true if close succeeded, false otherwise */ bool TCPAcceptingSocket::Close() { bool ret = true; if (m_handle != ola::io::INVALID_DESCRIPTOR) { #ifdef _WIN32 if (closesocket(m_handle.m_handle.m_fd)) { #else if (close(m_handle)) { #endif // _WIN32 OLA_WARN << "close() failed " << strerror(errno); ret = false; } } m_handle = ola::io::INVALID_DESCRIPTOR; return ret; } /* * Accept new connections * @return a new connected socket */ void TCPAcceptingSocket::PerformRead() { if (m_handle == ola::io::INVALID_DESCRIPTOR) return; while (1) { struct sockaddr_in cli_address; socklen_t length = sizeof(cli_address); #ifdef _WIN32 int sd = accept(m_handle.m_handle.m_fd, (struct sockaddr*) &cli_address, &length); #else int sd = accept(m_handle, (struct sockaddr*) &cli_address, &length); #endif // _WIN32 if (sd < 0) { #ifdef _WIN32 if (WSAGetLastError() == WSAEWOULDBLOCK) { #else if (errno == EWOULDBLOCK) { #endif // _WIN32 return; } OLA_WARN << "accept() failed, " << strerror(errno); return; } if (m_factory) { // The callback takes ownership of the new socket descriptor // coverity[RESOURCE_LEAK] m_factory->NewTCPSocket(sd); } else { OLA_WARN << "Accepted new TCP Connection but no factory registered"; #ifdef _WIN32 closesocket(sd); #else close(sd); #endif // _WIN32 } } } /** * Get the local IPAddress and port for this socket */ GenericSocketAddress TCPAcceptingSocket::GetLocalAddress() const { #ifdef _WIN32 return ola::network::GetLocalAddress(m_handle.m_handle.m_fd); #else return ola::network::GetLocalAddress(m_handle); #endif // _WIN32 } } // namespace network } // namespace ola ola-0.10.5.nojsmin/common/network/SocketCloser.cpp0000644000175000017500000000227113023355232021545 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SocketCloser.cpp * Close a socket when the object goes out of scope. * Copyright (C) 2013 Simon Newton */ #include "ola/network/SocketCloser.h" #include #include #ifdef _WIN32 #include #endif // _WIN32 namespace ola { namespace network { SocketCloser::~SocketCloser() { if (m_fd >= 0) { #ifdef _WIN32 closesocket(m_fd); #else close(m_fd); #endif // _WIN32 } } } // namespace network } // namespace ola ola-0.10.5.nojsmin/common/network/AdvancedTCPConnector.cpp0000644000175000017500000001523313023355232023076 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * AdvancedTCPConnector.cpp * Copyright (C) 2012 Simon Newton */ #include #include #include #include #include namespace ola { namespace network { using std::pair; AdvancedTCPConnector::AdvancedTCPConnector( ola::io::SelectServerInterface *ss, TCPSocketFactoryInterface *socket_factory, const ola::TimeInterval &connection_timeout) : m_socket_factory(socket_factory), m_ss(ss), m_connector(ss), m_connection_timeout(connection_timeout) { } AdvancedTCPConnector::~AdvancedTCPConnector() { ConnectionMap::iterator iter = m_connections.begin(); for (; iter != m_connections.end(); ++iter) { AbortConnection(iter->second); delete iter->second; } m_connections.clear(); } void AdvancedTCPConnector::AddEndpoint(const IPV4SocketAddress &endpoint, BackOffPolicy *backoff_policy, bool paused) { IPPortPair key(endpoint.Host(), endpoint.Port()); ConnectionMap::iterator iter = m_connections.find(key); if (iter != m_connections.end()) return; // new ip:port ConnectionInfo *state = new ConnectionInfo; state->state = paused ? PAUSED : DISCONNECTED; state->failed_attempts = 0; state->retry_timeout = ola::thread::INVALID_TIMEOUT; state->connection_id = 0; state->policy = backoff_policy; state->reconnect = true; m_connections[key] = state; if (!paused) AttemptConnection(key, state); } void AdvancedTCPConnector::RemoveEndpoint(const IPV4SocketAddress &endpoint) { IPPortPair key(endpoint.Host(), endpoint.Port()); ConnectionMap::iterator iter = m_connections.find(key); if (iter == m_connections.end()) return; AbortConnection(iter->second); delete iter->second; m_connections.erase(iter); } bool AdvancedTCPConnector::GetEndpointState( const IPV4SocketAddress &endpoint, ConnectionState *connected, unsigned int *failed_attempts) const { IPPortPair key(endpoint.Host(), endpoint.Port()); ConnectionMap::const_iterator iter = m_connections.find(key); if (iter == m_connections.end()) return false; *connected = iter->second->state; *failed_attempts = iter->second->failed_attempts; return true; } void AdvancedTCPConnector::Disconnect(const IPV4SocketAddress &endpoint, bool pause) { IPPortPair key(endpoint.Host(), endpoint.Port()); ConnectionMap::iterator iter = m_connections.find(key); if (iter == m_connections.end()) return; if (iter->second->state != CONNECTED) return; iter->second->failed_attempts = 0; if (pause) { iter->second->state = PAUSED; } else { // schedule a retry as if this endpoint failed once iter->second->state = DISCONNECTED; iter->second->retry_timeout = m_ss->RegisterSingleTimeout( iter->second->policy->BackOffTime(1), ola::NewSingleCallback( this, &AdvancedTCPConnector::RetryTimeout, iter->first)); } } void AdvancedTCPConnector::Resume(const IPV4SocketAddress &endpoint) { IPPortPair key(endpoint.Host(), endpoint.Port()); ConnectionMap::iterator iter = m_connections.find(key); if (iter == m_connections.end()) return; if (iter->second->state == PAUSED) { iter->second->state = DISCONNECTED; AttemptConnection(iter->first, iter->second); } } /** * Schedule the re-try attempt for this connection */ void AdvancedTCPConnector::ScheduleRetry(const IPPortPair &key, ConnectionInfo *info) { info->retry_timeout = m_ss->RegisterSingleTimeout( info->policy->BackOffTime(info->failed_attempts), ola::NewSingleCallback( this, &AdvancedTCPConnector::RetryTimeout, key)); } /** * Called when it's time to retry */ void AdvancedTCPConnector::RetryTimeout(IPPortPair key) { ConnectionMap::iterator iter = m_connections.find(key); if (iter == m_connections.end()) { OLA_FATAL << "Re-connect timer expired but unable to find state entry for " << key.first << ":" << key.second; return; } iter->second->retry_timeout = ola::thread::INVALID_TIMEOUT; AttemptConnection(key, iter->second); } /** * Called by the TCPConnector when a connection is ready or it times out. */ void AdvancedTCPConnector::ConnectionResult(IPPortPair key, int fd, int) { if (fd != -1) { OLA_INFO << "TCP Connection established to " << key.first << ":" << key.second; } ConnectionMap::iterator iter = m_connections.find(key); if (iter == m_connections.end()) { OLA_FATAL << "Unable to find state for " << key.first << ":" << key.second << ", leaking sockets"; return; } ConnectionInfo *info = iter->second; info->connection_id = 0; if (fd != -1) { // ok info->state = CONNECTED; m_socket_factory->NewTCPSocket(fd); } else { // error info->failed_attempts++; if (info->reconnect) { ScheduleRetry(key, info); } } } /** * Initiate a connection to this ip:port pair */ void AdvancedTCPConnector::AttemptConnection(const IPPortPair &key, ConnectionInfo *state) { state->connection_id = m_connector.Connect( IPV4SocketAddress(key.first, key.second), m_connection_timeout, ola::NewSingleCallback(this, &AdvancedTCPConnector::ConnectionResult, key)); } /** * Abort and clean up a pending connection * @param state the ConnectionInfo to cleanup. */ void AdvancedTCPConnector::AbortConnection(ConnectionInfo *state) { if (state->connection_id) { state->reconnect = false; if (!m_connector.Cancel(state->connection_id)) OLA_WARN << "Failed to cancel connection " << state->connection_id; } if (state->retry_timeout != ola::thread::INVALID_TIMEOUT) m_ss->RemoveTimeout(state->retry_timeout); } } // namespace network } // namespace ola ola-0.10.5.nojsmin/common/network/MACAddressTest.cpp0000644000175000017500000001006013023355232021706 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * MACAddressTest.cpp * Test fixture for the MACAddress class * Copyright (C) 2013 Peter Newman */ #include #include #include #include #include #include #include "ola/network/MACAddress.h" #include "ola/network/NetworkUtils.h" #include "ola/testing/TestUtils.h" using ola::network::MACAddress; using std::auto_ptr; using std::string; using std::vector; class MACAddressTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(MACAddressTest); CPPUNIT_TEST(testMACAddress); CPPUNIT_TEST(testMACAddressToString); CPPUNIT_TEST_SUITE_END(); public: void testMACAddress(); void testMACAddressToString(); }; CPPUNIT_TEST_SUITE_REGISTRATION(MACAddressTest); /* * Test the MAC Address class works */ void MACAddressTest::testMACAddress() { uint8_t hw_address[ola::network::MACAddress::LENGTH] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab}; MACAddress address1; OLA_ASSERT_TRUE(MACAddress::FromString(string("01:23:45:67:89:ab"), &address1)); // Test Get() uint8_t addr[MACAddress::LENGTH]; address1.Get(addr); OLA_ASSERT_EQ(0, memcmp(addr, hw_address, MACAddress::LENGTH)); // test copy and assignment MACAddress address2(address1); OLA_ASSERT_EQ(address1, address2); MACAddress address3 = address1; OLA_ASSERT_EQ(address1, address3); // test stringification OLA_ASSERT_EQ(string("01:23:45:67:89:ab"), address1.ToString()); std::ostringstream str; str << address1; OLA_ASSERT_EQ(string("01:23:45:67:89:ab"), str.str()); // test from string auto_ptr string_address( MACAddress::FromString("fe:dc:ba:98:76:54")); OLA_ASSERT_NOT_NULL(string_address.get()); OLA_ASSERT_EQ(string("fe:dc:ba:98:76:54"), string_address->ToString()); auto_ptr string_address2( MACAddress::FromString("98.76.54.fe.dc.ba")); OLA_ASSERT_NOT_NULL(string_address2.get()); OLA_ASSERT_EQ(string("98:76:54:fe:dc:ba"), string_address2->ToString()); auto_ptr string_address3(MACAddress::FromString("foo")); OLA_ASSERT_NULL(string_address3.get()); // and the second form MACAddress string_address4; OLA_ASSERT_TRUE(MACAddress::FromString("67:89:ab:01:23:45", &string_address4)); OLA_ASSERT_EQ(string("67:89:ab:01:23:45"), string_address4.ToString()); // make sure sorting works vector addresses; addresses.push_back(address1); addresses.push_back(*string_address); addresses.push_back(string_address4); std::sort(addresses.begin(), addresses.end()); OLA_ASSERT_EQ(string("01:23:45:67:89:ab"), addresses[0].ToString()); OLA_ASSERT_EQ(string("67:89:ab:01:23:45"), addresses[1].ToString()); OLA_ASSERT_EQ(string("fe:dc:ba:98:76:54"), addresses[2].ToString()); // Test comparison OLA_ASSERT_TRUE(address1 < string_address4); OLA_ASSERT_TRUE(string_address4 > address1); OLA_ASSERT_TRUE(string_address4 < *string_address); OLA_ASSERT_TRUE(*string_address > string_address4); } /* * Check that MACAddress::ToString works */ void MACAddressTest::testMACAddressToString() { uint8_t hw_address[ola::network::MACAddress::LENGTH] = { 0x0, 0xa, 0xff, 0x10, 0x25, 0x4}; const string mac_address = MACAddress(hw_address).ToString(); OLA_ASSERT_EQ(string("00:0a:ff:10:25:04"), mac_address); } ola-0.10.5.nojsmin/common/network/Interface.cpp0000644000175000017500000001324713023355232021052 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Interface.cpp * Represents network interface. * Copyright (C) 2005 Simon Newton */ #ifdef HAVE_SYS_TYPES_H #include // Required by FreeBSD, order is important to OpenBSD #endif // HAVE_SYS_TYPES_H #ifdef HAVE_SYS_SOCKET_H #include // Required by FreeBSD #endif // HAVE_SYS_SOCKET_H #ifdef HAVE_NET_IF_ARP_H #include #endif // HAVE_NET_IF_ARP_H #include #include #include #include #include "ola/StringUtils.h" #include "ola/network/InterfacePicker.h" #include "ola/network/NetworkUtils.h" #ifdef _WIN32 #include "common/network/WindowsInterfacePicker.h" #else #include "common/network/PosixInterfacePicker.h" #endif // _WIN32 namespace ola { namespace network { using std::string; using std::vector; #ifdef ARPHRD_VOID const uint16_t Interface::ARP_VOID_TYPE = ARPHRD_VOID; #else const uint16_t Interface::ARP_VOID_TYPE = 0xffff; #endif // ARPHRD_VOID #ifdef ARPHRD_ETHER const uint16_t Interface::ARP_ETHERNET_TYPE = ARPHRD_ETHER; #else const uint16_t Interface::ARP_ETHERNET_TYPE = 1; #endif // ARPHRD_ETHER Interface::Interface() : loopback(false), index(DEFAULT_INDEX), type(ARP_VOID_TYPE) { } Interface::Interface(const string &name, const IPV4Address &ip_address, const IPV4Address &broadcast_address, const IPV4Address &subnet_mask, const MACAddress &hw_address, bool loopback, int32_t index, uint16_t type) : name(name), ip_address(ip_address), bcast_address(broadcast_address), subnet_mask(subnet_mask), hw_address(hw_address), loopback(loopback), index(index), type(type) { } Interface::Interface(const Interface &other) : name(other.name), ip_address(other.ip_address), bcast_address(other.bcast_address), subnet_mask(other.subnet_mask), hw_address(other.hw_address), loopback(other.loopback), index(other.index), type(other.type) { } Interface& Interface::operator=(const Interface &other) { if (this != &other) { name = other.name; ip_address = other.ip_address; bcast_address = other.bcast_address; subnet_mask = other.subnet_mask; hw_address = other.hw_address; loopback = other.loopback; index = other.index; type = other.type; } return *this; } bool Interface::operator==(const Interface &other) { return (name == other.name && ip_address == other.ip_address && subnet_mask == other.subnet_mask && loopback == other.loopback && index == other.index && type == other.type); } /** * Create a new interface builder */ InterfaceBuilder::InterfaceBuilder() : m_ip_address(0), m_broadcast_address(0), m_subnet_mask(0), m_hw_address(), m_loopback(false), m_index(Interface::DEFAULT_INDEX), m_type(Interface::ARP_VOID_TYPE) { } /** * Set the address of the interface to build. */ bool InterfaceBuilder::SetAddress(const string &ip_address) { return SetAddress(ip_address, &m_ip_address); } /** * Set the broadcast address of the interface to build. */ bool InterfaceBuilder::SetBroadcast(const string &broadcast_address) { return SetAddress(broadcast_address, &m_broadcast_address); } /** * Set the subnet mask of the interface to build. */ bool InterfaceBuilder::SetSubnetMask(const string &mask) { return SetAddress(mask, &m_subnet_mask); } /** * Set the loopback flag. */ void InterfaceBuilder::SetLoopback(bool loopback) { m_loopback = loopback; } /** * Set the index. */ void InterfaceBuilder::SetIndex(int32_t index) { m_index = index; } /** * Set the type. */ void InterfaceBuilder::SetType(uint16_t type) { m_type = type; } /** * Reset the builder object */ void InterfaceBuilder::Reset() { m_name = ""; m_ip_address = IPV4Address(0); m_broadcast_address = IPV4Address(0); m_subnet_mask = IPV4Address(0); m_hw_address = MACAddress(); m_loopback = false; m_index = Interface::DEFAULT_INDEX; m_type = Interface::ARP_VOID_TYPE; } /** * Return a new interface object. * Maybe in the future we should check that the broadcast address, ip address * and netmask are consistent. We could even infer the broadcast_address if it * isn't provided. */ Interface InterfaceBuilder::Construct() { return Interface(m_name, m_ip_address, m_broadcast_address, m_subnet_mask, m_hw_address, m_loopback, m_index, m_type); } /** * Set a IPV4Address object from a string */ bool InterfaceBuilder::SetAddress(const string &str, IPV4Address *target) { IPV4Address tmp_address; if (!IPV4Address::FromString(str, &tmp_address)) return false; *target = tmp_address; return true; } } // namespace network } // namespace ola ola-0.10.5.nojsmin/common/network/SocketHelper.cpp0000644000175000017500000000413113023355232021532 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SocketHelper.cpp * Various functions to operate on sockets. * Copyright (C) 2013 Simon Newton */ #include #include #ifdef _WIN32 #include #endif // _WIN32 #include #include #include "common/network/SocketHelper.h" namespace ola { namespace network { /** * Wrapper around getsockname(). * The caller should check IsValid() on the GenericSocketAddress before using. */ GenericSocketAddress GetLocalAddress(int sd) { struct sockaddr remote_address; socklen_t length = sizeof(remote_address); int r = getsockname(sd, &remote_address, &length); if (r) { OLA_WARN << "Failed to get peer information for fd: " << sd << ", " << strerror(errno); return GenericSocketAddress(); } return GenericSocketAddress(remote_address); } /** * Wrapper around getpeername(). * The caller should check IsValid() on the GenericSocketAddress before using. */ GenericSocketAddress GetPeerAddress(int sd) { struct sockaddr remote_address; socklen_t length = sizeof(remote_address); int r = getpeername(sd, &remote_address, &length); if (r) { OLA_WARN << "Failed to get peer information for fd: " << sd << ", " << strerror(errno); return GenericSocketAddress(); } return GenericSocketAddress(remote_address); } } // namespace network } // namespace ola ola-0.10.5.nojsmin/common/network/NetworkUtilsTest.cpp0000644000175000017500000001144113023355232022456 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * NetworkUtilsTest.cpp * Test fixture for the NetworkUtils class * Copyright (C) 2005 Simon Newton */ #include #ifdef _WIN32 #include #endif // _WIN32 #include #include #include "ola/network/NetworkUtils.h" #include "ola/Logging.h" #include "ola/testing/TestUtils.h" using ola::network::FQDN; using ola::network::DomainNameFromFQDN; using ola::network::Hostname; using ola::network::HostnameFromFQDN; using ola::network::HostToLittleEndian; using ola::network::HostToNetwork; using ola::network::IPV4Address; using ola::network::LittleEndianToHost; using ola::network::NameServers; using ola::network::DefaultRoute; using ola::network::NetworkToHost; using std::string; using std::vector; class NetworkUtilsTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(NetworkUtilsTest); CPPUNIT_TEST(testToFromNetwork); CPPUNIT_TEST(testToFromLittleEndian); CPPUNIT_TEST(testNameProcessing); CPPUNIT_TEST(testNameServers); CPPUNIT_TEST(testDefaultRoute); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void tearDown(); void testToFromNetwork(); void testToFromLittleEndian(); void testNameProcessing(); void testNameServers(); void testDefaultRoute(); }; CPPUNIT_TEST_SUITE_REGISTRATION(NetworkUtilsTest); /* * Setup networking subsystem */ void NetworkUtilsTest::setUp() { #if _WIN32 WSADATA wsa_data; int result = WSAStartup(MAKEWORD(2, 0), &wsa_data); OLA_ASSERT_EQ(result, 0); #endif // _WIN32 } /* * Cleanup the networking subsystem */ void NetworkUtilsTest::tearDown() { #ifdef _WIN32 WSACleanup(); #endif // _WIN32 } /* * Check that we can convert to/from network byte order */ void NetworkUtilsTest::testToFromNetwork() { uint8_t v1 = 10; OLA_ASSERT_EQ(v1, HostToNetwork(v1)); OLA_ASSERT_EQ(v1, NetworkToHost(HostToNetwork(v1))); uint16_t v2 = 0x0102; OLA_ASSERT_EQ(v2, NetworkToHost(HostToNetwork(v2))); uint32_t v3 = 0x01020304; OLA_ASSERT_EQ(v3, NetworkToHost(HostToNetwork(v3))); } /* * Check that we can convert to/from little endian order */ void NetworkUtilsTest::testToFromLittleEndian() { uint8_t v1 = 10; OLA_ASSERT_EQ(v1, HostToLittleEndian(v1)); OLA_ASSERT_EQ(v1, LittleEndianToHost(HostToLittleEndian(v1))); uint16_t v2 = 0x0102; OLA_ASSERT_EQ(v2, LittleEndianToHost(HostToLittleEndian(v2))); uint32_t v3 = 0x01020304; OLA_ASSERT_EQ(v3, LittleEndianToHost(HostToLittleEndian(v3))); int8_t v4 = -10; OLA_ASSERT_EQ(v4, HostToLittleEndian(v4)); OLA_ASSERT_EQ(v4, LittleEndianToHost(HostToLittleEndian(v4))); int16_t v5 = -0x0102; OLA_ASSERT_EQ(v5, LittleEndianToHost(HostToLittleEndian(v5))); int32_t v6 = -0x01020304; OLA_ASSERT_EQ(v6, LittleEndianToHost(HostToLittleEndian(v6))); } /* * Check that name processing works */ void NetworkUtilsTest::testNameProcessing() { // HostnameFromFQDN OLA_ASSERT_EQ(string(""), HostnameFromFQDN("")); OLA_ASSERT_EQ(string("foo"), HostnameFromFQDN("foo")); OLA_ASSERT_EQ(string("foo"), HostnameFromFQDN("foo.bar")); OLA_ASSERT_EQ(string("foo"), HostnameFromFQDN("foo.barbaz")); OLA_ASSERT_EQ(string("foo"), HostnameFromFQDN("foo.bar.com")); // DomainNameFromFQDN OLA_ASSERT_EQ(string(""), DomainNameFromFQDN("")); OLA_ASSERT_EQ(string(""), DomainNameFromFQDN("foo")); OLA_ASSERT_EQ(string("bar"), DomainNameFromFQDN("foo.bar")); OLA_ASSERT_EQ(string("barbaz"), DomainNameFromFQDN("foo.barbaz")); OLA_ASSERT_EQ(string("bar.com"), DomainNameFromFQDN("foo.bar.com")); // Check we were able to get the hostname OLA_ASSERT_GT(FQDN().length(), 0); OLA_ASSERT_GT(Hostname().length(), 0); } /* * Check that name server fetching returns true (it may not actually return any) */ void NetworkUtilsTest::testNameServers() { vector name_servers; OLA_ASSERT_TRUE(NameServers(&name_servers)); } /* * Check that default route fetching returns true (it may not actually return * one) */ void NetworkUtilsTest::testDefaultRoute() { int32_t if_index; IPV4Address default_gateway; OLA_ASSERT_TRUE(DefaultRoute(&if_index, &default_gateway)); } ola-0.10.5.nojsmin/common/http/0000755000175000017500000000000013155164170015732 5ustar wouterwouterola-0.10.5.nojsmin/common/http/Makefile.mk0000644000175000017500000000045513023355232017777 0ustar wouterwouter# LIBRARIES ################################################## if HAVE_LIBMICROHTTPD noinst_LTLIBRARIES += common/http/libolahttp.la common_http_libolahttp_la_SOURCES = \ common/http/HTTPServer.cpp \ common/http/OlaHTTPServer.cpp common_http_libolahttp_la_LIBADD = $(libmicrohttpd_LIBS) endif ola-0.10.5.nojsmin/common/http/OlaHTTPServer.cpp0000644000175000017500000000677613023355232021053 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * OlaHTTPServer.cpp * A HTTP Server with export map integration. * Copyright (C) 2012 Simon Newton */ #include #include #include #include #include #include namespace ola { namespace http { using ola::ExportMap; using std::auto_ptr; using std::ostringstream; using std::string; using std::vector; const char OlaHTTPServer::K_DATA_DIR_VAR[] = "http_data_dir"; const char OlaHTTPServer::K_UPTIME_VAR[] = "uptime-in-ms"; /** * Create a new OlaHTTPServer. * @param options The HTTPServerOptions options, * @param export_map the ExportMap to server */ OlaHTTPServer::OlaHTTPServer(const HTTPServer::HTTPServerOptions &options, ExportMap *export_map) : m_export_map(export_map), m_server(options) { RegisterHandler("/debug", &OlaHTTPServer::DisplayDebug); RegisterHandler("/help", &OlaHTTPServer::DisplayHandlers); StringVariable *data_dir_var = export_map->GetStringVar(K_DATA_DIR_VAR); data_dir_var->Set(m_server.DataDir()); m_clock.CurrentTime(&m_start_time); export_map->GetStringVar(K_UPTIME_VAR); } /** * Setup the OLA HTTP server * @return true if this worked, false otherwise. */ bool OlaHTTPServer::Init() { return m_server.Init(); } /** * Display the contents of the ExportMap */ int OlaHTTPServer::DisplayDebug(const HTTPRequest*, HTTPResponse *raw_response) { auto_ptr response(raw_response); ola::TimeStamp now; m_clock.CurrentTime(&now); ola::TimeInterval diff = now - m_start_time; ostringstream str; str << diff.InMilliSeconds(); m_export_map->GetStringVar(K_UPTIME_VAR)->Set(str.str()); vector variables = m_export_map->AllVariables(); response->SetContentType(HTTPServer::CONTENT_TYPE_PLAIN); vector::iterator iter; for (iter = variables.begin(); iter != variables.end(); ++iter) { ostringstream out; out << (*iter)->Name() << ": " << (*iter)->Value() << "\n"; response->Append(out.str()); } int r = response->Send(); return r; } /** * Display a list of registered handlers */ int OlaHTTPServer::DisplayHandlers(const HTTPRequest*, HTTPResponse *raw_response) { auto_ptr response(raw_response); vector handlers; m_server.Handlers(&handlers); vector::const_iterator iter; response->SetContentType(HTTPServer::CONTENT_TYPE_HTML); response->Append("Registered Handlers
    "); for (iter = handlers.begin(); iter != handlers.end(); ++iter) { response->Append("
  • " + *iter + "
  • "); } response->Append("
"); int r = response->Send(); return r; } } // namespace http } // namespace ola ola-0.10.5.nojsmin/common/http/HTTPServer.cpp0000644000175000017500000006134513023355232020410 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * HTTPServer.cpp * The base HTTP Server class. * Copyright (C) 2005 Simon Newton */ #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #include #include #include #include #include #include #include #ifdef _WIN32 #include #endif // _WIN32 #include #include #include #include #include #include #include namespace ola { namespace http { #ifdef _WIN32 class UnmanagedSocketDescriptor : public ola::io::UnmanagedFileDescriptor { public: explicit UnmanagedSocketDescriptor(int fd) : ola::io::UnmanagedFileDescriptor(fd) { m_handle.m_type = ola::io::SOCKET_DESCRIPTOR; // Set socket to nonblocking to enable WSAEventSelect u_long mode = 1; ioctlsocket(fd, FIONBIO, &mode); } private: DISALLOW_COPY_AND_ASSIGN(UnmanagedSocketDescriptor); }; #endif // _WIN32 using std::ifstream; using std::map; using std::pair; using std::set; using std::string; using std::vector; using ola::io::UnmanagedFileDescriptor; using ola::web::JsonValue; using ola::web::JsonWriter; const char HTTPServer::CONTENT_TYPE_PLAIN[] = "text/plain"; const char HTTPServer::CONTENT_TYPE_HTML[] = "text/html"; const char HTTPServer::CONTENT_TYPE_GIF[] = "image/gif"; const char HTTPServer::CONTENT_TYPE_PNG[] = "image/png"; const char HTTPServer::CONTENT_TYPE_CSS[] = "text/css"; const char HTTPServer::CONTENT_TYPE_JS[] = "text/javascript"; const char HTTPServer::CONTENT_TYPE_OCT[] = "application/octet-stream"; /** * @brief Called by MHD_get_connection_values to add headers to a request * object. * @param cls a pointer to an HTTPRequest object. * @param kind the source of the key-value pair * @param key the header name * @param value the header value */ static int AddHeaders(void *cls, OLA_UNUSED enum MHD_ValueKind kind, const char *key, const char *value) { HTTPRequest *request = static_cast(cls); string key_string = key; string value_string = value; request->AddHeader(key, value); return MHD_YES; } /** * @brief Called by MHD_create_post_processor to iterate over the post form data * @param request_cls a pointer to a HTTPRequest object * @param kind the source of the key-value pair * @param key the header name * @param filename the name of the uploaded file or NULL if unknown * @param content_type the MIME type of the data or NULL if unknown * @param transfer_encoding the encoding of the data or NULL if unknown * @param data the header value * @param off the offset of the data * @param size the number of bytes available */ int IteratePost(void *request_cls, OLA_UNUSED enum MHD_ValueKind kind, const char *key, OLA_UNUSED const char *filename, OLA_UNUSED const char *content_type, OLA_UNUSED const char *transfer_encoding, const char *data, OLA_UNUSED uint64_t off, OLA_UNUSED size_t size) { // libmicrohttpd has a bug where the size isn't set correctly. HTTPRequest *request = static_cast(request_cls); string value(data); request->AddPostParameter(key, value); return MHD_YES; } /** * @brief Called whenever a new request is made. * * This sets up HTTPRequest & HTTPResponse objects and then calls * DispatchRequest. */ static int HandleRequest(void *http_server_ptr, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **ptr) { HTTPServer *http_server = static_cast(http_server_ptr); HTTPRequest *request; // on the first call ptr is null if (*ptr == NULL) { request = new HTTPRequest(url, method, version, connection); if (!request) return MHD_NO; if (!request->Init()) { delete request; return MHD_NO; } *ptr = static_cast(request); return MHD_YES; } request = static_cast(*ptr); if (request->InFlight()) // don't dispatch more than once return MHD_YES; if (request->Method() == MHD_HTTP_METHOD_GET) { HTTPResponse *response = new HTTPResponse(connection); request->SetInFlight(); return http_server->DispatchRequest(request, response); } else if (request->Method() == MHD_HTTP_METHOD_POST) { if (*upload_data_size != 0) { request->ProcessPostData(upload_data, upload_data_size); *upload_data_size = 0; return MHD_YES; } request->SetInFlight(); HTTPResponse *response = new HTTPResponse(connection); return http_server->DispatchRequest(request, response); } return MHD_NO; } /** * @brief Called when a request completes. * * This deletes the associated HTTPRequest object. */ void RequestCompleted(void*, struct MHD_Connection*, void **request_cls, enum MHD_RequestTerminationCode) { if (!request_cls) return; delete static_cast(*request_cls); *request_cls = NULL; } /* * HTTPRequest object * Setup the header callback and the post processor if needed. */ HTTPRequest::HTTPRequest(const string &url, const string &method, const string &version, struct MHD_Connection *connection): m_url(url), m_method(method), m_version(version), m_connection(connection), m_processor(NULL), m_in_flight(false) { } /* * @brief Initialize this request * @return true if succesful, false otherwise. */ bool HTTPRequest::Init() { MHD_get_connection_values(m_connection, MHD_HEADER_KIND, AddHeaders, this); if (m_method == MHD_HTTP_METHOD_POST) { m_processor = MHD_create_post_processor(m_connection, K_POST_BUFFER_SIZE, IteratePost, static_cast(this)); return m_processor; } return true; } /* * @brief Cleanup this request object */ HTTPRequest::~HTTPRequest() { if (m_processor) MHD_destroy_post_processor(m_processor); } /** * @brief Add a header to the request object. * @param key the header name * @param value the value of the header */ void HTTPRequest::AddHeader(const string &key, const string &value) { std::pair pair(key, value); m_headers.insert(pair); } /** * @brief Add a post parameter. * * This can be called multiple times and the values will be appended. * @param key the parameter name * @param value the value */ void HTTPRequest::AddPostParameter(const string &key, const string &value) { map::iterator iter = m_post_params.find(key); if (iter == m_post_params.end()) { std::pair pair(key, value); m_post_params.insert(pair); } else { iter->second.append(value); } } /** * @brief Process post data */ void HTTPRequest::ProcessPostData(const char *data, size_t *data_size) { MHD_post_process(m_processor, data, *data_size); } /** * @brief Return the value of the header sent with this request * @param key the name of the header * @returns the value of the header or empty string if it doesn't exist. */ const string HTTPRequest::GetHeader(const string &key) const { map::const_iterator iter = m_headers.find(key); if (iter == m_headers.end()) return ""; else return iter->second; } /** * @brief Return the value of a url parameter * @param key the name of the parameter * @return the value of the parameter */ const string HTTPRequest::GetParameter(const string &key) const { const char *value = MHD_lookup_connection_value(m_connection, MHD_GET_ARGUMENT_KIND, key.c_str()); if (value) return string(value); else return string(); } /** * @brief Return whether an url parameter exists * @param key the name of the parameter * @return if the parameter exists */ bool HTTPRequest::CheckParameterExists(const string &key) const { const char *value = MHD_lookup_connection_value(m_connection, MHD_GET_ARGUMENT_KIND, key.c_str()); if (value != NULL) { return true; } else { return false; /* * TODO(Peter): try and check the "trailer" ?key, only in since Tue Jul 17 * 2012 * const char *trailer = MHD_lookup_connection_value(m_connection, * MHD_GET_ARGUMENT_KIND, * NULL); */ } } /** * @brief Lookup a post parameter in this request * @param key the name of the parameter * @return the value of the parameter or the empty string if it doesn't exist */ const string HTTPRequest::GetPostParameter(const string &key) const { map::const_iterator iter = m_post_params.find(key); if (iter == m_post_params.end()) return ""; else return iter->second; } /** * @brief Set the content-type header * @param type the content type * @return true if the header was set correctly, false otherwise */ void HTTPResponse::SetContentType(const string &type) { SetHeader(MHD_HTTP_HEADER_CONTENT_TYPE, type); } /** * @brief Set the appropriate headers so this response isn't cached */ void HTTPResponse::SetNoCache() { SetHeader(MHD_HTTP_HEADER_CACHE_CONTROL, "no-cache, must-revalidate"); } /** * @brief Set a header in the response * @param key the header name * @param value the header value * @return true if the header was set correctly, false otherwise */ void HTTPResponse::SetHeader(const string &key, const string &value) { std::pair pair(key, value); m_headers.insert(pair); } /** * @brief Send a JsonObject as the response. * @return true on success, false on error */ int HTTPResponse::SendJson(const JsonValue &json) { const string output = JsonWriter::AsString(json); struct MHD_Response *response = HTTPServer::BuildResponse( static_cast(const_cast(output.data())), output.length()); HeadersMultiMap::const_iterator iter; for (iter = m_headers.begin(); iter != m_headers.end(); ++iter) MHD_add_response_header(response, iter->first.c_str(), iter->second.c_str()); int ret = MHD_queue_response(m_connection, m_status_code, response); MHD_destroy_response(response); return ret; } /** * @brief Send the HTTP response * @return true on success, false on error */ int HTTPResponse::Send() { HeadersMultiMap::const_iterator iter; struct MHD_Response *response = HTTPServer::BuildResponse( static_cast(const_cast(m_data.data())), m_data.length()); for (iter = m_headers.begin(); iter != m_headers.end(); ++iter) MHD_add_response_header(response, iter->first.c_str(), iter->second.c_str()); int ret = MHD_queue_response(m_connection, m_status_code, response); MHD_destroy_response(response); return ret; } /** * @brief Setup the HTTP server. * @param options the configuration options for the server */ HTTPServer::HTTPServer(const HTTPServerOptions &options) : Thread(Thread::Options("http")), m_httpd(NULL), m_default_handler(NULL), m_port(options.port), m_data_dir(options.data_dir) { ola::io::SelectServer::Options ss_options; // See issue #761. epoll/kqueue can't be used with the current // implementation. ss_options.force_select = true; m_select_server.reset(new ola::io::SelectServer(ss_options)); } /** * @brief Destroy this object */ HTTPServer::~HTTPServer() { Stop(); if (m_httpd) MHD_stop_daemon(m_httpd); map::const_iterator iter; for (iter = m_handlers.begin(); iter != m_handlers.end(); ++iter) delete iter->second; if (m_default_handler) { delete m_default_handler; m_default_handler = NULL; } m_handlers.clear(); } /** * @brief Setup the HTTP server * @return true on success, false on failure */ bool HTTPServer::Init() { if (m_httpd) { OLA_INFO << "Non null pointers found, Init() was probably called twice"; return false; } m_httpd = MHD_start_daemon(MHD_NO_FLAG, m_port, NULL, NULL, &HandleRequest, this, MHD_OPTION_NOTIFY_COMPLETED, RequestCompleted, NULL, MHD_OPTION_END); if (m_httpd) { m_select_server->RunInLoop(NewCallback(this, &HTTPServer::UpdateSockets)); } return m_httpd ? true : false; } /** * @brief The entry point into the new thread */ void *HTTPServer::Run() { if (!m_httpd) { OLA_WARN << "HTTPServer::Run called but the server wasn't setup."; return NULL; } OLA_INFO << "HTTP Server started on port " << m_port; #ifdef _WIN32 // set a short poll interval since we'd block too long otherwise. // TODO(Lukas) investigate why the poller does not wake up on HTTP requests. m_select_server->SetDefaultInterval(TimeInterval(1, 0)); #else // set a long poll interval so we don't spin m_select_server->SetDefaultInterval(TimeInterval(60, 0)); #endif // _WIN32 m_select_server->Run(); // clean up any remaining sockets SocketSet::iterator iter = m_sockets.begin(); for (; iter != m_sockets.end(); ++iter) { FreeSocket(*iter); } m_sockets.clear(); return NULL; } /** * @brief Stop the HTTP server */ void HTTPServer::Stop() { if (IsRunning()) { OLA_INFO << "Notifying HTTP server thread to stop"; m_select_server->Terminate(); OLA_INFO << "Waiting for HTTP server thread to exit"; Join(); OLA_INFO << "HTTP server thread exited"; } } /** * @brief This is run every loop iteration to update the list of sockets in the * SelectServer from MHD. */ void HTTPServer::UpdateSockets() { // We always call MHD_run so we send any queued responses. This isn't // inefficient because the only thing that can wake up the select server is // activity on a http socket or the client socket. The latter almost always // results in a change to HTTP state. if (MHD_run(m_httpd) == MHD_NO) { OLA_WARN << "MHD run failed"; } fd_set r_set, w_set, e_set; int max_fd = 0; FD_ZERO(&r_set); FD_ZERO(&w_set); #ifdef MHD_SOCKET_DEFINED if (MHD_YES != MHD_get_fdset(m_httpd, &r_set, &w_set, &e_set, reinterpret_cast(&max_fd))) { #else if (MHD_YES != MHD_get_fdset(m_httpd, &r_set, &w_set, &e_set, &max_fd)) { #endif // MHD_SOCKET_DEFINED OLA_WARN << "Failed to get a list of the file descriptors for MHD"; return; } SocketSet::iterator iter = m_sockets.begin(); // This isn't the best plan, talk to the MHD devs about exposing the list of // FD in a more suitable way int i = 0; while (iter != m_sockets.end() && i <= max_fd) { DescriptorState *state = *iter; if (ola::io::ToFD(state->descriptor->ReadDescriptor()) < i) { // This socket is no longer required so remove it FreeSocket(state); m_sockets.erase(iter++); } else if (ola::io::ToFD(state->descriptor->ReadDescriptor()) == i) { // Check if this socket must be updated. if (FD_ISSET(i, &r_set) && state->read == 0) { m_select_server->AddReadDescriptor(state->descriptor); state->read = 1; } else if ((!FD_ISSET(i, &r_set)) && state->read == 1) { m_select_server->RemoveReadDescriptor(state->descriptor); state->read = 0; } if (FD_ISSET(i, &w_set) && state->write == 0) { m_select_server->AddWriteDescriptor(state->descriptor); state->write = 1; } else if ((!FD_ISSET(i, &w_set)) && state->write == 1) { m_select_server->RemoveWriteDescriptor(state->descriptor); state->write = 0; } iter++; i++; } else { // this is a new socket if (FD_ISSET(i, &r_set) || FD_ISSET(i, &w_set)) { InsertSocket(FD_ISSET(i, &r_set), FD_ISSET(i, &w_set), i); } i++; } } while (iter != m_sockets.end()) { FreeSocket(*iter); m_sockets.erase(iter++); } for (; i <= max_fd; i++) { // add the remaining sockets to the SS if (FD_ISSET(i, &r_set) || FD_ISSET(i, &w_set)) { InsertSocket(FD_ISSET(i, &r_set), FD_ISSET(i, &w_set), i); } } } /** * @brief Call the appropriate handler. */ int HTTPServer::DispatchRequest(const HTTPRequest *request, HTTPResponse *response) { map::iterator iter = m_handlers.find(request->Url()); if (iter != m_handlers.end()) return iter->second->Run(request, response); map::iterator file_iter = m_static_content.find(request->Url()); if (file_iter != m_static_content.end()) return ServeStaticContent(&(file_iter->second), response); if (m_default_handler) return m_default_handler->Run(request, response); return ServeNotFound(response); } /** * @brief Register a handler * @param path the url to respond on * @param handler the Closure to call for this request. These will be freed * once the HTTPServer is destroyed. */ bool HTTPServer::RegisterHandler(const string &path, BaseHTTPCallback *handler) { map::const_iterator iter = m_handlers.find(path); if (iter != m_handlers.end()) return false; pair pair(path, handler); m_handlers.insert(pair); return true; } /** * @brief Register a static file. The root of the URL corresponds to the data dir. * @param path the URL path for the file e.g. '/foo.png' * @param content_type the content type. */ bool HTTPServer::RegisterFile(const std::string &path, const std::string &content_type) { if (path.empty() || path[0] != '/') { OLA_WARN << "Invalid static file: " << path; return false; } return RegisterFile(path, path.substr(1), content_type); } /** * @brief Register a static file * @param path the path to serve on e.g. /foo.png * @param file the path to the file to serve relative to the data dir e.g. * images/foo.png * @param content_type the content type. */ bool HTTPServer::RegisterFile(const std::string &path, const std::string &file, const std::string &content_type) { map::const_iterator file_iter = ( m_static_content.find(path)); if (file_iter != m_static_content.end()) return false; static_file_info file_info; file_info.file_path = file; file_info.content_type = content_type; pair pair(path, file_info); m_static_content.insert(pair); return true; } /** * @brief Set the default handler. * @param handler the default handler to call. This will be freed when the * HTTPServer is destroyed. */ void HTTPServer::RegisterDefaultHandler(BaseHTTPCallback *handler) { m_default_handler = handler; } /** * @brief Return a list of all handlers registered */ void HTTPServer::Handlers(vector *handlers) const { map::const_iterator iter; for (iter = m_handlers.begin(); iter != m_handlers.end(); ++iter) handlers->push_back(iter->first); map::const_iterator file_iter; for (file_iter = m_static_content.begin(); file_iter != m_static_content.end(); ++file_iter) handlers->push_back(file_iter->first); } /** * @brief Serve an error. * @param response the reponse to use. * @param details the error description */ int HTTPServer::ServeError(HTTPResponse *response, const string &details) { response->SetStatus(MHD_HTTP_INTERNAL_SERVER_ERROR); response->SetContentType(CONTENT_TYPE_HTML); response->Append("500 Server Error"); if (!details.empty()) { response->Append("

"); response->Append(details); response->Append("

"); } int r = response->Send(); delete response; return r; } /** * @brief Serve a 404 * @param response the response to use */ int HTTPServer::ServeNotFound(HTTPResponse *response) { response->SetStatus(MHD_HTTP_NOT_FOUND); response->SetContentType(CONTENT_TYPE_HTML); response->Append("404 Not Found"); int r = response->Send(); delete response; return r; } /** * @brief Serve a redirect * @param response the response to use * @param location the location to redirect to */ int HTTPServer::ServeRedirect(HTTPResponse *response, const string &location) { response->SetStatus(MHD_HTTP_FOUND); response->SetContentType(CONTENT_TYPE_HTML); response->SetHeader(MHD_HTTP_HEADER_LOCATION, location); response->Append("302 Found See " + location); int r = response->Send(); delete response; return r; } /** * @brief Return the contents of a file */ int HTTPServer::ServeStaticContent(const std::string &path, const std::string &content_type, HTTPResponse *response) { static_file_info file_info; file_info.file_path = path; file_info.content_type = content_type; return ServeStaticContent(&file_info, response); } /** * @brief Serve static content. * @param file_info details on the file to server * @param response the response to use */ int HTTPServer::ServeStaticContent(static_file_info *file_info, HTTPResponse *response) { char *data; unsigned int length; string file_path = m_data_dir; file_path.push_back(ola::file::PATH_SEPARATOR); file_path.append(file_info->file_path); ifstream i_stream(file_path.c_str(), ifstream::binary); if (!i_stream.is_open()) { OLA_WARN << "Missing file: " << file_path; return ServeNotFound(response); } i_stream.seekg(0, std::ios::end); length = i_stream.tellg(); i_stream.seekg(0, std::ios::beg); data = static_cast(malloc(length)); i_stream.read(data, length); i_stream.close(); struct MHD_Response *mhd_response = BuildResponse(static_cast(data), length); if (!file_info->content_type.empty()) MHD_add_response_header(mhd_response, MHD_HTTP_HEADER_CONTENT_TYPE, file_info->content_type.c_str()); int ret = MHD_queue_response(response->Connection(), MHD_HTTP_OK, mhd_response); MHD_destroy_response(mhd_response); delete response; return ret; } void HTTPServer::InsertSocket(bool is_readable, bool is_writeable, int fd) { #ifdef _WIN32 UnmanagedSocketDescriptor *socket = new UnmanagedSocketDescriptor(fd); #else UnmanagedFileDescriptor *socket = new UnmanagedFileDescriptor(fd); #endif // _WIN32 socket->SetOnData(NewCallback(this, &HTTPServer::HandleHTTPIO)); socket->SetOnWritable(NewCallback(this, &HTTPServer::HandleHTTPIO)); DescriptorState *state = new DescriptorState(socket); if (is_readable) { m_select_server->AddReadDescriptor(state->descriptor); state->read = 1; } if (is_writeable) { state->write = 1; m_select_server->AddWriteDescriptor(state->descriptor); } m_sockets.insert(state); } void HTTPServer::FreeSocket(DescriptorState *state) { if (state->read) { m_select_server->RemoveReadDescriptor(state->descriptor); } if (state->write) { m_select_server->RemoveWriteDescriptor(state->descriptor); } delete state->descriptor; delete state; } struct MHD_Response *HTTPServer::BuildResponse(void *data, size_t size) { #ifdef HAVE_MHD_CREATE_RESPONSE_FROM_BUFFER return MHD_create_response_from_buffer(size, data, MHD_RESPMEM_MUST_COPY); #else return MHD_create_response_from_data(size, data, MHD_NO, MHD_YES); #endif // HAVE_MHD_CREATE_RESPONSE_FROM_BUFFER } } // namespace http } // namespace ola ola-0.10.5.nojsmin/common/utils/0000755000175000017500000000000013155164170016113 5ustar wouterwouterola-0.10.5.nojsmin/common/utils/Makefile.mk0000644000175000017500000000162213023355232020155 0ustar wouterwouter# LIBRARIES ################################################ common_libolacommon_la_SOURCES += \ common/utils/ActionQueue.cpp \ common/utils/Clock.cpp \ common/utils/DmxBuffer.cpp \ common/utils/StringUtils.cpp \ common/utils/TokenBucket.cpp \ common/utils/Watchdog.cpp # TESTS ################################################ test_programs += common/utils/UtilsTester common_utils_UtilsTester_SOURCES = \ common/utils/ActionQueueTest.cpp \ common/utils/BackoffTest.cpp \ common/utils/CallbackTest.cpp \ common/utils/ClockTest.cpp \ common/utils/DmxBufferTest.cpp \ common/utils/MultiCallbackTest.cpp \ common/utils/StringUtilsTest.cpp \ common/utils/TokenBucketTest.cpp \ common/utils/UtilsTest.cpp \ common/utils/WatchdogTest.cpp common_utils_UtilsTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_utils_UtilsTester_LDADD = $(COMMON_TESTING_LIBS) ola-0.10.5.nojsmin/common/utils/MultiCallbackTest.cpp0000644000175000017500000000565113023355232022170 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * MultiCallbackTest.cpp * Unittest for MultiCallback class * Copyright (C) 2011 Simon Newton */ #include #include #include "ola/Callback.h" #include "ola/MultiCallback.h" #include "ola/testing/TestUtils.h" using std::string; class MultiCallbackTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(MultiCallbackTest); CPPUNIT_TEST(testMultiCallback); CPPUNIT_TEST(testZeroLimit); CPPUNIT_TEST(testSingleLimit); CPPUNIT_TEST_SUITE_END(); public: void testMultiCallback(); void testZeroLimit(); void testSingleLimit(); void CallbackMethod() { m_callback_count++; } void setUp() { m_callback_count = 0; } private: int m_callback_count; }; CPPUNIT_TEST_SUITE_REGISTRATION(MultiCallbackTest); using ola::BaseCallback0; using ola::NewSingleCallback; using ola::NewMultiCallback; /** * Test the MultiCallback class. */ void MultiCallbackTest::testMultiCallback() { BaseCallback0 *callback = NewSingleCallback( this, &MultiCallbackTest::CallbackMethod); OLA_ASSERT_EQ(0, m_callback_count); BaseCallback0 *multi_callback = NewMultiCallback(3, callback); OLA_ASSERT_EQ(0, m_callback_count); multi_callback->Run(); OLA_ASSERT_EQ(0, m_callback_count); multi_callback->Run(); OLA_ASSERT_EQ(0, m_callback_count); multi_callback->Run(); OLA_ASSERT_EQ(1, m_callback_count); } /** * Test the MultiCallback works with a 0 limit */ void MultiCallbackTest::testZeroLimit() { BaseCallback0 *callback = NewSingleCallback( this, &MultiCallbackTest::CallbackMethod); OLA_ASSERT_EQ(0, m_callback_count); BaseCallback0 *multi_callback = NewMultiCallback(0, callback); OLA_ASSERT_EQ(1, m_callback_count); (void) multi_callback; } /** * Test the MultiCallback works with a single limit */ void MultiCallbackTest::testSingleLimit() { BaseCallback0 *callback = NewSingleCallback( this, &MultiCallbackTest::CallbackMethod); OLA_ASSERT_EQ(0, m_callback_count); BaseCallback0 *multi_callback = NewMultiCallback(1, callback); OLA_ASSERT_EQ(0, m_callback_count); multi_callback->Run(); OLA_ASSERT_EQ(1, m_callback_count); } ola-0.10.5.nojsmin/common/utils/CallbackTest.cpp0000644000175000017500000004060513023355232021153 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * CallbackTest.cpp * Unittest for the autogen'ed Callback code * Copyright (C) 2005 Simon Newton */ #include #include #include "ola/Callback.h" #include "ola/testing/TestUtils.h" using std::string; class CallbackTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(CallbackTest); CPPUNIT_TEST(testFunctionCallbacks); CPPUNIT_TEST(testMethodCallbacks); CPPUNIT_TEST(testFunctionCallbacks1); CPPUNIT_TEST(testMethodCallbacks1); CPPUNIT_TEST(testMethodCallbacks2); CPPUNIT_TEST_SUITE_END(); public: void testFunctionCallbacks(); void testMethodCallbacks(); void testFunctionCallbacks1(); void testMethodCallbacks1(); void testMethodCallbacks2(); void testMethodCallbacks4(); void Method0() {} bool BoolMethod0() { return true; } void Method1(unsigned int i) { OLA_ASSERT_EQ(TEST_INT_VALUE, i); } bool BoolMethod1(unsigned int i) { OLA_ASSERT_EQ(TEST_INT_VALUE, i); return true; } void Method2(unsigned int i, int j) { OLA_ASSERT_EQ(TEST_INT_VALUE, i); OLA_ASSERT_EQ(TEST_INT_VALUE2, j); } bool BoolMethod2(unsigned int i, int j) { OLA_ASSERT_EQ(TEST_INT_VALUE, i); OLA_ASSERT_EQ(TEST_INT_VALUE2, j); return true; } void Method3(unsigned int i, int j, char c) { OLA_ASSERT_EQ(TEST_INT_VALUE, i); OLA_ASSERT_EQ(TEST_INT_VALUE2, j); OLA_ASSERT_EQ(TEST_CHAR_VALUE, c); } bool BoolMethod3(unsigned int i, int j, char c) { OLA_ASSERT_EQ(TEST_INT_VALUE, i); OLA_ASSERT_EQ(TEST_INT_VALUE2, j); OLA_ASSERT_EQ(TEST_CHAR_VALUE, c); return true; } void Method4(unsigned int i, int j, char c, const string &s) { OLA_ASSERT_EQ(TEST_INT_VALUE, i); OLA_ASSERT_EQ(TEST_INT_VALUE2, j); OLA_ASSERT_EQ(TEST_CHAR_VALUE, c); OLA_ASSERT_EQ(string(TEST_STRING_VALUE), s); } bool BoolMethod4(unsigned int i, int j, char c, const string &s) { OLA_ASSERT_EQ(TEST_INT_VALUE, i); OLA_ASSERT_EQ(TEST_INT_VALUE2, j); OLA_ASSERT_EQ(TEST_CHAR_VALUE, c); OLA_ASSERT_EQ(string(TEST_STRING_VALUE), s); return true; } static const unsigned int TEST_INT_VALUE; static const int TEST_INT_VALUE2; static const char TEST_CHAR_VALUE; static const char TEST_STRING_VALUE[]; }; const unsigned int CallbackTest::TEST_INT_VALUE = 42; const int CallbackTest::TEST_INT_VALUE2 = 53; const char CallbackTest::TEST_CHAR_VALUE = 'c'; const char CallbackTest::TEST_STRING_VALUE[] = "foo"; CPPUNIT_TEST_SUITE_REGISTRATION(CallbackTest); using ola::BaseCallback1; using ola::BaseCallback2; using ola::BaseCallback4; using ola::Callback0; using ola::NewCallback; using ola::NewCallback; using ola::NewSingleCallback; using ola::NewSingleCallback; using ola::SingleUseCallback0; // Functions used for testing void Function0() {} bool BoolFunction0() { return true; } void Function1(unsigned int i) { OLA_ASSERT_EQ(CallbackTest::TEST_INT_VALUE, i); } bool BoolFunction1(unsigned int i) { OLA_ASSERT_EQ(CallbackTest::TEST_INT_VALUE, i); return true; } void Function2(unsigned int i, int j) { OLA_ASSERT_EQ(CallbackTest::TEST_INT_VALUE, i); OLA_ASSERT_EQ(CallbackTest::TEST_INT_VALUE2, j); } bool BoolFunction2(unsigned int i, int j) { OLA_ASSERT_EQ(CallbackTest::TEST_INT_VALUE, i); OLA_ASSERT_EQ(CallbackTest::TEST_INT_VALUE2, j); return true; } /* * Test the Function Callbacks class */ void CallbackTest::testFunctionCallbacks() { // no arg, void return closures SingleUseCallback0 *c1 = NewSingleCallback(&Function0); c1->Run(); Callback0 *c2 = NewCallback(&Function0); c2->Run(); c2->Run(); delete c2; // no arg, bool closures SingleUseCallback0 *c3 = NewSingleCallback(&BoolFunction0); OLA_ASSERT_TRUE(c3->Run()); Callback0 *c4 = NewCallback(&BoolFunction0); OLA_ASSERT_TRUE(c4->Run()); OLA_ASSERT_TRUE(c4->Run()); delete c4; // one arg, void return SingleUseCallback0 *c5 = NewSingleCallback( &Function1, TEST_INT_VALUE); c5->Run(); Callback0 *c6 = NewCallback(&Function1, TEST_INT_VALUE); c6->Run(); c6->Run(); delete c6; // one arg, bool closures SingleUseCallback0 *c7 = NewSingleCallback( &BoolFunction1, TEST_INT_VALUE); OLA_ASSERT_TRUE(c7->Run()); Callback0 *c8 = NewCallback(&BoolFunction1, TEST_INT_VALUE); OLA_ASSERT_TRUE(c8->Run()); OLA_ASSERT_TRUE(c8->Run()); delete c8; } /* * Test the Method Callbacks */ void CallbackTest::testMethodCallbacks() { // no arg, void return closures SingleUseCallback0 *c1 = NewSingleCallback(this, &CallbackTest::Method0); c1->Run(); Callback0 *c2 = NewCallback(this, &CallbackTest::Method0); c2->Run(); c2->Run(); delete c2; // no arg, bool closures SingleUseCallback0 *c3 = NewSingleCallback(this, &CallbackTest::BoolMethod0); OLA_ASSERT_TRUE(c3->Run()); Callback0 *c4 = NewCallback(this, &CallbackTest::BoolMethod0); OLA_ASSERT_TRUE(c4->Run()); OLA_ASSERT_TRUE(c4->Run()); delete c4; // one arg, void return SingleUseCallback0 *c5 = NewSingleCallback( this, &CallbackTest::Method1, TEST_INT_VALUE); c5->Run(); Callback0 *c6 = NewCallback(this, &CallbackTest::Method1, TEST_INT_VALUE); c6->Run(); c6->Run(); delete c6; // one arg, bool closures SingleUseCallback0 *c7 = NewSingleCallback( this, &CallbackTest::BoolMethod1, TEST_INT_VALUE); OLA_ASSERT_TRUE(c7->Run()); Callback0 *c8 = NewCallback(this, &CallbackTest::BoolMethod1, TEST_INT_VALUE); OLA_ASSERT_TRUE(c8->Run()); OLA_ASSERT_TRUE(c8->Run()); delete c8; // two arg, void return SingleUseCallback0 *c9 = NewSingleCallback( this, &CallbackTest::Method2, TEST_INT_VALUE, TEST_INT_VALUE2); c9->Run(); Callback0 *c10 = NewCallback(this, &CallbackTest::Method2, TEST_INT_VALUE, TEST_INT_VALUE2); c10->Run(); c10->Run(); delete c10; // two arg, bool closures SingleUseCallback0 *c11 = NewSingleCallback( this, &CallbackTest::BoolMethod2, TEST_INT_VALUE, TEST_INT_VALUE2); OLA_ASSERT_TRUE(c11->Run()); Callback0 *c12 = NewCallback(this, &CallbackTest::BoolMethod2, TEST_INT_VALUE, TEST_INT_VALUE2); OLA_ASSERT_TRUE(c12->Run()); OLA_ASSERT_TRUE(c12->Run()); delete c12; // three arg, void return SingleUseCallback0 *c13 = NewSingleCallback( this, &CallbackTest::Method3, TEST_INT_VALUE, TEST_INT_VALUE2, TEST_CHAR_VALUE); c13->Run(); Callback0 *c14 = NewCallback(this, &CallbackTest::Method3, TEST_INT_VALUE, TEST_INT_VALUE2, TEST_CHAR_VALUE); c14->Run(); c14->Run(); delete c14; // three arg, bool closures SingleUseCallback0 *c15 = NewSingleCallback( this, &CallbackTest::BoolMethod3, TEST_INT_VALUE, TEST_INT_VALUE2, TEST_CHAR_VALUE); OLA_ASSERT_TRUE(c15->Run()); Callback0 *c16 = NewCallback(this, &CallbackTest::BoolMethod3, TEST_INT_VALUE, TEST_INT_VALUE2, TEST_CHAR_VALUE); OLA_ASSERT_TRUE(c16->Run()); OLA_ASSERT_TRUE(c16->Run()); delete c16; } /* * Test the single argument function closures */ void CallbackTest::testFunctionCallbacks1() { // single arg, void return closures BaseCallback1 *c1 = NewSingleCallback(&Function1); c1->Run(TEST_INT_VALUE); BaseCallback1 *c2 = NewCallback(&Function1); c2->Run(TEST_INT_VALUE); c2->Run(TEST_INT_VALUE); delete c2; // test a function that returns bool BaseCallback1 *c3 = NewSingleCallback(&BoolFunction1); OLA_ASSERT_TRUE(c3->Run(TEST_INT_VALUE)); BaseCallback1 *c4 = NewCallback(&BoolFunction1); OLA_ASSERT_TRUE(c4->Run(TEST_INT_VALUE)); OLA_ASSERT_TRUE(c4->Run(TEST_INT_VALUE)); delete c4; // single arg, void return closures BaseCallback1 *c6 = NewSingleCallback( &Function2, TEST_INT_VALUE); c6->Run(TEST_INT_VALUE2); BaseCallback1 *c7 = NewCallback( &Function2, TEST_INT_VALUE); c7->Run(TEST_INT_VALUE2); c7->Run(TEST_INT_VALUE2); delete c7; } /* * Test the Method Callbacks */ void CallbackTest::testMethodCallbacks1() { // test 1 arg callbacks that return unsigned ints BaseCallback1 *c1 = NewSingleCallback( this, &CallbackTest::Method1); c1->Run(TEST_INT_VALUE); BaseCallback1 *c2 = NewCallback(this, &CallbackTest::Method1); c2->Run(TEST_INT_VALUE); c2->Run(TEST_INT_VALUE); delete c2; // test 1 arg callbacks that return bools BaseCallback1 *c3 = NewSingleCallback( this, &CallbackTest::BoolMethod1); OLA_ASSERT_TRUE(c3->Run(TEST_INT_VALUE)); BaseCallback1 *c4 = NewCallback( this, &CallbackTest::BoolMethod1); OLA_ASSERT_TRUE(c4->Run(TEST_INT_VALUE)); OLA_ASSERT_TRUE(c4->Run(TEST_INT_VALUE)); delete c4; // test 1 arg initial, 1 arg deferred callbacks that return ints BaseCallback1 *c5 = NewSingleCallback( this, &CallbackTest::Method2, TEST_INT_VALUE); c5->Run(TEST_INT_VALUE2); BaseCallback1 *c6 = NewCallback( this, &CallbackTest::Method2, TEST_INT_VALUE); c6->Run(TEST_INT_VALUE2); c6->Run(TEST_INT_VALUE2); delete c6; // test 1 arg initial, 1 arg deferred callbacks that return bools BaseCallback1 *c7 = NewSingleCallback( this, &CallbackTest::BoolMethod2, TEST_INT_VALUE); OLA_ASSERT_TRUE(c7->Run(TEST_INT_VALUE2)); BaseCallback1 *c8 = NewCallback( this, &CallbackTest::BoolMethod2, TEST_INT_VALUE); OLA_ASSERT_TRUE(c8->Run(TEST_INT_VALUE2)); OLA_ASSERT_TRUE(c8->Run(TEST_INT_VALUE2)); delete c8; // test 2 arg initial, 1 arg deferred callbacks that return ints BaseCallback1 *c9 = NewSingleCallback( this, &CallbackTest::Method3, TEST_INT_VALUE, TEST_INT_VALUE2); c9->Run(TEST_CHAR_VALUE); BaseCallback1 *c10 = NewCallback( this, &CallbackTest::Method3, TEST_INT_VALUE, TEST_INT_VALUE2); c10->Run(TEST_CHAR_VALUE); c10->Run(TEST_CHAR_VALUE); delete c10; // test 2 arg initial, 1 arg deferred callbacks that return bools BaseCallback1 *c11 = NewSingleCallback( this, &CallbackTest::BoolMethod3, TEST_INT_VALUE, TEST_INT_VALUE2); OLA_ASSERT_TRUE(c11->Run(TEST_CHAR_VALUE)); BaseCallback1 *c12 = NewCallback( this, &CallbackTest::BoolMethod3, TEST_INT_VALUE, TEST_INT_VALUE2); OLA_ASSERT_TRUE(c12->Run(TEST_CHAR_VALUE)); OLA_ASSERT_TRUE(c12->Run(TEST_CHAR_VALUE)); delete c12; // test 3 arg initial, 1 arg deferred callbacks that return ints BaseCallback1 *c13 = NewSingleCallback( this, &CallbackTest::Method4, TEST_INT_VALUE, TEST_INT_VALUE2, TEST_CHAR_VALUE); c13->Run(TEST_STRING_VALUE); BaseCallback1 *c14 = NewCallback( this, &CallbackTest::Method4, TEST_INT_VALUE, TEST_INT_VALUE2, TEST_CHAR_VALUE); c14->Run(TEST_STRING_VALUE); c14->Run(TEST_STRING_VALUE); delete c14; // test 3 arg initial, 1 arg deferred callbacks that return bools BaseCallback1 *c15 = NewSingleCallback( this, &CallbackTest::BoolMethod4, TEST_INT_VALUE, TEST_INT_VALUE2, TEST_CHAR_VALUE); OLA_ASSERT_TRUE(c15->Run(TEST_STRING_VALUE)); BaseCallback1 *c16 = NewCallback( this, &CallbackTest::BoolMethod4, TEST_INT_VALUE, TEST_INT_VALUE2, TEST_CHAR_VALUE); OLA_ASSERT_TRUE(c16->Run(TEST_STRING_VALUE)); OLA_ASSERT_TRUE(c16->Run(TEST_STRING_VALUE)); delete c16; } /* * Test the Method Callbacks */ void CallbackTest::testMethodCallbacks2() { // test 2 arg callbacks that return void BaseCallback2 *c1 = NewSingleCallback( this, &CallbackTest::Method2); c1->Run(TEST_INT_VALUE, TEST_INT_VALUE2); BaseCallback2 *c2 = NewCallback( this, &CallbackTest::Method2); c2->Run(TEST_INT_VALUE, TEST_INT_VALUE2); c2->Run(TEST_INT_VALUE, TEST_INT_VALUE2); delete c2; // test 2 arg callbacks that return bools BaseCallback2 *c3 = NewSingleCallback( this, &CallbackTest::BoolMethod2); OLA_ASSERT_TRUE(c3->Run(TEST_INT_VALUE, TEST_INT_VALUE2)); BaseCallback2 *c4 = NewCallback( this, &CallbackTest::BoolMethod2); OLA_ASSERT_TRUE(c4->Run(TEST_INT_VALUE, TEST_INT_VALUE2)); OLA_ASSERT_TRUE(c4->Run(TEST_INT_VALUE, TEST_INT_VALUE2)); delete c4; // test 1 create time, 2 run time arg callbacks that return void BaseCallback2 *c5 = NewSingleCallback( this, &CallbackTest::Method3, TEST_INT_VALUE); c5->Run(TEST_INT_VALUE2, TEST_CHAR_VALUE); BaseCallback2 *c6 = NewCallback( this, &CallbackTest::Method3, TEST_INT_VALUE); c6->Run(TEST_INT_VALUE2, TEST_CHAR_VALUE); c6->Run(TEST_INT_VALUE2, TEST_CHAR_VALUE); delete c6; // test 1 create time, 2 run time arg callbacks that return bools BaseCallback2 *c7 = NewSingleCallback( this, &CallbackTest::BoolMethod3, TEST_INT_VALUE); OLA_ASSERT_TRUE(c7->Run(TEST_INT_VALUE2, TEST_CHAR_VALUE)); BaseCallback2 *c8 = NewCallback( this, &CallbackTest::BoolMethod3, TEST_INT_VALUE); OLA_ASSERT_TRUE(c8->Run(TEST_INT_VALUE2, TEST_CHAR_VALUE)); OLA_ASSERT_TRUE(c8->Run(TEST_INT_VALUE2, TEST_CHAR_VALUE)); delete c8; } /* * Test the Method Callbacks */ void CallbackTest::testMethodCallbacks4() { // test 2 arg callbacks that return unsigned ints BaseCallback4 *c1 = NewSingleCallback( this, &CallbackTest::Method4); c1->Run(TEST_INT_VALUE, TEST_INT_VALUE2, TEST_CHAR_VALUE, TEST_STRING_VALUE); BaseCallback4 *c2 = NewCallback( this, &CallbackTest::Method4); c2->Run(TEST_INT_VALUE, TEST_INT_VALUE2, TEST_CHAR_VALUE, TEST_STRING_VALUE); c2->Run(TEST_INT_VALUE, TEST_INT_VALUE2, TEST_CHAR_VALUE, TEST_STRING_VALUE); delete c2; // test 2 arg callbacks that return bools BaseCallback4 *c3 = NewSingleCallback( this, &CallbackTest::BoolMethod4); OLA_ASSERT_TRUE(c3->Run(TEST_INT_VALUE, TEST_INT_VALUE2, TEST_CHAR_VALUE, TEST_STRING_VALUE)); BaseCallback4 *c4 = NewCallback( this, &CallbackTest::BoolMethod4); OLA_ASSERT_TRUE(c4->Run(TEST_INT_VALUE, TEST_INT_VALUE2, TEST_CHAR_VALUE, TEST_STRING_VALUE)); OLA_ASSERT_TRUE(c4->Run(TEST_INT_VALUE, TEST_INT_VALUE2, TEST_CHAR_VALUE, TEST_STRING_VALUE)); delete c4; } ola-0.10.5.nojsmin/common/utils/ActionQueueTest.cpp0000644000175000017500000000756613023355232021712 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * ActionQueueTest.cpp * Test fixture for the ActionQueue class * Copyright (C) 2010 Simon Newton */ #include #include "ola/ActionQueue.h" #include "ola/Callback.h" #include "ola/testing/TestUtils.h" using ola::Action; using ola::ActionQueue; using ola::SingleUseCallback0; class ActionQueueTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(ActionQueueTest); CPPUNIT_TEST(testEmptyQueue); CPPUNIT_TEST(testSimpleQueue); CPPUNIT_TEST(testFailedQueue); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void CommandsComplete(ActionQueue *queue); void testEmptyQueue(); void testSimpleQueue(); void testFailedQueue(); private: ActionQueue *m_received_queue; }; /* * A basic test action */ class MockAction: public Action { public: explicit MockAction(bool fatal = false, bool fail = false): Action(), m_fatal(fatal), m_failed(fail), m_executed(false) {} bool IsFatal() const { return m_fatal; } bool Failed() const { return m_failed; } bool Executed() const { return m_executed; } void Perform(SingleUseCallback0 *on_done); private: bool m_fatal; bool m_failed; bool m_executed; }; void MockAction::Perform(SingleUseCallback0 *on_done) { m_executed = true; on_done->Run(); } CPPUNIT_TEST_SUITE_REGISTRATION(ActionQueueTest); void ActionQueueTest::setUp() { m_received_queue = NULL; } void ActionQueueTest::CommandsComplete(ActionQueue *queue) { m_received_queue = queue; } /* * Check that an empty queue works. */ void ActionQueueTest::testEmptyQueue() { ActionQueue queue( NewSingleCallback(this, &ActionQueueTest::CommandsComplete)); queue.NextAction(); OLA_ASSERT_EQ(&queue, m_received_queue); OLA_ASSERT_TRUE(queue.WasSuccessful()); // try calling next item to make sure nothing happens queue.NextAction(); } /* * Test that a simple queue works */ void ActionQueueTest::testSimpleQueue() { ActionQueue queue( NewSingleCallback(this, &ActionQueueTest::CommandsComplete)); MockAction *action1 = new MockAction(); queue.AddAction(action1); MockAction *action2 = new MockAction(); queue.AddAction(action2); queue.NextAction(); OLA_ASSERT_EQ(&queue, m_received_queue); OLA_ASSERT_TRUE(queue.WasSuccessful()); OLA_ASSERT_TRUE(action1->Executed()); OLA_ASSERT_TRUE(action2->Executed()); // try calling next item to make sure nothing happens queue.NextAction(); } /* * Test that a simple queue works */ void ActionQueueTest::testFailedQueue() { ActionQueue queue( NewSingleCallback(this, &ActionQueueTest::CommandsComplete)); MockAction *action1 = new MockAction(false, true); queue.AddAction(action1); MockAction *action2 = new MockAction(true, true); queue.AddAction(action2); MockAction *action3 = new MockAction(); queue.AddAction(action3); queue.NextAction(); OLA_ASSERT_EQ(&queue, m_received_queue); OLA_ASSERT_FALSE(queue.WasSuccessful()); OLA_ASSERT_TRUE(action1->Executed()); OLA_ASSERT_TRUE(action2->Executed()); OLA_ASSERT_FALSE(action3->Executed()); // try calling next item to make sure nothing happens queue.NextAction(); } ola-0.10.5.nojsmin/common/utils/StringUtils.cpp0000644000175000017500000002730413134123277021114 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * StringUtils.cpp * Random String functions. * Copyright (C) 2005 Simon Newton */ #define __STDC_LIMIT_MACROS // for UINT8_MAX & friends #include #include #include #include #include #include #include #include #include #include #include "ola/StringUtils.h" #include "ola/base/Macro.h" namespace ola { using std::endl; using std::ostringstream; using std::string; using std::vector; void StringSplit(const string &input, vector *tokens, const string &delimiters) { string::size_type start_offset = 0; string::size_type end_offset = 0; while (1) { end_offset = input.find_first_of(delimiters, start_offset); if (end_offset == string::npos) { tokens->push_back( input.substr(start_offset, input.size() - start_offset)); return; } tokens->push_back(input.substr(start_offset, end_offset - start_offset)); start_offset = (end_offset + 1 > input.size()) ? string::npos : (end_offset + 1); } } void StringTrim(string *input) { string characters_to_trim = " \n\r\t"; string::size_type start = input->find_first_not_of(characters_to_trim); string::size_type end = input->find_last_not_of(characters_to_trim); if (start == string::npos) { input->clear(); } else { *input = input->substr(start, end - start + 1); } } void ShortenString(string *input) { size_t index = input->find(static_cast(0)); if (index != string::npos) { input->erase(index); } } bool StringBeginsWith(const string &s, const string &prefix) { if (s.length() >= prefix.length()) { return (0 == s.compare(0, prefix.length(), prefix)); } else { return false; } } bool StringEndsWith(const string &s, const string &suffix) { if (s.length() >= suffix.length()) { return 0 == s.compare(s.length() - suffix.length(), suffix.length(), suffix); } else { return false; } } bool StripPrefix(string *s, const string &prefix) { if (StringBeginsWith(*s, prefix)) { *s = s->substr(prefix.length()); return true; } else { return false; } } bool StripSuffix(string *s, const string &suffix) { if (StringEndsWith(*s, suffix)) { *s = s->substr(0, s->length() - suffix.length()); return true; } else { return false; } } string IntToHexString(unsigned int i, unsigned int width) { strings::_ToHex v = strings::_ToHex( i, static_cast(width), true); ostringstream str; str << v; return str.str(); } bool StringToBool(const string &value, bool *output) { string lc_value(value); ToLower(&lc_value); if ((lc_value == "true") || (lc_value == "t") || (lc_value == "1")) { *output = true; return true; } else if ((lc_value == "false") || (lc_value == "f") || (lc_value == "0")) { *output = false; return true; } return false; } bool StringToBoolTolerant(const string &value, bool *output) { if (StringToBool(value, output)) { return true; } else { string lc_value(value); ToLower(&lc_value); if ((lc_value == "on") || (lc_value == "enable") || (lc_value == "enabled")) { *output = true; return true; } else if ((lc_value == "off") || (lc_value == "disable") || (lc_value == "disabled")) { *output = false; return true; } } return false; } bool StringToInt(const string &value, unsigned int *output, bool strict) { if (value.empty()) { return false; } char *end_ptr; errno = 0; long long l = strtoll(value.data(), &end_ptr, 10); // NOLINT(runtime/int) if (l < 0 || (l == 0 && errno != 0)) { return false; } if (value == end_ptr) { return false; } if (strict && *end_ptr != 0) { return false; } if (l > static_cast(UINT32_MAX)) { // NOLINT(runtime/int) return false; } *output = static_cast(l); return true; } bool StringToInt(const string &value, uint16_t *output, bool strict) { unsigned int v; if (!StringToInt(value, &v, strict)) { return false; } if (v > UINT16_MAX) { return false; } *output = static_cast(v); return true; } bool StringToInt(const string &value, uint8_t *output, bool strict) { unsigned int v; if (!StringToInt(value, &v, strict)) { return false; } if (v > UINT8_MAX) { return false; } *output = static_cast(v); return true; } bool StringToInt(const string &value, int *output, bool strict) { if (value.empty()) { return false; } char *end_ptr; errno = 0; long long l = strtoll(value.data(), &end_ptr, 10); // NOLINT(runtime/int) if (l == 0 && errno != 0) { return false; } if (value == end_ptr) { return false; } if (strict && *end_ptr != 0) { return false; } if (l < INT32_MIN || l > INT32_MAX) { return false; } *output = static_cast(l); return true; } bool StringToInt(const string &value, int16_t *output, bool strict) { int v; if (!StringToInt(value, &v, strict)) { return false; } if (v < INT16_MIN || v > INT16_MAX) { return false; } *output = static_cast(v); return true; } bool StringToInt(const string &value, int8_t *output, bool strict) { int v; if (!StringToInt(value, &v, strict)) { return false; } if (v < INT8_MIN || v > INT8_MAX) { return false; } *output = static_cast(v); return true; } void Escape(string *original) { for (string::iterator iter = original->begin(); iter != original->end(); ++iter) { switch (*iter) { case '"': iter = original->insert(iter, '\\'); iter++; break; case '\\': iter = original->insert(iter, '\\'); iter++; break; case '/': iter = original->insert(iter, '\\'); iter++; break; case '\b': *iter = 'b'; iter = original->insert(iter, '\\'); iter++; break; case '\f': *iter = 'f'; iter = original->insert(iter, '\\'); iter++; break; case '\n': *iter = 'n'; iter = original->insert(iter, '\\'); iter++; break; case '\r': *iter = 'r'; iter = original->insert(iter, '\\'); iter++; break; case '\t': *iter = 't'; iter = original->insert(iter, '\\'); iter++; break; default: break; } } } string EscapeString(const string &original) { string result = original; Escape(&result); return result; } string EncodeString(const string &original) { ostringstream encoded; for (string::const_iterator iter = original.begin(); iter != original.end(); ++iter) { if (isprint(*iter)) { encoded << *iter; } else { encoded << "\\x" << ola::strings::ToHex(static_cast(*iter), false); } } return encoded.str(); } void ReplaceAll(string *original, const string &find, const string &replace) { if (original->empty() || find.empty()) { return; // No text or nothing to find, so nothing to do } size_t start = 0; while ((start = original->find(find, start)) != string::npos) { original->replace(start, find.length(), replace); // Move to the end of the replaced section start += ((replace.length() > find.length()) ? replace.length() : 0); } } bool HexStringToInt(const string &value, uint8_t *output) { uint32_t temp; if (!HexStringToInt(value, &temp)) { return false; } if (temp > UINT8_MAX) { return false; } *output = static_cast(temp); return true; } bool HexStringToInt(const string &value, uint16_t *output) { uint32_t temp; if (!HexStringToInt(value, &temp)) { return false; } if (temp > UINT16_MAX) { return false; } *output = static_cast(temp); return true; } bool HexStringToInt(const string &value, uint32_t *output) { if (value.empty()) { return false; } size_t found = value.find_first_not_of("ABCDEFabcdef0123456789"); if (found != string::npos) { return false; } *output = strtoul(value.data(), NULL, 16); return true; } bool HexStringToInt(const string &value, int8_t *output) { int32_t temp; if (!HexStringToInt(value, &temp)) { return false; } if (temp < 0 || temp > static_cast(UINT8_MAX)) { return false; } *output = static_cast(temp); return true; } bool HexStringToInt(const string &value, int16_t *output) { int32_t temp; if (!HexStringToInt(value, &temp)) { return false; } if (temp < 0 || temp > static_cast(UINT16_MAX)) { return false; } *output = static_cast(temp); return true; } bool HexStringToInt(const string &value, int32_t *output) { if (value.empty()) { return false; } size_t found = value.find_first_not_of("ABCDEFabcdef0123456789"); if (found != string::npos) { return false; } *output = strtoll(value.data(), NULL, 16); return true; } void ToLower(string *s) { std::transform(s->begin(), s->end(), s->begin(), std::ptr_fun(std::tolower)); } void ToUpper(string *s) { std::transform(s->begin(), s->end(), s->begin(), std::ptr_fun(std::toupper)); } void CapitalizeLabel(string *s) { bool capitalize = true; for (string::iterator iter = s->begin(); iter != s->end(); ++iter) { switch (*iter) { case '-': // fall through, also convert to space then capitalize next character OLA_FALLTHROUGH case '_': *iter = ' '; // fall through, also convert to space then capitalize next character OLA_FALLTHROUGH case ' ': capitalize = true; break; default: if (capitalize && islower(*iter)) { *iter = toupper(*iter); } capitalize = false; } } } void CustomCapitalizeLabel(string *s) { static const char* const transforms[] = { "dhcp", "dmx", "dns", "ip", "ipv4", // Should really be IPv4 probably, but better than nothing "led", "rdm", "uid", NULL }; const size_t size = s->size(); const char* const *transform = transforms; while (*transform) { size_t last_match = 0; const string ancronym(*transform); const size_t ancronym_size = ancronym.size(); while (true) { size_t match_position = s->find(ancronym, last_match); if (match_position == string::npos) { break; } last_match = match_position + 1; size_t end_position = match_position + ancronym_size; if ((match_position == 0 || ispunct(s->at(match_position - 1))) && (end_position == size || ispunct(s->at(end_position)))) { while (match_position < end_position) { s->at(match_position) = toupper(s->at(match_position)); match_position++; } } } transform++; } CapitalizeLabel(s); } void CapitalizeFirst(string *s) { string::iterator iter = s->begin(); if (islower(*iter)) { *iter = toupper(*iter); } } } // namespace ola ola-0.10.5.nojsmin/common/utils/StringUtilsTest.cpp0000644000175000017500000011214613023355232021746 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * StringUtilsTest.cpp * Unittest for String functions. * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include #include "ola/StringUtils.h" #include "ola/testing/TestUtils.h" using ola::CapitalizeLabel; using ola::CustomCapitalizeLabel; using ola::CapitalizeFirst; using ola::EncodeString; using ola::Escape; using ola::EscapeString; using ola::FormatData; using ola::HexStringToInt; using ola::IntToHexString; using ola::IntToString; using ola::PrefixedHexStringToInt; using ola::ReplaceAll; using ola::ShortenString; using ola::StringBeginsWith; using ola::StringEndsWith; using ola::StringJoin; using ola::StringSplit; using ola::StringToBool; using ola::StringToBoolTolerant; using ola::StringToInt; using ola::StringToIntOrDefault; using ola::StringTrim; using ola::StripPrefix; using ola::StripSuffix; using ola::ToLower; using ola::ToUpper; using ola::strings::ToHex; using std::ostringstream; using std::string; using std::vector; class StringUtilsTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(StringUtilsTest); CPPUNIT_TEST(testSplit); CPPUNIT_TEST(testTrim); CPPUNIT_TEST(testShorten); CPPUNIT_TEST(testBeginsWith); CPPUNIT_TEST(testEndsWith); CPPUNIT_TEST(testStripPrefix); CPPUNIT_TEST(testStripSuffix); CPPUNIT_TEST(testIntToString); CPPUNIT_TEST(testIntToHexString); CPPUNIT_TEST(testEscape); CPPUNIT_TEST(testEncodeString); CPPUNIT_TEST(testStringToBool); CPPUNIT_TEST(testStringToBoolTolerant); CPPUNIT_TEST(testStringToUInt); CPPUNIT_TEST(testStringToUIntOrDefault); CPPUNIT_TEST(testStringToUInt16); CPPUNIT_TEST(testStringToUInt16OrDefault); CPPUNIT_TEST(testStringToUInt8); CPPUNIT_TEST(testStringToUInt8OrDefault); CPPUNIT_TEST(testStringToInt); CPPUNIT_TEST(testStringToIntOrDefault); CPPUNIT_TEST(testStringToInt16); CPPUNIT_TEST(testStringToInt16OrDefault); CPPUNIT_TEST(testStringToInt8); CPPUNIT_TEST(testStringToInt8OrDefault); CPPUNIT_TEST(testHexStringToInt); CPPUNIT_TEST(testPrefixedHexStringToInt); CPPUNIT_TEST(testToLower); CPPUNIT_TEST(testToUpper); CPPUNIT_TEST(testCapitalizeLabel); CPPUNIT_TEST(testCustomCapitalizeLabel); CPPUNIT_TEST(testCapitalizeFirst); CPPUNIT_TEST(testFormatData); CPPUNIT_TEST(testStringJoin); CPPUNIT_TEST(testReplaceAll); CPPUNIT_TEST_SUITE_END(); public: void testSplit(); void testTrim(); void testShorten(); void testBeginsWith(); void testEndsWith(); void testStripPrefix(); void testStripSuffix(); void testIntToString(); void testIntToHexString(); void testEscape(); void testEncodeString(); void testStringToBool(); void testStringToBoolTolerant(); void testStringToUInt(); void testStringToUIntOrDefault(); void testStringToUInt16(); void testStringToUInt16OrDefault(); void testStringToUInt8(); void testStringToUInt8OrDefault(); void testStringToInt(); void testStringToIntOrDefault(); void testStringToInt16(); void testStringToInt16OrDefault(); void testStringToInt8(); void testStringToInt8OrDefault(); void testHexStringToInt(); void testPrefixedHexStringToInt(); void testToLower(); void testToUpper(); void testCapitalizeLabel(); void testCustomCapitalizeLabel(); void testCapitalizeFirst(); void testFormatData(); void testStringJoin(); void testReplaceAll(); }; CPPUNIT_TEST_SUITE_REGISTRATION(StringUtilsTest); /* * Test the split function */ void StringUtilsTest::testSplit() { vector tokens; string input = ""; StringSplit(input, &tokens); OLA_ASSERT_EQ((size_t) 1, tokens.size()); OLA_ASSERT_EQ(string(""), tokens[0]); input = "1 2 345"; tokens.clear(); StringSplit(input, &tokens); OLA_ASSERT_EQ((size_t) 3, tokens.size()); OLA_ASSERT_EQ(string("1"), tokens[0]); OLA_ASSERT_EQ(string("2"), tokens[1]); OLA_ASSERT_EQ(string("345"), tokens[2]); input = "1,2,345"; tokens.clear(); StringSplit(input, &tokens, ","); OLA_ASSERT_EQ((size_t) 3, tokens.size()); OLA_ASSERT_EQ(string("1"), tokens[0]); OLA_ASSERT_EQ(string("2"), tokens[1]); OLA_ASSERT_EQ(string("345"), tokens[2]); input = ",1,2,345,,"; tokens.clear(); StringSplit(input, &tokens, ","); OLA_ASSERT_EQ((size_t) 6, tokens.size()); OLA_ASSERT_EQ(string(""), tokens[0]); OLA_ASSERT_EQ(string("1"), tokens[1]); OLA_ASSERT_EQ(string("2"), tokens[2]); OLA_ASSERT_EQ(string("345"), tokens[3]); OLA_ASSERT_EQ(string(""), tokens[4]); OLA_ASSERT_EQ(string(""), tokens[5]); input = "1 2,345"; tokens.clear(); StringSplit(input, &tokens, " ,"); OLA_ASSERT_EQ((size_t) 3, tokens.size()); OLA_ASSERT_EQ(string("1"), tokens[0]); OLA_ASSERT_EQ(string("2"), tokens[1]); OLA_ASSERT_EQ(string("345"), tokens[2]); input = "1, 2,345"; tokens.clear(); StringSplit(input, &tokens, " ,"); OLA_ASSERT_EQ((size_t) 4, tokens.size()); OLA_ASSERT_EQ(string("1"), tokens[0]); OLA_ASSERT_EQ(string(""), tokens[1]); OLA_ASSERT_EQ(string("2"), tokens[2]); OLA_ASSERT_EQ(string("345"), tokens[3]); input = "1"; tokens.clear(); StringSplit(input, &tokens, "."); OLA_ASSERT_EQ((size_t) 1, tokens.size()); OLA_ASSERT_EQ(string("1"), tokens[0]); // And the old non-pointer version input = ",1,2,345,,"; tokens.clear(); StringSplit(input, tokens, ","); OLA_ASSERT_EQ((size_t) 6, tokens.size()); OLA_ASSERT_EQ(string(""), tokens[0]); OLA_ASSERT_EQ(string("1"), tokens[1]); OLA_ASSERT_EQ(string("2"), tokens[2]); OLA_ASSERT_EQ(string("345"), tokens[3]); OLA_ASSERT_EQ(string(""), tokens[4]); OLA_ASSERT_EQ(string(""), tokens[5]); } /* * Test the trim function. */ void StringUtilsTest::testTrim() { string input = "foo bar baz"; StringTrim(&input); OLA_ASSERT_EQ(string("foo bar baz"), input); input = " \rfoo bar\t\n"; StringTrim(&input); OLA_ASSERT_EQ(string("foo bar"), input); input = " \r\t\n"; StringTrim(&input); OLA_ASSERT_EQ(string(""), input); } /* * Test the shorten function. */ void StringUtilsTest::testShorten() { string input = "foo bar baz"; ShortenString(&input); OLA_ASSERT_EQ(string("foo bar baz"), input); input = "foo \0bar"; ShortenString(&input); OLA_ASSERT_EQ(string("foo "), input); input = "foo\0bar\0baz"; StringTrim(&input); OLA_ASSERT_EQ(string("foo"), input); } /* * Test the StringBeginsWith function. */ void StringUtilsTest::testBeginsWith() { string input = "foo bar baz"; OLA_ASSERT_TRUE(StringBeginsWith(input, "foo")); OLA_ASSERT_TRUE(StringBeginsWith(input, "foo ")); OLA_ASSERT_TRUE(StringBeginsWith(input, "foo bar")); OLA_ASSERT_TRUE(StringBeginsWith(input, "")); OLA_ASSERT_FALSE(StringBeginsWith(input, "baz")); } /* * Test the StringEndsWith function. */ void StringUtilsTest::testEndsWith() { string input = "foo bar baz"; OLA_ASSERT_TRUE(StringEndsWith(input, "baz")); OLA_ASSERT_TRUE(StringEndsWith(input, " baz")); OLA_ASSERT_TRUE(StringEndsWith(input, "bar baz")); OLA_ASSERT_TRUE(StringEndsWith(input, "")); OLA_ASSERT_FALSE(StringEndsWith(input, "foo")); } /* * Test the StripPrefix function. */ void StringUtilsTest::testStripPrefix() { string input = "foo bar baz"; OLA_ASSERT_TRUE(StripPrefix(&input, "foo")); OLA_ASSERT_EQ(string(" bar baz"), input); input = "foo bar baz"; OLA_ASSERT_TRUE(StripPrefix(&input, "foo ")); OLA_ASSERT_EQ(string("bar baz"), input); input = "foo bar baz"; OLA_ASSERT_TRUE(StripPrefix(&input, "foo bar")); OLA_ASSERT_EQ(string(" baz"), input); input = "foo bar baz"; OLA_ASSERT_TRUE(StripPrefix(&input, "")); OLA_ASSERT_EQ(string("foo bar baz"), input); input = "foo bar baz"; OLA_ASSERT_FALSE(StripPrefix(&input, "baz")); } /* * Test the StripSuffix function. */ void StringUtilsTest::testStripSuffix() { string input = "foo bar baz"; OLA_ASSERT_TRUE(StripSuffix(&input, "baz")); OLA_ASSERT_EQ(string("foo bar "), input); input = "foo bar baz"; OLA_ASSERT_TRUE(StripSuffix(&input, " baz")); OLA_ASSERT_EQ(string("foo bar"), input); input = "foo bar baz"; OLA_ASSERT_TRUE(StripSuffix(&input, "bar baz")); OLA_ASSERT_EQ(string("foo "), input); input = "foo bar baz"; OLA_ASSERT_TRUE(StripSuffix(&input, "")); OLA_ASSERT_EQ(string("foo bar baz"), input); input = "foo bar baz"; OLA_ASSERT_FALSE(StripSuffix(&input, "foo")); } /* * test the IntToString function. */ void StringUtilsTest::testIntToString() { OLA_ASSERT_EQ(string("0"), IntToString(0)); OLA_ASSERT_EQ(string("1234"), IntToString(1234)); OLA_ASSERT_EQ(string("-1234"), IntToString(-1234)); unsigned int i = 42; OLA_ASSERT_EQ(string("42"), IntToString(i)); } /* * test the IntToHexString function. */ void StringUtilsTest::testIntToHexString() { // Using the old IntToHexString OLA_ASSERT_EQ(string("0x00"), IntToHexString((uint8_t)0)); OLA_ASSERT_EQ(string("0x01"), IntToHexString((uint8_t)1)); OLA_ASSERT_EQ(string("0x42"), IntToHexString((uint8_t)0x42)); OLA_ASSERT_EQ(string("0x0001"), IntToHexString((uint16_t)0x0001)); OLA_ASSERT_EQ(string("0xabcd"), IntToHexString((uint16_t)0xABCD)); OLA_ASSERT_EQ(string("0xdeadbeef"), IntToHexString((uint32_t)0xDEADBEEF)); unsigned int i = 0x42; OLA_ASSERT_EQ(string("0x00000042"), IntToHexString(i)); // Using the inline string concatenation ostringstream str; str << ToHex((uint8_t)0); OLA_ASSERT_EQ(string("0x00"), str.str()); str.str(""); str << ToHex((uint8_t)1); OLA_ASSERT_EQ(string("0x01"), str.str()); str.str(""); str << ToHex((uint8_t)0x42); OLA_ASSERT_EQ(string("0x42"), str.str()); str.str(""); str << ToHex((uint16_t)0x0001); OLA_ASSERT_EQ(string("0x0001"), str.str()); str.str(""); str << ToHex((uint16_t)0xABCD); OLA_ASSERT_EQ(string("0xabcd"), str.str()); str.str(""); str << ToHex((uint32_t)0xDEADBEEF); OLA_ASSERT_EQ(string("0xdeadbeef"), str.str()); str.str(""); str << ToHex(i); OLA_ASSERT_EQ(string("0x00000042"), str.str()); str.str(""); // Without prefix str << ToHex((uint8_t)0x42, false); OLA_ASSERT_EQ(string("42"), str.str()); str.str(""); str << ToHex((uint16_t)0xABCD, false); OLA_ASSERT_EQ(string("abcd"), str.str()); str.str(""); } /** * Test escaping. */ void StringUtilsTest::testEscape() { string s1 = "foo\""; Escape(&s1); OLA_ASSERT_EQ(string("foo\\\""), s1); s1 = "he said \"foo\""; Escape(&s1); OLA_ASSERT_EQ(string("he said \\\"foo\\\""), s1); s1 = "backslash\\test"; Escape(&s1); OLA_ASSERT_EQ(string("backslash\\\\test"), s1); s1 = "newline\ntest"; Escape(&s1); OLA_ASSERT_EQ(string("newline\\ntest"), s1); s1 = "tab\ttest"; Escape(&s1); OLA_ASSERT_EQ(string("tab\\ttest"), s1); s1 = "one\"two\\three/four\bfive\fsix\nseven\reight\tnine"; Escape(&s1); OLA_ASSERT_EQ( string("one\\\"two\\\\three\\/four\\bfive\\fsix\\nseven\\reight\\tnine"), s1); s1 = "one\"two\\three/four\bfive\fsix\nseven\reight\tnine"; string result = EscapeString(s1); OLA_ASSERT_EQ( string("one\\\"two\\\\three\\/four\\bfive\\fsix\\nseven\\reight\\tnine"), result); } /** * Test encoding string */ void StringUtilsTest::testEncodeString() { string s1 = "foo"; OLA_ASSERT_EQ(string("foo"), EncodeString(s1)); s1 = "newline\ntest"; OLA_ASSERT_EQ(string("newline\\x0atest"), EncodeString(s1)); s1 = "newline\n\ntest"; OLA_ASSERT_EQ(string("newline\\x0a\\x0atest"), EncodeString(s1)); s1 = "\x01newline\x02test"; OLA_ASSERT_EQ(string("\\x01newline\\x02test"), EncodeString(s1)); // Test a null in the middle of a string s1 = string("newline" "\x00" "test", 12); OLA_ASSERT_EQ(string("newline\\x00test"), EncodeString(s1)); } void StringUtilsTest::testStringToBool() { bool value; OLA_ASSERT_FALSE(StringToBool("", &value)); OLA_ASSERT_FALSE(StringToBool("-1", &value)); OLA_ASSERT_FALSE(StringToBool("2", &value)); OLA_ASSERT_FALSE(StringToBool("a", &value)); OLA_ASSERT_TRUE(StringToBool("true", &value)); OLA_ASSERT_EQ(value, true); OLA_ASSERT_TRUE(StringToBool("false", &value)); OLA_ASSERT_EQ(value, false); OLA_ASSERT_TRUE(StringToBool("TrUE", &value)); OLA_ASSERT_EQ(value, true); OLA_ASSERT_TRUE(StringToBool("FalSe", &value)); OLA_ASSERT_EQ(value, false); OLA_ASSERT_TRUE(StringToBool("t", &value)); OLA_ASSERT_EQ(value, true); OLA_ASSERT_TRUE(StringToBool("f", &value)); OLA_ASSERT_EQ(value, false); OLA_ASSERT_TRUE(StringToBool("T", &value)); OLA_ASSERT_EQ(value, true); OLA_ASSERT_TRUE(StringToBool("F", &value)); OLA_ASSERT_EQ(value, false); OLA_ASSERT_TRUE(StringToBool("1", &value)); OLA_ASSERT_EQ(value, true); OLA_ASSERT_TRUE(StringToBool("0", &value)); OLA_ASSERT_EQ(value, false); } void StringUtilsTest::testStringToBoolTolerant() { bool value; OLA_ASSERT_FALSE(StringToBoolTolerant("", &value)); OLA_ASSERT_FALSE(StringToBoolTolerant("-1", &value)); OLA_ASSERT_FALSE(StringToBoolTolerant("2", &value)); OLA_ASSERT_FALSE(StringToBoolTolerant("a", &value)); OLA_ASSERT_TRUE(StringToBoolTolerant("true", &value)); OLA_ASSERT_EQ(value, true); OLA_ASSERT_TRUE(StringToBoolTolerant("false", &value)); OLA_ASSERT_EQ(value, false); OLA_ASSERT_TRUE(StringToBoolTolerant("TrUE", &value)); OLA_ASSERT_EQ(value, true); OLA_ASSERT_TRUE(StringToBoolTolerant("FalSe", &value)); OLA_ASSERT_EQ(value, false); OLA_ASSERT_TRUE(StringToBoolTolerant("t", &value)); OLA_ASSERT_EQ(value, true); OLA_ASSERT_TRUE(StringToBoolTolerant("f", &value)); OLA_ASSERT_EQ(value, false); OLA_ASSERT_TRUE(StringToBoolTolerant("T", &value)); OLA_ASSERT_EQ(value, true); OLA_ASSERT_TRUE(StringToBoolTolerant("F", &value)); OLA_ASSERT_EQ(value, false); OLA_ASSERT_TRUE(StringToBoolTolerant("1", &value)); OLA_ASSERT_EQ(value, true); OLA_ASSERT_TRUE(StringToBoolTolerant("0", &value)); OLA_ASSERT_EQ(value, false); OLA_ASSERT_TRUE(StringToBoolTolerant("on", &value)); OLA_ASSERT_EQ(value, true); OLA_ASSERT_TRUE(StringToBoolTolerant("off", &value)); OLA_ASSERT_EQ(value, false); OLA_ASSERT_TRUE(StringToBoolTolerant("On", &value)); OLA_ASSERT_EQ(value, true); OLA_ASSERT_TRUE(StringToBoolTolerant("oFf", &value)); OLA_ASSERT_EQ(value, false); OLA_ASSERT_TRUE(StringToBoolTolerant("enable", &value)); OLA_ASSERT_EQ(value, true); OLA_ASSERT_TRUE(StringToBoolTolerant("disable", &value)); OLA_ASSERT_EQ(value, false); OLA_ASSERT_TRUE(StringToBoolTolerant("EnAblE", &value)); OLA_ASSERT_EQ(value, true); OLA_ASSERT_TRUE(StringToBoolTolerant("dISaBle", &value)); OLA_ASSERT_EQ(value, false); OLA_ASSERT_TRUE(StringToBoolTolerant("enabled", &value)); OLA_ASSERT_EQ(value, true); OLA_ASSERT_TRUE(StringToBoolTolerant("disabled", &value)); OLA_ASSERT_EQ(value, false); OLA_ASSERT_TRUE(StringToBoolTolerant("eNabLED", &value)); OLA_ASSERT_EQ(value, true); OLA_ASSERT_TRUE(StringToBoolTolerant("DisaBLED", &value)); OLA_ASSERT_EQ(value, false); } void StringUtilsTest::testStringToUInt() { unsigned int value; OLA_ASSERT_FALSE(StringToInt("", &value)); OLA_ASSERT_FALSE(StringToInt("-1", &value)); OLA_ASSERT_TRUE(StringToInt("0", &value)); OLA_ASSERT_EQ(0u, value); OLA_ASSERT_TRUE(StringToInt("1", &value)); OLA_ASSERT_EQ(1u, value); OLA_ASSERT_TRUE(StringToInt(" 42050", &value)); OLA_ASSERT_EQ(42050u, value); OLA_ASSERT_TRUE(StringToInt("65537", &value)); OLA_ASSERT_EQ(65537u, value); OLA_ASSERT_TRUE(StringToInt("4294967295", &value)); OLA_ASSERT_EQ(4294967295U, value); OLA_ASSERT_FALSE(StringToInt("4294967296", &value)); OLA_ASSERT_FALSE(StringToInt("foo", &value)); // same tests with strict mode on OLA_ASSERT_FALSE(StringToInt("-1 foo", &value, true)); OLA_ASSERT_FALSE(StringToInt("0 ", &value, true)); OLA_ASSERT_FALSE(StringToInt("1 bar baz", &value, true)); OLA_ASSERT_FALSE(StringToInt("65537cat", &value, true)); OLA_ASSERT_FALSE(StringToInt("4294967295bat bar", &value, true)); } void StringUtilsTest::testStringToUIntOrDefault() { OLA_ASSERT_EQ(42u, StringToIntOrDefault("", 42u)); OLA_ASSERT_EQ(42u, StringToIntOrDefault("-1", 42u)); OLA_ASSERT_EQ(0u, StringToIntOrDefault("0", 42u)); OLA_ASSERT_EQ(1u, StringToIntOrDefault("1", 42u)); OLA_ASSERT_EQ(65537u, StringToIntOrDefault("65537", 42u)); OLA_ASSERT_EQ(4294967295U, StringToIntOrDefault("4294967295", 42u)); OLA_ASSERT_EQ(42u, StringToIntOrDefault("4294967296", 42u)); OLA_ASSERT_EQ(42u, StringToIntOrDefault("foo", 42u)); // same tests with strict mode on OLA_ASSERT_EQ(42u, StringToIntOrDefault("-1 foo", 42u, true)); OLA_ASSERT_EQ(42u, StringToIntOrDefault("0 ", 42u, true)); OLA_ASSERT_EQ(42u, StringToIntOrDefault("1 bar baz", 42u, true)); OLA_ASSERT_EQ(42u, StringToIntOrDefault("65537cat", 42u, true)); OLA_ASSERT_EQ(42u, StringToIntOrDefault("4294967295bat bar", 42u, true)); } void StringUtilsTest::testHexStringToInt() { unsigned int value; OLA_ASSERT_FALSE(HexStringToInt("", &value)); OLA_ASSERT_FALSE(HexStringToInt("-1", &value)); OLA_ASSERT_TRUE(HexStringToInt("0", &value)); OLA_ASSERT_EQ(0u, value); OLA_ASSERT_TRUE(HexStringToInt("1", &value)); OLA_ASSERT_EQ(1u, value); OLA_ASSERT_TRUE(HexStringToInt("a", &value)); OLA_ASSERT_EQ(10u, value); OLA_ASSERT_TRUE(HexStringToInt("f", &value)); OLA_ASSERT_EQ(15u, value); OLA_ASSERT_TRUE(HexStringToInt("a1", &value)); OLA_ASSERT_EQ(161u, value); OLA_ASSERT_TRUE(HexStringToInt("ff", &value)); OLA_ASSERT_EQ(255u, value); OLA_ASSERT_TRUE(HexStringToInt("a1", &value)); OLA_ASSERT_EQ(161u, value); OLA_ASSERT_TRUE(HexStringToInt("ff", &value)); OLA_ASSERT_EQ(255u, value); OLA_ASSERT_TRUE(HexStringToInt("ffff", &value)); OLA_ASSERT_EQ(65535u, value); OLA_ASSERT_TRUE(HexStringToInt("ffffff", &value)); OLA_ASSERT_EQ((unsigned int) 16777215, value); OLA_ASSERT_TRUE(HexStringToInt("ffffffff", &value)); OLA_ASSERT_EQ((unsigned int) 4294967295UL, value); OLA_ASSERT_TRUE(HexStringToInt("ef123456", &value)); OLA_ASSERT_EQ((unsigned int) 4010947670UL, value); OLA_ASSERT_FALSE(HexStringToInt("fz", &value)); OLA_ASSERT_FALSE(HexStringToInt("zfff", &value)); OLA_ASSERT_FALSE(HexStringToInt("0xf", &value)); // uint16_t uint16_t value2; OLA_ASSERT_FALSE(HexStringToInt("", &value2)); OLA_ASSERT_FALSE(HexStringToInt("-1", &value2)); OLA_ASSERT_TRUE(HexStringToInt("0", &value2)); OLA_ASSERT_EQ((uint16_t) 0, value2); OLA_ASSERT_TRUE(HexStringToInt("1", &value2)); OLA_ASSERT_EQ((uint16_t) 1, value2); OLA_ASSERT_TRUE(HexStringToInt("a", &value2)); OLA_ASSERT_EQ((uint16_t) 10, value2); OLA_ASSERT_TRUE(HexStringToInt("f", &value2)); OLA_ASSERT_EQ((uint16_t) 15, value2); OLA_ASSERT_TRUE(HexStringToInt("a1", &value2)); OLA_ASSERT_EQ((uint16_t) 161, value2); OLA_ASSERT_TRUE(HexStringToInt("ff", &value2)); OLA_ASSERT_EQ((uint16_t) 255, value2); OLA_ASSERT_TRUE(HexStringToInt("a1", &value2)); OLA_ASSERT_EQ((uint16_t) 161, value2); OLA_ASSERT_TRUE(HexStringToInt("ff", &value2)); OLA_ASSERT_EQ((uint16_t) 255, value2); OLA_ASSERT_TRUE(HexStringToInt("400", &value2)); OLA_ASSERT_EQ((uint16_t) 1024, value2); OLA_ASSERT_TRUE(HexStringToInt("ffff", &value2)); OLA_ASSERT_EQ((uint16_t) 65535, value2); OLA_ASSERT_FALSE(HexStringToInt("ffffff", &value2)); OLA_ASSERT_FALSE(HexStringToInt("ffffffff", &value2)); OLA_ASSERT_FALSE(HexStringToInt("ef123456", &value2)); OLA_ASSERT_FALSE(HexStringToInt("fz", &value2)); OLA_ASSERT_FALSE(HexStringToInt("zfff", &value2)); OLA_ASSERT_FALSE(HexStringToInt("0xf", &value2)); // int8_t int8_t value3; OLA_ASSERT_FALSE(HexStringToInt("", &value3)); OLA_ASSERT_FALSE(HexStringToInt("-1", &value3)); OLA_ASSERT_TRUE(HexStringToInt("0", &value3)); OLA_ASSERT_EQ((int8_t) 0, value3); OLA_ASSERT_TRUE(HexStringToInt("1", &value3)); OLA_ASSERT_EQ((int8_t) 1, value3); OLA_ASSERT_TRUE(HexStringToInt("a", &value3)); OLA_ASSERT_EQ((int8_t) 10, value3); OLA_ASSERT_TRUE(HexStringToInt("f", &value3)); OLA_ASSERT_EQ((int8_t) 15, value3); OLA_ASSERT_TRUE(HexStringToInt("7f", &value3)); OLA_ASSERT_EQ((int8_t) 127, value3); OLA_ASSERT_TRUE(HexStringToInt("a1", &value3)); OLA_ASSERT_EQ((int8_t) -95, value3); OLA_ASSERT_TRUE(HexStringToInt("80", &value3)); OLA_ASSERT_EQ((int8_t) -128, value3); OLA_ASSERT_TRUE(HexStringToInt("ff", &value3)); OLA_ASSERT_EQ((int8_t) -1, value3); OLA_ASSERT_FALSE(HexStringToInt("ffff", &value3)); OLA_ASSERT_FALSE(HexStringToInt("fff0", &value3)); OLA_ASSERT_FALSE(HexStringToInt("ffffff", &value3)); OLA_ASSERT_FALSE(HexStringToInt("ffffffff", &value3)); OLA_ASSERT_FALSE(HexStringToInt("ef123456", &value3)); OLA_ASSERT_FALSE(HexStringToInt("fz", &value3)); OLA_ASSERT_FALSE(HexStringToInt("zfff", &value3)); OLA_ASSERT_FALSE(HexStringToInt("0xf", &value3)); // int16_t int16_t value4; OLA_ASSERT_FALSE(HexStringToInt("", &value4)); OLA_ASSERT_FALSE(HexStringToInt("-1", &value4)); OLA_ASSERT_TRUE(HexStringToInt("0", &value4)); OLA_ASSERT_EQ((int16_t) 0, value4); OLA_ASSERT_TRUE(HexStringToInt("1", &value4)); OLA_ASSERT_EQ((int16_t) 1, value4); OLA_ASSERT_TRUE(HexStringToInt("a", &value4)); OLA_ASSERT_EQ((int16_t) 10, value4); OLA_ASSERT_TRUE(HexStringToInt("f", &value4)); OLA_ASSERT_EQ((int16_t) 15, value4); OLA_ASSERT_TRUE(HexStringToInt("a1", &value4)); OLA_ASSERT_EQ((int16_t) 161, value4); OLA_ASSERT_TRUE(HexStringToInt("ff", &value4)); OLA_ASSERT_EQ((int16_t) 255, value4); OLA_ASSERT_TRUE(HexStringToInt("7fff", &value4)); OLA_ASSERT_EQ((int16_t) 32767, value4); OLA_ASSERT_TRUE(HexStringToInt("ffff", &value4)); OLA_ASSERT_EQ((int16_t) -1, value4); OLA_ASSERT_TRUE(HexStringToInt("fff0", &value4)); OLA_ASSERT_EQ((int16_t) -16, value4); OLA_ASSERT_TRUE(HexStringToInt("8000", &value4)); OLA_ASSERT_EQ((int16_t) -32768, value4); OLA_ASSERT_FALSE(HexStringToInt("ffffff", &value4)); OLA_ASSERT_FALSE(HexStringToInt("ffffffff", &value4)); OLA_ASSERT_FALSE(HexStringToInt("ef123456", &value4)); OLA_ASSERT_FALSE(HexStringToInt("fz", &value4)); OLA_ASSERT_FALSE(HexStringToInt("zfff", &value4)); OLA_ASSERT_FALSE(HexStringToInt("0xf", &value4)); // int32 int32_t value5; OLA_ASSERT_FALSE(HexStringToInt("", &value5)); OLA_ASSERT_FALSE(HexStringToInt("-1", &value5)); OLA_ASSERT_TRUE(HexStringToInt("0", &value5)); OLA_ASSERT_EQ((int32_t) 0, value5); OLA_ASSERT_TRUE(HexStringToInt("1", &value5)); OLA_ASSERT_EQ((int32_t) 1, value5); OLA_ASSERT_TRUE(HexStringToInt("a", &value5)); OLA_ASSERT_EQ((int32_t) 10, value5); OLA_ASSERT_TRUE(HexStringToInt("f", &value5)); OLA_ASSERT_EQ((int32_t) 15, value5); OLA_ASSERT_TRUE(HexStringToInt("a1", &value5)); OLA_ASSERT_EQ((int32_t) 161, value5); OLA_ASSERT_TRUE(HexStringToInt("ff", &value5)); OLA_ASSERT_EQ((int32_t) 255, value5); OLA_ASSERT_TRUE(HexStringToInt("7fff", &value5)); OLA_ASSERT_EQ((int32_t) 32767, value5); OLA_ASSERT_TRUE(HexStringToInt("ffff", &value5)); OLA_ASSERT_EQ((int32_t) 65535, value5); OLA_ASSERT_TRUE(HexStringToInt("ffffffff", &value5)); OLA_ASSERT_EQ((int32_t) -1, value5); OLA_ASSERT_TRUE(HexStringToInt("fffffff0", &value5)); OLA_ASSERT_EQ((int32_t) -16, value5); OLA_ASSERT_TRUE(HexStringToInt("80000000", &value5)); OLA_ASSERT_EQ((int32_t) -2147483647 - 1, value5); } void StringUtilsTest::testPrefixedHexStringToInt() { int value; OLA_ASSERT_FALSE(PrefixedHexStringToInt("", &value)); OLA_ASSERT_FALSE(PrefixedHexStringToInt("-1", &value)); OLA_ASSERT_FALSE(PrefixedHexStringToInt("0", &value)); OLA_ASSERT_FALSE(PrefixedHexStringToInt("2000", &value)); OLA_ASSERT_FALSE(PrefixedHexStringToInt("0x", &value)); OLA_ASSERT_TRUE(PrefixedHexStringToInt("0x1", &value)); OLA_ASSERT_EQ(1, value); OLA_ASSERT_TRUE(PrefixedHexStringToInt("0xff", &value)); OLA_ASSERT_EQ(255, value); OLA_ASSERT_TRUE(PrefixedHexStringToInt("0x70ff", &value)); OLA_ASSERT_EQ(28927, value); OLA_ASSERT_TRUE(PrefixedHexStringToInt("0xffffffff", &value)); OLA_ASSERT_EQ(-1, value); OLA_ASSERT_TRUE(PrefixedHexStringToInt("0X7f", &value)); OLA_ASSERT_EQ(127, value); OLA_ASSERT_TRUE(PrefixedHexStringToInt("0X7F", &value)); OLA_ASSERT_EQ(127, value); OLA_ASSERT_TRUE(PrefixedHexStringToInt("0x7F", &value)); OLA_ASSERT_EQ(127, value); } void StringUtilsTest::testStringToUInt16() { uint16_t value; OLA_ASSERT_FALSE(StringToInt("", &value)); OLA_ASSERT_FALSE(StringToInt("-1", &value)); OLA_ASSERT_FALSE(StringToInt("65536", &value)); OLA_ASSERT_TRUE(StringToInt("0", &value)); OLA_ASSERT_EQ((uint16_t) 0, value); OLA_ASSERT_TRUE(StringToInt("1", &value)); OLA_ASSERT_EQ((uint16_t) 1, value); OLA_ASSERT_TRUE(StringToInt("143", &value)); OLA_ASSERT_EQ((uint16_t) 143, value); OLA_ASSERT_TRUE(StringToInt("65535", &value)); OLA_ASSERT_EQ((uint16_t) 65535, value); } void StringUtilsTest::testStringToUInt16OrDefault() { OLA_ASSERT_EQ((uint16_t) 42, StringToIntOrDefault("", (uint16_t) 42)); OLA_ASSERT_EQ((uint16_t) 42, StringToIntOrDefault("-1", (uint16_t) 42)); OLA_ASSERT_EQ((uint16_t) 42, StringToIntOrDefault("65536", (uint16_t) 42)); OLA_ASSERT_EQ((uint16_t) 0, StringToIntOrDefault("0", (uint16_t) 42)); OLA_ASSERT_EQ((uint16_t) 1, StringToIntOrDefault("1", (uint16_t) 42)); OLA_ASSERT_EQ((uint16_t) 143, StringToIntOrDefault("143", (uint16_t) 42)); OLA_ASSERT_EQ((uint16_t) 65535, StringToIntOrDefault("65535", (uint16_t) 42)); } void StringUtilsTest::testStringToUInt8() { uint8_t value; OLA_ASSERT_FALSE(StringToInt("", &value)); OLA_ASSERT_FALSE(StringToInt("-1", &value)); OLA_ASSERT_FALSE(StringToInt("256", &value)); OLA_ASSERT_TRUE(StringToInt("0", &value)); OLA_ASSERT_EQ((uint8_t) 0, value); OLA_ASSERT_TRUE(StringToInt("1", &value)); OLA_ASSERT_EQ((uint8_t) 1, value); OLA_ASSERT_TRUE(StringToInt("143", &value)); OLA_ASSERT_EQ((uint8_t) 143, value); OLA_ASSERT_TRUE(StringToInt("255", &value)); OLA_ASSERT_EQ((uint8_t) 255, value); } void StringUtilsTest::testStringToUInt8OrDefault() { OLA_ASSERT_EQ((uint8_t) 42, StringToIntOrDefault("", (uint8_t) 42)); OLA_ASSERT_EQ((uint8_t) 42, StringToIntOrDefault("-1", (uint8_t) 42)); OLA_ASSERT_EQ((uint8_t) 42, StringToIntOrDefault("256", (uint8_t) 42)); OLA_ASSERT_EQ((uint8_t) 0, StringToIntOrDefault("0", (uint8_t) 42)); OLA_ASSERT_EQ((uint8_t) 1, StringToIntOrDefault("1", (uint8_t) 42)); OLA_ASSERT_EQ((uint8_t) 143, StringToIntOrDefault("143", (uint8_t) 42)); OLA_ASSERT_EQ((uint8_t) 255, StringToIntOrDefault("255", (uint8_t) 42)); } void StringUtilsTest::testStringToInt() { int value; OLA_ASSERT_FALSE(StringToInt("", &value)); OLA_ASSERT_FALSE(StringToInt("a", &value)); OLA_ASSERT_FALSE(StringToInt("2147483649", &value)); OLA_ASSERT_TRUE(StringToInt("-2147483648", &value)); OLA_ASSERT_EQ(static_cast(-2147483647 - 1), value); OLA_ASSERT_TRUE(StringToInt("-2147483647", &value)); OLA_ASSERT_EQ(-2147483647, value); OLA_ASSERT_TRUE(StringToInt("-1", &value)); OLA_ASSERT_EQ(-1, value); OLA_ASSERT_TRUE(StringToInt("0", &value)); OLA_ASSERT_EQ(0, value); OLA_ASSERT_TRUE(StringToInt("1", &value)); OLA_ASSERT_EQ(1, value); OLA_ASSERT_TRUE(StringToInt("143", &value)); OLA_ASSERT_EQ(143, value); OLA_ASSERT_TRUE(StringToInt("2147483647", &value)); OLA_ASSERT_EQ(2147483647, value); OLA_ASSERT_FALSE(StringToInt("2147483648", &value)); // strict mode on OLA_ASSERT_FALSE(StringToInt("2147483649 ", &value, true)); OLA_ASSERT_FALSE(StringToInt("-2147483648bar", &value, true)); OLA_ASSERT_FALSE(StringToInt("-2147483647 baz", &value, true)); OLA_ASSERT_FALSE(StringToInt("-1.", &value, true)); OLA_ASSERT_FALSE(StringToInt("0!", &value, true)); OLA_ASSERT_FALSE(StringToInt("1 this is a test", &value, true)); OLA_ASSERT_FALSE(StringToInt("143car", &value, true)); OLA_ASSERT_FALSE(StringToInt("2147483647 !@#", &value, true)); OLA_ASSERT_FALSE(StringToInt("2147483648mm", &value, true)); } void StringUtilsTest::testStringToIntOrDefault() { OLA_ASSERT_EQ(42, StringToIntOrDefault("", 42)); OLA_ASSERT_EQ(42, StringToIntOrDefault("a", 42)); OLA_ASSERT_EQ(42, StringToIntOrDefault("2147483649", 42)); OLA_ASSERT_EQ(static_cast(-2147483647 - 1), StringToIntOrDefault("-2147483648", 42)); OLA_ASSERT_EQ(-2147483647, StringToIntOrDefault("-2147483647", 42)); OLA_ASSERT_EQ(-1, StringToIntOrDefault("-1", 42)); OLA_ASSERT_EQ(0, StringToIntOrDefault("0", 42)); OLA_ASSERT_EQ(1, StringToIntOrDefault("1", 42)); OLA_ASSERT_EQ(143, StringToIntOrDefault("143", 42)); OLA_ASSERT_EQ(2147483647, StringToIntOrDefault("2147483647", 42)); OLA_ASSERT_EQ(42, StringToIntOrDefault("2147483648", 42)); // strict mode on OLA_ASSERT_EQ(42, StringToIntOrDefault("2147483649 ", 42, true)); OLA_ASSERT_EQ(42, StringToIntOrDefault("-2147483648bar", 42, true)); OLA_ASSERT_EQ(42, StringToIntOrDefault("-2147483647 baz", 42, true)); OLA_ASSERT_EQ(42, StringToIntOrDefault("-1.", 42, true)); OLA_ASSERT_EQ(42, StringToIntOrDefault("0!", 42, true)); OLA_ASSERT_EQ(42, StringToIntOrDefault("1 this is a test", 42, true)); OLA_ASSERT_EQ(42, StringToIntOrDefault("143car", 42, true)); OLA_ASSERT_EQ(42, StringToIntOrDefault("2147483647 !@#", 42, true)); OLA_ASSERT_EQ(42, StringToIntOrDefault("2147483648mm", 42, true)); } void StringUtilsTest::testStringToInt16() { int16_t value; OLA_ASSERT_FALSE(StringToInt("", &value)); OLA_ASSERT_FALSE(StringToInt("a", &value)); OLA_ASSERT_FALSE(StringToInt("-32769", &value)); OLA_ASSERT_TRUE(StringToInt("-32768", &value)); OLA_ASSERT_EQ((int16_t) -32768, value); OLA_ASSERT_TRUE(StringToInt("-32767", &value)); OLA_ASSERT_EQ((int16_t) -32767, value); OLA_ASSERT_TRUE(StringToInt("-1", &value)); OLA_ASSERT_EQ((int16_t) -1, value); OLA_ASSERT_TRUE(StringToInt("0", &value)); OLA_ASSERT_EQ((int16_t) 0, value); OLA_ASSERT_TRUE(StringToInt("1", &value)); OLA_ASSERT_EQ((int16_t) 1, value); OLA_ASSERT_TRUE(StringToInt("143", &value)); OLA_ASSERT_EQ((int16_t) 143, value); OLA_ASSERT_TRUE(StringToInt("32767", &value)); OLA_ASSERT_EQ((int16_t) 32767, value); OLA_ASSERT_FALSE(StringToInt("32768", &value)); } void StringUtilsTest::testStringToInt16OrDefault() { OLA_ASSERT_EQ((int16_t) 42, StringToIntOrDefault("", (int16_t) 42)); OLA_ASSERT_EQ((int16_t) 42, StringToIntOrDefault("a", (int16_t) 42)); OLA_ASSERT_EQ((int16_t) 42, StringToIntOrDefault("-32769", (int16_t) 42)); OLA_ASSERT_EQ((int16_t) -32768, StringToIntOrDefault("-32768", (int16_t) 42)); OLA_ASSERT_EQ((int16_t) -32767, StringToIntOrDefault("-32767", (int16_t) 42)); OLA_ASSERT_EQ((int16_t) -1, StringToIntOrDefault("-1", (int16_t) 42)); OLA_ASSERT_EQ((int16_t) 0, StringToIntOrDefault("0", (int16_t) 42)); OLA_ASSERT_EQ((int16_t) 1, StringToIntOrDefault("1", (int16_t) 42)); OLA_ASSERT_EQ((int16_t) 143, StringToIntOrDefault("143", (int16_t) 42)); OLA_ASSERT_EQ((int16_t) 32767, StringToIntOrDefault("32767", (int16_t) 42)); OLA_ASSERT_EQ((int16_t) 42, StringToIntOrDefault("32768", (int16_t) 42)); } void StringUtilsTest::testStringToInt8() { int8_t value; OLA_ASSERT_FALSE(StringToInt("", &value)); OLA_ASSERT_FALSE(StringToInt("a", &value)); OLA_ASSERT_FALSE(StringToInt("-129", &value)); OLA_ASSERT_TRUE(StringToInt("-128", &value)); OLA_ASSERT_EQ((int8_t) -128, value); OLA_ASSERT_TRUE(StringToInt("-127", &value)); OLA_ASSERT_EQ((int8_t) -127, value); OLA_ASSERT_TRUE(StringToInt("-127", &value)); OLA_ASSERT_EQ((int8_t) -127, value); OLA_ASSERT_TRUE(StringToInt("-1", &value)); OLA_ASSERT_EQ((int8_t) -1, value); OLA_ASSERT_TRUE(StringToInt("0", &value)); OLA_ASSERT_EQ((int8_t) 0, value); OLA_ASSERT_TRUE(StringToInt("1", &value)); OLA_ASSERT_EQ((int8_t) 1, value); OLA_ASSERT_TRUE(StringToInt("127", &value)); OLA_ASSERT_EQ((int8_t) 127, value); OLA_ASSERT_FALSE(StringToInt("128", &value)); OLA_ASSERT_FALSE(StringToInt("129", &value)); } void StringUtilsTest::testStringToInt8OrDefault() { OLA_ASSERT_EQ((int8_t) 42, StringToIntOrDefault("", (int8_t) 42)); OLA_ASSERT_EQ((int8_t) 42, StringToIntOrDefault("a", (int8_t) 42)); OLA_ASSERT_EQ((int8_t) 42, StringToIntOrDefault("-129", (int8_t) 42)); OLA_ASSERT_EQ((int8_t) -128, StringToIntOrDefault("-128", (int8_t) 42)); OLA_ASSERT_EQ((int8_t) -127, StringToIntOrDefault("-127", (int8_t) 42)); OLA_ASSERT_EQ((int8_t) -127, StringToIntOrDefault("-127", (int8_t) 42)); OLA_ASSERT_EQ((int8_t) -1, StringToIntOrDefault("-1", (int8_t) 42)); OLA_ASSERT_EQ((int8_t) 0, StringToIntOrDefault("0", (int8_t) 42)); OLA_ASSERT_EQ((int8_t) 1, StringToIntOrDefault("1", (int8_t) 42)); OLA_ASSERT_EQ((int8_t) 127, StringToIntOrDefault("127", (int8_t) 42)); OLA_ASSERT_EQ((int8_t) 42, StringToIntOrDefault("128", (int8_t) 42)); OLA_ASSERT_EQ((int8_t) 42, StringToIntOrDefault("129", (int8_t) 42)); } void StringUtilsTest::testToLower() { string s = "HelLo There"; ToLower(&s); OLA_ASSERT_EQ(string("hello there"), s); } void StringUtilsTest::testToUpper() { string s = "HelLo There"; ToUpper(&s); OLA_ASSERT_EQ(string("HELLO THERE"), s); } void StringUtilsTest::testCapitalizeLabel() { string label = "this-is_a_test"; CapitalizeLabel(&label); OLA_ASSERT_EQ(string("This Is A Test"), label); } void StringUtilsTest::testCustomCapitalizeLabel() { string label1 = "dmx_start_address"; CustomCapitalizeLabel(&label1); OLA_ASSERT_EQ(string("DMX Start Address"), label1); string label2 = "foo-dmx"; CustomCapitalizeLabel(&label2); OLA_ASSERT_EQ(string("Foo DMX"), label2); string label3 = "mini_dmxter_device"; CustomCapitalizeLabel(&label3); OLA_ASSERT_EQ(string("Mini Dmxter Device"), label3); string label4 = "this-is_a_test"; CustomCapitalizeLabel(&label4); OLA_ASSERT_EQ(string("This Is A Test"), label4); string label5 = "ip_address"; CustomCapitalizeLabel(&label5); OLA_ASSERT_EQ(string("IP Address"), label5); string label6 = "controller_ip_address"; CustomCapitalizeLabel(&label6); OLA_ASSERT_EQ(string("Controller IP Address"), label6); string label7 = "dazzled_led_type"; CustomCapitalizeLabel(&label7); OLA_ASSERT_EQ(string("Dazzled LED Type"), label7); string label8 = "device_rdm_uid"; CustomCapitalizeLabel(&label8); OLA_ASSERT_EQ(string("Device RDM UID"), label8); string label9 = "dns_via_ipv4_dhcp"; CustomCapitalizeLabel(&label9); OLA_ASSERT_EQ(string("DNS Via IPV4 DHCP"), label9); } void StringUtilsTest::testCapitalizeFirst() { string label1 = "foo bar"; CapitalizeFirst(&label1); OLA_ASSERT_EQ(string("Foo bar"), label1); string label2 = "RDM bar"; CapitalizeFirst(&label2); OLA_ASSERT_EQ(string("RDM bar"), label2); } void StringUtilsTest::testFormatData() { uint8_t data[] = {0, 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', 1, 2}; std::ostringstream str; FormatData(&str, data, sizeof(data)); OLA_ASSERT_EQ( string("00 48 65 6c 6c 6f 20 57 .Hello W\n" "6f 72 6c 64 01 02 orld..\n"), str.str()); // try 4 bytes per line with a 2 space indent str.str(""); FormatData(&str, data, sizeof(data), 2, 4); OLA_ASSERT_EQ( string(" 00 48 65 6c .Hel\n" " 6c 6f 20 57 lo W\n" " 6f 72 6c 64 orld\n" " 01 02 ..\n"), str.str()); str.str(""); // try ending on the block boundary uint8_t data1[] = {'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o'}; FormatData(&str, data1, sizeof(data1), 0, 4); OLA_ASSERT_EQ( string("48 65 6c 6c Hell\n" "6f 20 57 6f o Wo\n"), str.str()); } void StringUtilsTest::testStringJoin() { vector ints; ints.push_back(1); ints.push_back(2); ints.push_back(3); OLA_ASSERT_EQ(string("1,2,3"), StringJoin(",", ints)); vector chars; chars.push_back('a'); chars.push_back('b'); chars.push_back('c'); OLA_ASSERT_EQ(string("a,b,c"), StringJoin(",", chars)); vector strings; strings.push_back("one"); strings.push_back("two"); strings.push_back("three"); OLA_ASSERT_EQ(string("one,two,three"), StringJoin(",", strings)); } void StringUtilsTest::testReplaceAll() { string input = ""; ReplaceAll(&input, "", ""); OLA_ASSERT_EQ(string(""), input); input = "abc"; ReplaceAll(&input, "", ""); OLA_ASSERT_EQ(string("abc"), input); ReplaceAll(&input, "", "def"); OLA_ASSERT_EQ(string("abc"), input); input = "abc"; ReplaceAll(&input, "b", "d"); OLA_ASSERT_EQ(string("adc"), input); input = "aaa"; ReplaceAll(&input, "a", "b"); OLA_ASSERT_EQ(string("bbb"), input); input = "abcdef"; ReplaceAll(&input, "cd", "cds"); OLA_ASSERT_EQ(string("abcdsef"), input); input = "abcdefabcdef"; ReplaceAll(&input, "cd", "gh"); OLA_ASSERT_EQ(string("abghefabghef"), input); input = "abcde"; ReplaceAll(&input, "c", "cdc"); OLA_ASSERT_EQ(string("abcdcde"), input); input = "abcdcdce"; ReplaceAll(&input, "cdc", "c"); OLA_ASSERT_EQ(string("abce"), input); input = "abcdcdcdce"; ReplaceAll(&input, "cdcdc", "cdc"); OLA_ASSERT_EQ(string("abcdce"), input); } ola-0.10.5.nojsmin/common/utils/BackoffTest.cpp0000644000175000017500000000663413023355232021016 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * BackoffTest.cpp * Test fixture for the TCPConnector class * Copyright (C) 2012 Simon Newton */ #include #include #include #include #include #include "ola/Callback.h" #include "ola/Clock.h" #include "ola/util/Backoff.h" #include "ola/testing/TestUtils.h" using ola::BackoffGenerator; using ola::ExponentialBackoffPolicy; using ola::LinearBackoffPolicy; using ola::TimeInterval; class BackoffTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(BackoffTest); CPPUNIT_TEST(testLinearBackoffPolicy); CPPUNIT_TEST(testExponentialBackoffPolicy); CPPUNIT_TEST(testBackoffGenerator); CPPUNIT_TEST_SUITE_END(); public: void testLinearBackoffPolicy(); void testExponentialBackoffPolicy(); void testBackoffGenerator(); }; CPPUNIT_TEST_SUITE_REGISTRATION(BackoffTest); /** * Test the linear backoff policy. */ void BackoffTest::testLinearBackoffPolicy() { // 5 per attempt, up to a max of 30 LinearBackoffPolicy policy(TimeInterval(5, 0), TimeInterval(30, 0)); OLA_ASSERT_EQ(TimeInterval(5, 0), policy.BackOffTime(1)); OLA_ASSERT_EQ(TimeInterval(10, 0), policy.BackOffTime(2)); OLA_ASSERT_EQ(TimeInterval(15, 0), policy.BackOffTime(3)); OLA_ASSERT_EQ(TimeInterval(30, 0), policy.BackOffTime(6)); OLA_ASSERT_EQ(TimeInterval(30, 0), policy.BackOffTime(7)); } /** * Test the exponential backoff policy. */ void BackoffTest::testExponentialBackoffPolicy() { // start with 10s, up to 170s. ExponentialBackoffPolicy policy(TimeInterval(10, 0), TimeInterval(170, 0)); OLA_ASSERT_EQ(TimeInterval(10, 0), policy.BackOffTime(1)); OLA_ASSERT_EQ(TimeInterval(20, 0), policy.BackOffTime(2)); OLA_ASSERT_EQ(TimeInterval(40, 0), policy.BackOffTime(3)); OLA_ASSERT_EQ(TimeInterval(80, 0), policy.BackOffTime(4)); OLA_ASSERT_EQ(TimeInterval(160, 0), policy.BackOffTime(5)); OLA_ASSERT_EQ(TimeInterval(170, 0), policy.BackOffTime(6)); OLA_ASSERT_EQ(TimeInterval(170, 0), policy.BackOffTime(7)); } /** * Test the BackoffGenerator */ void BackoffTest::testBackoffGenerator() { BackoffGenerator generator( new LinearBackoffPolicy(TimeInterval(5, 0), TimeInterval(30, 0))); OLA_ASSERT_EQ(TimeInterval(5, 0), generator.Next()); OLA_ASSERT_EQ(TimeInterval(10, 0), generator.Next()); OLA_ASSERT_EQ(TimeInterval(15, 0), generator.Next()); OLA_ASSERT_EQ(TimeInterval(20, 0), generator.Next()); OLA_ASSERT_EQ(TimeInterval(25, 0), generator.Next()); OLA_ASSERT_EQ(TimeInterval(30, 0), generator.Next()); generator.Reset(); OLA_ASSERT_EQ(TimeInterval(5, 0), generator.Next()); OLA_ASSERT_EQ(TimeInterval(10, 0), generator.Next()); OLA_ASSERT_EQ(TimeInterval(15, 0), generator.Next()); } ola-0.10.5.nojsmin/common/utils/ClockTest.cpp0000644000175000017500000001203413023355232020505 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * ClockTest.cpp * Unittest for String functions. * Copyright (C) 2005 Simon Newton */ #include #include #include #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #define VC_EXTRALEAN #include #endif // _WIN32 #include "ola/Clock.h" #include "ola/testing/TestUtils.h" class ClockTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(ClockTest); CPPUNIT_TEST(testTimeStamp); CPPUNIT_TEST(testTimeInterval); CPPUNIT_TEST(testTimeIntervalMutliplication); CPPUNIT_TEST(testClock); CPPUNIT_TEST(testMockClock); CPPUNIT_TEST_SUITE_END(); public: void testTimeStamp(); void testTimeInterval(); void testTimeIntervalMutliplication(); void testClock(); void testMockClock(); }; CPPUNIT_TEST_SUITE_REGISTRATION(ClockTest); using ola::Clock; using ola::MockClock; using ola::TimeStamp; using ola::TimeInterval; using std::string; /* * Test the TimeStamp class */ void ClockTest::testTimeStamp() { Clock clock; TimeStamp timestamp, timestamp2; OLA_ASSERT_FALSE(timestamp.IsSet()); OLA_ASSERT_FALSE(timestamp2.IsSet()); // test assignment & copy constructor clock.CurrentTime(×tamp); OLA_ASSERT_TRUE(timestamp.IsSet()); timestamp2 = timestamp; OLA_ASSERT_TRUE(timestamp2.IsSet()); TimeStamp timestamp3(timestamp); OLA_ASSERT_TRUE(timestamp3.IsSet()); OLA_ASSERT_EQ(timestamp, timestamp2); OLA_ASSERT_EQ(timestamp, timestamp3); // test equalities // Windows only seems to have ms resolution, to make the tests pass we need // to sleep here; XP only has 16ms resolution, so sleep a bit longer usleep(20000); clock.CurrentTime(×tamp3); OLA_ASSERT_NE(timestamp3, timestamp); OLA_ASSERT_GT(timestamp3, timestamp); OLA_ASSERT_LT(timestamp, timestamp3); // test intervals TimeInterval interval = timestamp3 - timestamp; // test subtraction / addition timestamp2 = timestamp + interval; OLA_ASSERT_EQ(timestamp2, timestamp3); timestamp2 -= interval; OLA_ASSERT_EQ(timestamp, timestamp2); // test toString and AsInt TimeInterval one_point_five_seconds(1500000); OLA_ASSERT_EQ(string("1.500000"), one_point_five_seconds.ToString()); OLA_ASSERT_EQ(static_cast(1500000), one_point_five_seconds.AsInt()); OLA_ASSERT_EQ(static_cast(1500), one_point_five_seconds.InMilliSeconds()); } /* * test time intervals */ void ClockTest::testTimeInterval() { // test intervals TimeInterval interval(500000); // 0.5s TimeInterval interval2 = interval; TimeInterval interval3(interval); OLA_ASSERT_EQ(interval, interval2); OLA_ASSERT_EQ(interval, interval3); TimeInterval interval4(1, 500000); // 1.5s OLA_ASSERT_NE(interval, interval4); OLA_ASSERT_LT(interval, interval4); TimeInterval interval5(1, 600000); // 1.6s OLA_ASSERT_NE(interval4, interval5); OLA_ASSERT_LT(interval4, interval5); } /* * Test multiplication of TimeIntervals. */ void ClockTest::testTimeIntervalMutliplication() { TimeInterval half_second(500000); // 0.5s TimeInterval zero_seconds = half_second * 0; OLA_ASSERT_EQ((int64_t) 0, zero_seconds.InMilliSeconds()); TimeInterval another_half_second = half_second * 1; OLA_ASSERT_EQ((int64_t) 500, another_half_second.InMilliSeconds()); TimeInterval two_seconds = half_second * 4; OLA_ASSERT_EQ((int64_t) 2000, two_seconds.InMilliSeconds()); TimeInterval twenty_seconds = half_second * 40; OLA_ASSERT_EQ((int64_t) 20000, twenty_seconds.InMilliSeconds()); } /** * test the clock */ void ClockTest::testClock() { Clock clock; TimeStamp first; clock.CurrentTime(&first); #ifdef _WIN32 Sleep(1000); #else sleep(1); #endif // _WIN32 TimeStamp second; clock.CurrentTime(&second); OLA_ASSERT_LT(first, second); } /** * test the Mock Clock */ void ClockTest::testMockClock() { MockClock clock; TimeStamp first; clock.CurrentTime(&first); TimeInterval one_second(1, 0); clock.AdvanceTime(one_second); TimeStamp second; clock.CurrentTime(&second); OLA_ASSERT_LT(first, second); OLA_ASSERT_TRUE(one_second <= (second - first)); TimeInterval ten_point_five_seconds(10, 500000); clock.AdvanceTime(10, 500000); TimeStamp third; clock.CurrentTime(&third); OLA_ASSERT_LT(second, third); OLA_ASSERT_TRUE(ten_point_five_seconds <= (third - second)); } ola-0.10.5.nojsmin/common/utils/Clock.cpp0000644000175000017500000001624213023355232017652 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Clock.cpp * Provides the TimeInterval and TimeStamp classes. * Copyright (C) 2005 Simon Newton * * The struct timeval can represent both absolute time and time intervals. * We define our own wrapper classes that: * - hide some of the platform differences, like the fact windows doesn't * provide timersub. * - Reduces bugs by using the compiler to check if the value was supposed * to be an interval or absolute time. For example, passing an absolute * time intstead of an Interval to RegisterTimeout would be bad. */ #include #include #include #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #include #include #include namespace ola { using std::string; BaseTimeVal::BaseTimeVal(int32_t sec, int32_t usec) { m_tv.tv_sec = sec; m_tv.tv_usec = usec; } BaseTimeVal& BaseTimeVal::operator=(const BaseTimeVal& other) { if (this != &other) { m_tv = other.m_tv; } return *this; } BaseTimeVal& BaseTimeVal::operator=(const struct timeval &tv) { m_tv = tv; return *this; } bool BaseTimeVal::operator==(const BaseTimeVal &other) const { return timercmp(&m_tv, &other.m_tv, ==); } bool BaseTimeVal::operator!=(const BaseTimeVal &other) const { return !(*this == other); } bool BaseTimeVal::operator>(const BaseTimeVal &other) const { return timercmp(&m_tv, &other.m_tv, >); } bool BaseTimeVal::operator>=(const BaseTimeVal &other) const { return timercmp(&m_tv, &other.m_tv, >=); } bool BaseTimeVal::operator<(const BaseTimeVal &other) const { return timercmp(&m_tv, &other.m_tv, <); } bool BaseTimeVal::operator<=(const BaseTimeVal &other) const { return timercmp(&m_tv, &other.m_tv, <=); } BaseTimeVal& BaseTimeVal::operator+=(const BaseTimeVal& other) { if (this != &other) { TimerAdd(m_tv, other.m_tv, &m_tv); } return *this; } BaseTimeVal &BaseTimeVal::operator-=(const BaseTimeVal &other) { if (this != &other) { TimerSub(m_tv, other.m_tv, &m_tv); } return *this; } const BaseTimeVal BaseTimeVal::operator+(const BaseTimeVal &interval) const { BaseTimeVal result = *this; result += interval; return result; } const BaseTimeVal BaseTimeVal::operator-(const BaseTimeVal &other) const { BaseTimeVal result; TimerSub(m_tv, other.m_tv, &result.m_tv); return result; } BaseTimeVal BaseTimeVal::operator*(unsigned int i) const { int64_t as_int = (*this).AsInt(); as_int *= i; return BaseTimeVal(as_int); } bool BaseTimeVal::IsSet() const { return timerisset(&m_tv); } void BaseTimeVal::AsTimeval(struct timeval *tv) const { *tv = m_tv; } int64_t BaseTimeVal::InMilliSeconds() const { return (m_tv.tv_sec * static_cast(ONE_THOUSAND) + m_tv.tv_usec / ONE_THOUSAND); } int64_t BaseTimeVal::AsInt() const { return (m_tv.tv_sec * static_cast(USEC_IN_SECONDS) + m_tv.tv_usec); } string BaseTimeVal::ToString() const { std::ostringstream str; str << m_tv.tv_sec << "." << std::setfill('0') << std::setw(6) << m_tv.tv_usec; return str.str(); } void BaseTimeVal::TimerAdd(const struct timeval &tv1, const struct timeval &tv2, struct timeval *result) const { result->tv_sec = tv1.tv_sec + tv2.tv_sec; result->tv_usec = tv1.tv_usec + tv2.tv_usec; if (result->tv_usec >= USEC_IN_SECONDS) { result->tv_sec++; result->tv_usec -= USEC_IN_SECONDS; } } void BaseTimeVal::TimerSub(const struct timeval &tv1, const struct timeval &tv2, struct timeval *result) const { result->tv_sec = tv1.tv_sec - tv2.tv_sec; result->tv_usec = tv1.tv_usec - tv2.tv_usec; if (result->tv_usec < 0) { result->tv_sec--; result->tv_usec += USEC_IN_SECONDS; } } void BaseTimeVal::Set(int64_t interval_useconds) { #ifdef HAVE_TIME_T m_tv.tv_sec = static_cast( interval_useconds / USEC_IN_SECONDS); #else m_tv.tv_sec = interval_useconds / USEC_IN_SECONDS; #endif // HAVE_TIME_T #ifdef HAVE_SUSECONDS_T m_tv.tv_usec = static_cast(interval_useconds % USEC_IN_SECONDS); #else m_tv.tv_usec = interval_useconds % USEC_IN_SECONDS; #endif // HAVE_SUSECONDS_T } TimeInterval& TimeInterval::operator=(const TimeInterval& other) { if (this != &other) { m_interval = other.m_interval; } return *this; } bool TimeInterval::operator==(const TimeInterval &other) const { return m_interval == other.m_interval; } bool TimeInterval::operator!=(const TimeInterval &other) const { return m_interval != other.m_interval; } bool TimeInterval::operator>(const TimeInterval &other) const { return m_interval > other.m_interval; } bool TimeInterval::operator>=(const TimeInterval &other) const { return m_interval >= other.m_interval; } bool TimeInterval::operator<(const TimeInterval &other) const { return m_interval < other.m_interval; } bool TimeInterval::operator<=(const TimeInterval &other) const { return m_interval <= other.m_interval; } TimeInterval& TimeInterval::operator+=(const TimeInterval& other) { if (this != &other) { m_interval += other.m_interval; } return *this; } TimeInterval TimeInterval::operator*(unsigned int i) const { return TimeInterval(m_interval * i); } TimeStamp& TimeStamp::operator=(const TimeStamp& other) { if (this != &other) { m_tv = other.m_tv; } return *this; } TimeStamp& TimeStamp::operator=(const struct timeval &tv) { m_tv = tv; return *this; } TimeStamp &TimeStamp::operator+=(const TimeInterval &interval) { m_tv += interval.m_interval; return *this; } TimeStamp &TimeStamp::operator-=(const TimeInterval &interval) { m_tv -= interval.m_interval; return *this; } const TimeStamp TimeStamp::operator+(const TimeInterval &interval) const { return TimeStamp(m_tv + interval.m_interval); } const TimeInterval TimeStamp::operator-(const TimeStamp &other) const { return TimeInterval(m_tv - other.m_tv); } const TimeStamp TimeStamp::operator-(const TimeInterval &interval) const { return TimeStamp(m_tv - interval.m_interval); } void Clock::CurrentTime(TimeStamp *timestamp) const { struct timeval tv; gettimeofday(&tv, NULL); *timestamp = tv; } void MockClock::AdvanceTime(const TimeInterval &interval) { m_offset += interval; } void MockClock::AdvanceTime(int32_t sec, int32_t usec) { TimeInterval interval(sec, usec); m_offset += interval; } void MockClock::CurrentTime(TimeStamp *timestamp) const { struct timeval tv; gettimeofday(&tv, NULL); *timestamp = tv; *timestamp += m_offset; } } // namespace ola ola-0.10.5.nojsmin/common/utils/DmxBufferTest.cpp0000644000175000017500000004216513023355232021344 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * DmxBufferTest.cpp * Unittest for the DmxBuffer * Copyright (C) 2005 Simon Newton */ #include #include #include #include "ola/Constants.h" #include "ola/DmxBuffer.h" #include "ola/testing/TestUtils.h" using std::ostringstream; using std::string; using ola::DmxBuffer; class DmxBufferTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(DmxBufferTest); CPPUNIT_TEST(testBlackout); CPPUNIT_TEST(testGetSet); CPPUNIT_TEST(testStringGetSet); CPPUNIT_TEST(testAssign); CPPUNIT_TEST(testCopy); CPPUNIT_TEST(testMerge); CPPUNIT_TEST(testStringToDmx); CPPUNIT_TEST(testCopyOnWrite); CPPUNIT_TEST(testSetRange); CPPUNIT_TEST(testSetRangeToValue); CPPUNIT_TEST(testSetChannel); CPPUNIT_TEST(testToString); CPPUNIT_TEST_SUITE_END(); public: void testBlackout(); void testGetSet(); void testAssign(); void testStringGetSet(); void testCopy(); void testMerge(); void testStringToDmx(); void testCopyOnWrite(); void testSetRange(); void testSetRangeToValue(); void testSetChannel(); void testToString(); private: static const uint8_t TEST_DATA[]; static const uint8_t TEST_DATA2[]; static const uint8_t TEST_DATA3[]; static const uint8_t MERGE_RESULT[]; static const uint8_t MERGE_RESULT2[]; void runStringToDmx(const string &input, const DmxBuffer &expected); }; const uint8_t DmxBufferTest::TEST_DATA[] = {1, 2, 3, 4, 5}; const uint8_t DmxBufferTest::TEST_DATA2[] = {9, 8, 7, 6, 5, 4, 3, 2, 1}; const uint8_t DmxBufferTest::TEST_DATA3[] = {10, 11, 12}; const uint8_t DmxBufferTest::MERGE_RESULT[] = {10, 11, 12, 4, 5}; const uint8_t DmxBufferTest::MERGE_RESULT2[] = {10, 11, 12, 6, 5, 4, 3, 2, 1}; CPPUNIT_TEST_SUITE_REGISTRATION(DmxBufferTest); /* * Test that Blackout() works */ void DmxBufferTest::testBlackout() { DmxBuffer buffer; OLA_ASSERT_TRUE(buffer.Blackout()); uint8_t *result = new uint8_t[ola::DMX_UNIVERSE_SIZE]; uint8_t *zero = new uint8_t[ola::DMX_UNIVERSE_SIZE]; unsigned int result_length = ola::DMX_UNIVERSE_SIZE; memset(zero, 0, ola::DMX_UNIVERSE_SIZE); buffer.Get(result, &result_length); OLA_ASSERT_EQ((unsigned int) ola::DMX_UNIVERSE_SIZE, result_length); OLA_ASSERT_EQ(0, memcmp(zero, result, result_length)); delete[] result; delete[] zero; buffer.Reset(); OLA_ASSERT_EQ(0u, buffer.Size()); } /* * Check that Get/Set works correctly */ void DmxBufferTest::testGetSet() { unsigned int fudge_factor = 10; unsigned int result_length = sizeof(TEST_DATA2) + fudge_factor; uint8_t *result = new uint8_t[result_length]; unsigned int size = result_length; DmxBuffer buffer; string str_result; OLA_ASSERT_EQ((uint8_t) 0, buffer.Get(0)); OLA_ASSERT_EQ((uint8_t) 0, buffer.Get(1)); OLA_ASSERT_FALSE(buffer.Set(NULL, sizeof(TEST_DATA))); OLA_ASSERT_TRUE(buffer.Set(TEST_DATA, sizeof(TEST_DATA))); OLA_ASSERT_EQ((uint8_t) 1, buffer.Get(0)); OLA_ASSERT_EQ((uint8_t) 2, buffer.Get(1)); OLA_ASSERT_EQ((unsigned int) sizeof(TEST_DATA), buffer.Size()); buffer.Get(result, &size); OLA_ASSERT_EQ((unsigned int) sizeof(TEST_DATA), size); OLA_ASSERT_EQ(0, memcmp(TEST_DATA, result, size)); str_result = buffer.Get(); OLA_ASSERT_EQ((size_t) sizeof(TEST_DATA), str_result.length()); OLA_ASSERT_EQ(0, memcmp(TEST_DATA, str_result.data(), str_result.length())); size = result_length; OLA_ASSERT_TRUE(buffer.Set(TEST_DATA2, sizeof(TEST_DATA2))); OLA_ASSERT_EQ((unsigned int) sizeof(TEST_DATA2), buffer.Size()); buffer.Get(result, &size); OLA_ASSERT_EQ((unsigned int) sizeof(TEST_DATA2), size); OLA_ASSERT_EQ(0, memcmp(TEST_DATA2, result, size)); str_result = buffer.Get(); OLA_ASSERT_EQ((size_t) sizeof(TEST_DATA2), str_result.length()); OLA_ASSERT_EQ(0, memcmp(TEST_DATA2, str_result.data(), str_result.length())); // now check that Set() with another buffer works DmxBuffer buffer2; buffer2.Set(buffer); str_result = buffer2.Get(); OLA_ASSERT_EQ((size_t) sizeof(TEST_DATA2), str_result.length()); OLA_ASSERT_EQ(0, memcmp(TEST_DATA2, str_result.data(), str_result.length())); delete[] result; } /* * Check that the string set/get methods work */ void DmxBufferTest::testStringGetSet() { const string data = "abcdefg"; DmxBuffer buffer; uint8_t *result = new uint8_t[data.length()]; unsigned int size = data.length(); // Check that setting works OLA_ASSERT_TRUE(buffer.Set(data)); OLA_ASSERT_EQ(data.length(), (size_t) buffer.Size()); OLA_ASSERT_EQ(data, buffer.Get()); buffer.Get(result, &size); OLA_ASSERT_EQ(data.length(), (size_t) size); OLA_ASSERT_EQ(0, memcmp(data.data(), result, size)); // Check the string constructor DmxBuffer string_buffer(data); OLA_ASSERT_TRUE(buffer == string_buffer); // Set with an empty string string data2; size = data.length(); OLA_ASSERT_TRUE(buffer.Set(data2)); OLA_ASSERT_EQ(data2.length(), (size_t) buffer.Size()); OLA_ASSERT_EQ(data2, buffer.Get()); buffer.Get(result, &size); OLA_ASSERT_EQ(data2.length(), (size_t) size); OLA_ASSERT_EQ(0, memcmp(data2.data(), result, size)); delete[] result; } /* * Check the copy and assignment operators work */ void DmxBufferTest::testAssign() { unsigned int fudge_factor = 10; unsigned int result_length = sizeof(TEST_DATA) + fudge_factor; uint8_t *result = new uint8_t[result_length]; DmxBuffer buffer(TEST_DATA, sizeof(TEST_DATA)); DmxBuffer assignment_buffer(TEST_DATA3, sizeof(TEST_DATA3)); DmxBuffer assignment_buffer2; // assigning to ourself does nothing buffer = buffer; // assinging to a previously init'ed buffer unsigned int size = result_length; assignment_buffer = buffer; assignment_buffer.Get(result, &size); OLA_ASSERT_EQ((unsigned int) sizeof(TEST_DATA), assignment_buffer.Size()); OLA_ASSERT_EQ((unsigned int) sizeof(TEST_DATA), size); OLA_ASSERT_EQ(0, memcmp(TEST_DATA, result, size)); OLA_ASSERT_TRUE(assignment_buffer == buffer); // assigning to a non-init'ed buffer assignment_buffer2 = buffer; size = result_length; assignment_buffer2.Get(result, &result_length); OLA_ASSERT_EQ((unsigned int) sizeof(TEST_DATA), assignment_buffer2.Size()); OLA_ASSERT_EQ((unsigned int) sizeof(TEST_DATA), result_length); OLA_ASSERT_EQ(0, memcmp(TEST_DATA, result, result_length)); OLA_ASSERT_TRUE(assignment_buffer2 == buffer); // now try assigning an unitialized buffer DmxBuffer uninitialized_buffer; DmxBuffer assignment_buffer3; assignment_buffer3 = uninitialized_buffer; OLA_ASSERT_EQ(0u, assignment_buffer3.Size()); size = result_length; assignment_buffer3.Get(result, &result_length); OLA_ASSERT_EQ(0u, result_length); OLA_ASSERT_TRUE(assignment_buffer3 == uninitialized_buffer); // Check two buffers differ OLA_ASSERT_TRUE(assignment_buffer3 != assignment_buffer2); OLA_ASSERT_TRUE(buffer != assignment_buffer3); delete[] result; } /* * Check that the copy constructor works */ void DmxBufferTest::testCopy() { DmxBuffer buffer(TEST_DATA2, sizeof(TEST_DATA2)); OLA_ASSERT_EQ((unsigned int) sizeof(TEST_DATA2), buffer.Size()); DmxBuffer copy_buffer(buffer); OLA_ASSERT_EQ((unsigned int) sizeof(TEST_DATA2), copy_buffer.Size()); OLA_ASSERT_TRUE(copy_buffer == buffer); unsigned int result_length = sizeof(TEST_DATA2); uint8_t *result = new uint8_t[result_length]; copy_buffer.Get(result, &result_length); OLA_ASSERT_EQ((unsigned int) sizeof(TEST_DATA2), result_length); OLA_ASSERT_EQ(0, memcmp(TEST_DATA2, result, result_length)); delete[] result; } /* * Check that HTP Merging works */ void DmxBufferTest::testMerge() { DmxBuffer buffer1(TEST_DATA, sizeof(TEST_DATA)); DmxBuffer buffer2(TEST_DATA3, sizeof(TEST_DATA3)); DmxBuffer merge_result(MERGE_RESULT, sizeof(MERGE_RESULT)); const DmxBuffer test_buffer(buffer1); const DmxBuffer test_buffer2(buffer2); DmxBuffer uninitialized_buffer, uninitialized_buffer2; // merge into an empty buffer OLA_ASSERT_TRUE(uninitialized_buffer.HTPMerge(buffer2)); OLA_ASSERT_EQ((unsigned int) sizeof(TEST_DATA3), buffer2.Size()); OLA_ASSERT_TRUE(test_buffer2 == uninitialized_buffer); // merge from an empty buffer OLA_ASSERT_TRUE(buffer2.HTPMerge(uninitialized_buffer2)); OLA_ASSERT_TRUE(buffer2 == test_buffer2); // merge two buffers (longer into shorter) buffer2 = test_buffer2; OLA_ASSERT_TRUE(buffer2.HTPMerge(buffer1)); OLA_ASSERT_TRUE(buffer2 == merge_result); // merge shorter into longer buffer2 = test_buffer2; OLA_ASSERT_TRUE(buffer1.HTPMerge(buffer2)); OLA_ASSERT_TRUE(buffer1 == merge_result); } /* * Run the StringToDmxTest * @param input the string to parse * @param expected the expected result */ void DmxBufferTest::runStringToDmx(const string &input, const DmxBuffer &expected) { DmxBuffer buffer; OLA_ASSERT_TRUE(buffer.SetFromString(input)); OLA_ASSERT_TRUE(expected == buffer); } /* * Test the StringToDmx function */ void DmxBufferTest::testStringToDmx() { string input = "1,2,3,4"; uint8_t expected1[] = {1, 2, 3, 4}; runStringToDmx(input, DmxBuffer(expected1, sizeof(expected1))); input = "a,b,c,d"; uint8_t expected2[] = {0, 0, 0, 0}; runStringToDmx(input, DmxBuffer(expected2, sizeof(expected2))); input = "a,b,c,"; uint8_t expected3[] = {0, 0, 0, 0}; runStringToDmx(input, DmxBuffer(expected3, sizeof(expected3))); input = "255,,,"; uint8_t expected4[] = {255, 0, 0, 0}; runStringToDmx(input, DmxBuffer(expected4, sizeof(expected4))); input = "255,,,10"; uint8_t expected5[] = {255, 0, 0, 10}; runStringToDmx(input, DmxBuffer(expected5, sizeof(expected5))); input = " 266,,,10 "; uint8_t expected6[] = {10, 0, 0, 10}; runStringToDmx(input, DmxBuffer(expected6, sizeof(expected6))); input = ""; uint8_t expected7[] = {}; runStringToDmx(input, DmxBuffer(expected7, sizeof(expected7))); } /* * Check that we make a copy of the buffers before writing */ void DmxBufferTest::testCopyOnWrite() { string initial_data; initial_data.append((const char*) TEST_DATA2, sizeof(TEST_DATA2)); // these are used for comparisons and don't change const DmxBuffer buffer3(TEST_DATA3, sizeof(TEST_DATA3)); const DmxBuffer merge_result(MERGE_RESULT2, sizeof(MERGE_RESULT2)); DmxBuffer src_buffer(initial_data); DmxBuffer dest_buffer(src_buffer); // Check HTPMerge dest_buffer.HTPMerge(buffer3); OLA_ASSERT_EQ(initial_data, src_buffer.Get()); OLA_ASSERT_TRUE(merge_result == dest_buffer); dest_buffer = src_buffer; // Check the other way src_buffer.HTPMerge(buffer3); OLA_ASSERT_TRUE(merge_result == src_buffer); OLA_ASSERT_TRUE(initial_data == dest_buffer.Get()); src_buffer = dest_buffer; // Check Set works dest_buffer.Set(TEST_DATA3, sizeof(TEST_DATA3)); OLA_ASSERT_EQ(initial_data, src_buffer.Get()); OLA_ASSERT_TRUE(buffer3 == dest_buffer); dest_buffer = src_buffer; // Check it works the other way OLA_ASSERT_TRUE(initial_data == src_buffer.Get()); OLA_ASSERT_TRUE(initial_data == dest_buffer.Get()); src_buffer.Set(TEST_DATA3, sizeof(TEST_DATA3)); OLA_ASSERT_TRUE(buffer3 == src_buffer); OLA_ASSERT_TRUE(initial_data == dest_buffer.Get()); src_buffer = dest_buffer; // Check that SetFromString works dest_buffer = src_buffer; dest_buffer.SetFromString("10,11,12"); OLA_ASSERT_EQ(initial_data, src_buffer.Get()); OLA_ASSERT_TRUE(buffer3 == dest_buffer); dest_buffer = src_buffer; // Check it works the other way OLA_ASSERT_EQ(initial_data, src_buffer.Get()); OLA_ASSERT_EQ(initial_data, dest_buffer.Get()); src_buffer.SetFromString("10,11,12"); OLA_ASSERT_TRUE(buffer3 == src_buffer); OLA_ASSERT_EQ(initial_data, dest_buffer.Get()); src_buffer = dest_buffer; // Check the SetChannel() method, this should force a copy. dest_buffer.SetChannel(0, 244); string expected_change = initial_data; expected_change[0] = (uint8_t) 244; OLA_ASSERT_EQ(initial_data, src_buffer.Get()); OLA_ASSERT_EQ(expected_change, dest_buffer.Get()); dest_buffer = src_buffer; // Check it works the other way OLA_ASSERT_EQ(initial_data, src_buffer.Get()); OLA_ASSERT_EQ(initial_data, dest_buffer.Get()); src_buffer.SetChannel(0, 234); expected_change[0] = (uint8_t) 234; OLA_ASSERT_EQ(expected_change, src_buffer.Get()); OLA_ASSERT_EQ(initial_data, dest_buffer.Get()); src_buffer.Set(initial_data); } /* * Check that SetRange works. */ void DmxBufferTest::testSetRange() { unsigned int data_size = sizeof(TEST_DATA); DmxBuffer buffer; OLA_ASSERT_FALSE(buffer.SetRange(0, NULL, data_size)); OLA_ASSERT_FALSE(buffer.SetRange(600, TEST_DATA, data_size)); // Setting an uninitialized buffer calls blackout first OLA_ASSERT_TRUE(buffer.SetRange(0, TEST_DATA, data_size)); OLA_ASSERT_EQ((unsigned int) ola::DMX_UNIVERSE_SIZE, buffer.Size()); OLA_ASSERT_EQ(0, memcmp(TEST_DATA, buffer.GetRaw(), data_size)); // try overrunning the buffer OLA_ASSERT_TRUE(buffer.SetRange(ola::DMX_UNIVERSE_SIZE - 2, TEST_DATA, data_size)); OLA_ASSERT_EQ((unsigned int) ola::DMX_UNIVERSE_SIZE, buffer.Size()); OLA_ASSERT_EQ(0, memcmp(TEST_DATA, buffer.GetRaw() + ola::DMX_UNIVERSE_SIZE - 2, 2)); // reset the buffer so that the valid data is 0, and try again buffer.Reset(); OLA_ASSERT_TRUE(buffer.SetRange(0, TEST_DATA, data_size)); OLA_ASSERT_EQ((unsigned int) data_size, buffer.Size()); OLA_ASSERT_EQ(0, memcmp(TEST_DATA, buffer.GetRaw(), data_size)); // setting past the end of the valid data should fail OLA_ASSERT_FALSE(buffer.SetRange(50, TEST_DATA, data_size)); OLA_ASSERT_EQ((unsigned int) data_size, buffer.Size()); OLA_ASSERT_EQ(0, memcmp(TEST_DATA, buffer.GetRaw(), buffer.Size())); // overwrite part of the valid data unsigned int offset = 2; OLA_ASSERT_TRUE(buffer.SetRange(offset, TEST_DATA, data_size)); OLA_ASSERT_EQ((unsigned int) data_size + offset, buffer.Size()); OLA_ASSERT_EQ(0, memcmp(TEST_DATA, buffer.GetRaw(), offset)); OLA_ASSERT_EQ(0, memcmp(TEST_DATA, buffer.GetRaw() + offset, buffer.Size() - offset)); // now try writing 1 channel past the valid data buffer.Reset(); OLA_ASSERT_TRUE(buffer.SetRange(0, TEST_DATA, data_size)); OLA_ASSERT_TRUE(buffer.SetRange(data_size, TEST_DATA, data_size)); OLA_ASSERT_EQ((unsigned int) data_size * 2, buffer.Size()); OLA_ASSERT_EQ(0, memcmp(TEST_DATA, buffer.GetRaw(), data_size)); OLA_ASSERT_EQ(0, memcmp(TEST_DATA, buffer.GetRaw() + data_size, data_size)); } /* * Check that SetRangeToValue works */ void DmxBufferTest::testSetRangeToValue() { const uint8_t RANGE_DATA[] = {50, 50, 50, 50, 50}; DmxBuffer buffer; OLA_ASSERT_FALSE(buffer.SetRangeToValue(600, 50, 2)); unsigned int range_size = 5; OLA_ASSERT_TRUE(buffer.SetRangeToValue(0, 50, range_size)); OLA_ASSERT_EQ((unsigned int) ola::DMX_UNIVERSE_SIZE, buffer.Size()); OLA_ASSERT_EQ(0, memcmp(RANGE_DATA, buffer.GetRaw(), range_size)); // setting outside the value range should fail buffer.Reset(); OLA_ASSERT_FALSE(buffer.SetRange(10, TEST_DATA, range_size)); } /* * Check that SetChannel works */ void DmxBufferTest::testSetChannel() { DmxBuffer buffer; buffer.SetChannel(1, 10); buffer.SetChannel(10, 50); uint8_t expected[ola::DMX_UNIVERSE_SIZE]; memset(expected, 0, ola::DMX_UNIVERSE_SIZE); expected[1] = 10; expected[10] = 50; OLA_ASSERT_EQ((unsigned int) ola::DMX_UNIVERSE_SIZE, buffer.Size()); OLA_ASSERT_EQ(0, memcmp(expected, buffer.GetRaw(), buffer.Size())); // Check we can't set values greater than the buffer size buffer.SetChannel(999, 50); OLA_ASSERT_EQ((unsigned int) ola::DMX_UNIVERSE_SIZE, buffer.Size()); OLA_ASSERT_EQ(0, memcmp(expected, buffer.GetRaw(), buffer.Size())); // Check we can't set values outside the current valida data range unsigned int slice_size = 20; buffer.Set(expected, slice_size); buffer.SetChannel(30, 90); buffer.SetChannel(200, 10); OLA_ASSERT_EQ(slice_size, buffer.Size()); OLA_ASSERT_EQ(0, memcmp(expected, buffer.GetRaw(), buffer.Size())); } /* * Test ToString() */ void DmxBufferTest::testToString() { DmxBuffer buffer; OLA_ASSERT_EQ(string(""), buffer.ToString()); buffer.SetFromString("1,2,3,4"); OLA_ASSERT_EQ(string("1,2,3,4"), buffer.ToString()); buffer.SetRangeToValue(0, 255, 5); OLA_ASSERT_EQ(string("255,255,255,255,255"), buffer.ToString()); buffer.SetFromString("1,2,3,4"); ostringstream str; str << buffer; OLA_ASSERT_EQ(string("1,2,3,4"), str.str()); } ola-0.10.5.nojsmin/common/utils/DmxBuffer.cpp0000644000175000017500000002074513023355232020504 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * DmxBuffer.cpp * The DmxBuffer class * Copyright (C) 2005 Simon Newton * * This implements a DmxBuffer which uses copy-on-write and delayed init. * * A DmxBuffer can hold up to 512 bytes of channel information. The amount of * valid data is returned by calling Size(). */ /** * @file DmxBuffer.cpp */ #include #include #include #include #include #include "ola/Constants.h" #include "ola/DmxBuffer.h" #include "ola/Logging.h" #include "ola/StringUtils.h" namespace ola { using std::min; using std::max; using std::string; using std::vector; DmxBuffer::DmxBuffer() : m_ref_count(NULL), m_copy_on_write(false), m_data(NULL), m_length(0) { } DmxBuffer::DmxBuffer(const DmxBuffer &other) : m_ref_count(NULL), m_copy_on_write(false), m_data(NULL), m_length(0) { if (other.m_data && other.m_ref_count) { CopyFromOther(other); } } DmxBuffer::DmxBuffer(const uint8_t *data, unsigned int length) : m_ref_count(0), m_copy_on_write(false), m_data(NULL), m_length(0) { Set(data, length); } DmxBuffer::DmxBuffer(const string &data) : m_ref_count(0), m_copy_on_write(false), m_data(NULL), m_length(0) { Set(data); } DmxBuffer::~DmxBuffer() { CleanupMemory(); } DmxBuffer& DmxBuffer::operator=(const DmxBuffer &other) { if (this != &other) { CleanupMemory(); if (other.m_data) { CopyFromOther(other); } } return *this; } bool DmxBuffer::operator==(const DmxBuffer &other) const { return (m_length == other.m_length && (m_data == other.m_data || 0 == memcmp(m_data, other.m_data, m_length))); } bool DmxBuffer::operator!=(const DmxBuffer &other) const { return !(*this == other); } bool DmxBuffer::HTPMerge(const DmxBuffer &other) { if (!m_data) { if (!Init()) return false; } DuplicateIfNeeded(); unsigned int other_length = min((unsigned int) DMX_UNIVERSE_SIZE, other.m_length); unsigned int merge_length = min(m_length, other.m_length); for (unsigned int i = 0; i < merge_length; i++) { m_data[i] = max(m_data[i], other.m_data[i]); } if (other_length > m_length) { memcpy(m_data + merge_length, other.m_data + merge_length, other_length - merge_length); m_length = other_length; } return true; } bool DmxBuffer::Set(const uint8_t *data, unsigned int length) { if (!data) return false; if (m_copy_on_write) CleanupMemory(); if (!m_data) { if (!Init()) return false; } m_length = min(length, (unsigned int) DMX_UNIVERSE_SIZE); memcpy(m_data, data, m_length); return true; } bool DmxBuffer::Set(const string &data) { return Set(reinterpret_cast(data.data()), data.length()); } bool DmxBuffer::Set(const DmxBuffer &other) { return Set(other.m_data, other.m_length); } bool DmxBuffer::SetFromString(const string &input) { unsigned int i = 0; vector dmx_values; vector::const_iterator iter; if (m_copy_on_write) CleanupMemory(); if (!m_data) if (!Init()) return false; if (input.empty()) { m_length = 0; return true; } StringSplit(input, &dmx_values, ","); for (iter = dmx_values.begin(); iter != dmx_values.end() && i < DMX_UNIVERSE_SIZE; ++iter, ++i) { m_data[i] = atoi(iter->data()); } m_length = i; return true; } bool DmxBuffer::SetRangeToValue(unsigned int offset, uint8_t value, unsigned int length) { if (offset >= DMX_UNIVERSE_SIZE) return false; if (!m_data) { Blackout(); } if (offset > m_length) return false; DuplicateIfNeeded(); unsigned int copy_length = min(length, DMX_UNIVERSE_SIZE - offset); memset(m_data + offset, value, copy_length); m_length = max(m_length, offset + copy_length); return true; } bool DmxBuffer::SetRange(unsigned int offset, const uint8_t *data, unsigned int length) { if (!data || offset >= DMX_UNIVERSE_SIZE) return false; if (!m_data) { Blackout(); } if (offset > m_length) return false; DuplicateIfNeeded(); unsigned int copy_length = min(length, DMX_UNIVERSE_SIZE - offset); memcpy(m_data + offset, data, copy_length); m_length = max(m_length, offset + copy_length); return true; } void DmxBuffer::SetChannel(unsigned int channel, uint8_t data) { if (channel >= DMX_UNIVERSE_SIZE) return; if (!m_data) { Blackout(); } if (channel > m_length) { OLA_WARN << "Attempting to set channel " << channel << " when length is " << m_length; return; } DuplicateIfNeeded(); m_data[channel] = data; m_length = max(channel+1, m_length); } void DmxBuffer::Get(uint8_t *data, unsigned int *length) const { if (m_data) { *length = min(*length, m_length); memcpy(data, m_data, *length); } else { *length = 0; } } void DmxBuffer::GetRange(unsigned int slot, uint8_t *data, unsigned int *length) const { if (slot >= m_length) { *length = 0; return; } if (m_data) { *length = min(*length, m_length - slot); memcpy(data, m_data + slot, *length); } else { *length = 0; } } uint8_t DmxBuffer::Get(unsigned int channel) const { if (m_data && channel < m_length) { return m_data[channel]; } else { return 0; } } string DmxBuffer::Get() const { string data; data.append(reinterpret_cast(m_data), m_length); return data; } bool DmxBuffer::Blackout() { if (m_copy_on_write) { CleanupMemory(); } if (!m_data) { if (!Init()) { return false; } } memset(m_data, DMX_MIN_SLOT_VALUE, DMX_UNIVERSE_SIZE); m_length = DMX_UNIVERSE_SIZE; return true; } void DmxBuffer::Reset() { if (m_data) { m_length = 0; } } string DmxBuffer::ToString() const { if (!m_data) { return ""; } // TODO(Peter): Change to the uint8_t version of StringJoin std::ostringstream str; for (unsigned int i = 0; i < Size(); i++) { if (i) { str << ","; } str << static_cast(m_data[i]); } return str.str(); } /* * Allocate memory * @return true on success, otherwise raises an exception */ bool DmxBuffer::Init() { m_data = new uint8_t[DMX_UNIVERSE_SIZE]; m_ref_count = new unsigned int; m_length = 0; *m_ref_count = 1; return true; } /* * Called before making a change, this duplicates the data if required. * @return true on Duplication, and false it duplication was not needed */ bool DmxBuffer::DuplicateIfNeeded() { if (m_copy_on_write && *m_ref_count == 1) { m_copy_on_write = false; } if (m_copy_on_write && *m_ref_count > 1) { unsigned int *old_ref_count = m_ref_count; uint8_t *original_data = m_data; unsigned int length = m_length; m_copy_on_write = false; if (Init()) { Set(original_data, length); (*old_ref_count)--; return true; } return false; } return true; } /* * Setup this buffer to point to the data of the other buffer * @param other the source buffer * @pre other.m_data and other.m_ref_count are not NULL */ void DmxBuffer::CopyFromOther(const DmxBuffer &other) { m_copy_on_write = true; other.m_copy_on_write = true; m_ref_count = other.m_ref_count; (*m_ref_count)++; m_data = other.m_data; m_length = other.m_length; } /* * Decrement the ref count by one and free the memory if required */ void DmxBuffer::CleanupMemory() { if (m_ref_count && m_data) { (*m_ref_count)--; if (!*m_ref_count) { delete[] m_data; delete m_ref_count; } m_data = NULL; m_ref_count = NULL; m_length = 0; } } std::ostream& operator<<(std::ostream &out, const DmxBuffer &data) { return out << data.ToString(); } } // namespace ola ola-0.10.5.nojsmin/common/utils/TokenBucketTest.cpp0000644000175000017500000000654013023355232021675 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * TokenBucketTest.cpp * Test fixture for the TokenBucket class * Copyright (C) 2010 Simon Newton */ #include #include "ola/Clock.h" #include "olad/TokenBucket.h" #include "ola/Logging.h" #include "ola/testing/TestUtils.h" using ola::Clock; using ola::TimeInterval; using ola::TimeStamp; using ola::TokenBucket; class TokenBucketTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(TokenBucketTest); CPPUNIT_TEST(testTokenBucket); CPPUNIT_TEST(testTokenBucketTwo); CPPUNIT_TEST_SUITE_END(); public: void testTokenBucket(); void testTokenBucketTwo(); }; CPPUNIT_TEST_SUITE_REGISTRATION(TokenBucketTest); /* * Check that the Token Bucket works */ void TokenBucketTest::testTokenBucket() { TimeStamp now; Clock clock; TimeInterval ten_ms(10000); TimeInterval one_hundred_ms(100000); TimeInterval one_second(1000000); clock.CurrentTime(&now); TokenBucket bucket(0, 10, 10, now); // one every 100ms OLA_ASSERT_EQ(0u, bucket.Count(now)); now += one_hundred_ms; OLA_ASSERT_EQ(1u, bucket.Count(now)); now += ten_ms; OLA_ASSERT_EQ(1u, bucket.Count(now)); now += ten_ms; OLA_ASSERT_EQ(1u, bucket.Count(now)); now += one_hundred_ms; OLA_ASSERT_EQ(2u, bucket.Count(now)); OLA_ASSERT_TRUE(bucket.GetToken(now)); OLA_ASSERT_TRUE(bucket.GetToken(now)); OLA_ASSERT_FALSE(bucket.GetToken(now)); OLA_ASSERT_EQ(0u, bucket.Count(now)); now += one_second; OLA_ASSERT_EQ(10u, bucket.Count(now)); } void TokenBucketTest::testTokenBucketTwo() { TimeStamp now; Clock clock; TimeInterval ten_ms(10000); TimeInterval one_hundred_ms(100000); TimeInterval one_second(1000000); TimeInterval five_minutes(5 * 60 * 1000000); clock.CurrentTime(&now); TokenBucket bucket(0, 40, 40, now); // one every 25ms OLA_ASSERT_EQ(0u, bucket.Count(now)); now += one_hundred_ms; OLA_ASSERT_EQ(4u, bucket.Count(now)); now += ten_ms; OLA_ASSERT_EQ(4u, bucket.Count(now)); now += ten_ms; OLA_ASSERT_EQ(4u, bucket.Count(now)); now += ten_ms; OLA_ASSERT_EQ(5u, bucket.Count(now)); now += ten_ms; OLA_ASSERT_EQ(5u, bucket.Count(now)); now += one_hundred_ms; OLA_ASSERT_EQ(9u, bucket.Count(now)); now += ten_ms; OLA_ASSERT_EQ(10u, bucket.Count(now)); now += one_second; OLA_ASSERT_EQ(40u, bucket.Count(now)); // now try a very long duration now += five_minutes; OLA_ASSERT_EQ(40u, bucket.Count(now)); // take 10 tokens from the bucket for (unsigned int i = 0; i < 10; i++) { OLA_ASSERT_TRUE(bucket.GetToken(now)); } OLA_ASSERT_EQ(30u, bucket.Count(now)); // add a bit of time now += ten_ms; OLA_ASSERT_EQ(30u, bucket.Count(now)); } ola-0.10.5.nojsmin/common/utils/Watchdog.cpp0000644000175000017500000000322413023355232020353 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Watchdog.cpp * Copyright (C) 2015 Simon Newton */ #include "ola/util/Watchdog.h" namespace ola { using ola::thread::MutexLocker; Watchdog::Watchdog(unsigned int cycle_limit, Callback0 *reset_callback) : m_limit(cycle_limit), m_callback(reset_callback), m_enabled(false), m_count(0), m_fired(false) { } void Watchdog::Enable() { MutexLocker lock(&m_mu); m_count = 0; m_fired = false; m_enabled = true; } void Watchdog::Disable() { MutexLocker lock(&m_mu); m_enabled = false; m_fired = false; } void Watchdog::Kick() { MutexLocker lock(&m_mu); m_count = 0; } void Watchdog::Clock() { bool run_callback = false; { MutexLocker lock(&m_mu); if (!m_enabled) { return; } m_count++; if (m_count >= m_limit && !m_fired) { m_fired = true; run_callback = true; } } if (run_callback) { m_callback->Run(); } } } // namespace ola ola-0.10.5.nojsmin/common/utils/UtilsTest.cpp0000644000175000017500000000474413023355232020563 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * UtilsTest.cpp * Unittest for util functions. * Copyright (C) 2013 Peter Newman */ #include #include "ola/util/Utils.h" #include "ola/testing/TestUtils.h" using ola::utils::SplitUInt16; using ola::utils::JoinUInt8; class UtilsTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(UtilsTest); CPPUNIT_TEST(testSplitUInt16); CPPUNIT_TEST(testJoinUInt8); CPPUNIT_TEST_SUITE_END(); public: void testSplitUInt16(); void testJoinUInt8(); }; CPPUNIT_TEST_SUITE_REGISTRATION(UtilsTest); /* * Test the SplitUInt16 function */ void UtilsTest::testSplitUInt16() { uint16_t input = 0xabcd; uint8_t high = 0x00; uint8_t low = 0x00; SplitUInt16(input, &high, &low); OLA_ASSERT_EQ(high, static_cast(0xab)); OLA_ASSERT_EQ(low, static_cast(0xcd)); input = 0x0000; SplitUInt16(input, &high, &low); OLA_ASSERT_EQ(high, static_cast(0x00)); OLA_ASSERT_EQ(low, static_cast(0x00)); input = 0xffff; SplitUInt16(input, &high, &low); OLA_ASSERT_EQ(high, static_cast(0xff)); OLA_ASSERT_EQ(low, static_cast(0xff)); input = 0x0001; SplitUInt16(input, &high, &low); OLA_ASSERT_EQ(high, static_cast(0x00)); OLA_ASSERT_EQ(low, static_cast(0x01)); } /* * Test the JoinUInt8 function */ void UtilsTest::testJoinUInt8() { uint8_t high = 0xab; uint8_t low = 0xcd; OLA_ASSERT_EQ(JoinUInt8(high, low), static_cast(0xabcd)); high = 0x00; low = 0x00; OLA_ASSERT_EQ(JoinUInt8(high, low), static_cast(0x0000)); high = 0xff; low = 0xff; OLA_ASSERT_EQ(JoinUInt8(high, low), static_cast(0xffff)); high = 0x00; low = 0x01; OLA_ASSERT_EQ(JoinUInt8(high, low), static_cast(0x0001)); } ola-0.10.5.nojsmin/common/utils/ActionQueue.cpp0000644000175000017500000000407213023355232021037 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * ActionQueue.cpp * The Action Queue class. * Copyright (C) 2005 Simon Newton */ #include #include "ola/ActionQueue.h" #include "ola/Callback.h" #include "ola/Logging.h" #include "ola/stl/STLUtils.h" namespace ola { using std::vector; ActionQueue::~ActionQueue() { STLDeleteElements(&m_actions); } void ActionQueue::AddAction(Action *action) { m_actions.push_back(action); } /* * Check the state of the current action, and if necessary run the next action. */ void ActionQueue::NextAction() { if (!m_success) return; if (m_action_index >= 0 && m_action_index < static_cast(m_actions.size())) { if (m_actions[m_action_index]->IsFatal() && m_actions[m_action_index]->Failed()) { // abort the chain here m_success = false; m_on_complete->Run(this); return; } } if (m_action_index >= static_cast(m_actions.size())) { OLA_WARN << "Action queue already finished!"; } else if (m_action_index == static_cast(m_actions.size()) - 1) { m_action_index++; m_on_complete->Run(this); } else { m_action_index++; m_actions[m_action_index]->Perform( NewSingleCallback(this, &ActionQueue::NextAction)); } } Action *ActionQueue::GetAction(unsigned int i) { if (i >= ActionCount()) return NULL; return m_actions[i]; } } // namespace ola ola-0.10.5.nojsmin/common/utils/WatchdogTest.cpp0000644000175000017500000000435313023355232021217 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * WatchdogTest.cpp * Unittest for the Watchdog. * Copyright (C) 2015 Simon Newton */ #include #include "ola/util/Watchdog.h" #include "ola/testing/TestUtils.h" class WatchdogTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(WatchdogTest); CPPUNIT_TEST(testWatchdog); CPPUNIT_TEST_SUITE_END(); public: WatchdogTest(): m_timeouts(0) {} void testWatchdog(); private: unsigned int m_timeouts; void Timeout() { m_timeouts++; } }; CPPUNIT_TEST_SUITE_REGISTRATION(WatchdogTest); void WatchdogTest::testWatchdog() { m_timeouts = 0; ola::Watchdog watchdog(4, ola::NewCallback(this, &WatchdogTest::Timeout)); // Not enabled yet for (unsigned int i = 0; i < 10; i++) { watchdog.Clock(); } OLA_ASSERT_EQ(0u, m_timeouts); watchdog.Enable(); // Test with regular kicks. for (unsigned int i = 0; i < 10; i++) { watchdog.Clock(); if (i % 2) { watchdog.Kick(); } } OLA_ASSERT_EQ(0u, m_timeouts); // test with non kicks for (unsigned int i = 0; i < 10; i++) { watchdog.Clock(); } OLA_ASSERT_EQ(1u, m_timeouts); // Disable and re-enable. watchdog.Disable(); watchdog.Enable(); for (unsigned int i = 0; i < 3; i++) { watchdog.Clock(); } OLA_ASSERT_EQ(1u, m_timeouts); // Disable triggers a reset of the count watchdog.Disable(); watchdog.Enable(); watchdog.Clock(); watchdog.Clock(); OLA_ASSERT_EQ(1u, m_timeouts); watchdog.Clock(); watchdog.Clock(); OLA_ASSERT_EQ(2u, m_timeouts); } ola-0.10.5.nojsmin/common/utils/TokenBucket.cpp0000644000175000017500000000317413023355232021035 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * TokenBucket.cpp * Token Bucket implementation. * Copyright (C) 2010 Simon Newton */ #include #include "olad/TokenBucket.h" namespace ola { /* * Check if we have enough tokens for an operation. Assuming there is enough * tokens, the count is decremented by one. * @param now the current time * @returns true if there is enough tokens, false otherwise */ bool TokenBucket::GetToken(const TimeStamp &now) { Count(now); if (m_count > 0) { m_count--; return true; } return false; } /* * Get the number of tokens in the bucket */ unsigned int TokenBucket::Count(const TimeStamp &now) { int64_t delta = (now - m_last).AsInt(); uint64_t tokens = delta * m_rate / USEC_IN_SECONDS; m_count = std::min(static_cast(m_max), m_count + tokens); if (tokens) m_last += ola::TimeInterval(tokens * USEC_IN_SECONDS / m_rate); return m_count; } } // namespace ola ola-0.10.5.nojsmin/common/base/0000755000175000017500000000000013155164170015665 5ustar wouterwouterola-0.10.5.nojsmin/common/base/Makefile.mk0000644000175000017500000000204013023355232017722 0ustar wouterwouter# LIBRARIES ################################################## common_libolacommon_la_SOURCES += \ common/base/Credentials.cpp \ common/base/Env.cpp \ common/base/Flags.cpp \ common/base/Init.cpp \ common/base/Logging.cpp \ common/base/SysExits.cpp \ common/base/Version.cpp # TESTS ################################################## test_programs += common/base/CredentialsTester \ common/base/FlagsTester \ common/base/LoggingTester common_base_CredentialsTester_SOURCES = common/base/CredentialsTest.cpp common_base_CredentialsTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_base_CredentialsTester_LDADD = $(COMMON_TESTING_LIBS) common_base_FlagsTester_SOURCES = common/base/FlagsTest.cpp common_base_FlagsTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_base_FlagsTester_LDADD = $(COMMON_TESTING_LIBS) common_base_LoggingTester_SOURCES = common/base/LoggingTest.cpp common_base_LoggingTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_base_LoggingTester_LDADD = $(COMMON_TESTING_LIBS) ola-0.10.5.nojsmin/common/base/SysExits.cpp0000644000175000017500000000633413023355232020165 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SysExits.cpp * Exit codes. * * Some platforms (android) don't provide sysexits.h. To work around this we * define our own exit codes, which use the system values if provided, or * otherwise default values. */ /** * @addtogroup sysexit * @{ * @file SysExits.cpp * @} */ #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #ifdef HAVE_SYSEXITS_H #include #else // Copied from the Berkeley sources. /** * @addtogroup sysexit * @{ */ /** * @name Fallback values * @details These are the values we fall back to in case the os doesn't provide * exit codes * @{ */ #define EX_OK 0 /**< @brief successful termination */ #define EX__BASE 64 /**< @brief base value for error messages */ #define EX_USAGE 64 /**< @brief command line usage error */ #define EX_DATAERR 65 /**< @brief data format error */ #define EX_NOINPUT 66 /**< @brief cannot open input */ #define EX_NOUSER 67 /**< @brief addressee unknown */ #define EX_NOHOST 68 /**< @brief host name unknown */ #define EX_UNAVAILABLE 69 /**< @brief service unavailable */ #define EX_SOFTWARE 70 /**< @brief internal software error */ #define EX_OSERR 71 /**< @brief system error (e.g., can't fork) */ #define EX_OSFILE 72 /**< @brief critical OS file missing */ #define EX_CANTCREAT 73 /**< @brief can't create (user) output file */ #define EX_IOERR 74 /**< @brief input/output error */ #define EX_TEMPFAIL 75 /**< @brief temp failure; user is invited to retry */ #define EX_PROTOCOL 76 /**< @brief remote error in protocol */ #define EX_NOPERM 77 /**< @brief permission denied */ #define EX_CONFIG 78 /**< @brief configuration error */ #define EX__MAX 78 /**< @brief maximum listed value */ /** * @} * @} */ #endif // HAVE_SYSEXITS_H #include "ola/base/SysExits.h" namespace ola { /** * @addtogroup sysexit * @{ */ const int EXIT_OK = EX_OK; const int EXIT__BASE = EX__BASE; const int EXIT_USAGE = EX_USAGE; const int EXIT_DATAERR = EX_DATAERR; const int EXIT_NOINPUT = EX_NOINPUT; const int EXIT_NOUSER = EX_NOUSER; const int EXIT_NOHOST = EX_NOHOST; const int EXIT_UNAVAILABLE = EX_UNAVAILABLE; const int EXIT_SOFTWARE = EX_SOFTWARE; const int EXIT_OSERR = EX_OSERR; const int EXIT_OSFILE = EX_OSFILE; const int EXIT_CANTCREAT = EX_CANTCREAT; const int EXIT_IOERR = EX_IOERR; const int EXIT_TEMPFAIL = EX_TEMPFAIL; const int EXIT_PROTOCOL = EX_PROTOCOL; const int EXIT_NOPERM = EX_NOPERM; const int EXIT_CONFIG = EX_CONFIG; const int EXIT__MAX = EX__MAX; /**@}*/ } // namespace ola ola-0.10.5.nojsmin/common/base/Logging.cpp0000644000175000017500000001305713023355232017760 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Logging.cpp * The logging functions. See include/ola/Logging.h for details on how to use * these. * Copyright (C) 2005 Simon Newton */ /** * @addtogroup logging * @{ * * @file Logging.cpp * * @} */ #include #ifdef _WIN32 #define VC_EXTRALEAN #include #include #else #include #endif // _WIN32 #include #include #include #include "ola/Logging.h" #include "ola/base/Flags.h" /**@private*/ DEFINE_s_int8(log_level, l, ola::OLA_LOG_WARN, "Set the logging level 0 .. 4."); /**@private*/ DEFINE_default_bool(syslog, false, "Send to syslog rather than stderr."); namespace ola { using std::ostringstream; using std::string; /** * @cond HIDDEN_SYMBOLS * @brief pointer to a log target */ LogDestination *log_target = NULL; log_level logging_level = OLA_LOG_WARN; /**@endcond*/ /** * @addtogroup logging * @{ */ void SetLogLevel(log_level level) { logging_level = level; } void IncrementLogLevel() { logging_level = (log_level) (logging_level + 1); if (logging_level == OLA_LOG_MAX) logging_level = OLA_LOG_NONE; } bool InitLoggingFromFlags() { log_output output = OLA_LOG_NULL; if (FLAGS_syslog) { output = OLA_LOG_SYSLOG; } else { output = OLA_LOG_STDERR; } log_level log_level = ola::OLA_LOG_WARN; switch (FLAGS_log_level) { case 0: // nothing is written at this level // so this turns logging off log_level = ola::OLA_LOG_NONE; break; case 1: log_level = ola::OLA_LOG_FATAL; break; case 2: log_level = ola::OLA_LOG_WARN; break; case 3: log_level = ola::OLA_LOG_INFO; break; case 4: log_level = ola::OLA_LOG_DEBUG; break; default : break; } return InitLogging(log_level, output); } bool InitLogging(log_level level, log_output output) { LogDestination *destination; if (output == OLA_LOG_SYSLOG) { #ifdef _WIN32 SyslogDestination *syslog_dest = new WindowsSyslogDestination(); #else SyslogDestination *syslog_dest = new UnixSyslogDestination(); #endif // _WIN32 if (!syslog_dest->Init()) { delete syslog_dest; return false; } destination = syslog_dest; } else if (output == OLA_LOG_STDERR) { destination = new StdErrorLogDestination(); } else { destination = NULL; } InitLogging(level, destination); return true; } void InitLogging(log_level level, LogDestination *destination) { SetLogLevel(level); if (log_target) { delete log_target; } log_target = destination; } /**@}*/ /**@cond HIDDEN_SYMBOLS*/ LogLine::LogLine(const char *file, int line, log_level level): m_level(level), m_stream(ostringstream::out) { m_stream << file << ":" << line << ": "; m_prefix_length = m_stream.str().length(); } LogLine::~LogLine() { Write(); } void LogLine::Write() { if (m_stream.str().length() == m_prefix_length) return; if (m_level > logging_level) return; string line = m_stream.str(); if (line.at(line.length() - 1) != '\n') line.append("\n"); if (log_target) log_target->Write(m_level, line); } /**@endcond*/ /** * @addtogroup logging * @{ */ void StdErrorLogDestination::Write(log_level level, const string &log_line) { ssize_t bytes = write(STDERR_FILENO, log_line.c_str(), log_line.size()); (void) bytes; (void) level; } #ifdef _WIN32 bool WindowsSyslogDestination::Init() { m_eventlog = RegisterEventSourceA(NULL, "OLA"); if (!m_eventlog) { printf("Failed to initialize event logging\n"); return false; } return true; } void WindowsSyslogDestination::Write(log_level level, const string &log_line) { WORD pri; const char* strings[1]; strings[0] = log_line.data(); switch (level) { case OLA_LOG_FATAL: pri = EVENTLOG_ERROR_TYPE; break; case OLA_LOG_WARN: pri = EVENTLOG_WARNING_TYPE; break; case OLA_LOG_INFO: pri = EVENTLOG_INFORMATION_TYPE; break; case OLA_LOG_DEBUG: pri = EVENTLOG_INFORMATION_TYPE; break; default: pri = EVENTLOG_INFORMATION_TYPE; } ReportEventA(reinterpret_cast(m_eventlog), pri, (WORD) NULL, (DWORD) NULL, NULL, 1, 0, strings, NULL); } #else bool UnixSyslogDestination::Init() { return true; } void UnixSyslogDestination::Write(log_level level, const string &log_line) { int pri; switch (level) { case OLA_LOG_FATAL: pri = LOG_CRIT; break; case OLA_LOG_WARN: pri = LOG_WARNING; break; case OLA_LOG_INFO: pri = LOG_INFO; break; case OLA_LOG_DEBUG: pri = LOG_DEBUG; break; default : pri = LOG_INFO; } syslog(pri, "%s", log_line.data()); } #endif // _WIN32 } // namespace ola /**@}*/ ola-0.10.5.nojsmin/common/base/Init.cpp0000644000175000017500000002220613023355232017271 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Init.cpp * A grab bag of functions useful for programs. * Copyright (C) 2012 Simon Newton * * Maybe one day this will handle command line parsing as well. Wouldn't that * be nice. */ /** * @addtogroup init * @{ * @file Init.cpp * @} */ #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #ifdef HAVE_EXECINFO_H #include #endif // HAVE_EXECINFO_H #include #include #include #include #ifdef _WIN32 #include #define WIN32_LEAN_AND_MEAN #define VC_EXTRALEAN #include #else #include #endif // _WIN32 #include #include #include #include #include #include #include #include #include #include #include #include // Scheduling options. DEFINE_string(scheduler_policy, "", "The thread scheduling policy, one of {fifo, rr}."); DEFINE_uint16(scheduler_priority, 0, "The thread priority, only used if --scheduler-policy is set."); namespace { using std::cout; using std::endl; using std::string; /* * @private * @brief Print a stack trace. */ static void _DumpStackAndExit(int sig) { #ifdef _WIN32 cout << "Received " << sig << endl; #else cout << "Received " << strsignal(sig) << endl; #endif // _WIN32 #ifdef HAVE_EXECINFO_H enum {STACK_SIZE = 64}; void *array[STACK_SIZE]; size_t size = backtrace(array, STACK_SIZE); backtrace_symbols_fd(array, size, STDERR_FILENO); #endif // HAVE_EXECINFO_H exit(ola::EXIT_SOFTWARE); } bool SetThreadScheduling() { string policy_str = FLAGS_scheduler_policy.str(); ola::ToLower(&policy_str); if (policy_str.empty()) { if (FLAGS_scheduler_priority.present()) { OLA_WARN << "Must provide both of --scheduler-policy & " "--scheduler-priority"; return false; } return true; } int policy = 0; if (policy_str == "fifo") { policy = SCHED_FIFO; } else if (policy_str == "rr") { policy = SCHED_RR; } else { OLA_FATAL << "Unknown scheduling policy " << policy_str; return false; } if (!FLAGS_scheduler_priority.present()) { OLA_WARN << "Must provide both of --scheduler-policy & " "--scheduler-priority"; return false; } int requested_priority = FLAGS_scheduler_priority; #ifdef _POSIX_PRIORITY_SCHEDULING int min = sched_get_priority_min(policy); int max = sched_get_priority_max(policy); if (requested_priority < min) { OLA_WARN << "Minimum value for --scheduler-priority is " << min; return false; } if (requested_priority > max) { OLA_WARN << "Maximum value for --scheduler-priority is " << max; return false; } #endif // _POSIX_PRORITY_SCHEDULING // Set the scheduling parameters. struct sched_param param; param.sched_priority = requested_priority; OLA_INFO << "Scheduling policy is " << ola::thread::PolicyToString(policy) << ", priority " << param.sched_priority; bool ok = ola::thread::SetSchedParam(pthread_self(), policy, param); if (!ok) { return false; } // If RLIMIT_RTTIME is available, set a bound on the length of uninterrupted // CPU time we can consume. #if HAVE_DECL_RLIMIT_RTTIME struct rlimit rlim; if (!ola::system::GetRLimit(RLIMIT_RTTIME, &rlim)) { return false; } // Cap CPU time at 1s. rlim.rlim_cur = 1000000; OLA_DEBUG << "Setting RLIMIT_RTTIME " << rlim.rlim_cur << " / " << rlim.rlim_max; if (!ola::system::SetRLimit(RLIMIT_RTTIME, rlim)) { return false; } if (!ola::InstallSignal(SIGXCPU, _DumpStackAndExit)) { return false; } #endif // HAVE_DECL_RLIMIT_RTTIME return true; } } // namespace namespace ola { /** * @addtogroup init * @{ */ using std::cout; using std::endl; using std::string; bool ServerInit(int argc, char *argv[], ExportMap *export_map) { ola::math::InitRandom(); if (!InstallSEGVHandler()) { return false; } if (export_map) { InitExportMap(argc, argv, export_map); } return SetThreadScheduling() && NetworkInit(); } bool ServerInit(int *argc, char *argv[], ExportMap *export_map, const string &first_line, const string &description) { // Take a copy of the arguments otherwise the export map is incorrect. int original_argc = *argc; char *original_argv[original_argc]; for (int i = 0; i < original_argc; i++) { original_argv[i] = argv[i]; } SetHelpString(first_line, description); ParseFlags(argc, argv); InitLoggingFromFlags(); return ServerInit(original_argc, original_argv, export_map); } bool AppInit(int *argc, char *argv[], const string &first_line, const string &description) { ola::math::InitRandom(); SetHelpString(first_line, description); ParseFlags(argc, argv); InitLoggingFromFlags(); if (!InstallSEGVHandler()) { return false; } return SetThreadScheduling() && NetworkInit(); } #ifdef _WIN32 static void NetworkShutdown() { WSACleanup(); } #endif // _WIN32 bool NetworkInit() { #ifdef _WIN32 WSADATA wsa_data; int result = WSAStartup(MAKEWORD(2, 0), &wsa_data); if (result != 0) { OLA_WARN << "WinSock initialization failed with " << result; return false; } else { atexit(NetworkShutdown); return true; } #else return true; #endif // _WIN32 } bool InstallSignal(int sig, void(*fp)(int signo)) { #ifdef _WIN32 if (::signal(sig, fp) == SIG_ERR) { OLA_WARN << "signal(" << sig << ": " << strerror(errno); return false; } #else struct sigaction action; action.sa_handler = fp; sigemptyset(&action.sa_mask); action.sa_flags = 0; if (sigaction(sig, &action, NULL) < 0) { OLA_WARN << "sigaction(" << strsignal(sig) << ": " << strerror(errno); return false; } #endif // _WIN32 return true; } bool InstallSEGVHandler() { #ifndef _WIN32 if (!InstallSignal(SIGBUS, _DumpStackAndExit)) { return false; } #endif // !_WIN32 if (!InstallSignal(SIGSEGV, _DumpStackAndExit)) { return false; } return true; } void InitExportMap(int argc, char* argv[], ExportMap *export_map) { ola::StringVariable *var = export_map->GetStringVar("binary"); var->Set(argv[0]); var = export_map->GetStringVar("cmd-line"); std::ostringstream out; for (int i = 1; i < argc; i++) { out << argv[i] << " "; } var->Set(out.str()); var = export_map->GetStringVar("fd-limit"); #ifdef _WIN32 { std::ostringstream out; out << _getmaxstdio(); var->Set(out.str()); } #else struct rlimit rl; if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { var->Set("undetermined"); } else { std::ostringstream out; out << rl.rlim_cur; var->Set(out.str()); } #endif // _WIN32 } void Daemonise() { #ifndef _WIN32 struct rlimit rl; if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { OLA_FATAL << "Could not determine file limit"; exit(EXIT_OSFILE); } // fork so we're not the process group leader pid_t pid; if ((pid = fork()) < 0) { OLA_FATAL << "Could not fork\n"; exit(EXIT_OSERR); } else if (pid != 0) { exit(EXIT_OK); } // start a new session so we're the session leader and we free ourselves from // the controlling terminal. setsid(); struct sigaction sa; sa.sa_handler = SIG_IGN; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; if (sigaction(SIGHUP, &sa, NULL) < 0) { OLA_FATAL << "Could not install signal\n"; exit(EXIT_OSERR); } // fork to ensure we're not the session leader. if ((pid = fork()) < 0) { OLA_FATAL << "Could not fork\n"; exit(EXIT_OSERR); } else if (pid != 0) { exit(EXIT_OK); } // change the current working directory if (chdir("/") < 0) { OLA_FATAL << "Can't change directory to /"; exit(EXIT_OSERR); } // close all fds int maxfd = sysconf(_SC_OPEN_MAX); if (maxfd == -1) { if (rl.rlim_max == RLIM_INFINITY) { maxfd = 1024; } else { maxfd = rl.rlim_max; } } for (int fd = 0; fd < maxfd; fd++) { close(fd); } // send stdout, in and err to /dev/null int fd0 = open("/dev/null", O_RDWR); int fd1 = dup(0); int fd2 = dup(0); if (fd0 != STDIN_FILENO || fd1 != STDOUT_FILENO || fd2 != STDERR_FILENO) { OLA_FATAL << "Unexpected file descriptors: " << fd0 << ", " << fd1 << ", " << fd2; exit(EXIT_OSERR); } #endif // _WIN32 } /**@}*/ } // namespace ola ola-0.10.5.nojsmin/common/base/FlagsTest.cpp0000644000175000017500000003141013023355232020257 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * FlagsTest.cpp * Test the flags parsing code. * Copyright (C) 2013 Simon Newton */ #include #include #include "ola/Logging.h" #include "ola/base/Flags.h" #include "ola/testing/TestUtils.h" DEFINE_default_bool(default_false, false, "Default False"); DEFINE_default_bool(default_true, true, "Default True"); DEFINE_bool(default_false_arg, false, "Default False Arg"); DEFINE_bool(default_true_arg, true, "Default True Arg"); DEFINE_int8(f_int8, -10, "Default -10"); DEFINE_uint8(f_uint8, 10, "Default 10"); DEFINE_int16(f_int16, -1000, "Default -1000"); DEFINE_uint16(f_uint16, 1000, "Default 1000"); DEFINE_int32(f_int32, -2000, "Default -2000"); DEFINE_uint32(f_uint32, 2000, "Default 2000"); DEFINE_string(f_str, "foo", "Test String"); // now flags with short options DEFINE_s_default_bool(s_default_false, a, false, "Default False"); DEFINE_s_default_bool(s_default_true, b, true, "Default True"); DEFINE_s_bool(s_default_false_arg, c, false, "Default False Arg"); DEFINE_s_bool(s_default_true_arg, d, true, "Default True Arg"); DEFINE_s_int8(s_int8, e, -10, "Default -10"); DEFINE_s_uint8(s_uint8, f, 10, "Default 10"); DEFINE_s_int16(s_int16, g, -1000, "Default -1000"); // no h, already reserved for help DEFINE_s_uint16(s_uint16, i, 1000, "Default 1000"); DEFINE_s_int32(s_int32, j, -2000, "Default -2000"); DEFINE_s_uint32(s_uint32, k, 2000, "Default 2000"); // no l, already reserved for logging DEFINE_s_string(s_str, m, "bar", "Test String"); using std::string; class FlagsTest: public CppUnit::TestFixture { public: CPPUNIT_TEST_SUITE(FlagsTest); CPPUNIT_TEST(testDefaults); CPPUNIT_TEST(testSetting); CPPUNIT_TEST(testBoolFlags); CPPUNIT_TEST(testIntFlags); CPPUNIT_TEST(testStringFlags); CPPUNIT_TEST(testFinalPresence); CPPUNIT_TEST_SUITE_END(); public: void testDefaults(); void testPresence(bool presence); void testSetting(); void testBoolFlags(); void testIntFlags(); void testStringFlags(); void testFinalPresence(); }; CPPUNIT_TEST_SUITE_REGISTRATION(FlagsTest); /** * Check the defaults are correct. */ void FlagsTest::testDefaults() { OLA_ASSERT_EQ(false, static_cast(FLAGS_default_false)); OLA_ASSERT_EQ(true, static_cast(FLAGS_default_true)); OLA_ASSERT_EQ(false, static_cast(FLAGS_default_false_arg)); OLA_ASSERT_EQ(true, static_cast(FLAGS_default_true_arg)); OLA_ASSERT_EQ(static_cast(-10), static_cast(FLAGS_f_int8)); OLA_ASSERT_EQ(static_cast(10), static_cast(FLAGS_f_uint8)); OLA_ASSERT_EQ(static_cast(-1000), static_cast(FLAGS_f_int16)); OLA_ASSERT_EQ(static_cast(1000), static_cast(FLAGS_f_uint16)); OLA_ASSERT_EQ(static_cast(-2000), static_cast(FLAGS_f_int32)); OLA_ASSERT_EQ(static_cast(2000), static_cast(FLAGS_f_uint32)); OLA_ASSERT_EQ(string("foo"), FLAGS_f_str.str()); OLA_ASSERT_EQ(false, static_cast(FLAGS_s_default_false)); OLA_ASSERT_EQ(true, static_cast(FLAGS_s_default_true)); OLA_ASSERT_EQ(false, static_cast(FLAGS_s_default_false_arg)); OLA_ASSERT_EQ(true, static_cast(FLAGS_s_default_true_arg)); OLA_ASSERT_EQ(static_cast(-10), static_cast(FLAGS_s_int8)); OLA_ASSERT_EQ(static_cast(10), static_cast(FLAGS_s_uint8)); OLA_ASSERT_EQ(static_cast(-1000), static_cast(FLAGS_s_int16)); OLA_ASSERT_EQ(static_cast(1000), static_cast(FLAGS_s_uint16)); OLA_ASSERT_EQ(static_cast(-2000), static_cast(FLAGS_s_int32)); OLA_ASSERT_EQ(static_cast(2000), static_cast(FLAGS_s_uint32)); OLA_ASSERT_EQ(string("bar"), FLAGS_s_str.str()); testPresence(false); } /** * Check the presence state. */ void FlagsTest::testPresence(bool presence) { OLA_ASSERT_EQ(presence, FLAGS_default_false.present()); OLA_ASSERT_EQ(presence, FLAGS_default_true.present()); OLA_ASSERT_EQ(presence, FLAGS_default_false_arg.present()); OLA_ASSERT_EQ(presence, FLAGS_default_true_arg.present()); OLA_ASSERT_EQ(presence, FLAGS_f_int8.present()); OLA_ASSERT_EQ(presence, FLAGS_f_uint8.present()); OLA_ASSERT_EQ(presence, FLAGS_f_int16.present()); OLA_ASSERT_EQ(presence, FLAGS_f_uint16.present()); OLA_ASSERT_EQ(presence, FLAGS_f_int32.present()); OLA_ASSERT_EQ(presence, FLAGS_f_uint32.present()); OLA_ASSERT_EQ(presence, FLAGS_f_str.present()); OLA_ASSERT_EQ(presence, FLAGS_s_default_false.present()); OLA_ASSERT_EQ(presence, FLAGS_s_default_true.present()); OLA_ASSERT_EQ(presence, FLAGS_s_default_false_arg.present()); OLA_ASSERT_EQ(presence, FLAGS_s_default_true_arg.present()); OLA_ASSERT_EQ(presence, FLAGS_s_int8.present()); OLA_ASSERT_EQ(presence, FLAGS_s_uint8.present()); OLA_ASSERT_EQ(presence, FLAGS_s_int16.present()); OLA_ASSERT_EQ(presence, FLAGS_s_uint16.present()); OLA_ASSERT_EQ(presence, FLAGS_s_int32.present()); OLA_ASSERT_EQ(presence, FLAGS_s_uint32.present()); OLA_ASSERT_EQ(presence, FLAGS_s_str.present()); } /** * Check that we can set the flags */ void FlagsTest::testSetting() { OLA_ASSERT_EQ(false, static_cast(FLAGS_default_false)); OLA_ASSERT_EQ(true, static_cast(FLAGS_default_true)); OLA_ASSERT_EQ(false, static_cast(FLAGS_default_false_arg)); OLA_ASSERT_EQ(true, static_cast(FLAGS_default_true_arg)); OLA_ASSERT_EQ(static_cast(-10), static_cast(FLAGS_f_int8)); OLA_ASSERT_EQ(static_cast(10), static_cast(FLAGS_f_uint8)); OLA_ASSERT_EQ(static_cast(-1000), static_cast(FLAGS_f_int16)); OLA_ASSERT_EQ(static_cast(1000), static_cast(FLAGS_f_uint16)); OLA_ASSERT_EQ(static_cast(-2000), static_cast(FLAGS_f_int32)); OLA_ASSERT_EQ(static_cast(2000), static_cast(FLAGS_f_uint32)); OLA_ASSERT_EQ(string("foo"), FLAGS_f_str.str()); FLAGS_default_false = true; FLAGS_default_true = false; FLAGS_default_false_arg = true; FLAGS_default_true_arg = false; FLAGS_f_int8 = -20; FLAGS_f_uint8 = 20; FLAGS_f_int16 = -2000; FLAGS_f_uint16 = 2000; FLAGS_f_int32 = -4000; FLAGS_f_uint32 = 4000; FLAGS_f_str = "hello"; OLA_ASSERT_EQ(true, static_cast(FLAGS_default_false)); OLA_ASSERT_EQ(false, static_cast(FLAGS_default_true)); OLA_ASSERT_EQ(true, static_cast(FLAGS_default_false_arg)); OLA_ASSERT_EQ(false, static_cast(FLAGS_default_true_arg)); OLA_ASSERT_EQ(static_cast(-20), static_cast(FLAGS_f_int8)); OLA_ASSERT_EQ(static_cast(20), static_cast(FLAGS_f_uint8)); OLA_ASSERT_EQ(static_cast(-2000), static_cast(FLAGS_f_int16)); OLA_ASSERT_EQ(static_cast(2000), static_cast(FLAGS_f_uint16)); OLA_ASSERT_EQ(static_cast(-4000), static_cast(FLAGS_f_int32)); OLA_ASSERT_EQ(static_cast(4000), static_cast(FLAGS_f_uint32)); OLA_ASSERT_EQ(string("hello"), FLAGS_f_str.str()); testPresence(false); } /** * Check bool flags */ void FlagsTest::testBoolFlags() { char bin_name[] = "foo"; char opt1[] = "--default-false"; char opt2[] = "--no-default-true"; char opt3[] = "--default-false-arg"; char opt4[] = "true"; char opt5[] = "--default-true-arg"; char opt6[] = "off"; char *argv[] = {bin_name, opt1, opt2, opt3, opt4, opt5, opt6}; int argc = sizeof(argv) / sizeof(argv[0]); ola::ParseFlags(&argc, argv); OLA_ASSERT_EQ(1, argc); OLA_ASSERT_EQ(string(bin_name), string(argv[0])); OLA_ASSERT_EQ(true, static_cast(FLAGS_default_false)); OLA_ASSERT_EQ(false, static_cast(FLAGS_default_true)); OLA_ASSERT_EQ(true, static_cast(FLAGS_default_false_arg)); OLA_ASSERT_EQ(false, static_cast(FLAGS_default_true_arg)); // now try the short option versions char sopt1[] = "-a"; char sopt2[] = "-b"; char sopt3[] = "-con"; char sopt4[] = "-d"; char sopt5[] = "false"; char *argv2[] = {bin_name, sopt1, sopt2, sopt3, sopt4, sopt5}; argc = sizeof(argv2) / sizeof(argv2[0]); ola::ParseFlags(&argc, argv2); OLA_ASSERT_EQ(1, argc); OLA_ASSERT_EQ(string(bin_name), string(argv2[0])); OLA_ASSERT_EQ(true, static_cast(FLAGS_s_default_false)); OLA_ASSERT_EQ(false, static_cast(FLAGS_s_default_true)); OLA_ASSERT_EQ(true, static_cast(FLAGS_s_default_false_arg)); OLA_ASSERT_EQ(false, static_cast(FLAGS_s_default_true_arg)); } /** * Check the int flags */ void FlagsTest::testIntFlags() { char bin_name[] = "foo"; char opt1[] = "--f-int8"; char opt2[] = "-20"; char opt3[] = "--f-uint8"; char opt4[] = "20"; char opt5[] = "--f-int16"; char opt6[] = "-2000"; char opt7[] = "--f-uint16"; char opt8[] = "2000"; char opt9[] = "--f-int32=-4000"; char opt10[] = "--f-uint32=4000"; char *argv[] = {bin_name, opt1, opt2, opt3, opt4, opt5, opt6, opt7, opt8, opt9, opt10}; int argc = sizeof(argv) / sizeof(argv[0]); ola::ParseFlags(&argc, argv); OLA_ASSERT_EQ(1, argc); OLA_ASSERT_EQ(string(bin_name), string(argv[0])); OLA_ASSERT_EQ(static_cast(-20), static_cast(FLAGS_f_int8)); OLA_ASSERT_EQ(static_cast(20), static_cast(FLAGS_f_uint8)); OLA_ASSERT_EQ(static_cast(-2000), static_cast(FLAGS_f_int16)); OLA_ASSERT_EQ(static_cast(2000), static_cast(FLAGS_f_uint16)); OLA_ASSERT_EQ(static_cast(-4000), static_cast(FLAGS_f_int32)); OLA_ASSERT_EQ(static_cast(4000), static_cast(FLAGS_f_uint32)); // now try the short versions char sopt1[] = "-e-20"; char sopt2[] = "-f"; char sopt3[] = "20"; char sopt4[] = "-g"; char sopt5[] = "-2000"; char sopt6[] = "-i"; char sopt7[] = "2000"; char sopt8[] = "-j-4000"; char sopt9[] = "-k4000"; char *argv2[] = {bin_name, sopt1, sopt2, sopt3, sopt4, sopt5, sopt6, sopt7, sopt8, sopt9}; argc = sizeof(argv2) / sizeof(argv[0]); ola::ParseFlags(&argc, argv2); OLA_ASSERT_EQ(1, argc); OLA_ASSERT_EQ(string(bin_name), string(argv[0])); OLA_ASSERT_EQ(static_cast(-20), static_cast(FLAGS_s_int8)); OLA_ASSERT_EQ(static_cast(20), static_cast(FLAGS_s_uint8)); OLA_ASSERT_EQ(static_cast(-2000), static_cast(FLAGS_s_int16)); OLA_ASSERT_EQ(static_cast(2000), static_cast(FLAGS_s_uint16)); OLA_ASSERT_EQ(static_cast(-4000), static_cast(FLAGS_s_int32)); OLA_ASSERT_EQ(static_cast(4000), static_cast(FLAGS_s_uint32)); } /** * Check string flags */ void FlagsTest::testStringFlags() { char bin_name[] = "a.out"; char opt1[] = "--f-str"; char opt2[] = "data"; char opt3[] = "extra arg"; char *argv[] = {bin_name, opt1, opt2, opt3}; int argc = sizeof(argv) / sizeof(argv[0]); ola::ParseFlags(&argc, argv); OLA_ASSERT_EQ(2, argc); OLA_ASSERT_EQ(string(bin_name), string(argv[0])); OLA_ASSERT_EQ(string(opt3), string(argv[1])); OLA_ASSERT_EQ(string(opt2), FLAGS_f_str.str()); // try the --foo=bar version char opt4[] = "--f-str=data2"; char *argv2[] = {bin_name, opt4}; argc = sizeof(argv2) / sizeof(argv[0]); ola::ParseFlags(&argc, argv2); OLA_ASSERT_EQ(1, argc); OLA_ASSERT_EQ(string(bin_name), string(argv[0])); OLA_ASSERT_EQ(string("data2"), FLAGS_f_str.str()); // try the short version char opt5[] = "-m"; char opt6[] = "data3"; char *argv3[] = {bin_name, opt5, opt6}; argc = sizeof(argv3) / sizeof(argv[0]); ola::ParseFlags(&argc, argv3); OLA_ASSERT_EQ(1, argc); OLA_ASSERT_EQ(string(bin_name), string(argv[0])); OLA_ASSERT_EQ(string("data3"), FLAGS_s_str.str()); } /** * Check the final presence state. */ void FlagsTest::testFinalPresence() { testPresence(true); } ola-0.10.5.nojsmin/common/base/LoggingTest.cpp0000644000175000017500000000743413023355232020622 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * LoggingTest.cpp * Test fixture for the Logging framework * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include #include "ola/Logging.h" #include "ola/StringUtils.h" #include "ola/testing/TestUtils.h" using std::deque; using std::vector; using std::string; using ola::IncrementLogLevel; using ola::log_level; class LoggingTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(LoggingTest); CPPUNIT_TEST(testLogging); CPPUNIT_TEST_SUITE_END(); public: void testLogging(); }; class MockLogDestination: public ola::LogDestination { public: void AddExpected(log_level level, string log_line); void Write(log_level level, const string &log_line); int LinesRemaining() const { return m_log_lines.size(); } private: deque > m_log_lines; }; CPPUNIT_TEST_SUITE_REGISTRATION(LoggingTest); void MockLogDestination::AddExpected(log_level level, string log_line) { std::pair expected_result(level, log_line); m_log_lines.push_back(expected_result); } /* * Check that what gets written is what we expected */ void MockLogDestination::Write(log_level level, const string &log_line) { vector tokens; ola::StringSplit(log_line, &tokens, ":"); vector::iterator iter; OLA_ASSERT_EQ(tokens.size() , (size_t) 3); OLA_ASSERT_GT(m_log_lines.size(), 0); std::pair expected_result = m_log_lines.at(0); m_log_lines.pop_front(); OLA_ASSERT_EQ(expected_result.first, level); OLA_ASSERT_EQ(expected_result.second, tokens.at(2)); } /* * Check that logging works correctly. */ void LoggingTest::testLogging() { MockLogDestination *destination = new MockLogDestination(); InitLogging(ola::OLA_LOG_DEBUG, destination); destination->AddExpected(ola::OLA_LOG_DEBUG, " debug\n"); OLA_DEBUG << "debug"; destination->AddExpected(ola::OLA_LOG_INFO, " info\n"); OLA_INFO << "info"; destination->AddExpected(ola::OLA_LOG_WARN, " warn\n"); OLA_WARN << "warn"; destination->AddExpected(ola::OLA_LOG_FATAL, " fatal\n"); OLA_FATAL << "fatal"; // Now make sure nothing below WARN is logged ola::SetLogLevel(ola::OLA_LOG_WARN); OLA_DEBUG << "debug"; OLA_INFO << "info"; destination->AddExpected(ola::OLA_LOG_WARN, " warn\n"); OLA_WARN << "warn"; destination->AddExpected(ola::OLA_LOG_FATAL, " fatal\n"); OLA_FATAL << "fatal"; OLA_ASSERT_EQ(destination->LinesRemaining(), 0); // set the log level to INFO IncrementLogLevel(); OLA_DEBUG << "debug"; destination->AddExpected(ola::OLA_LOG_INFO, " info\n"); OLA_INFO << "info"; destination->AddExpected(ola::OLA_LOG_WARN, " warn\n"); OLA_WARN << "warn"; destination->AddExpected(ola::OLA_LOG_FATAL, " fatal\n"); OLA_FATAL << "fatal"; OLA_ASSERT_EQ(destination->LinesRemaining(), 0); IncrementLogLevel(); // this should wrap to NONE IncrementLogLevel(); OLA_DEBUG << "debug"; OLA_INFO << "info"; OLA_WARN << "warn"; OLA_FATAL << "fatal"; OLA_ASSERT_EQ(destination->LinesRemaining(), 0); } ola-0.10.5.nojsmin/common/base/Version.cpp0000644000175000017500000000310413023355232020007 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Version.cpp * Provides version information for all of OLA. * Copyright (C) 2014 Peter Newman */ #include "ola/base/Version.h" #include #include namespace ola { namespace base { using std::string; unsigned int Version::GetMajor() { return OLA_VERSION_MAJOR; } unsigned int Version::GetMinor() { return OLA_VERSION_MINOR; } unsigned int Version::GetRevision() { return OLA_VERSION_REVISION; } string Version::GetVersion() { std::ostringstream str; str << GetMajor() << "." << GetMinor() << "." << GetRevision(); return str.str(); } bool Version::IsAtLeast(unsigned int major, unsigned int minor, unsigned int revision) { return ( GetMajor() >= major && GetMinor() >= minor && GetRevision() >= revision); } } // namespace base } // namespace ola ola-0.10.5.nojsmin/common/base/Flags.cpp0000644000175000017500000002626013134123277017433 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Flags.cpp * Handle command line flags. * Copyright (C) 2013 Simon Newton */ /** * @addtogroup flags * @{ * @file common/base/Flags.cpp * @} */ #include #include #include #include #include #include "ola/base/Array.h" #include "ola/base/Flags.h" #include "ola/base/SysExits.h" #include "ola/base/Version.h" #include "ola/file/Util.h" #include "ola/stl/STLUtils.h" /** * @private * @brief Define the help flag */ DEFINE_s_default_bool(help, h, false, "Display the help message"); DEFINE_s_default_bool(version, v, false, "Display version information"); DEFINE_default_bool(gen_manpage, false, "Generate a man page snippet"); namespace ola { /** * @addtogroup flags * @{ */ using std::cerr; using std::cout; using std::endl; using std::string; using std::vector; /** * The prefix used on inverted bool flags * @examplepara * @code * DEFINE_s_default_bool(noMaster, d, false, "Dummy flag to show NO_PREFIX") * @endcode * * Then if you called your application with that flag: * @code * bash$myapplication -d * @endcode * Then the noMaster flag would be true. */ const char Flag::NO_PREFIX[] = "no-"; void SetHelpString(const string &first_line, const string &description) { GetRegistry()->SetFirstLine(first_line); GetRegistry()->SetDescription(description); } void DisplayUsage() { GetRegistry()->DisplayUsage(); } void DisplayUsageAndExit() { GetRegistry()->DisplayUsage(); exit(ola::EXIT_USAGE); } void DisplayVersion() { GetRegistry()->DisplayVersion(); } void GenManPage() { GetRegistry()->GenManPage(); } void ParseFlags(int *argc, char **argv) { GetRegistry()->ParseFlags(argc, argv); } /** * @} * @cond HIDDEN_SYMBOLS */ static FlagRegistry *registry = NULL; /* * Registered as an atexit function by the FlagRegistry constructor. */ void DeleteFlagRegistry() { FlagRegistry *old_registry = registry; registry = NULL; delete old_registry; } /* * Change the input to s/_/-/g */ void BaseFlag::ReplaceUnderscoreWithHyphen(char *input) { for (char *c = input; *c; c++) { if (*c == '_') *c = '-'; } } /* * Convert a flag name to the canonical representation. */ const char *BaseFlag::NewCanonicalName(const char *name) { unsigned int total_size = strlen(name) + 1; char *output = new char[total_size]; char *o = output; for (const char *i = name; *i; i++, o++) { if (*i == '_') *o = '-'; else *o = *i; } output[total_size - 1] = 0; return output; } /** * @private * Get the global FlagRegistry object. */ FlagRegistry *GetRegistry() { if (!registry) { registry = new FlagRegistry(); atexit(DeleteFlagRegistry); } return registry; } /** * Register a flag. */ void FlagRegistry::RegisterFlag(FlagInterface *flag) { STLInsertOrDie(&m_long_opts, flag->name(), flag); if (flag->short_opt()) { STLInsertOrDie(&m_short_opts, flag->short_opt(), flag); } } /** * @brief Parse the command line flags. This re-arranges argv so that only the * non-flag options remain. */ void FlagRegistry::ParseFlags(int *argc, char **argv) { const string long_option_prefix("--"); const string short_option_prefix("-"); m_argv0 = argv[0]; int c; int option_index = 0; const string short_opts = GetShortOptsString(); FlagMap flags; const struct option *long_options = GetLongOpts(&flags); optind = 0; // reset each time while (1) { c = getopt_long(*argc, argv, short_opts.c_str(), long_options, &option_index); if (c == -1) { break; } else if (c == '?') { exit(EXIT_USAGE); } FlagInterface *flag = STLFindOrNull(flags, c); if (!flag) { cerr << "Missing flag " << c << endl; } else { if (flag->has_arg()) { if (!flag->SetValue(optarg)) { cerr << "Invalid arg value " << optarg << " for flag " << flag->name() << endl; exit(EXIT_USAGE); } } else { if (!flag->SetValue("1")) { cerr << "Failed to set value of 1 for flag " << flag->name() << endl; exit(EXIT_USAGE); } } } } if (FLAGS_help) { DisplayUsage(); exit(EXIT_OK); } if (FLAGS_version) { DisplayVersion(); exit(EXIT_OK); } if (FLAGS_gen_manpage) { GenManPage(); exit(EXIT_OK); } delete[] long_options; // Remove flags so only non-flag arguments remain. for (int i = 0; i < *argc - optind; i++) { argv[1 + i] = argv[optind + i]; } *argc = 1 + *argc - optind; } void FlagRegistry::SetFirstLine(const string &first_line) { m_first_line = first_line; } void FlagRegistry::SetDescription(const string &description) { m_description = description; } /* * @brief Print the usage text to stdout */ void FlagRegistry::DisplayUsage() { cout << "Usage: " << m_argv0 << " " << m_first_line << endl << endl; if (!m_description.empty()) { cout << m_description << endl << endl; } // - comes before a-z which means flags without long options appear first. To // avoid this we keep two lists. vector short_flag_lines, long_flag_lines; LongOpts::const_iterator iter = m_long_opts.begin(); for (; iter != m_long_opts.end(); ++iter) { std::ostringstream str; const FlagInterface *flag = iter->second; if (flag->name() == FLAGS_gen_manpage.name()) { continue; } str << " "; if (flag->short_opt()) { str << "-" << flag->short_opt() << ", "; } str << "--" << flag->name(); if (flag->has_arg()) { str << " <" << flag->arg_type() << ">"; } str << endl << " " << iter->second->help() << endl; if (flag->short_opt()) short_flag_lines.push_back(str.str()); else long_flag_lines.push_back(str.str()); } PrintFlags(&short_flag_lines); PrintFlags(&long_flag_lines); } /* * @brief Print the version text to stdout */ void FlagRegistry::DisplayVersion() { cout << "OLA " << m_argv0 << " version: " << ola::base::Version::GetVersion() << endl; } void FlagRegistry::GenManPage() { char date_str[100]; time_t curtime; curtime = time(NULL); struct tm loctime; #ifdef _WIN32 loctime = *gmtime(&curtime); // NOLINT(runtime/threadsafe_fn) #else gmtime_r(&curtime, &loctime); #endif // _WIN32 strftime(date_str, arraysize(date_str), "%B %Y", &loctime); string exe_name = ola::file::FilenameFromPathOrPath(m_argv0); if (0 != exe_name.compare(m_argv0)) { // Strip lt- off the start if present, in case we're generating the man // page from a libtool wrapper script for the exe ola::StripPrefix(&exe_name, "lt-"); } // Convert newlines to a suitable format for man pages string man_description = m_description; ReplaceAll(&man_description, "\n", "\n.PP\n"); // Guess at a single line synopsis, match ". " so we don't get standards string synopsis = ""; std::size_t pos = man_description.find(". "); if (pos != string::npos) { synopsis = man_description.substr(0, pos + 1); } else { synopsis = man_description; } cout << ".TH " << exe_name << " 1 \"" << date_str << "\"" << endl; cout << ".SH NAME" << endl; cout << exe_name << " \\- " << synopsis << endl; cout << ".SH SYNOPSIS" << endl; cout << ".B " << exe_name << endl; cout << m_first_line << endl; cout << ".SH DESCRIPTION" << endl; cout << ".B " << exe_name << endl; cout << man_description << endl; cout << ".SH OPTIONS" << endl; // - comes before a-z which means flags without long options appear first. To // avoid this we keep two lists. vector short_flag_lines, long_flag_lines; LongOpts::const_iterator iter = m_long_opts.begin(); for (; iter != m_long_opts.end(); ++iter) { const FlagInterface *flag = iter->second; if (flag->name() == FLAGS_gen_manpage.name()) { continue; } std::ostringstream str; if (flag->short_opt()) { str << "-" << flag->short_opt() << ", "; } str << "--" << flag->name(); if (flag->has_arg()) { str << " <" << flag->arg_type() << ">"; } if (flag->short_opt()) { short_flag_lines.push_back( OptionPair(str.str(), iter->second->help())); } else { long_flag_lines.push_back( OptionPair(str.str(), iter->second->help())); } } PrintManPageFlags(&short_flag_lines); PrintManPageFlags(&long_flag_lines); } /** * @brief Generate the short opts string for getopt. See `man 3 getopt` for the * format. */ string FlagRegistry::GetShortOptsString() const { string short_opts; ShortOpts::const_iterator iter = m_short_opts.begin(); for (; iter != m_short_opts.end(); ++iter) { char short_opt = iter->second->short_opt(); if (!short_opt) continue; short_opts.push_back(iter->second->short_opt()); if (iter->second->has_arg()) { short_opts.push_back(':'); } } return short_opts; } /** * @brief Allocate & populate the array of option structs for the call to * getopt_long. The caller is responsible for deleting the array. * * The flag_map is populated with the option identifier (int) to FlagInterface* * mappings. The ownership of the pointers to FlagInterfaces is not transferred * to the caller. */ struct option *FlagRegistry::GetLongOpts(FlagMap *flag_map) { unsigned int flag_count = m_long_opts.size() + 1; struct option *long_options = new struct option[flag_count]; memset(long_options, 0, sizeof(struct option) * flag_count); LongOpts::iterator iter = m_long_opts.begin(); struct option *opt = long_options; int flag_counter = 256; for (; iter != m_long_opts.end(); ++iter) { FlagInterface *flag = iter->second; opt->name = flag->name(); opt->has_arg = flag->has_arg() ? required_argument : no_argument; opt->flag = 0; int flag_option = flag->short_opt() ? flag->short_opt() : flag_counter++; opt->val = flag_option; flag_map->insert(FlagMap::value_type(flag_option, flag)); opt++; } return long_options; } /** * @brief Given a vector of flags lines, sort them and print to stdout. */ void FlagRegistry::PrintFlags(vector *lines) { std::sort(lines->begin(), lines->end()); vector::const_iterator iter = lines->begin(); for (; iter != lines->end(); ++iter) cout << *iter; } void FlagRegistry::PrintManPageFlags(vector *lines) { std::sort(lines->begin(), lines->end()); vector::const_iterator iter = lines->begin(); for (; iter != lines->end(); ++iter) { cout << ".IP \"" << iter->first << "\"" << endl; cout << iter->second << endl; } } /** * @endcond * End Hidden Symbols */ } // namespace ola ola-0.10.5.nojsmin/common/base/Credentials.cpp0000644000175000017500000001540113023355232020622 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Credentials.cpp * Handle getting and setting a process's credentials. * Copyright (C) 2012 Simon Newton */ /** * @addtogroup cred * @{ * @file Credentials.cpp * @} */ #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #ifndef _WIN32 #include #include #endif // _WIN32 #include #include #include #include #include namespace ola { using std::string; /** * @addtogroup cred * @{ */ bool SupportsUIDs() { #ifdef _WIN32 return false; #else return true; #endif // _WIN32 } bool GetUID(uid_t* uid) { #ifdef _WIN32 (void) uid; return false; #else if (uid) { *uid = getuid(); return true; } else { return false; } #endif // _WIN32 } bool GetEUID(uid_t* euid) { #ifdef _WIN32 (void) euid; return false; #else if (euid) { *euid = geteuid(); return true; } else { return false; } #endif // _WIN32 } bool GetGID(gid_t* gid) { #ifdef _WIN32 (void) gid; return false; #else if (gid) { *gid = getgid(); return true; } else { return false; } #endif // _WIN32 } bool GetEGID(gid_t* egid) { #ifdef _WIN32 (void) egid; return false; #else if (egid) { *egid = getegid(); return true; } else { return false; } #endif // _WIN32 } bool SetUID(uid_t new_uid) { #ifdef _WIN32 (void) new_uid; return false; #else if (setuid(new_uid)) { OLA_WARN << "setuid(" << new_uid << "): " << strerror(errno); return false; } return true; #endif // _WIN32 } bool SetGID(gid_t new_gid) { #ifdef _WIN32 (void) new_gid; return false; #else if (setgid(new_gid)) { OLA_WARN << "setgid(" << new_gid << "): " << strerror(errno); return false; } return true; #endif // _WIN32 } int GetGroups(int size, gid_t list[]) { #ifdef _WIN32 (void) size; (void) list; return -1; #else return getgroups(size, list); #endif // _WIN32 } bool SetGroups(size_t size, const gid_t *list) { #ifdef _WIN32 (void) size; (void) list; return false; #else if (setgroups(size, list)) { OLA_WARN << "setgroups(): " << strerror(errno); return false; } return true; #endif // _WIN32 } /** * @} */ #ifndef _WIN32 /** @private */ template bool GenericGetPasswdReentrant(F f, arg a, PasswdEntry *passwd) { if (!passwd) return false; struct passwd pwd, *pwd_ptr; unsigned int size = 1024; bool ok = false; char *buffer; while (!ok) { buffer = new char[size]; int ret = f(a, &pwd, buffer, size, &pwd_ptr); switch (ret) { case 0: ok = true; break; case ERANGE: delete[] buffer; size += 1024; break; default: delete[] buffer; return false; } } if (!pwd_ptr) return false; passwd->pw_name = pwd_ptr->pw_name; passwd->pw_uid = pwd_ptr->pw_uid; passwd->pw_gid = pwd_ptr->pw_gid; passwd->pw_dir = pwd_ptr->pw_dir; passwd->pw_shell = pwd_ptr->pw_shell; delete[] buffer; return true; } /* * Some platforms (Android) don't have the _r versions. So we fall back to the * non-thread safe versions. */ /** @private */ template bool GenericGetPasswd(F f, arg a, PasswdEntry *passwd) { if (!passwd) return false; struct passwd *pwd = f(a); if (!pwd) return false; passwd->pw_name = pwd->pw_name; passwd->pw_uid = pwd->pw_uid; passwd->pw_gid = pwd->pw_gid; passwd->pw_dir = pwd->pw_dir; passwd->pw_shell = pwd->pw_shell; return true; } #endif // !_WIN32 bool GetPasswdName(const string &name, PasswdEntry *passwd) { #ifdef _WIN32 (void) name; (void) passwd; return false; #else #ifdef HAVE_GETPWNAM_R return GenericGetPasswdReentrant(getpwnam_r, name.c_str(), passwd); #else return GenericGetPasswd(getpwnam, name.c_str(), passwd); #endif // HAVE_GETPWNAM_R #endif // _WIN32 } bool GetPasswdUID(uid_t uid, PasswdEntry *passwd) { #ifdef _WIN32 (void) uid; (void) passwd; return false; #else #ifdef HAVE_GETPWUID_R return GenericGetPasswdReentrant(getpwuid_r, uid, passwd); #else return GenericGetPasswd(getpwuid, uid, passwd); #endif // HAVE_GETPWUID_R #endif // _WIN32 } #ifndef _WIN32 /** @private */ template bool GenericGetGroupReentrant(F f, arg a, GroupEntry *group_entry) { if (!group_entry) return false; struct group grp, *grp_ptr; unsigned int size = 1024; bool ok = false; char *buffer; while (!ok) { buffer = new char[size]; int ret = f(a, &grp, buffer, size, &grp_ptr); switch (ret) { case 0: ok = true; break; case ERANGE: delete[] buffer; size += 1024; break; default: delete[] buffer; return false; } } if (!grp_ptr) { // not found return false; } group_entry->gr_name = grp_ptr->gr_name; group_entry->gr_gid = grp_ptr->gr_gid; delete[] buffer; return true; } /* * Some platforms (Android) don't have the _r versions. So we fall back to the * non-thread safe versions. */ /** @private */ template bool GenericGetGroup(F f, arg a, GroupEntry *group_entry) { if (!group_entry) return false; struct group *grp_ptr = f(a); if (!grp_ptr) return false; group_entry->gr_name = grp_ptr->gr_name; group_entry->gr_gid = grp_ptr->gr_gid; return true; } #endif // !_WIN32 bool GetGroupName(const string &name, GroupEntry *group_entry) { #ifdef _WIN32 (void) name; (void) group_entry; return false; #else #ifdef HAVE_GETGRNAM_R return GenericGetGroupReentrant(getgrnam_r, name.c_str(), group_entry); #else return GenericGetGroup(getgrnam, name.c_str(), group_entry); #endif // HAVE_GETGRNAM_R #endif // _WIN32 } bool GetGroupGID(gid_t gid, GroupEntry *group_entry) { #ifdef _WIN32 (void) gid; (void) group_entry; return false; #else #ifdef HAVE_GETGRGID_R return GenericGetGroupReentrant(getgrgid_r, gid, group_entry); #else return GenericGetGroup(getgrgid, gid, group_entry); #endif // HAVE_GETGRGID_R #endif // _WIN32 } } // namespace ola ola-0.10.5.nojsmin/common/base/CredentialsTest.cpp0000644000175000017500000001237313023355232021467 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * CredentialsTest.cpp * Test the credentials functions. * Copyright (C) 2012 Simon Newton */ #include #include "ola/base/Credentials.h" #include "ola/Logging.h" #include "ola/testing/TestUtils.h" using ola::SupportsUIDs; using ola::GetEGID; using ola::GetEUID; using ola::GetGID; using ola::GetGroupGID; using ola::GetGroupName; using ola::GetPasswdName; using ola::GetPasswdUID; using ola::GetUID; using ola::GroupEntry; using ola::PasswdEntry; using ola::SetGID; using ola::SetUID; class CredentialsTest: public CppUnit::TestFixture { public: CPPUNIT_TEST_SUITE(CredentialsTest); CPPUNIT_TEST(testGetUIDs); CPPUNIT_TEST(testGetGIDs); CPPUNIT_TEST(testSetUID); CPPUNIT_TEST(testSetGID); CPPUNIT_TEST(testGetPasswd); CPPUNIT_TEST(testGetGroup); CPPUNIT_TEST_SUITE_END(); public: void testGetUIDs(); void testGetGIDs(); void testSetUID(); void testSetGID(); void testGetPasswd(); void testGetGroup(); }; CPPUNIT_TEST_SUITE_REGISTRATION(CredentialsTest); /** * Check we're not running as root. */ void CredentialsTest::testGetUIDs() { if (SupportsUIDs()) { uid_t uid; OLA_ASSERT_TRUE(GetUID(&uid)); OLA_ASSERT_TRUE_MSG(uid, "Don't run the tests as root!"); uid_t euid; OLA_ASSERT_TRUE(GetEUID(&euid)); OLA_ASSERT_TRUE_MSG(euid, "Don't run the tests as suid root!"); } else { // Make sure the Get*UID functions actually return false. uid_t uid; OLA_ASSERT_FALSE(GetUID(&uid)); uid_t euid; OLA_ASSERT_FALSE(GetEUID(&euid)); } } /** * Check we're not running as root. */ void CredentialsTest::testGetGIDs() { if (SupportsUIDs()) { gid_t gid; OLA_ASSERT_TRUE(GetGID(&gid)); OLA_ASSERT_TRUE_MSG(gid, "Don't run the tests as root!"); gid_t egid; OLA_ASSERT_TRUE(GetEGID(&egid)); OLA_ASSERT_TRUE_MSG(egid, "Don't run the tests as sgid root!"); } else { // Make sure the Get*GID functions actually return false. gid_t gid; OLA_ASSERT_FALSE(GetGID(&gid)); gid_t egid; OLA_ASSERT_FALSE(GetEGID(&egid)); } } /** * Check SetUID as much as we can. */ void CredentialsTest::testSetUID() { if (SupportsUIDs()) { uid_t euid; OLA_ASSERT_TRUE(GetEUID(&euid)); if (euid) { OLA_ASSERT_TRUE(SetUID(euid)); OLA_ASSERT_FALSE(SetUID(0)); OLA_ASSERT_FALSE(SetUID(euid + 1)); } } } /** * Check SetGID as much as we can. */ void CredentialsTest::testSetGID() { if (SupportsUIDs()) { gid_t egid; OLA_ASSERT_TRUE(GetEGID(&egid)); if (egid) { OLA_ASSERT_TRUE(SetGID(egid)); OLA_ASSERT_FALSE(SetGID(0)); OLA_ASSERT_FALSE(SetGID(egid + 1)); } } } /** * Check the GetPasswd functions work. */ void CredentialsTest::testGetPasswd() { if (SupportsUIDs()) { uid_t uid; OLA_ASSERT_TRUE(GetUID(&uid)); PasswdEntry passwd_entry; OLA_ASSERT_TRUE(GetPasswdUID(uid, &passwd_entry)); // at the very least we shoud have a name OLA_ASSERT_FALSE(passwd_entry.pw_name.empty()); OLA_ASSERT_EQ(uid, passwd_entry.pw_uid); // now fetch by name and check it's the same // this could fail. if the accounts were really messed up PasswdEntry passwd_entry2; OLA_ASSERT_TRUE(GetPasswdName(passwd_entry.pw_name, &passwd_entry2)); OLA_ASSERT_EQ(uid, passwd_entry2.pw_uid); } else { // Make sure GetPasswd* actually return false. PasswdEntry unused; OLA_ASSERT_FALSE(GetPasswdUID(0, &unused)); // Check with an account name that likely exists. OLA_ASSERT_FALSE(GetPasswdName("SYSTEM", &unused)); } } /** * Check the GetGroup functions work. */ void CredentialsTest::testGetGroup() { if (SupportsUIDs()) { gid_t gid; OLA_ASSERT_TRUE(GetGID(&gid)); GroupEntry group_entry; // not all systems will be configured with a group entry so this isn't a // failure. bool ok = GetGroupGID(gid, &group_entry); if (ok) { // at the very least we shoud have a name OLA_ASSERT_FALSE(group_entry.gr_name.empty()); OLA_ASSERT_EQ(gid, group_entry.gr_gid); // now fetch by name and check it's the same // this could fail. if the accounts were really messed up GroupEntry group_entry2; OLA_ASSERT_TRUE(GetGroupName(group_entry.gr_name, &group_entry2)); OLA_ASSERT_EQ(gid, group_entry2.gr_gid); } } else { // Make sure GetPasswd* actually return false. GroupEntry unused; OLA_ASSERT_FALSE(GetGroupGID(0, &unused)); // Check with a group name that might exist. OLA_ASSERT_FALSE(GetGroupName("SYSTEM", &unused)); } } ola-0.10.5.nojsmin/common/base/Env.cpp0000644000175000017500000000223613023355232017117 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Env.cpp * Get / Set Environment variables. */ #include #include #include "ola/base/Env.h" using std::string; namespace ola { bool GetEnv(const string &var, string *value) { char *v = NULL; #ifdef HAVE_SECURE_GETENV v = secure_getenv(var.c_str()); #else v = getenv(var.c_str()); #endif // HAVE_SECURE_GETENV if (v) { value->assign(v); return true; } return false; } } // namespace ola ola-0.10.5.nojsmin/common/strings/0000755000175000017500000000000013155164170016444 5ustar wouterwouterola-0.10.5.nojsmin/common/strings/Makefile.mk0000644000175000017500000000070713023355232020511 0ustar wouterwouter# LIBRARIES ################################################## common_libolacommon_la_SOURCES += \ common/strings/Format.cpp \ common/strings/Utils.cpp # TESTS ################################################ test_programs += common/strings/UtilsTester common_strings_UtilsTester_SOURCES = \ common/strings/UtilsTest.cpp common_strings_UtilsTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_strings_UtilsTester_LDADD = $(COMMON_TESTING_LIBS) ola-0.10.5.nojsmin/common/strings/Utils.cpp0000644000175000017500000000236613023355232020252 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Utils.cpp * Miscellaneous string functions. * Copyright (C) 2014 Simon Newton */ #include "ola/strings/Utils.h" #include #include namespace ola { namespace strings { using std::string; void CopyToFixedLengthBuffer(const std::string &input, char *buffer, unsigned int size) { // buffer may not be NULL terminated. // coverity[BUFFER_SIZE_WARNING] strncpy(buffer, input.c_str(), size); } } // namespace strings } // namespace ola ola-0.10.5.nojsmin/common/strings/UtilsTest.cpp0000644000175000017500000000434613023355232021112 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * UtilsTest.cpp * Unittest for strings Util functions. * Copyright (C) 2014 Simon Newton */ #include #include #include "ola/base/Array.h" #include "ola/strings/Utils.h" #include "ola/testing/TestUtils.h" using ola::strings::CopyToFixedLengthBuffer; using std::string; class UtilsTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(UtilsTest); CPPUNIT_TEST(testCopyToFixedLengthBuffer); CPPUNIT_TEST_SUITE_END(); public: void testCopyToFixedLengthBuffer(); }; CPPUNIT_TEST_SUITE_REGISTRATION(UtilsTest); /* * Test the CopyToFixedLengthBuffer function */ void UtilsTest::testCopyToFixedLengthBuffer() { char buffer[6]; const string short_input("foo"); const string input("foobar"); const string oversized_input("foobarbaz"); const char short_output[] = {'f', 'o', 'o', 0, 0, 0}; CopyToFixedLengthBuffer(short_input, buffer, arraysize(buffer)); OLA_ASSERT_DATA_EQUALS(short_output, arraysize(short_output), buffer, arraysize(buffer)); const char output[] = {'f', 'o', 'o', 'b', 'a', 'r'}; CopyToFixedLengthBuffer(input, buffer, arraysize(buffer)); OLA_ASSERT_DATA_EQUALS(output, arraysize(output), buffer, arraysize(buffer)); const char oversized_output[] = {'f', 'o', 'o', 'b', 'a', 'r'}; CopyToFixedLengthBuffer(oversized_input, buffer, arraysize(buffer)); OLA_ASSERT_DATA_EQUALS(oversized_output, arraysize(oversized_output), buffer, arraysize(buffer)); } ola-0.10.5.nojsmin/common/strings/Format.cpp0000644000175000017500000000410613023355232020374 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Format.cpp * Formatting functions for basic types. * Copyright (C) 2005 Simon Newton */ #include "ola/strings/Format.h" #include #include #include namespace ola { namespace strings { using std::endl; using std::ostringstream; using std::string; string IntToString(int i) { ostringstream str; str << i; return str.str(); } string IntToString(unsigned int i) { ostringstream str; str << i; return str.str(); } void FormatData(std::ostream *out, const uint8_t *data, unsigned int length, unsigned int indent, unsigned int byte_per_line) { ostringstream raw, ascii; raw << std::hex; for (unsigned int i = 0; i != length; i++) { raw << std::setfill('0') << std::setw(2) << static_cast(data[i]) << " "; if (isprint(data[i])) { ascii << data[i]; } else { ascii << "."; } if (i % byte_per_line == byte_per_line - 1) { *out << string(indent, ' ') << raw.str() << " " << ascii.str() << endl; raw.str(""); ascii.str(""); } } if (length % byte_per_line != 0) { // pad if needed raw << string(3 * (byte_per_line - (length % byte_per_line)), ' '); *out << string(indent, ' ') << raw.str() << " " << ascii.str() << endl; } } } // namespace strings } // namespace ola ola-0.10.5.nojsmin/common/protocol/0000755000175000017500000000000013155164170016614 5ustar wouterwouterola-0.10.5.nojsmin/common/protocol/Makefile.mk0000644000175000017500000000246613023355232020665 0ustar wouterwouterEXTRA_DIST += common/protocol/Ola.proto # The .h files are included elsewhere so we have to put them in BUILT_SOURCES built_sources += \ common/protocol/Ola.pb.cc \ common/protocol/Ola.pb.h \ common/protocol/OlaService.pb.h \ common/protocol/OlaService.pb.cpp # LIBRARIES ################################################## # We build the .cc files as a separate unit because they aren't warning-clean. noinst_LTLIBRARIES += common/protocol/libolaproto.la nodist_common_protocol_libolaproto_la_SOURCES = \ common/protocol/Ola.pb.cc \ common/protocol/OlaService.pb.cpp common_protocol_libolaproto_la_LIBADD = $(libprotobuf_LIBS) # required, otherwise we get build errors common_protocol_libolaproto_la_CXXFLAGS = $(COMMON_CXXFLAGS_ONLY_WARNINGS) common_libolacommon_la_LIBADD += common/protocol/libolaproto.la common/protocol/Ola.pb.cc common/protocol/Ola.pb.h: common/protocol/Makefile.mk common/protocol/Ola.proto $(PROTOC) --cpp_out common/protocol --proto_path $(srcdir)/common/protocol $(srcdir)/common/protocol/Ola.proto common/protocol/OlaService.pb.cpp common/protocol/OlaService.pb.h: common/protocol/Makefile.mk common/protocol/Ola.proto protoc/ola_protoc_plugin$(EXEEXT) $(OLA_PROTOC) --cppservice_out common/protocol --proto_path $(srcdir)/common/protocol $(srcdir)/common/protocol/Ola.proto ola-0.10.5.nojsmin/common/protocol/Ola.proto0000644000175000017500000002674213134123277020427 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Ola.proto * Defines the protocol buffers used to talk to olad * Copyright (C) 2005 Simon Newton */ package ola.proto; option cc_generic_services = false; option py_generic_services = true; option java_generic_services = true; enum RegisterAction { REGISTER = 1; UNREGISTER = 2; } enum PatchAction { PATCH = 1; UNPATCH = 2; } enum MergeMode { HTP = 1; LTP = 2; } /** * Please see the note below about getting a new Plugin ID. */ enum PluginIds { OLA_PLUGIN_ALL = 0; OLA_PLUGIN_DUMMY = 1; OLA_PLUGIN_ARTNET = 2; OLA_PLUGIN_SHOWNET = 3; OLA_PLUGIN_ESPNET = 4; OLA_PLUGIN_USBPRO = 5; OLA_PLUGIN_OPENDMX = 6; OLA_PLUGIN_SANDNET = 7; OLA_PLUGIN_STAGEPROFI = 8; OLA_PLUGIN_PATHPORT = 9; OLA_PLUGIN_DMX4LINUX = 10; OLA_PLUGIN_E131 = 11; OLA_PLUGIN_USBDMX = 12; OLA_PLUGIN_FTDIDMX = 13; OLA_PLUGIN_OSC = 14; OLA_PLUGIN_SPI = 15; OLA_PLUGIN_KINET = 16; OLA_PLUGIN_KARATE = 17; OLA_PLUGIN_MILINST = 18; OLA_PLUGIN_RENARD = 19; OLA_PLUGIN_UARTDMX = 20; OLA_PLUGIN_OPENPIXELCONTROL = 21; OLA_PLUGIN_GPIO = 22; /* * To obtain a new plugin ID, open a ticket at * https://github.com/OpenLightingProject/ola/issues/new * Plugin IDs are usually assigned just prior to merging the code into the * mainline. For development of plugins please use the value of * OLA_PLUGIN_EXPERIMENTAL in a plugin ID you define above. */ OLA_PLUGIN_EXPERIMENTAL = 10000; } /** * If you add more here be sure to update ResponseCodeToString in RDMHelper.cpp */ enum RDMResponseCode { // The request/response completed correctly RDM_COMPLETED_OK = 0; // The request was broadcast, no response expected RDM_WAS_BROADCAST = 1; // We failed to send this request RDM_FAILED_TO_SEND = 2; // The response timed out RDM_TIMEOUT = 3; // The response was invalid RDM_INVALID_RESPONSE = 4; // The UID could not be located (may have been removed) RDM_UNKNOWN_UID = 5; // The response checksum was wrong RDM_CHECKSUM_INCORRECT = 6; // Invalid transaction number RDM_TRANSACTION_MISMATCH = 7; // Wrong sub device RDM_SUB_DEVICE_MISMATCH = 8; //Source UID in response doesn't match RDM_SRC_UID_MISMATCH = 9; //Destination UID in response doesn't match RDM_DEST_UID_MISMATCH = 10; //Incorrect sub start code RDM_WRONG_SUB_START_CODE = 11; //RDM response was smaller than the minimum size RDM_PACKET_TOO_SHORT = 12; //The length field of packet didn't match length received RDM_PACKET_LENGTH_MISMATCH = 13; //The parameter length exceeds the remaining packet size RDM_PARAM_LENGTH_MISMATCH = 14; //The command class was not one of GET_RESPONSE or SET_RESPONSE RDM_INVALID_COMMAND_CLASS = 15; //The command class didn't match the request RDM_COMMAND_CLASS_MISMATCH = 16; //The response type was not ACK, ACK_OVERFLOW, ACK_TIMER or NACK RDM_INVALID_RESPONSE_TYPE = 17; // The discovery command class is not supported by this device. This // typically means the hardware doesn't support discovery commands. RDM_PLUGIN_DISCOVERY_NOT_SUPPORTED = 18; // Responses to DUB commands, these responses won't have a defined RDM // message, but rather just a string of bytes from the wire. RDM_DUB_RESPONSE = 19; } /** * The valid Response Types when the response_code is RDM_COMPLETED_OK. * ACK_OVERFLOW isn't in this list because overflows are handed by the plugins, * not the clients. */ enum RDMResponseType { RDM_ACK = 0; RDM_ACK_TIMER = 1; RDM_NACK_REASON = 2; // OVERFLOW can never be returned } /** * The RDM command class */ enum RDMCommandClass { RDM_GET_RESPONSE = 0; RDM_SET_RESPONSE = 1; RDM_DISCOVERY_RESPONSE = 2; } // This is a special string which indicates that no response will be received // for an RPC. message STREAMING_NO_RESPONSE {} // Generic Ack Message message Ack {} // request the list of available plugins message PluginListRequest {} // Trigger a plugin reload. message PluginReloadRequest {} message PluginInfo { required int32 plugin_id = 1; required string name = 2; required bool active = 3; optional bool enabled = 4; } message PluginListReply { repeated PluginInfo plugin = 1; } // request the description for a plugin message PluginDescriptionRequest { required int32 plugin_id = 1; } message PluginDescriptionReply { required string name = 1; required string description = 2; } // request the state for a plugin message PluginStateRequest { required int32 plugin_id = 1; } message PluginStateReply { required string name = 1; required bool enabled = 2; required bool active = 3; required string preferences_source = 4; repeated PluginInfo conflicts_with = 5; } message PluginStateChangeRequest { required int32 plugin_id = 1; required bool enabled = 2; } // request info on a device message DeviceInfoRequest { optional int32 plugin_id = 1; } message PortInfo { required int32 port_id = 1; required int32 priority_capability = 2; required string description = 5; optional int32 universe = 3; optional bool active = 4; optional int32 priority_mode = 6; optional int32 priority = 7; optional bool supports_rdm = 8 [default = false]; } message DeviceInfo { required int32 device_alias = 1; required int32 plugin_id = 2; required string device_name = 3; repeated PortInfo input_port = 4; repeated PortInfo output_port = 5; required string device_id = 6; } message DeviceInfoReply { repeated DeviceInfo device = 1; } message DmxData { required int32 universe = 1; required bytes data = 2; optional int32 priority = 3; } message RegisterDmxRequest { required int32 universe = 1; required RegisterAction action = 2; } message PatchPortRequest { required int32 universe = 1; required int32 device_alias = 2; required int32 port_id = 3; required PatchAction action = 4; required bool is_output = 5; } message UniverseNameRequest { required int32 universe = 1; required string name = 2; } message MergeModeRequest { required int32 universe = 1; required MergeMode merge_mode = 2; } // request info about a universe message OptionalUniverseRequest { optional int32 universe = 1; } message UniverseInfo { required int32 universe = 1; required string name = 2; required MergeMode merge_mode = 3; required int32 input_port_count = 4; required int32 output_port_count = 5; required int32 rdm_devices = 6; repeated PortInfo input_ports = 7; repeated PortInfo output_ports = 8; } message UniverseInfoReply { repeated UniverseInfo universe = 1; } message PortPriorityRequest { required int32 device_alias = 1; required bool is_output = 2; required int32 port_id = 3; required int32 priority_mode = 4; optional int32 priority = 5; } // a device config request message DeviceConfigRequest { required int32 device_alias = 1; required bytes data = 2; } message DeviceConfigReply { required bytes data = 1; } // RDM Messages // This represents a UID message UID { required int32 esta_id = 1; // only lower 2 bytes are used required fixed32 device_id = 2; } // Request the UID list for a universe message UniverseRequest { required int32 universe = 1; } message DiscoveryRequest { required int32 universe = 1; required bool full = 2; } message UIDListReply { required int32 universe = 1; repeated UID uid = 2; } message RDMRequestOverrideOptions { optional uint32 sub_start_code = 1; optional uint32 message_length = 2; optional uint32 message_count = 3; optional uint32 checksum = 4; } message RDMRequest { required int32 universe = 1; required UID uid = 2; required int32 sub_device = 3; required int32 param_id = 4; required bytes data = 5; // 0 - 231 bytes required bool is_set = 6; optional bool include_raw_response = 7 [default = false]; optional RDMRequestOverrideOptions options = 8; } message RDMDiscoveryRequest { required int32 universe = 1; required UID uid = 2; required int32 sub_device = 3; required int32 param_id = 4; required bytes data = 5; // 0 - 231 bytes optional bool include_raw_response = 6 [default = false]; optional RDMRequestOverrideOptions options = 8; } message RDMFrameTiming { optional int32 response_delay = 1; optional int32 break_time = 2; optional int32 mark_time = 3; optional int32 data_time = 4; } message RDMFrame { optional bytes raw_response = 1; optional RDMFrameTiming timing = 2; } message RDMResponse { required RDMResponseCode response_code = 1; optional UID source_uid = 9; optional UID dest_uid = 10; optional int32 transaction_number = 11; // ACK, NACK or TIMER optional RDMResponseType response_type = 2; optional uint32 message_count = 3 [default = 0]; optional uint32 sub_device = 7; // the sub device optional RDMCommandClass command_class = 6; // the command class optional uint32 param_id = 5; // the param id, required for queued messages optional bytes data = 4 [default = ""]; // 0 - 231 bytes repeated bytes raw_response = 8; // deprecated repeated RDMFrame raw_frame = 12; } // timecode enum TimeCodeType { TIMECODE_FILM = 0; // 24fps TIMECODE_EBU = 1; // 25fps TIMECODE_DF = 2; // 29.97fps TIMECODE_SMPTE = 3; // 30fps }; message TimeCode { required uint32 hours = 1; required uint32 minutes = 2; required uint32 seconds = 3; required uint32 frames = 4; required TimeCodeType type = 5; } // Services // RPCs handled by the OLA Server service OlaServerService { rpc GetPlugins (PluginListRequest) returns (PluginListReply); rpc ReloadPlugins (PluginReloadRequest) returns (Ack); rpc GetPluginDescription (PluginDescriptionRequest) returns (PluginDescriptionReply); rpc GetPluginState (PluginStateRequest) returns (PluginStateReply); rpc GetDeviceInfo (DeviceInfoRequest) returns (DeviceInfoReply); rpc GetCandidatePorts (OptionalUniverseRequest) returns (DeviceInfoReply); rpc ConfigureDevice (DeviceConfigRequest) returns (DeviceConfigReply); rpc SetPluginState (PluginStateChangeRequest) returns (Ack); rpc SetPortPriority (PortPriorityRequest) returns (Ack); rpc GetUniverseInfo (OptionalUniverseRequest) returns (UniverseInfoReply); rpc SetUniverseName (UniverseNameRequest) returns (Ack); rpc SetMergeMode (MergeModeRequest) returns (Ack); rpc PatchPort (PatchPortRequest) returns (Ack); rpc RegisterForDmx (RegisterDmxRequest) returns (Ack); rpc UpdateDmxData (DmxData) returns (Ack); rpc GetDmx (UniverseRequest) returns (DmxData); rpc GetUIDs (UniverseRequest) returns (UIDListReply); rpc ForceDiscovery (DiscoveryRequest) returns (UIDListReply); rpc SetSourceUID (UID) returns (Ack); rpc RDMCommand (RDMRequest) returns (RDMResponse); rpc RDMDiscoveryCommand (RDMDiscoveryRequest) returns (RDMResponse); rpc StreamDmxData (DmxData) returns (STREAMING_NO_RESPONSE); // timecode rpc SendTimeCode(TimeCode) returns (Ack); } // RPCs handled by the OLA Client service OlaClientService { rpc UpdateDmxData (DmxData) returns (Ack); } ola-0.10.5.nojsmin/common/rpc/0000755000175000017500000000000013155164170015537 5ustar wouterwouterola-0.10.5.nojsmin/common/rpc/RpcController.cpp0000644000175000017500000000252213023355232021027 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * RpcController.cpp * The RpcController. * Copyright (C) 2005 Simon Newton */ #include "common/rpc/RpcController.h" #include #include "common/rpc/RpcSession.h" namespace ola { namespace rpc { RpcController::RpcController(RpcSession *session) : m_session(session), m_failed(false), m_error_text("") { } void RpcController::Reset() { m_failed = false; m_error_text = ""; } void RpcController::SetFailed(const std::string &reason) { m_failed = true; m_error_text = reason; } RpcSession *RpcController::Session() { return m_session; } } // namespace rpc } // namespace ola ola-0.10.5.nojsmin/common/rpc/RpcServer.cpp0000644000175000017500000001241313023355232020152 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * RpcServer.cpp * A generic RPC server. * Copyright (C) 2014 Simon Newton */ #include "common/rpc/RpcServer.h" #include #include #include #include #include #include "common/rpc/RpcChannel.h" #include "common/rpc/RpcSession.h" namespace ola { namespace rpc { using std::auto_ptr; using ola::io::ConnectedDescriptor; using ola::network::GenericSocketAddress; using ola::network::IPV4Address; using ola::network::IPV4SocketAddress; using ola::network::TCPAcceptingSocket; using ola::network::TCPSocket; namespace { void CleanupChannel(RpcChannel *channel, ConnectedDescriptor *descriptor) { delete channel; delete descriptor; } } // namespace const char RpcServer::K_CLIENT_VAR[] = "clients-connected"; const char RpcServer::K_RPC_PORT_VAR[] = "rpc-port"; RpcServer::RpcServer(ola::io::SelectServerInterface *ss, RpcService *service, RpcSessionHandlerInterface *session_handler, const Options &options) : m_ss(ss), m_service(service), m_session_handler(session_handler), m_options(options), m_tcp_socket_factory( ola::NewCallback(this, &RpcServer::NewTCPConnection)) { if (m_options.export_map) { m_options.export_map->GetIntegerVar(K_CLIENT_VAR); } } RpcServer::~RpcServer() { // Take a copy since calling the close handler will cause the socket to be // removed from m_connected_sockets ClientDescriptors sockets = m_connected_sockets; ClientDescriptors::const_iterator iter = sockets.begin(); for (; iter != sockets.end(); ++iter) { (*iter)->TransferOnClose()->Run(); } if (!sockets.empty()) { m_ss->DrainCallbacks(); } if (m_accepting_socket.get() && m_accepting_socket->ValidReadDescriptor()) { m_ss->RemoveReadDescriptor(m_accepting_socket.get()); } } bool RpcServer::Init() { if (m_accepting_socket.get()) { return false; } auto_ptr accepting_socket; if (m_options.listen_socket) { accepting_socket.reset(m_options.listen_socket); accepting_socket->SetFactory(&m_tcp_socket_factory); } else { accepting_socket.reset( new TCPAcceptingSocket(&m_tcp_socket_factory)); if (!accepting_socket->Listen( IPV4SocketAddress(IPV4Address::Loopback(), m_options.listen_port))) { OLA_FATAL << "Could not listen on the RPC port " << m_options.listen_port << ", you probably have another instance of running."; return false; } if (m_options.export_map) { m_options.export_map->GetIntegerVar(K_RPC_PORT_VAR)->Set( m_options.listen_port); } } if (!m_ss->AddReadDescriptor(accepting_socket.get())) { OLA_WARN << "Failed to add RPC socket to SelectServer"; return false; } m_accepting_socket.reset(accepting_socket.release()); return true; } GenericSocketAddress RpcServer::ListenAddress() { if (m_accepting_socket.get()) { return m_accepting_socket->GetLocalAddress(); } return GenericSocketAddress(); } bool RpcServer::AddClient(ConnectedDescriptor *descriptor) { // If RpcChannel had a pointer to the SelectServer to use, we could hand off // ownership of the socket here. RpcChannel *channel = new RpcChannel(m_service, descriptor, m_options.export_map); if (m_session_handler) { m_session_handler->NewClient(channel->Session()); } channel->SetChannelCloseHandler( NewSingleCallback(this, &RpcServer::ChannelClosed, descriptor)); if (m_options.export_map) { (*m_options.export_map->GetIntegerVar(K_CLIENT_VAR))++; } m_ss->AddReadDescriptor(descriptor); m_connected_sockets.insert(descriptor); return true; } void RpcServer::NewTCPConnection(TCPSocket *socket) { if (!socket) return; socket->SetNoDelay(); AddClient(socket); } void RpcServer::ChannelClosed(ConnectedDescriptor *descriptor, RpcSession *session) { if (m_session_handler) { m_session_handler->ClientRemoved(session); } if (m_options.export_map) { (*m_options.export_map->GetIntegerVar(K_CLIENT_VAR))--; } m_ss->RemoveReadDescriptor(descriptor); m_connected_sockets.erase(descriptor); // We're in the call stack of both the descriptor and the channel here. // We schedule deletion during the next run of the event loop to break out of // the stack. m_ss->Execute( NewSingleCallback(CleanupChannel, session->Channel(), descriptor)); } } // namespace rpc } // namespace ola ola-0.10.5.nojsmin/common/rpc/Rpc.proto0000644000175000017500000000272213023355232017346 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Rpc.proto * Defines the protocol buffers used in the underlying RPC implementation. * Copyright (C) 2005 Simon Newton */ /* * Based on, but not guaranteed to be the same as the specification here: * http://protorpc.likbilen.com/Protorpcdocprotobuf.html */ package ola.rpc; enum Type { REQUEST = 1; RESPONSE = 2; RESPONSE_CANCEL = 3; RESPONSE_FAILED = 4; RESPONSE_NOT_IMPLEMENTED = 5; DISCONNECT = 6; DESCRIPTOR_REQUEST = 7; // not implemented DESCRIPTOR_RESPONSE = 8; // not implemented REQUEST_CANCEL = 9; STREAM_REQUEST = 10; // a request that we don't expect a response for }; message RpcMessage { required Type type = 1; optional uint32 id = 2; optional string name = 3; optional bytes buffer = 4; } ola-0.10.5.nojsmin/common/rpc/RpcHeader.h0000644000175000017500000000346613023355232017551 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * RpcHeader.h * The header for the RPC messages. * Copyright (C) 2005 Simon Newton */ #ifndef COMMON_RPC_RPCHEADER_H_ #define COMMON_RPC_RPCHEADER_H_ #include namespace ola { namespace rpc { class RpcHeader { /* * The first 4 bytes are the header which contains the RPC protocol version * (this is separate from the protobuf version) and the size of the protobuf. */ public: /** * Encode a header */ static void EncodeHeader(uint32_t *header, unsigned int version, unsigned int size) { *header = (version << 28) & VERSION_MASK; *header |= size & SIZE_MASK; } /** * Decode a header */ static void DecodeHeader(uint32_t header, unsigned int *version, unsigned int *size) { *version = (header & VERSION_MASK) >> 28; *size = header & SIZE_MASK; } private: static const unsigned int VERSION_MASK = 0xf0000000; static const unsigned int SIZE_MASK = 0x0fffffff; }; } // namespace rpc } // namespace ola #endif // COMMON_RPC_RPCHEADER_H_ ola-0.10.5.nojsmin/common/rpc/Makefile.mk0000644000175000017500000000516613023355232017610 0ustar wouterwouterbuilt_sources += \ common/rpc/Rpc.pb.cc \ common/rpc/Rpc.pb.h \ common/rpc/TestService.pb.cc \ common/rpc/TestService.pb.h \ common/rpc/TestServiceService.pb.cpp \ common/rpc/TestServiceService.pb.h # LIBRARIES ################################################## common_libolacommon_la_SOURCES += \ common/rpc/RpcChannel.cpp \ common/rpc/RpcChannel.h \ common/rpc/RpcSession.h \ common/rpc/RpcController.cpp \ common/rpc/RpcController.h \ common/rpc/RpcHeader.h \ common/rpc/RpcPeer.h \ common/rpc/RpcServer.cpp \ common/rpc/RpcServer.h \ common/rpc/RpcService.h nodist_common_libolacommon_la_SOURCES += common/rpc/Rpc.pb.cc common_libolacommon_la_LIBADD += $(libprotobuf_LIBS) EXTRA_DIST += \ common/rpc/Rpc.proto \ common/rpc/TestService.proto common/rpc/Rpc.pb.cc common/rpc/Rpc.pb.h: common/rpc/Makefile.mk common/rpc/Rpc.proto $(PROTOC) --cpp_out common/rpc --proto_path $(srcdir)/common/rpc $(srcdir)/common/rpc/Rpc.proto common/rpc/TestService.pb.cc common/rpc/TestService.pb.h: common/rpc/Makefile.mk common/rpc/TestService.proto $(PROTOC) --cpp_out common/rpc --proto_path $(srcdir)/common/rpc $(srcdir)/common/rpc/TestService.proto common/rpc/TestServiceService.pb.cpp common/rpc/TestServiceService.pb.h: common/rpc/Makefile.mk common/rpc/TestService.proto protoc/ola_protoc_plugin$(EXEEXT) $(OLA_PROTOC) --cppservice_out common/rpc --proto_path $(srcdir)/common/rpc $(srcdir)/common/rpc/TestService.proto # TESTS ################################################## test_programs += common/rpc/RpcTester common/rpc/RpcServerTester common_rpc_TEST_SOURCES = \ common/rpc/TestService.h \ common/rpc/TestService.cpp common_rpc_RpcTester_SOURCES = \ common/rpc/RpcControllerTest.cpp \ common/rpc/RpcChannelTest.cpp \ common/rpc/RpcHeaderTest.cpp \ $(common_rpc_TEST_SOURCES) nodist_common_rpc_RpcTester_SOURCES = \ common/rpc/TestService.pb.cc \ common/rpc/TestServiceService.pb.cpp # required, otherwise we get build errors common_rpc_RpcTester_CXXFLAGS = $(COMMON_TESTING_FLAGS_ONLY_WARNINGS) common_rpc_RpcTester_LDADD = $(COMMON_TESTING_LIBS) \ $(libprotobuf_LIBS) common_rpc_RpcServerTester_SOURCES = \ common/rpc/RpcServerTest.cpp \ $(common_rpc_TEST_SOURCES) nodist_common_rpc_RpcServerTester_SOURCES = \ common/rpc/TestService.pb.cc \ common/rpc/TestServiceService.pb.cpp # required, otherwise we get build errors common_rpc_RpcServerTester_CXXFLAGS = $(COMMON_TESTING_FLAGS_ONLY_WARNINGS) common_rpc_RpcServerTester_LDADD = $(COMMON_TESTING_LIBS) \ $(libprotobuf_LIBS) ola-0.10.5.nojsmin/common/rpc/RpcService.h0000644000175000017500000000403513023355232017752 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * RpcService.h * Interface for the RpcService. * Copyright (C) 2013 Simon Newton * * All Services generated by the ola protoc plugin inherit from this one. */ #ifndef COMMON_RPC_RPCSERVICE_H_ #define COMMON_RPC_RPCSERVICE_H_ #include #include #include "ola/Callback.h" namespace ola { namespace rpc { class RpcController; class RpcService { public: typedef SingleUseCallback0 CompletionCallback; RpcService() {} virtual ~RpcService() {} // Return the descriptor for this service. virtual const google::protobuf::ServiceDescriptor* GetDescriptor() = 0; // Invoke a method. virtual void CallMethod(const google::protobuf::MethodDescriptor *method, RpcController *controller, const google::protobuf::Message *request, google::protobuf::Message *response, CompletionCallback *done) = 0; virtual const google::protobuf::Message& GetRequestPrototype( const google::protobuf::MethodDescriptor *method) const = 0; virtual const google::protobuf::Message& GetResponsePrototype( const google::protobuf::MethodDescriptor *method) const = 0; }; } // namespace rpc } // namespace ola #endif // COMMON_RPC_RPCSERVICE_H_ ola-0.10.5.nojsmin/common/rpc/RpcChannel.cpp0000644000175000017500000004127413023355232020263 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * RpcChannel.cpp * Interface for the UDP RPC Channel * Copyright (C) 2005 Simon Newton */ #include "common/rpc/RpcChannel.h" #include #include #include #include #include #include #include "common/rpc/Rpc.pb.h" #include "common/rpc/RpcSession.h" #include "common/rpc/RpcController.h" #include "common/rpc/RpcHeader.h" #include "common/rpc/RpcService.h" #include "ola/Callback.h" #include "ola/Logging.h" #include "ola/base/Array.h" #include "ola/stl/STLUtils.h" namespace ola { namespace rpc { using google::protobuf::Message; using google::protobuf::MethodDescriptor; using google::protobuf::ServiceDescriptor; using std::auto_ptr; using std::string; const char RpcChannel::K_RPC_RECEIVED_TYPE_VAR[] = "rpc-received-type"; const char RpcChannel::K_RPC_RECEIVED_VAR[] = "rpc-received"; const char RpcChannel::K_RPC_SENT_ERROR_VAR[] = "rpc-send-errors"; const char RpcChannel::K_RPC_SENT_VAR[] = "rpc-sent"; const char RpcChannel::STREAMING_NO_RESPONSE[] = "STREAMING_NO_RESPONSE"; const char *RpcChannel::K_RPC_VARIABLES[] = { K_RPC_RECEIVED_VAR, K_RPC_SENT_ERROR_VAR, K_RPC_SENT_VAR, }; class OutstandingRequest { /* * These are requests on the server end that haven't completed yet. */ public: OutstandingRequest(int id, RpcSession *session, google::protobuf::Message *response) : id(id), controller(new RpcController(session)), response(response) { } ~OutstandingRequest() { if (controller) { delete controller; } if (response) { delete response; } } int id; RpcController *controller; google::protobuf::Message *response; }; class OutstandingResponse { /* * These are Requests on the client end that haven't completed yet. */ public: OutstandingResponse(int id, RpcController *controller, SingleUseCallback0 *callback, Message *reply) : id(id), controller(controller), callback(callback), reply(reply) { } int id; RpcController *controller; SingleUseCallback0 *callback; Message *reply; }; RpcChannel::RpcChannel( RpcService *service, ola::io::ConnectedDescriptor *descriptor, ExportMap *export_map) : m_session(new RpcSession(this)), m_service(service), m_descriptor(descriptor), m_buffer(NULL), m_buffer_size(0), m_expected_size(0), m_current_size(0), m_export_map(export_map), m_recv_type_map(NULL) { if (descriptor) { descriptor->SetOnData( ola::NewCallback(this, &RpcChannel::DescriptorReady)); descriptor->SetOnClose( ola::NewSingleCallback(this, &RpcChannel::HandleChannelClose)); } if (m_export_map) { for (unsigned int i = 0; i < arraysize(K_RPC_VARIABLES); ++i) { m_export_map->GetCounterVar(string(K_RPC_VARIABLES[i])); } m_recv_type_map = m_export_map->GetUIntMapVar(K_RPC_RECEIVED_TYPE_VAR, "type"); } } RpcChannel::~RpcChannel() { free(m_buffer); } void RpcChannel::DescriptorReady() { if (!m_expected_size) { // this is a new msg unsigned int version; if (ReadHeader(&version, &m_expected_size) < 0) return; if (!m_expected_size) return; if (version != PROTOCOL_VERSION) { OLA_WARN << "protocol mismatch " << version << " != " << PROTOCOL_VERSION; return; } if (m_expected_size > MAX_BUFFER_SIZE) { OLA_WARN << "Incoming message size " << m_expected_size << " is larger than MAX_BUFFER_SIZE: " << MAX_BUFFER_SIZE; m_descriptor->Close(); return; } m_current_size = 0; m_buffer_size = AllocateMsgBuffer(m_expected_size); if (m_buffer_size < m_expected_size) { OLA_WARN << "buffer size to small " << m_buffer_size << " < " << m_expected_size; return; } } if (!m_descriptor) { return; } unsigned int data_read; if (m_descriptor->Receive(m_buffer + m_current_size, m_expected_size - m_current_size, data_read) < 0) { OLA_WARN << "something went wrong in descriptor recv\n"; return; } m_current_size += data_read; if (m_current_size == m_expected_size) { // we've got all of this message so parse it. if (!HandleNewMsg(m_buffer, m_expected_size)) { // this probably means we've messed the framing up, close the channel OLA_WARN << "Errors detected on RPC channel, closing"; m_descriptor->Close(); } m_expected_size = 0; } return; } void RpcChannel::SetChannelCloseHandler(CloseCallback *callback) { m_on_close.reset(callback); } void RpcChannel::CallMethod(const MethodDescriptor *method, RpcController *controller, const Message *request, Message *reply, SingleUseCallback0 *done) { // TODO(simonn): reduce the number of copies here string output; RpcMessage message; bool is_streaming = false; // Streaming methods are those with a reply set to STREAMING_NO_RESPONSE and // no controller, request or closure provided if (method->output_type()->name() == STREAMING_NO_RESPONSE) { if (controller || reply || done) { OLA_FATAL << "Calling streaming method " << method->name() << " but a controller, reply or closure in non-NULL"; return; } is_streaming = true; } message.set_type(is_streaming ? STREAM_REQUEST : REQUEST); message.set_id(m_sequence.Next()); message.set_name(method->name()); request->SerializeToString(&output); message.set_buffer(output); bool r = SendMsg(&message); if (is_streaming) return; if (!r) { // Send failed, call the handler now. controller->SetFailed("Failed to send request"); done->Run(); return; } OutstandingResponse *response = new OutstandingResponse( message.id(), controller, done, reply); auto_ptr old_response( STLReplacePtr(&m_responses, message.id(), response)); if (old_response.get()) { // fail any outstanding response with the same id OLA_WARN << "response " << old_response->id << " already pending, failing " << "now"; response->controller->SetFailed("Duplicate request found"); response->callback->Run(); } } void RpcChannel::RequestComplete(OutstandingRequest *request) { string output; RpcMessage message; if (request->controller->Failed()) { SendRequestFailed(request); return; } message.set_type(RESPONSE); message.set_id(request->id); request->response->SerializeToString(&output); message.set_buffer(output); SendMsg(&message); DeleteOutstandingRequest(request); } RpcSession *RpcChannel::Session() { return m_session.get(); } // private //----------------------------------------------------------------------------- /* * Write an RpcMessage to the write descriptor. */ bool RpcChannel::SendMsg(RpcMessage *msg) { if (!(m_descriptor && m_descriptor->ValidReadDescriptor())) { OLA_WARN << "RPC descriptor closed, not sending messages"; return false; } uint32_t header; // reserve the first 4 bytes for the header string output(sizeof(header), 0); msg->AppendToString(&output); int length = output.size(); RpcHeader::EncodeHeader(&header, PROTOCOL_VERSION, length - sizeof(header)); output.replace( 0, sizeof(header), reinterpret_cast(&header), sizeof(header)); ssize_t ret = m_descriptor->Send( reinterpret_cast(output.data()), length); if (ret != length) { OLA_WARN << "Failed to send full RPC message, closing channel"; if (m_export_map) { (*m_export_map->GetCounterVar(K_RPC_SENT_ERROR_VAR))++; } // At this point there is no point using the descriptor since framing has // probably been messed up. // TODO(simon): consider if it's worth leaving the descriptor open for // reading. m_descriptor = NULL; HandleChannelClose(); return false; } if (m_export_map) { (*m_export_map->GetCounterVar(K_RPC_SENT_VAR))++; } return true; } /* * Allocate an incoming message buffer * @param size the size of the new buffer to allocate * @returns the size of the new buffer */ int RpcChannel::AllocateMsgBuffer(unsigned int size) { unsigned int requested_size = size; uint8_t *new_buffer; if (size < m_buffer_size) return size; if (m_buffer_size == 0 && size < INITIAL_BUFFER_SIZE) requested_size = INITIAL_BUFFER_SIZE; if (requested_size > MAX_BUFFER_SIZE) { OLA_WARN << "Incoming message size " << requested_size << " is larger than MAX_BUFFER_SIZE: " << MAX_BUFFER_SIZE; return m_buffer_size; } new_buffer = static_cast(realloc(m_buffer, requested_size)); if (!new_buffer) return m_buffer_size; m_buffer = new_buffer; m_buffer_size = requested_size; return requested_size; } /* * Read 4 bytes and decode the header fields. * @returns: -1 if there is no data is available, version and size are 0 */ int RpcChannel::ReadHeader(unsigned int *version, unsigned int *size) const { uint32_t header; unsigned int data_read = 0; *version = *size = 0; if (m_descriptor->Receive(reinterpret_cast(&header), sizeof(header), data_read)) { OLA_WARN << "read header error: " << strerror(errno); return -1; } if (!data_read) return 0; RpcHeader::DecodeHeader(header, version, size); return 0; } /* * Parse a new message and handle it. */ bool RpcChannel::HandleNewMsg(uint8_t *data, unsigned int size) { RpcMessage msg; if (!msg.ParseFromArray(data, size)) { OLA_WARN << "Failed to parse RPC"; return false; } if (m_export_map) (*m_export_map->GetCounterVar(K_RPC_RECEIVED_VAR))++; switch (msg.type()) { case REQUEST: if (m_recv_type_map) (*m_recv_type_map)["request"]++; HandleRequest(&msg); break; case RESPONSE: if (m_recv_type_map) (*m_recv_type_map)["response"]++; HandleResponse(&msg); break; case RESPONSE_CANCEL: if (m_recv_type_map) (*m_recv_type_map)["cancelled"]++; HandleCanceledResponse(&msg); break; case RESPONSE_FAILED: if (m_recv_type_map) (*m_recv_type_map)["failed"]++; HandleFailedResponse(&msg); break; case RESPONSE_NOT_IMPLEMENTED: if (m_recv_type_map) (*m_recv_type_map)["not-implemented"]++; HandleNotImplemented(&msg); break; case STREAM_REQUEST: if (m_recv_type_map) (*m_recv_type_map)["stream_request"]++; HandleStreamRequest(&msg); break; default: OLA_WARN << "not sure of msg type " << msg.type(); break; } return true; } /* * Handle a new RPC method call. */ void RpcChannel::HandleRequest(RpcMessage *msg) { if (!m_service) { OLA_WARN << "no service registered"; return; } const ServiceDescriptor *service = m_service->GetDescriptor(); if (!service) { OLA_WARN << "failed to get service descriptor"; return; } const MethodDescriptor *method = service->FindMethodByName(msg->name()); if (!method) { OLA_WARN << "failed to get method descriptor"; SendNotImplemented(msg->id()); return; } Message* request_pb = m_service->GetRequestPrototype(method).New(); Message* response_pb = m_service->GetResponsePrototype(method).New(); if (!request_pb || !response_pb) { OLA_WARN << "failed to get request or response objects"; return; } if (!request_pb->ParseFromString(msg->buffer())) { OLA_WARN << "parsing of request pb failed"; return; } OutstandingRequest *request = new OutstandingRequest( msg->id(), m_session.get(), response_pb); if (m_requests.find(msg->id()) != m_requests.end()) { OLA_WARN << "dup sequence number for request " << msg->id(); SendRequestFailed(m_requests[msg->id()]); } m_requests[msg->id()] = request; SingleUseCallback0 *callback = NewSingleCallback( this, &RpcChannel::RequestComplete, request); m_service->CallMethod(method, request->controller, request_pb, response_pb, callback); delete request_pb; } /* * Handle a streaming RPC call. This doesn't return any response to the client. */ void RpcChannel::HandleStreamRequest(RpcMessage *msg) { if (!m_service) { OLA_WARN << "no service registered"; return; } const ServiceDescriptor *service = m_service->GetDescriptor(); if (!service) { OLA_WARN << "failed to get service descriptor"; return; } const MethodDescriptor *method = service->FindMethodByName(msg->name()); if (!method) { OLA_WARN << "failed to get method descriptor"; SendNotImplemented(msg->id()); return; } if (method->output_type()->name() != STREAMING_NO_RESPONSE) { OLA_WARN << "Streaming request received for " << method->name() << ", but the output type isn't STREAMING_NO_RESPONSE"; return; } Message* request_pb = m_service->GetRequestPrototype(method).New(); if (!request_pb) { OLA_WARN << "failed to get request or response objects"; return; } if (!request_pb->ParseFromString(msg->buffer())) { OLA_WARN << "parsing of request pb failed"; return; } RpcController controller(m_session.get()); m_service->CallMethod(method, &controller, request_pb, NULL, NULL); delete request_pb; } // server side /* * Notify the caller that the request failed. */ void RpcChannel::SendRequestFailed(OutstandingRequest *request) { RpcMessage message; message.set_type(RESPONSE_FAILED); message.set_id(request->id); message.set_buffer(request->controller->ErrorText()); SendMsg(&message); DeleteOutstandingRequest(request); } /* * Sent if we get a request for a non-existant method. */ void RpcChannel::SendNotImplemented(int msg_id) { RpcMessage message; message.set_type(RESPONSE_NOT_IMPLEMENTED); message.set_id(msg_id); SendMsg(&message); } /* * Cleanup an outstanding request after the response has been returned */ void RpcChannel::DeleteOutstandingRequest(OutstandingRequest *request) { STLRemoveAndDelete(&m_requests, request->id); } // client side methods /* * Handle a RPC response by invoking the callback. */ void RpcChannel::HandleResponse(RpcMessage *msg) { auto_ptr response( STLLookupAndRemovePtr(&m_responses, msg->id())); if (response.get()) { if (!response->reply->ParseFromString(msg->buffer())) { OLA_WARN << "Failed to parse response proto for " << response->reply->GetTypeName(); } response->callback->Run(); } } /* * Handle a RPC response by invoking the callback. */ void RpcChannel::HandleFailedResponse(RpcMessage *msg) { auto_ptr response( STLLookupAndRemovePtr(&m_responses, msg->id())); if (response.get()) { response->controller->SetFailed(msg->buffer()); response->callback->Run(); } } /* * Handle a RPC response by invoking the callback. */ void RpcChannel::HandleCanceledResponse(RpcMessage *msg) { OLA_INFO << "Received a canceled response"; auto_ptr response( STLLookupAndRemovePtr(&m_responses, msg->id())); if (response.get()) { response->controller->SetFailed(msg->buffer()); response->callback->Run(); } } /* * Handle a NOT_IMPLEMENTED by invoking the callback. */ void RpcChannel::HandleNotImplemented(RpcMessage *msg) { OLA_INFO << "Received a non-implemented response"; auto_ptr response( STLLookupAndRemovePtr(&m_responses, msg->id())); if (response.get()) { response->controller->SetFailed("Not Implemented"); response->callback->Run(); } } /* * Invoke the Channel close handler/ */ void RpcChannel::HandleChannelClose() { if (m_on_close.get()) { m_on_close.release()->Run(m_session.get()); } } } // namespace rpc } // namespace ola ola-0.10.5.nojsmin/common/rpc/RpcSession.h0000644000175000017500000000516013023355232017775 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * RpcSession.h * The RPC Session object. * Copyright (C) 2014 Simon Newton */ #ifndef COMMON_RPC_RPCSESSION_H_ #define COMMON_RPC_RPCSESSION_H_ namespace ola { namespace rpc { class RpcChannel; /** * @brief Represents the RPC session between a client and server. * * The RPCSession object contains information about the session an RPC is part * of. For each RPC method on the server side, the RPCSession can be accessed * via the RpcController::Session() method. * * Sessions can have arbitary user data associated with them, similar to a * cookie in an HTTP request. The user data is usually set in the call to * RpcSessionHandlerInterface::NewClient() but can be set or modified in any of * the RPC calls themselves. * * Since the RPCSession object doesn't take ownership of the user data, its * should be deleted in the call to * RpcSessionHandlerInterface::ClientRemoved(). */ class RpcSession { public: /** * @brief Create a new session object. * @param channel the RpcChannel that the session is using. Ownership is not * transferred. */ explicit RpcSession(RpcChannel *channel) : m_channel(channel), m_data(NULL) { } /** * @brief Returns the underlying RPCChannel * @returns The RPCChannel that corresponds to this session. */ RpcChannel *Channel() { return m_channel; } /** * @brief Associate user data with this session. * @param ptr Opaque user data to associate with this session. Ownership is * not transferred. */ void SetData(void *ptr) { m_data = ptr; } /** * @brief Retrieve the user data associated with this session. * @returns The user data associated with the session. */ void *GetData() const { return m_data; } // TODO(simon): return the RpcPeer here as well. private: RpcChannel *m_channel; void *m_data; }; } // namespace rpc } // namespace ola #endif // COMMON_RPC_RPCSESSION_H_ ola-0.10.5.nojsmin/common/rpc/TestService.proto0000644000175000017500000000243313023355232021061 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * TestService.proto * Defines a simple service for testing the RpcChannel * Copyright (C) 2005 Simon Newton */ package ola.rpc; option cc_generic_services = false; option py_generic_services = true; message EchoRequest { required string data = 1; optional int64 session_ptr = 2; } message EchoReply { required string data = 1; } message STREAMING_NO_RESPONSE { } service TestService { rpc Echo (EchoRequest) returns (EchoReply); rpc FailedEcho (EchoRequest) returns (EchoReply); rpc Stream (EchoRequest) returns (STREAMING_NO_RESPONSE); } ola-0.10.5.nojsmin/common/rpc/RpcServer.h0000644000175000017500000001005213023355232017614 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * RpcServer.h * A generic RPC server. * Copyright (C) 2014 Simon Newton */ #ifndef COMMON_RPC_RPCSERVER_H_ #define COMMON_RPC_RPCSERVER_H_ #include #include #include #include #include namespace ola { class ExportMap; namespace rpc { /** * @brief An RPC server. * * The RPCServer starts listening on 127.0.0.0:[listen_port] for new client * connections. After accepting a new client connection it calls * RpcSessionHandlerInterface::NewClient() on the session_handler. For each RPC * it then invokes the correct method from the RpcService object. * * Finally when each client disconnects, it calls * RpcSessionHandlerInterface::ClientRemoved() on the session_handler. */ class RpcServer { public: /** * @brief Options for the RpcServer. */ struct Options { public: /** * @brief The TCP port to listen on. * * If listen_socket is passed, this option is ignored. */ uint16_t listen_port; class ExportMap *export_map; ///< The export map to use for stats. /** * @brief The listening TCP socket to wait for clients on. * * The socket should be in listening mode, i.e. have had * TCPAcceptingSocket::Listen() called. * * Ownership of the socket is transferred to the RpcServer. * This overrides the listen_port option. */ ola::network::TCPAcceptingSocket *listen_socket; Options() : listen_port(0), export_map(NULL), listen_socket(NULL) { } }; /** * @brief Create a new RpcServer. * @param ss The SelectServer to use. * @param service The RPCService to expose. * @param session_handler the RpcSessionHandlerInterface to use for client * connect / disconnect notifications. * @param options Options for the RpcServer. */ RpcServer(ola::io::SelectServerInterface *ss, class RpcService *service, class RpcSessionHandlerInterface *session_handler, const Options &options); ~RpcServer(); /** * @brief Initialize the RpcServer. * @returns true if initialization succeeded, false if it failed. */ bool Init(); /** * @brief Return the address this RpcServer is listening on. * @returns The SocketAddress this RpcServer is listening on. */ ola::network::GenericSocketAddress ListenAddress(); /** * @brief Manually attach a new client on the given descriptor * @param descriptor The ConnectedDescriptor that the client is using. * Ownership of the descriptor is transferred. */ bool AddClient(ola::io::ConnectedDescriptor *descriptor); private: typedef std::set ClientDescriptors; ola::io::SelectServerInterface *m_ss; RpcService *m_service; class RpcSessionHandlerInterface *m_session_handler; const Options m_options; ola::network::TCPSocketFactory m_tcp_socket_factory; std::auto_ptr m_accepting_socket; ClientDescriptors m_connected_sockets; void NewTCPConnection(ola::network::TCPSocket *socket); void ChannelClosed(ola::io::ConnectedDescriptor *socket, class RpcSession *session); static const char K_CLIENT_VAR[]; static const char K_RPC_PORT_VAR[]; }; } // namespace rpc } // namespace ola #endif // COMMON_RPC_RPCSERVER_H_ ola-0.10.5.nojsmin/common/rpc/RpcChannelTest.cpp0000644000175000017500000000736513023355232021126 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * RpcChannelTest.cpp * Test fixture for the RpcChannel class * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include "common/rpc/RpcChannel.h" #include "common/rpc/RpcController.h" #include "common/rpc/TestService.h" #include "common/rpc/TestService.pb.h" #include "common/rpc/TestServiceService.pb.h" #include "ola/Callback.h" #include "ola/io/SelectServer.h" #include "ola/network/Socket.h" #include "ola/testing/TestUtils.h" using ola::NewSingleCallback; using ola::io::LoopbackDescriptor; using ola::io::SelectServer; using ola::rpc::EchoReply; using ola::rpc::EchoRequest; using ola::rpc::RpcChannel; using ola::rpc::RpcController; using ola::rpc::STREAMING_NO_RESPONSE; using ola::rpc::RpcController; using ola::rpc::TestService; using ola::rpc::TestService_Stub; using std::auto_ptr; using std::string; class RpcChannelTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(RpcChannelTest); CPPUNIT_TEST(testEcho); CPPUNIT_TEST(testFailedEcho); CPPUNIT_TEST(testStreamRequest); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void tearDown(); void testEcho(); void testFailedEcho(); void testStreamRequest(); void EchoComplete(); void FailedEchoComplete(); private: RpcController m_controller; EchoRequest m_request; EchoReply m_reply; SelectServer m_ss; auto_ptr m_service; auto_ptr m_channel; auto_ptr m_stub; auto_ptr m_socket; }; CPPUNIT_TEST_SUITE_REGISTRATION(RpcChannelTest); void RpcChannelTest::setUp() { m_socket.reset(new LoopbackDescriptor()); m_socket->Init(); m_service.reset(new TestServiceImpl(&m_ss)); m_channel.reset(new RpcChannel(m_service.get(), m_socket.get())); m_ss.AddReadDescriptor(m_socket.get()); m_stub.reset(new TestService_Stub(m_channel.get())); } void RpcChannelTest::tearDown() { m_ss.RemoveReadDescriptor(m_socket.get()); } void RpcChannelTest::EchoComplete() { m_ss.Terminate(); OLA_ASSERT_FALSE(m_controller.Failed()); OLA_ASSERT_EQ(m_reply.data(), m_request.data()); } void RpcChannelTest::FailedEchoComplete() { m_ss.Terminate(); OLA_ASSERT_TRUE(m_controller.Failed()); } /* * Check that we can call the echo method in the TestServiceImpl. */ void RpcChannelTest::testEcho() { m_request.set_data("foo"); m_request.set_session_ptr(0); m_stub->Echo(&m_controller, &m_request, &m_reply, NewSingleCallback(this, &RpcChannelTest::EchoComplete)); m_ss.Run(); } /* * Check that method that fail return correctly */ void RpcChannelTest::testFailedEcho() { m_request.set_data("foo"); m_stub->FailedEcho( &m_controller, &m_request, &m_reply, NewSingleCallback(this, &RpcChannelTest::FailedEchoComplete)); m_ss.Run(); } /* * Check stream requests work */ void RpcChannelTest::testStreamRequest() { m_request.set_data("foo"); m_stub->Stream(NULL, &m_request, NULL, NULL); m_ss.Run(); } ola-0.10.5.nojsmin/common/rpc/RpcControllerTest.cpp0000644000175000017500000000340013023355232021663 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * RpcControllerTest.cpp * Test fixture for the RpcController class * Copyright (C) 2005 Simon Newton */ #include #include #include #include "common/rpc/RpcController.h" #include "ola/testing/TestUtils.h" #include "ola/Callback.h" using std::string; using ola::rpc::RpcController; using ola::rpc::RpcController; class RpcControllerTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(RpcControllerTest); CPPUNIT_TEST(testFailed); CPPUNIT_TEST_SUITE_END(); public: void testFailed(); private: void Callback(); bool m_callback_run; }; CPPUNIT_TEST_SUITE_REGISTRATION(RpcControllerTest); void RpcControllerTest::testFailed() { RpcController controller; string failure = "Failed"; controller.SetFailed(failure); OLA_ASSERT_TRUE(controller.Failed()); OLA_ASSERT_EQ(controller.ErrorText(), failure); controller.Reset(); OLA_ASSERT_FALSE(controller.Failed()); } void RpcControllerTest::Callback() { m_callback_run = true; } ola-0.10.5.nojsmin/common/rpc/RpcChannel.h0000644000175000017500000001445013023355232017724 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * RpcChannel.h * The RPC Channel * Copyright (C) 2005 Simon Newton */ #ifndef COMMON_RPC_RPCCHANNEL_H_ #define COMMON_RPC_RPCCHANNEL_H_ #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #include #include #include #include #include #include "ola/ExportMap.h" #include HASH_MAP_H namespace ola { namespace rpc { class RpcMessage; class RpcService; /** * @brief The RPC channel used to communicate between the client and the * server. * This implementation runs over a ConnectedDescriptor which means it can be * used over TCP or pipes. */ class RpcChannel { public : /** * @brief The callback to run when the channel is closed. * * When run, the callback is passed the RpcSession associated with this * channel. */ typedef SingleUseCallback1 CloseCallback; /** * @brief Create a new RpcChannel. * @param service the Service to use to handle incoming requests. Ownership * is not transferred. * @param descriptor the descriptor to use for reading/writing data. The * caller is responsible for registering the descriptor with the * SelectServer. Ownership of the descriptor is not transferred. * @param export_map the ExportMap to use for stats */ RpcChannel(RpcService *service, ola::io::ConnectedDescriptor *descriptor, ExportMap *export_map = NULL); /** * @brief Destructor */ ~RpcChannel(); /** * @brief Set the Service to use to handle incoming requests. * @param service the new Service to use, ownership is not transferred. */ void SetService(RpcService *service) { m_service = service; } /** * @brief Check if there are any pending RPCs on the channel. * Pending RPCs are those where a request has been sent, but no reply has * been received. * @returns true if there is one or more pending RPCs. */ bool PendingRPCs() const { return !m_requests.empty(); } /** * @brief Called when new data arrives on the descriptor. */ void DescriptorReady(); /** * @brief Set the Callback to be run when the channel fails. * The callback will be invoked if the descriptor is closed, or if writes * to the descriptor fail. * @param callback the callback to run when the channel fails. * * @note * The callback will be run from the call stack of the RpcChannel * object. This means you can't delete the RpcChannel object from * within the called, you'll need to queue it up and delete it later. */ void SetChannelCloseHandler(CloseCallback *callback); /** * @brief Invoke an RPC method on this channel. */ void CallMethod(const google::protobuf::MethodDescriptor *method, class RpcController *controller, const google::protobuf::Message *request, google::protobuf::Message *response, SingleUseCallback0 *done); /** * @brief Invoked by the RPC completion handler when the server side * response is ready. * @param request the OutstandingRequest that is now complete. */ void RequestComplete(class OutstandingRequest *request); /** * @brief Return the RpcSession associated with this channel. * @returns the RpcSession associated with this channel. */ RpcSession *Session(); /** * @brief the RPC protocol version. */ static const unsigned int PROTOCOL_VERSION = 1; private: typedef HASH_NAMESPACE::HASH_MAP_CLASS ResponseMap; std::auto_ptr m_session; RpcService *m_service; // service to dispatch requests to std::auto_ptr m_on_close; // the descriptor to read/write to. class ola::io::ConnectedDescriptor *m_descriptor; SequenceNumber m_sequence; uint8_t *m_buffer; // buffer for incoming msgs unsigned int m_buffer_size; // size of the buffer unsigned int m_expected_size; // the total size of the current msg unsigned int m_current_size; // the amount of data read for the current msg HASH_NAMESPACE::HASH_MAP_CLASS m_requests; ResponseMap m_responses; ExportMap *m_export_map; UIntMap *m_recv_type_map; bool SendMsg(RpcMessage *msg); int AllocateMsgBuffer(unsigned int size); int ReadHeader(unsigned int *version, unsigned int *size) const; bool HandleNewMsg(uint8_t *buffer, unsigned int size); void HandleRequest(RpcMessage *msg); void HandleStreamRequest(RpcMessage *msg); // server end void SendRequestFailed(class OutstandingRequest *request); void SendNotImplemented(int msg_id); void DeleteOutstandingRequest(class OutstandingRequest *request); // client end void HandleResponse(RpcMessage *msg); void HandleFailedResponse(RpcMessage *msg); void HandleCanceledResponse(RpcMessage *msg); void HandleNotImplemented(RpcMessage *msg); void HandleChannelClose(); static const char K_RPC_RECEIVED_TYPE_VAR[]; static const char K_RPC_RECEIVED_VAR[]; static const char K_RPC_SENT_ERROR_VAR[]; static const char K_RPC_SENT_VAR[]; static const char *K_RPC_VARIABLES[]; static const char STREAMING_NO_RESPONSE[]; static const unsigned int INITIAL_BUFFER_SIZE = 1 << 11; // 2k static const unsigned int MAX_BUFFER_SIZE = 1 << 20; // 1M }; } // namespace rpc } // namespace ola #endif // COMMON_RPC_RPCCHANNEL_H_ ola-0.10.5.nojsmin/common/rpc/RpcController.h0000644000175000017500000000524213023355232020476 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * RpcController.h * The RpcController. * Copyright (C) 2005 Simon Newton */ #ifndef COMMON_RPC_RPCCONTROLLER_H_ #define COMMON_RPC_RPCCONTROLLER_H_ #include #include namespace ola { namespace rpc { class RpcSession; /** * @brief A RpcController object is passed every time an RPC is invoked and is * used to indicate the success or failure of the RPC. * * On the client side, the controller can is used once the callback completes to * check the outcome of the RPC with Failed(). If the RPC failed, a description * of the error is available by calling ErrorText(). * * On the server side, the server can fail the RPC by calling SetFailed(...). */ class RpcController { public: /** * @brief Create a new RpcController * @param session the RpcSession to use. Ownership is not transferred. */ explicit RpcController(RpcSession *session = NULL); ~RpcController() {} /** * @brief Reset the state of this controller. Does not affect the session. */ void Reset(); /** * @brief Check if the RPC call this controller was associated with failed. * @returns true if the RPC failed, false if the RPC succeeded. */ bool Failed() const { return m_failed; } /** * @brief Return the error string if the RPC failed. * @returns the error text, or the empty string if the RPC succeeded. */ std::string ErrorText() const { return m_error_text; } /** * @brief Mark this RPC as failed. * @param reason the string to return in ErrorText(). */ void SetFailed(const std::string &reason); /** * @brief Get the session infomation for this RPC. * * Unless specfically provided, the session be NULL on the client side. * @returns the RpcSession object, ownership is not transferred. */ RpcSession *Session(); private: RpcSession *m_session; bool m_failed; std::string m_error_text; }; } // namespace rpc } // namespace ola #endif // COMMON_RPC_RPCCONTROLLER_H_ ola-0.10.5.nojsmin/common/rpc/TestService.h0000644000175000017500000000540513023355232020147 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * TestService.h * The client and server implementation for the simple echo service. * Copyright (C) 2014 Simon Newton */ #ifndef COMMON_RPC_TESTSERVICE_H_ #define COMMON_RPC_TESTSERVICE_H_ #include #include "common/rpc/RpcController.h" #include "common/rpc/TestServiceService.pb.h" #include "ola/network/TCPSocket.h" #include "ola/io/SelectServer.h" #include "common/rpc/RpcChannel.h" class TestServiceImpl: public ola::rpc::TestService { public: explicit TestServiceImpl(ola::io::SelectServer *ss) : m_ss(ss) {} ~TestServiceImpl() {} void Echo(ola::rpc::RpcController* controller, const ola::rpc::EchoRequest* request, ola::rpc::EchoReply* response, CompletionCallback* done); void FailedEcho(ola::rpc::RpcController* controller, const ola::rpc::EchoRequest* request, ola::rpc::EchoReply* response, CompletionCallback* done); void Stream(ola::rpc::RpcController* controller, const ola::rpc::EchoRequest* request, ola::rpc::STREAMING_NO_RESPONSE* response, CompletionCallback* done); private: ola::io::SelectServer *m_ss; }; class TestClient { public: TestClient(ola::io::SelectServer *ss, const ola::network::GenericSocketAddress &server_addr); ~TestClient(); bool Init(); // These block until the transaction completes. void CallEcho(void *session_ptr); void CallFailedEcho(); void StreamMessage(); // Completion handlers. void EchoComplete(ola::rpc::RpcController *controller, ola::rpc::EchoReply *reply); void FailedEchoComplete(ola::rpc::RpcController *controller, ola::rpc::EchoReply *reply); static const char kTestData[]; private: ola::io::SelectServer *m_ss; const ola::network::GenericSocketAddress m_server_addr; std::auto_ptr m_socket; std::auto_ptr m_stub; std::auto_ptr m_channel; }; #endif // COMMON_RPC_TESTSERVICE_H_ ola-0.10.5.nojsmin/common/rpc/RpcPeer.h0000644000175000017500000000375013023355232017250 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * RpcPeer.h * Represents the peer of an RpcChannel. * Copyright (C) 2013 Simon Newton */ #ifndef COMMON_RPC_RPCPEER_H_ #define COMMON_RPC_RPCPEER_H_ #include #include #include namespace ola { namespace rpc { class RpcPeer { public: explicit RpcPeer(const ola::network::GenericSocketAddress &socket_addr) : m_socket_addr(socket_addr) { } const ola::network::GenericSocketAddress& SocketAddress() const { return m_socket_addr; } /** * @brief Assignment operator */ RpcPeer& operator=(const RpcPeer& other) { if (this != &other) { m_socket_addr = other.m_socket_addr; } return *this; } /** * @brief Convert a peer to a human readable string. * @returns a string representation of the peer. */ std::string ToString() const { return m_socket_addr.ToString(); } /** * @brief A helper function to write an RpcPeer to an ostream. * @param out the ostream * @param peer the RpcPeer to write. */ friend ostream& operator<<(ostream &out, const RpcPeer &peer) { return out << peer.ToString(); } private: ola::network::GenericSocketAddress m_socket_addr; }; } // namespace rpc } // namespace ola #endif // COMMON_RPC_RPCPEER_H_ ola-0.10.5.nojsmin/common/rpc/RpcServerTest.cpp0000644000175000017500000000512613023355232021015 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * RpcServerTest.cpp * Test fixture for the RpcServer class * Copyright (C) 2014 Simon Newton */ #include #include "common/rpc/RpcServer.h" #include "common/rpc/RpcSession.h" #include "common/rpc/TestService.h" #include "common/rpc/TestServiceService.pb.h" #include "ola/io/SelectServer.h" #include "ola/rpc/RpcSessionHandler.h" #include "ola/testing/TestUtils.h" using ola::io::SelectServer; using ola::rpc::RpcSession; using ola::rpc::RpcServer; using std::auto_ptr; class RpcServerTest: public CppUnit::TestFixture, public ola::rpc::RpcSessionHandlerInterface { CPPUNIT_TEST_SUITE(RpcServerTest); CPPUNIT_TEST(testEcho); CPPUNIT_TEST(testFailedEcho); CPPUNIT_TEST(testStreamRequest); CPPUNIT_TEST_SUITE_END(); public: void testEcho(); void testFailedEcho(); void testStreamRequest(); void setUp(); void NewClient(RpcSession *session); void ClientRemoved(RpcSession *session); private: SelectServer m_ss; auto_ptr m_service; auto_ptr m_server; auto_ptr m_client; uint8_t ptr_data; }; CPPUNIT_TEST_SUITE_REGISTRATION(RpcServerTest); void RpcServerTest::setUp() { m_service.reset(new TestServiceImpl(&m_ss)); m_server.reset(new RpcServer( &m_ss, m_service.get(), this, RpcServer::Options())); OLA_ASSERT_TRUE(m_server->Init()); m_client.reset(new TestClient(&m_ss, m_server->ListenAddress())); OLA_ASSERT_TRUE(m_client->Init()); } void RpcServerTest::NewClient(RpcSession *session) { session->SetData(&ptr_data); } void RpcServerTest::ClientRemoved(RpcSession *session) { OLA_ASSERT_EQ(reinterpret_cast(&ptr_data), session->GetData()); } void RpcServerTest::testEcho() { m_client->CallEcho(&ptr_data); } void RpcServerTest::testFailedEcho() { m_client->CallFailedEcho(); } void RpcServerTest::testStreamRequest() { m_client->StreamMessage(); } ola-0.10.5.nojsmin/common/rpc/RpcHeaderTest.cpp0000644000175000017500000000351713023355232020741 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * RpcHeaderTest.cpp * Test fixture for the RpcHeader class * Copyright (C) 2005 Simon Newton */ #include #include #include "common/rpc/RpcChannel.h" #include "common/rpc/RpcHeader.h" #include "ola/testing/TestUtils.h" using ola::rpc::RpcChannel; using ola::rpc::RpcHeader; class RpcHeaderTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(RpcHeaderTest); CPPUNIT_TEST(testHeaderEncoding); CPPUNIT_TEST_SUITE_END(); public: void testHeaderEncoding(); }; CPPUNIT_TEST_SUITE_REGISTRATION(RpcHeaderTest); void RpcHeaderTest::testHeaderEncoding() { /* * Test we can encode and decode headers correctly. */ uint32_t header; unsigned int size, version, o_size, o_version; size = 0; version = 0; RpcHeader::EncodeHeader(&header, version, size); RpcHeader::DecodeHeader(header, &o_version, &o_size); OLA_ASSERT_EQ(version, o_version); version = RpcChannel::PROTOCOL_VERSION; size = 24; RpcHeader::EncodeHeader(&header, version, size); RpcHeader::DecodeHeader(header, &o_version, &o_size); OLA_ASSERT_EQ(version, o_version); } ola-0.10.5.nojsmin/common/rpc/TestService.cpp0000644000175000017500000001074513023355232020505 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * TestService.cpp * The client and server implementation for the simple echo service. * Copyright (C) 2014 Simon Newton */ #include "common/rpc/TestService.h" #include #include #include "common/rpc/RpcController.h" #include "common/rpc/RpcSession.h" #include "common/rpc/TestServiceService.pb.h" #include "ola/io/SelectServer.h" #include "ola/testing/TestUtils.h" #include "common/rpc/RpcChannel.h" using ola::NewSingleCallback; using ola::io::SelectServer; using ola::rpc::EchoReply; using ola::rpc::EchoRequest; using ola::rpc::RpcChannel; using ola::rpc::RpcController; using ola::rpc::STREAMING_NO_RESPONSE; using ola::rpc::TestService_Stub; using ola::network::TCPSocket; using ola::network::GenericSocketAddress; using std::string; const char TestClient::kTestData[] = "foo"; void TestServiceImpl::Echo(OLA_UNUSED RpcController* controller, OLA_UNUSED const EchoRequest* request, EchoReply* response, CompletionCallback* done) { OLA_ASSERT_TRUE(request->has_session_ptr()); uintptr_t expected_ptr = request->session_ptr(); OLA_ASSERT_EQ(expected_ptr, reinterpret_cast(controller->Session()->GetData())); response->set_data(request->data()); done->Run(); } void TestServiceImpl::FailedEcho(RpcController* controller, OLA_UNUSED const EchoRequest* request, OLA_UNUSED EchoReply* response, CompletionCallback* done) { controller->SetFailed("Error"); done->Run(); } void TestServiceImpl::Stream(RpcController* controller, const ::ola::rpc::EchoRequest* request, STREAMING_NO_RESPONSE* response, CompletionCallback* done) { OLA_ASSERT_NOT_NULL(controller); OLA_ASSERT_FALSE(response); OLA_ASSERT_FALSE(done); OLA_ASSERT_TRUE(request); OLA_ASSERT_EQ(string(TestClient::kTestData), request->data()); m_ss->Terminate(); } TestClient::TestClient(SelectServer *ss, const GenericSocketAddress &server_addr) : m_ss(ss), m_server_addr(server_addr) { } TestClient::~TestClient() { m_ss->RemoveReadDescriptor(m_socket.get()); } bool TestClient::Init() { m_socket.reset(TCPSocket::Connect(m_server_addr)); OLA_ASSERT_NOT_NULL(m_socket.get()); m_channel.reset(new RpcChannel(NULL, m_socket.get())); m_stub.reset(new TestService_Stub(m_channel.get())); m_ss->AddReadDescriptor(m_socket.get()); return true; } void TestClient::CallEcho(void *session_ptr) { EchoRequest request; EchoReply reply; RpcController controller; request.set_data(kTestData); request.set_session_ptr(reinterpret_cast(session_ptr)); m_stub->Echo( &controller, &request, &reply, NewSingleCallback(this, &TestClient::EchoComplete, &controller, &reply)); m_ss->Run(); } void TestClient::CallFailedEcho() { EchoRequest request; EchoReply reply; RpcController controller; request.set_data(kTestData); m_stub->FailedEcho( &controller, &request, &reply, NewSingleCallback(this, &TestClient::FailedEchoComplete, &controller, &reply)); m_ss->Run(); } void TestClient::StreamMessage() { EchoRequest request; request.set_data(kTestData); m_stub->Stream(NULL, &request, NULL, NULL); m_ss->Run(); } void TestClient::EchoComplete(RpcController *controller, EchoReply *reply) { OLA_ASSERT_FALSE(controller->Failed()); OLA_ASSERT_EQ(string(kTestData), reply->data()); m_ss->Terminate(); } void TestClient::FailedEchoComplete(RpcController *controller, OLA_UNUSED EchoReply *reply) { OLA_ASSERT_TRUE(controller->Failed()); m_ss->Terminate(); } ola-0.10.5.nojsmin/common/timecode/0000755000175000017500000000000013155164170016544 5ustar wouterwouterola-0.10.5.nojsmin/common/timecode/Makefile.mk0000644000175000017500000000067413023355232020614 0ustar wouterwouter# LIBRARIES ################################################## common_libolacommon_la_SOURCES += \ common/timecode/TimeCode.cpp # TESTS ################################################## test_programs += common/timecode/TimeCodeTester common_timecode_TimeCodeTester_SOURCES = common/timecode/TimeCodeTest.cpp common_timecode_TimeCodeTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_timecode_TimeCodeTester_LDADD = $(COMMON_TESTING_LIBS) ola-0.10.5.nojsmin/common/timecode/TimeCodeTest.cpp0000644000175000017500000000534613023355232021604 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * TimeCodeTest.cpp * Test fixture for the TimeCode classes * Copyright (C) 2011 Simon Newton */ #include #include #include "ola/timecode/TimeCode.h" #include "ola/timecode/TimeCodeEnums.h" #include "ola/testing/TestUtils.h" using ola::timecode::TimeCode; using std::ostringstream; using std::string; using ola::timecode::TIMECODE_FILM; using ola::timecode::TIMECODE_EBU; using ola::timecode::TIMECODE_DF; using ola::timecode::TIMECODE_SMPTE; class TimeCodeTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(TimeCodeTest); CPPUNIT_TEST(testTimeCode); CPPUNIT_TEST(testIsValid); CPPUNIT_TEST_SUITE_END(); public: void testTimeCode(); void testIsValid(); }; CPPUNIT_TEST_SUITE_REGISTRATION(TimeCodeTest); /* * Test the TimeCodes work. */ void TimeCodeTest::testTimeCode() { ostringstream str1; TimeCode t1(TIMECODE_FILM, 0, 0, 0, 0); OLA_ASSERT_EQ(TIMECODE_FILM, t1.Type()); OLA_ASSERT_EQ(static_cast(0), t1.Hours()); OLA_ASSERT_EQ(static_cast(0), t1.Minutes()); OLA_ASSERT_EQ(static_cast(0), t1.Seconds()); OLA_ASSERT_EQ(static_cast(0), t1.Frames()); OLA_ASSERT_EQ(string("00:00:00:00"), t1.AsString()); str1 << t1; OLA_ASSERT_EQ(string("00:00:00:00"), str1.str()); OLA_ASSERT_TRUE(t1.IsValid()); ostringstream str3; TimeCode t2(t1); OLA_ASSERT_EQ(t1, t2); TimeCode t3(TIMECODE_SMPTE, 10, 9, 12, 14); OLA_ASSERT_EQ(string("10:09:12:14"), t3.AsString()); str3 << t3; OLA_ASSERT_EQ(string("10:09:12:14"), str3.str()); OLA_ASSERT_TRUE(t3.IsValid()); OLA_ASSERT_NE(t1, t3); t3 = t1; OLA_ASSERT_EQ(t1, t3); } /** * test invalid codes */ void TimeCodeTest::testIsValid() { TimeCode t1(TIMECODE_FILM, 0, 0, 0, 24); OLA_ASSERT_FALSE(t1.IsValid()); TimeCode t2(TIMECODE_EBU, 0, 0, 0, 25); OLA_ASSERT_FALSE(t2.IsValid()); TimeCode t3(TIMECODE_DF, 0, 0, 0, 30); OLA_ASSERT_FALSE(t3.IsValid()); TimeCode t4(TIMECODE_SMPTE, 0, 0, 0, 30); OLA_ASSERT_FALSE(t4.IsValid()); } ola-0.10.5.nojsmin/common/timecode/TimeCode.cpp0000644000175000017500000000537413023355232020745 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * TimeCode.cpp * The TimeCode class * Copyright (C) 2011 Simon Newton */ #include #include #include #include "ola/Logging.h" #include "ola/timecode/TimeCode.h" #include "ola/timecode/TimeCodeEnums.h" namespace ola { namespace timecode { using std::setw; using std::setfill; using std::string; TimeCode::TimeCode(const TimeCode &other) : m_type(other.m_type), m_hours(other.m_hours), m_minutes(other.m_minutes), m_seconds(other.m_seconds), m_frames(other.m_frames) { } TimeCode& TimeCode::operator=(const TimeCode &other) { m_type = other.m_type; m_hours = other.m_hours; m_minutes = other.m_minutes; m_seconds = other.m_seconds; m_frames = other.m_frames; return *this; } /** * Returns true if this timecode value is consistent, given the time */ bool TimeCode::IsValid() const { if (m_hours > MAX_HOURS || m_minutes > MAX_MINUTES || m_seconds > MAX_SECONDS) return false; switch (m_type) { case TIMECODE_FILM: return m_frames < 24; case TIMECODE_EBU: return m_frames < 25; case TIMECODE_DF: return m_frames < 30; case TIMECODE_SMPTE: return m_frames < 30; } return false; } string TimeCode::AsString() const { std::ostringstream str; str << setw(2) << setfill('0') << static_cast(m_hours) << ":" << setw(2) << setfill('0') << static_cast(m_minutes) << ":" << setw(2) << setfill('0') << static_cast(m_seconds) << ":" << setw(2) << setfill('0') << static_cast(m_frames); return str.str(); } std::ostream& operator<<(std::ostream &out, const TimeCode &t) { return out << t.AsString(); } bool TimeCode::operator==(const TimeCode &other) const { return (m_type == other.m_type && m_hours == other.m_hours && m_minutes == other.m_minutes && m_seconds == other.m_seconds && m_frames == other.m_frames); } bool TimeCode::operator!=(const TimeCode &other) const { return !(*this == other); } } // namespace timecode } // namespace ola ola-0.10.5.nojsmin/common/file/0000755000175000017500000000000013155164170015672 5ustar wouterwouterola-0.10.5.nojsmin/common/file/Makefile.mk0000644000175000017500000000060513023355232017734 0ustar wouterwouter# LIBRARIES ################################################## common_libolacommon_la_SOURCES += common/file/Util.cpp # TESTS ################################################## test_programs += common/file/UtilTester common_file_UtilTester_SOURCES = common/file/UtilTest.cpp common_file_UtilTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_file_UtilTester_LDADD = $(COMMON_TESTING_LIBS) ola-0.10.5.nojsmin/common/file/Util.cpp0000644000175000017500000001241413023355232017310 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Util.cpp * File related helper functions. * Copyright (C) 2013 Simon Newton */ #include #include #include #include #include #ifdef _WIN32 #define VC_EXTRALEAN #include #endif // _WIN32 #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #include #include #include namespace ola { namespace file { using std::string; using std::vector; #ifdef _WIN32 const char PATH_SEPARATOR = '\\'; #else const char PATH_SEPARATOR = '/'; #endif // _WIN32 string ConvertPathSeparators(const string &path) { string result = path; #ifdef _WIN32 std::replace(result.begin(), result.end(), '/', PATH_SEPARATOR); #else std::replace(result.begin(), result.end(), '\\', PATH_SEPARATOR); #endif // _WIN32 return result; } string JoinPaths(const string &first, const string &second) { if (second.empty()) { return first; } if (first.empty()) { return second; } if (second[0] == PATH_SEPARATOR) { return second; } string output(first); if (output[output.size() - 1] != PATH_SEPARATOR) { output.push_back(PATH_SEPARATOR); } output.append(second); return output; } bool FindMatchingFiles(const string &directory, const string &prefix, vector *files) { vector prefixes; prefixes.push_back(prefix); return FindMatchingFiles(directory, prefixes, files); } bool FindMatchingFiles(const string &directory, const vector &prefixes, vector *files) { if (directory.empty() || prefixes.empty()) { return true; } #ifdef _WIN32 WIN32_FIND_DATA find_file_data; HANDLE h_find; string mutable_directory = ConvertPathSeparators(directory); // Strip trailing path separators, otherwise FindFirstFile fails while (*mutable_directory.rbegin() == PATH_SEPARATOR) { mutable_directory.erase(mutable_directory.size() - 1); } string search_pattern = mutable_directory + PATH_SEPARATOR + "*"; h_find = FindFirstFileA(search_pattern.data(), &find_file_data); if (h_find == INVALID_HANDLE_VALUE) { OLA_WARN << "Find first file failed: " << GetLastError() << " for " << search_pattern; return false; } do { vector::const_iterator iter; for (iter = prefixes.begin(); iter != prefixes.end(); ++iter) { if (!strncmp(find_file_data.cFileName, iter->data(), iter->size())) { std::ostringstream str; str << mutable_directory << PATH_SEPARATOR << find_file_data.cFileName; files->push_back(str.str()); } } } while (FindNextFile(h_find, &find_file_data)); FindClose(h_find); #else DIR *dp; struct dirent dir_ent; struct dirent *dir_ent_p; if ((dp = opendir(directory.data())) == NULL) { OLA_WARN << "Could not open " << directory << ":" << strerror(errno); return false; } if (readdir_r(dp, &dir_ent, &dir_ent_p)) { OLA_WARN << "readdir_r(" << directory << "): " << strerror(errno); closedir(dp); return false; } while (dir_ent_p != NULL) { vector::const_iterator iter; for (iter = prefixes.begin(); iter != prefixes.end(); ++iter) { if (!strncmp(dir_ent_p->d_name, iter->data(), iter->size())) { std::ostringstream str; str << directory << PATH_SEPARATOR << dir_ent_p->d_name; files->push_back(str.str()); } } if (readdir_r(dp, &dir_ent, &dir_ent_p)) { OLA_WARN << "readdir_r(" << directory << "): " << strerror(errno); closedir(dp); return false; } } if (closedir(dp)) { OLA_WARN << "closedir(" << directory << "): " << strerror(errno); return false; } #endif // _WIN32 return true; } bool ListDirectory(const string& directory, vector *files) { return FindMatchingFiles(directory, "", files); } string FilenameFromPathOrDefault(const string &path, const string &default_value) { string mutable_path = ConvertPathSeparators(path); string::size_type last_path_sep = string::npos; last_path_sep = mutable_path.find_last_of(PATH_SEPARATOR); if (last_path_sep == string::npos) return default_value; // Don't return the path sep itself return mutable_path.substr(last_path_sep + 1); } string FilenameFromPathOrPath(const string &path) { return FilenameFromPathOrDefault(path, path); } string FilenameFromPath(const string &path) { return FilenameFromPathOrDefault(path, ""); } } // namespace file } // namespace ola ola-0.10.5.nojsmin/common/file/UtilTest.cpp0000644000175000017500000000703313023355232020151 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * UtilTest.cpp * Unittest for file util functions. * Copyright (C) 2013 Peter Newman */ #include #include #include "ola/file/Util.h" #include "ola/testing/TestUtils.h" using ola::file::FilenameFromPath; using ola::file::FilenameFromPathOrDefault; using ola::file::FilenameFromPathOrPath; using ola::file::JoinPaths; using std::string; class UtilTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(UtilTest); CPPUNIT_TEST(testJoinPaths); CPPUNIT_TEST(testFilenameFromPath); CPPUNIT_TEST_SUITE_END(); public: void testFilenameFromPath(); void testJoinPaths(); }; CPPUNIT_TEST_SUITE_REGISTRATION(UtilTest); void UtilTest::testJoinPaths() { // Same behaviour as os.path.join() OLA_ASSERT_EQ(string("/tmp/1"), JoinPaths("/tmp", "1")); OLA_ASSERT_EQ(string("/tmp/1"), JoinPaths("/tmp/", "1")); OLA_ASSERT_EQ(string("1"), JoinPaths("", "1")); OLA_ASSERT_EQ(string("/tmp/"), JoinPaths("/tmp/", "")); OLA_ASSERT_EQ(string("/tmp"), JoinPaths("/tmp", "")); OLA_ASSERT_EQ(string("/foo"), JoinPaths("/tmp", "/foo")); OLA_ASSERT_EQ(string(""), JoinPaths("", "")); } /* * Test the FilenameFromPath function */ void UtilTest::testFilenameFromPath() { // TODO(Peter): Make these tests work on Windows too OLA_ASSERT_EQ(string(""), FilenameFromPath("")); OLA_ASSERT_EQ(string(""), FilenameFromPath("foo")); OLA_ASSERT_EQ(string(""), FilenameFromPath("/")); OLA_ASSERT_EQ(string("foo"), FilenameFromPath("/foo")); OLA_ASSERT_EQ(string(""), FilenameFromPath("/foo/")); OLA_ASSERT_EQ(string("bar"), FilenameFromPath("/foo/bar")); OLA_ASSERT_EQ(string(""), FilenameFromPath("/foo/bar/")); OLA_ASSERT_EQ(string("baz"), FilenameFromPath("/foo/bar/baz")); OLA_ASSERT_EQ(string("bak"), FilenameFromPathOrDefault("", "bak")); OLA_ASSERT_EQ(string("bak"), FilenameFromPathOrDefault("foo", "bak")); OLA_ASSERT_EQ(string(""), FilenameFromPathOrDefault("/", "bak")); OLA_ASSERT_EQ(string("foo"), FilenameFromPathOrDefault("/foo", "bak")); OLA_ASSERT_EQ(string(""), FilenameFromPathOrDefault("/foo/", "bak")); OLA_ASSERT_EQ(string("bar"), FilenameFromPathOrDefault("/foo/bar", "bak")); OLA_ASSERT_EQ(string(""), FilenameFromPathOrDefault("/foo/bar/", "bak")); OLA_ASSERT_EQ(string("baz"), FilenameFromPathOrDefault("/foo/bar/baz", "bak")); OLA_ASSERT_EQ(string(""), FilenameFromPathOrPath("")); OLA_ASSERT_EQ(string("foo"), FilenameFromPathOrPath("foo")); OLA_ASSERT_EQ(string(""), FilenameFromPathOrPath("/")); OLA_ASSERT_EQ(string("foo"), FilenameFromPathOrPath("/foo")); OLA_ASSERT_EQ(string(""), FilenameFromPathOrPath("/foo/")); OLA_ASSERT_EQ(string("bar"), FilenameFromPathOrPath("/foo/bar")); OLA_ASSERT_EQ(string(""), FilenameFromPathOrPath("/foo/bar/")); OLA_ASSERT_EQ(string("baz"), FilenameFromPathOrPath("/foo/bar/baz")); } ola-0.10.5.nojsmin/common/export_map/0000755000175000017500000000000013155164170017131 5ustar wouterwouterola-0.10.5.nojsmin/common/export_map/Makefile.mk0000644000175000017500000000071513023355232021175 0ustar wouterwouter# LIBRARIES ################################################## common_libolacommon_la_SOURCES += \ common/export_map/ExportMap.cpp # TESTS ################################################## test_programs += common/export_map/ExportMapTester common_export_map_ExportMapTester_SOURCES = common/export_map/ExportMapTest.cpp common_export_map_ExportMapTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_export_map_ExportMapTester_LDADD = $(COMMON_TESTING_LIBS) ola-0.10.5.nojsmin/common/export_map/ExportMap.cpp0000644000175000017500000000775513023355232021565 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * ExportMap.cpp * Exported Variables * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include #include "ola/ExportMap.h" #include "ola/StringUtils.h" #include "ola/stl/STLUtils.h" namespace ola { using std::map; using std::ostringstream; using std::string; using std::vector; ExportMap::~ExportMap() { STLDeleteValues(&m_bool_variables); STLDeleteValues(&m_counter_variables); STLDeleteValues(&m_int_map_variables); STLDeleteValues(&m_int_variables); STLDeleteValues(&m_str_map_variables); STLDeleteValues(&m_string_variables); STLDeleteValues(&m_uint_map_variables); } BoolVariable *ExportMap::GetBoolVar(const string &name) { return GetVar(&m_bool_variables, name); } IntegerVariable *ExportMap::GetIntegerVar(const string &name) { return GetVar(&m_int_variables, name); } CounterVariable *ExportMap::GetCounterVar(const string &name) { return GetVar(&m_counter_variables, name); } StringVariable *ExportMap::GetStringVar(const string &name) { return GetVar(&m_string_variables, name); } /* * Lookup or create a string map variable * @param name the name of the variable * @param label the label to use for the map (optional) * @return a MapVariable */ StringMap *ExportMap::GetStringMapVar(const string &name, const string &label) { return GetMapVar(&m_str_map_variables, name, label); } /* * Lookup or create an int map variable * @param name the name of the variable * @param label the label to use for the map (optional) * @return a MapVariable */ IntMap *ExportMap::GetIntMapVar(const string &name, const string &label) { return GetMapVar(&m_int_map_variables, name, label); } /* * Lookup or create an unsigned int map variable * @param name the name of the variable * @param label the label to use for the map (optional) * @return a MapVariable */ UIntMap *ExportMap::GetUIntMapVar(const string &name, const string &label) { return GetMapVar(&m_uint_map_variables, name, label); } /* * Return a list of all variables. * @return a vector of all variables. */ vector ExportMap::AllVariables() const { vector variables; STLValues(m_bool_variables, &variables); STLValues(m_counter_variables, &variables); STLValues(m_int_map_variables, &variables); STLValues(m_int_variables, &variables); STLValues(m_str_map_variables, &variables); STLValues(m_string_variables, &variables); STLValues(m_uint_map_variables, &variables); sort(variables.begin(), variables.end(), VariableLessThan()); return variables; } template Type *ExportMap::GetVar(map *var_map, const string &name) { typename map::iterator iter; iter = var_map->find(name); if (iter == var_map->end()) { Type *var = new Type(name); (*var_map)[name] = var; return var; } return iter->second; } template Type *ExportMap::GetMapVar(map *var_map, const string &name, const string &label) { typename map::iterator iter; iter = var_map->find(name); if (iter == var_map->end()) { Type *var = new Type(name, label); (*var_map)[name] = var; return var; } return iter->second; } } // namespace ola ola-0.10.5.nojsmin/common/export_map/ExportMapTest.cpp0000644000175000017500000001516313023355232022415 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * ExportMapTest.cpp * Test fixture for the ExportMap and Variable classes * Copyright (C) 2005 Simon Newton */ #include #include #include #include "ola/ExportMap.h" #include "ola/testing/TestUtils.h" using ola::BaseVariable; using ola::BoolVariable; using ola::CounterVariable; using ola::ExportMap; using ola::IntMap; using ola::IntegerVariable; using ola::StringMap; using ola::StringVariable; using std::string; using std::vector; class ExportMapTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(ExportMapTest); CPPUNIT_TEST(testIntegerVariable); CPPUNIT_TEST(testCounterVariable); CPPUNIT_TEST(testStringVariable); CPPUNIT_TEST(testBoolVariable); CPPUNIT_TEST(testStringMapVariable); CPPUNIT_TEST(testIntMapVariable); CPPUNIT_TEST(testExportMap); CPPUNIT_TEST_SUITE_END(); public: void testIntegerVariable(); void testCounterVariable(); void testStringVariable(); void testBoolVariable(); void testStringMapVariable(); void testIntMapVariable(); void testExportMap(); }; CPPUNIT_TEST_SUITE_REGISTRATION(ExportMapTest); /* * Check that the IntegerVariable works correctly. */ void ExportMapTest::testIntegerVariable() { string name = "foo"; IntegerVariable var(name); OLA_ASSERT_EQ(var.Name(), name); OLA_ASSERT_EQ(var.Value(), string("0")); OLA_ASSERT_EQ(var.Get(), 0); var++; OLA_ASSERT_EQ(var.Get(), 1); OLA_ASSERT_EQ(var.Value(), string("1")); var--; OLA_ASSERT_EQ(var.Get(), 0); OLA_ASSERT_EQ(var.Value(), string("0")); var.Set(100); OLA_ASSERT_EQ(var.Get(), 100); OLA_ASSERT_EQ(var.Value(), string("100")); } /* * Check that the CounterVariable works correctly. */ void ExportMapTest::testCounterVariable() { string name = "foo"; CounterVariable var(name); OLA_ASSERT_EQ(var.Name(), name); OLA_ASSERT_EQ(var.Value(), string("0")); OLA_ASSERT_EQ((unsigned int) 0, var.Get()); var++; OLA_ASSERT_EQ((unsigned int) 1, var.Get()); OLA_ASSERT_EQ(var.Value(), string("1")); var += 10; OLA_ASSERT_EQ((unsigned int) 11, var.Get()); OLA_ASSERT_EQ(var.Value(), string("11")); var += 100; OLA_ASSERT_EQ((unsigned int) 111, var.Get()); OLA_ASSERT_EQ(var.Value(), string("111")); } /* * Check that the StringVariable works correctly. */ void ExportMapTest::testStringVariable() { string name = "foo"; StringVariable var(name); OLA_ASSERT_EQ(var.Name(), name); OLA_ASSERT_EQ(var.Value(), string("")); OLA_ASSERT_EQ(var.Get(), string("")); var.Set("bar"); OLA_ASSERT_EQ(var.Value(), string("bar")); OLA_ASSERT_EQ(var.Get(), string("bar")); } /* * Check that the BoolVariable works correctly. */ void ExportMapTest::testBoolVariable() { string name = "foo"; BoolVariable var(name); OLA_ASSERT_EQ(name, var.Name()); OLA_ASSERT_EQ(false, var.Get()); OLA_ASSERT_EQ(string("0"), var.Value()); var.Set(true); OLA_ASSERT_EQ(string("1"), var.Value()); OLA_ASSERT_EQ(true, var.Get()); } /* * Check that the StringMap works correctly. */ void ExportMapTest::testStringMapVariable() { string name = "foo"; string label = "count"; StringMap var(name, label); OLA_ASSERT_EQ(var.Name(), name); OLA_ASSERT_EQ(var.Label(), label); OLA_ASSERT_EQ(var.Value(), string("map:count")); string key1 = "key1"; string value1 = "value1"; var[key1] = value1; OLA_ASSERT_EQ(value1, var[key1]); OLA_ASSERT_EQ(var.Value(), string("map:count key1:\"value1\"")); string key2 = "key2"; string value2 = "value 2"; var[key2] = value2; OLA_ASSERT_EQ(value2, var[key2]); OLA_ASSERT_EQ(var.Value(), string("map:count key1:\"value1\" key2:\"value 2\"")); var.Remove(key1); OLA_ASSERT_EQ(string(""), var[key1]); var.Remove(key1); OLA_ASSERT_EQ(var.Value(), string("map:count key2:\"value 2\"")); var[key2] = "foo\""; OLA_ASSERT_EQ(var.Value(), string("map:count key2:\"foo\\\"\"")); } /* * Check that the IntMap works correctly. */ void ExportMapTest::testIntMapVariable() { string name = "foo"; string label = "count"; IntMap var(name, label); OLA_ASSERT_EQ(var.Name(), name); OLA_ASSERT_EQ(var.Label(), label); OLA_ASSERT_EQ(var.Value(), string("map:count")); string key1 = "key1"; var[key1] = 100; OLA_ASSERT_EQ(100, var[key1]); OLA_ASSERT_EQ(var.Value(), string("map:count key1:100")); string key2 = "key2"; var[key2] = 99; OLA_ASSERT_EQ(99, var[key2]); OLA_ASSERT_EQ(var.Value(), string("map:count key1:100 key2:99")); var.Remove(key1); OLA_ASSERT_EQ(0, var[key1]); var.Remove(key1); OLA_ASSERT_EQ(var.Value(), string("map:count key2:99")); var.Remove(key2); // check references work string key3 = "key3"; int &var1 = var[key3]; OLA_ASSERT_EQ(0, var1); var1++; OLA_ASSERT_EQ(1, var[key3]); OLA_ASSERT_EQ(var.Value(), string("map:count key3:1")); var.Remove(key3); // check increments work var.Increment(key1); OLA_ASSERT_EQ(var.Value(), string("map:count key1:1")); } /* * Check the export map works correctly. */ void ExportMapTest::testExportMap() { ExportMap map; string bool_var_name = "bool_var"; string int_var_name = "int_var"; string str_var_name = "str_var"; string map_var_name = "map_var"; string map_var_label = "label"; BoolVariable *bool_var = map.GetBoolVar(bool_var_name); IntegerVariable *int_var = map.GetIntegerVar(int_var_name); StringVariable *str_var = map.GetStringVar(str_var_name); StringMap *map_var = map.GetStringMapVar(map_var_name, map_var_label); OLA_ASSERT_EQ(bool_var->Name(), bool_var_name); OLA_ASSERT_EQ(int_var->Name(), int_var_name); OLA_ASSERT_EQ(str_var->Name(), str_var_name); OLA_ASSERT_EQ(map_var->Name(), map_var_name); OLA_ASSERT_EQ(map_var->Label(), map_var_label); map_var = map.GetStringMapVar(map_var_name); OLA_ASSERT_EQ(map_var->Name(), map_var_name); OLA_ASSERT_EQ(map_var->Label(), map_var_label); vector variables = map.AllVariables(); OLA_ASSERT_EQ(variables.size(), (size_t) 4); } ola-0.10.5.nojsmin/common/dmx/0000755000175000017500000000000013155164170015543 5ustar wouterwouterola-0.10.5.nojsmin/common/dmx/Makefile.mk0000644000175000017500000000070713023355232017610 0ustar wouterwouter# LIBRARIES ################################################## common_libolacommon_la_SOURCES += common/dmx/RunLengthEncoder.cpp # TESTS ################################################## test_programs += common/dmx/RunLengthEncoderTester common_dmx_RunLengthEncoderTester_SOURCES = common/dmx/RunLengthEncoderTest.cpp common_dmx_RunLengthEncoderTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) common_dmx_RunLengthEncoderTester_LDADD = $(COMMON_TESTING_LIBS) ola-0.10.5.nojsmin/common/dmx/RunLengthEncoderTest.cpp0000644000175000017500000001245713023355232022321 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * RunLengthEncoderTest.cpp * Test fixture for the RunLengthEncoder class * Copyright (C) 2005 Simon Newton */ #include #include #include #include "ola/Constants.h" #include "ola/DmxBuffer.h" #include "ola/dmx/RunLengthEncoder.h" #include "ola/testing/TestUtils.h" using ola::dmx::RunLengthEncoder; using ola::DmxBuffer; class RunLengthEncoderTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(RunLengthEncoderTest); CPPUNIT_TEST(testEncode); CPPUNIT_TEST(testEncode2); CPPUNIT_TEST_SUITE_END(); public: void testEncode(); void testEncode2(); void testEncodeDecode(); void setUp(); void tearDown(); private: RunLengthEncoder m_encoder; uint8_t *m_dst; void checkEncode(const DmxBuffer &buffer, unsigned int dst_size, bool is_incomplete, const uint8_t *expected_data, unsigned int expected_length); void checkEncodeDecode(const uint8_t *data, unsigned int data_size); }; CPPUNIT_TEST_SUITE_REGISTRATION(RunLengthEncoderTest); /* * allocate a scratch pad */ void RunLengthEncoderTest::setUp() { m_dst = new uint8_t[ola::DMX_UNIVERSE_SIZE]; } /* * clean up */ void RunLengthEncoderTest::tearDown() { delete[] m_dst; } /* * Check that for a given buffer and dst buffer size, we get the expected data */ void RunLengthEncoderTest::checkEncode(const DmxBuffer &buffer, unsigned int dst_size, bool is_complete, const uint8_t *expected_data, unsigned int expected_length) { memset(m_dst, 0, ola::DMX_UNIVERSE_SIZE); OLA_ASSERT_EQ(is_complete, m_encoder.Encode(buffer, m_dst, &dst_size)); OLA_ASSERT_EQ(expected_length, dst_size); OLA_ASSERT_EQ(0, memcmp(expected_data, m_dst, dst_size)); } /* * Check that encoding works. */ void RunLengthEncoderTest::testEncode() { const uint8_t TEST_DATA[] = {1, 2, 2, 3, 0, 0, 0, 1, 3, 3, 3, 1, 2}; const uint8_t EXPECTED_DATA[] = {4, 1, 2, 2, 3, 0x83, 0, 1, 1, 0x83, 3, 2, 1, 2}; const uint8_t EXPECTED_DATA2[] = {3, 1, 2, 2}; const uint8_t EXPECTED_DATA3[] = {4, 1, 2, 2, 3, 0x83, 0, 1, 1, 0x83, 3, 1, 1}; DmxBuffer buffer(TEST_DATA, sizeof(TEST_DATA)); checkEncode(buffer, ola::DMX_UNIVERSE_SIZE, true, EXPECTED_DATA, sizeof(EXPECTED_DATA)); checkEncode(buffer, 4, false, EXPECTED_DATA2, sizeof(EXPECTED_DATA2)); checkEncode(buffer, 5, false, EXPECTED_DATA, 5); checkEncode(buffer, 6, false, EXPECTED_DATA, 5); checkEncode(buffer, 7, false, EXPECTED_DATA, 7); checkEncode(buffer, 8, false, EXPECTED_DATA, 7); checkEncode(buffer, 9, false, EXPECTED_DATA, 9); checkEncode(buffer, 10, false, EXPECTED_DATA, 9); checkEncode(buffer, 11, false, EXPECTED_DATA, 11); checkEncode(buffer, 12, false, EXPECTED_DATA, 11); checkEncode(buffer, 13, false, EXPECTED_DATA3, sizeof(EXPECTED_DATA3)); } /* * Check that encoding works. */ void RunLengthEncoderTest::testEncode2() { const uint8_t TEST_DATA[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; const uint8_t EXPECTED_DATA[] = {0x8A, 0}; DmxBuffer buffer(TEST_DATA, sizeof(TEST_DATA)); checkEncode(buffer, ola::DMX_UNIVERSE_SIZE, true, EXPECTED_DATA, sizeof(EXPECTED_DATA)); checkEncode(buffer, 2, true, EXPECTED_DATA, sizeof(EXPECTED_DATA)); checkEncode(buffer, 1, false, EXPECTED_DATA, 0); checkEncode(buffer, 0, false, EXPECTED_DATA, 0); } /* * Call Encode then Decode and check the results */ void RunLengthEncoderTest::checkEncodeDecode(const uint8_t *data, unsigned int data_size) { DmxBuffer src(data, data_size); DmxBuffer dst; unsigned int dst_size = ola::DMX_UNIVERSE_SIZE; memset(m_dst, 0, dst_size); OLA_ASSERT_TRUE(m_encoder.Encode(src, m_dst, &dst_size)); OLA_ASSERT_TRUE(m_encoder.Decode(0, m_dst, dst_size, &dst)); OLA_ASSERT_TRUE(src == dst); OLA_ASSERT_EQ(dst.Size(), data_size); OLA_ASSERT_NE(0, memcmp(data, dst.GetRaw(), dst.Size())); } /* * Check that an Encode/Decode pair works */ void RunLengthEncoderTest::testEncodeDecode() { const uint8_t TEST_DATA[] = {1, 2, 2, 3, 0, 0, 0, 1, 3, 3, 3, 1, 2}; const uint8_t TEST_DATA2[] = {0, 0, 0, 0, 6, 5, 4, 3, 3, 3}; const uint8_t TEST_DATA3[] = {0, 0, 0}; checkEncodeDecode(TEST_DATA, sizeof(TEST_DATA)); checkEncodeDecode(TEST_DATA2, sizeof(TEST_DATA2)); checkEncodeDecode(TEST_DATA3, sizeof(TEST_DATA3)); } ola-0.10.5.nojsmin/common/dmx/RunLengthEncoder.cpp0000644000175000017500000000724313023355232021456 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * RunLengthEncoder.cpp * The Run Length Encoder * Copyright (C) 2005 Simon Newton */ #include #include namespace ola { namespace dmx { bool RunLengthEncoder::Encode(const DmxBuffer &src, uint8_t *data, unsigned int *data_size) { unsigned int src_size = src.Size(); unsigned int dst_size = *data_size; unsigned int &dst_index = *data_size; dst_index = 0; unsigned int i; for (i = 0; i < src_size && dst_index < dst_size;) { // j points to the first non-repeating value unsigned int j = i + 1; while (j < src_size && src.Get(i) == src.Get(j) && j - i < 0x7f) { j++; } // if the number of repeats is more than 2 // don't encode only two repeats, if (j - i > 2) { // if room left in dst buffer if (dst_size - dst_index > 1) { data[dst_index++] = (REPEAT_FLAG | (j - i)); data[dst_index++] = src.Get(i); } else { // else return what we have done so far return false; } i = j; } else { // this value doesn't repeat more than twice // find out where the next repeat starts // postcondition: j is one more than the last value we want to send for (j = i + 1; j < src_size - 2 && j - i < 0x7f; j++) { // at the end of the array if (j == src_size - 2) { j = src_size; break; } // if we're found a repeat of 3 or more stop here if (src.Get(j) == src.Get(j+1) && src.Get(j) == src.Get(j+2)) break; } if (j >= src_size - 2) j = src_size; // if we have enough room left for all the values if (dst_index + j - i < dst_size) { data[dst_index++] = j - i; memcpy(&data[dst_index], src.GetRaw() + i, j-i); dst_index += j - i; i = j; // see how much data we can get in } else if (dst_size - dst_index > 1) { unsigned int l = dst_size - dst_index -1; data[dst_index++] = l; memcpy(&data[dst_index], src.GetRaw() + i, l); dst_index += l; return false; } else { return false; } } } if (i < src_size) return false; else return true; } bool RunLengthEncoder::Decode(unsigned int start_channel, const uint8_t *src_data, unsigned int length, DmxBuffer *dst) { int destination_index = start_channel; for (unsigned int i = 0; i < length;) { unsigned int segment_length = src_data[i] & (~REPEAT_FLAG); if (src_data[i] & REPEAT_FLAG) { i++; dst->SetRangeToValue(destination_index, src_data[i++], segment_length); } else { i++; dst->SetRange(destination_index, src_data + i, segment_length); i += segment_length; } destination_index += segment_length; } return true; } } // namespace dmx } // namespace ola ola-0.10.5.nojsmin/common/testing/0000755000175000017500000000000013155164170016430 5ustar wouterwouterola-0.10.5.nojsmin/common/testing/GenericTester.cpp0000644000175000017500000000420413023355232021672 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * GenericTester.cpp * Run the tests. * Copyright (C) 2012 Simon Newton */ #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #include #include #include #include "ola/base/Env.h" #include "ola/base/Flags.h" #include "ola/base/Init.h" #include "ola/Logging.h" #include "ola/StringUtils.h" using std::string; #ifdef HAVE_EPOLL DECLARE_bool(use_epoll); #endif // HAVE_EPOLL #ifdef HAVE_KQUEUE DECLARE_bool(use_kqueue); #endif // HAVE_KQUEUE DECLARE_uint8(log_level); bool GetBoolEnvVar(const string &var_name) { string var; bool result = false; ola::GetEnv(var_name, &var) && ola::StringToBool(var, &result); return result; } int main(int argc, char* argv[]) { // Default to INFO since it's tests. FLAGS_log_level = ola::OLA_LOG_INFO; #ifdef HAVE_EPOLL FLAGS_use_epoll = GetBoolEnvVar("OLA_USE_EPOLL"); #endif // HAVE_EPOLL #ifdef HAVE_KQUEUE FLAGS_use_kqueue = GetBoolEnvVar("OLA_USE_KQUEUE"); #endif // HAVE_KQUEUE ola::AppInit(&argc, argv, "[options]", ""); CppUnit::Test *suite = CppUnit::TestFactoryRegistry::getRegistry().makeTest(); CppUnit::TextUi::TestRunner runner; runner.addTest(suite); runner.setOutputter( new CppUnit::CompilerOutputter(&runner.result(), std::cerr)); bool wasSucessful = runner.run(); return wasSucessful ? 0 : 1; } ola-0.10.5.nojsmin/common/testing/Makefile.mk0000644000175000017500000000057513023355232020500 0ustar wouterwouter# LIBRARIES ################################################## if BUILD_TESTS noinst_LTLIBRARIES += common/testing/libolatesting.la \ common/testing/libtestmain.la common_testing_libolatesting_la_SOURCES = \ common/testing/MockUDPSocket.cpp \ common/testing/TestUtils.cpp common_testing_libtestmain_la_SOURCES = common/testing/GenericTester.cpp endif ola-0.10.5.nojsmin/common/testing/TestUtils.cpp0000644000175000017500000000612113023355232021067 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * TestUtils.cpp * Functions used for unit testing. * Copyright (C) 2012 Simon Newton */ #include #include #include #include #include "ola/testing/TestUtils.h" #include "ola/Logging.h" namespace ola { namespace testing { using std::string; /* * Assert that two blocks of data match. * @param source_line the file name and line number of this assert * @param expected pointer to the expected data * @param expected_length the length of the expected data * @param actual point to the actual data * @param actual_length length of the actual data */ void ASSERT_DATA_EQUALS(const SourceLine &source_line, const uint8_t *expected, unsigned int expected_length, const uint8_t *actual, unsigned int actual_length) { _AssertEquals(source_line, expected_length, actual_length, "Data lengths differ"); bool data_matches = (0 == memcmp(expected, actual, expected_length)); if (!data_matches) { std::ostringstream str; for (unsigned int i = 0; i < expected_length; ++i) { str.str(""); str << std::dec << i << ": 0x" << std::hex << static_cast(expected[i]); str << ((expected[i] == actual[i]) ? " == " : " != "); str << "0x" << static_cast(actual[i]) << " ("; str << ((expected[i] >= '!' && expected[i] <= '~') ? static_cast(expected[i]) : ' '); str << ((expected[i] == actual[i]) ? " == " : " != "); str << ((actual[i] >= '!' && actual[i] <= '~') ? static_cast(actual[i]) : ' '); str << ")"; if (expected[i] != actual[i]) { str << " ## MISMATCH"; } OLA_INFO << str.str(); } } CPPUNIT_NS::Asserter::failIf(!data_matches, "Data differs", source_line); } void ASSERT_DATA_EQUALS(const SourceLine &source_line, const char *expected, unsigned int expected_length, const char *actual, unsigned int actual_length) { ASSERT_DATA_EQUALS(source_line, reinterpret_cast(expected), expected_length, reinterpret_cast(actual), actual_length); } } // namespace testing } // namespace ola ola-0.10.5.nojsmin/common/testing/MockUDPSocket.cpp0000644000175000017500000002231113023355232021541 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * MockUDPSocket.cpp * This implements the UDPSocketInterface in a way that we can use it for * testing. * Copyright (C) 2010 Simon Newton */ #include #include #include #include #include #include #include #include "ola/Logging.h" #include "ola/network/IPV4Address.h" #include "ola/network/NetworkUtils.h" #include "ola/testing/MockUDPSocket.h" #include "ola/testing/TestUtils.h" namespace ola { namespace testing { using ola::io::IOQueue; using ola::io::IOVec; using ola::io::IOVecInterface; using ola::network::HostToNetwork; using ola::network::IPV4Address; using ola::network::IPV4SocketAddress; MockUDPSocket::MockUDPSocket() : ola::network::UDPSocketInterface(), m_init_called(false), m_dummy_handle(ola::io::INVALID_DESCRIPTOR), m_bound_to_port(false), m_broadcast_set(false), m_port(0), m_tos(0), m_discard_mode(false) { } bool MockUDPSocket::Init() { if (m_dummy_handle == ola::io::INVALID_DESCRIPTOR) { #ifdef _WIN32 m_dummy_handle.m_handle.m_fd = socket(PF_INET, SOCK_DGRAM, 0); if (m_dummy_handle.m_handle.m_fd < 0) { #else m_dummy_handle = socket(PF_INET, SOCK_DGRAM, 0); if (m_dummy_handle < 0) { #endif // _WIN32 OLA_WARN << "Could not create socket " << strerror(errno); return false; } } m_init_called = true; return true; } bool MockUDPSocket::Bind(const ola::network::IPV4SocketAddress &endpoint) { m_bound_to_port = true; m_port = endpoint.Port(); return true; } bool MockUDPSocket::GetSocketAddress(IPV4SocketAddress *address) const { // Return a dummy address *address = IPV4SocketAddress(IPV4Address::Loopback(), 0); return true; } bool MockUDPSocket::Close() { m_bound_to_port = false; if (m_dummy_handle != ola::io::INVALID_DESCRIPTOR) { #ifdef _WIN32 closesocket(m_dummy_handle.m_handle.m_fd); #else close(m_dummy_handle); #endif // _WIN32 } return true; } ssize_t MockUDPSocket::SendTo(const uint8_t *buffer, unsigned int size, const ola::network::IPV4Address &ip_address, unsigned short port) const { if (m_discard_mode) { return size; } OLA_ASSERT_FALSE(m_expected_calls.empty()); expected_call call = m_expected_calls.front(); OLA_ASSERT_DATA_EQUALS(call.data, call.size, buffer, size); OLA_ASSERT_EQ(call.address, ip_address); OLA_ASSERT_EQ(call.port, port); if (call.free_data) { delete[] call.data; } m_expected_calls.pop(); return size; } ssize_t MockUDPSocket::SendTo(IOVecInterface *data, const ola::network::IPV4Address &ip_address, unsigned short port) const { // This incurs a copy but it's only testing code. int io_len; const struct IOVec *iov = data->AsIOVec(&io_len); if (iov == NULL) { return 0; } unsigned int data_size = 0; for (int i = 0; i < io_len; i++) { data_size += iov[i].iov_len; } uint8_t *raw_data = new uint8_t[data_size]; unsigned int offset = 0; for (int i = 0; i < io_len; i++) { memcpy(raw_data + offset, iov[i].iov_base, iov[i].iov_len); offset += iov[i].iov_len; } data->Pop(data_size); data->FreeIOVec(iov); ssize_t data_sent = SendTo(raw_data, data_size, ip_address, port); delete[] raw_data; return data_sent; } bool MockUDPSocket::RecvFrom(uint8_t *buffer, ssize_t *data_read) const { IPV4Address address; uint16_t port; return RecvFrom(buffer, data_read, address, port); } bool MockUDPSocket::RecvFrom( uint8_t *buffer, ssize_t *data_read, ola::network::IPV4Address &source) const { // NOLINT(runtime/references) uint16_t port; return RecvFrom(buffer, data_read, source, port); } bool MockUDPSocket::RecvFrom( uint8_t *buffer, ssize_t *data_read, ola::network::IPV4Address &source, // NOLINT(runtime/references) uint16_t &port) const { // NOLINT(runtime/references) OLA_ASSERT_FALSE(m_received_data.empty()); const received_data &new_data = m_received_data.front(); OLA_ASSERT_TRUE(static_cast(*data_read) >= new_data.size); unsigned int size = std::min(new_data.size, static_cast(*data_read)); memcpy(buffer, new_data.data, size); *data_read = new_data.size; source = new_data.address; port = new_data.port; if (new_data.free_data) { delete[] new_data.data; } m_received_data.pop(); return true; } bool MockUDPSocket::RecvFrom( uint8_t *buffer, ssize_t *data_read, ola::network::IPV4SocketAddress *source) { IPV4Address source_ip; uint16_t port; bool ok = RecvFrom(buffer, data_read, source_ip, port); if (ok) { *source = IPV4SocketAddress(source_ip, port); } return ok; } bool MockUDPSocket::EnableBroadcast() { m_broadcast_set = true; return true; } bool MockUDPSocket::SetMulticastInterface(const IPV4Address &iface) { OLA_ASSERT_EQ(m_interface, iface); return true; } bool MockUDPSocket::JoinMulticast(const IPV4Address &iface, OLA_UNUSED const IPV4Address &group, OLA_UNUSED bool loop) { OLA_ASSERT_EQ(m_interface, iface); return true; } bool MockUDPSocket::LeaveMulticast(const IPV4Address &iface, OLA_UNUSED const IPV4Address &group) { OLA_ASSERT_EQ(m_interface, iface); return true; } bool MockUDPSocket::SetTos(uint8_t tos) { m_tos = tos; return true; } void MockUDPSocket::AddExpectedData(const uint8_t *data, unsigned int size, const IPV4Address &ip, uint16_t port) { expected_call call = {data, size, ip, port, false}; m_expected_calls.push(call); } void MockUDPSocket::AddExpectedData(IOQueue *ioqueue, const IPV4SocketAddress &dest) { unsigned int size; uint8_t *data = IOQueueToBuffer(ioqueue, &size); expected_call call = {data, size, dest.Host(), dest.Port(), true}; m_expected_calls.push(call); } /** * Ownership of the data is not transferred. */ void MockUDPSocket::InjectData(const uint8_t *data, unsigned int size, const IPV4Address &ip, uint16_t port) { expected_call call = {data, size, ip, port, false}; m_received_data.push(call); PerformRead(); } /** * Ownership of the data is not transferred. */ void MockUDPSocket::InjectData(const uint8_t *data, unsigned int size, const IPV4SocketAddress &source) { InjectData(data, size, source.Host(), source.Port()); } /** * Inject the data in an IOQueue into the socket. This acts as if the data was * received on the UDP socket. * @param ioqueue the data to inject * @param source the socket address where this fake data came from */ void MockUDPSocket::InjectData(IOQueue *ioqueue, const IPV4SocketAddress &source) { unsigned int data_size; // This incurs a copy, but this is just testing code so it doesn't matter. uint8_t *data = IOQueueToBuffer(ioqueue, &data_size); expected_call call = {data, data_size, source.Host(), source.Port(), true}; m_received_data.push(call); PerformRead(); } void MockUDPSocket::Verify() { // if an exception is outstanding, don't both to check if we have consumed // all calls. This avoids raising a second exception which calls terminate. if (!std::uncaught_exception()) { std::ostringstream msg; msg << m_expected_calls.size() << " packets remain on the MockUDPSocket"; OLA_ASSERT_TRUE_MSG(m_expected_calls.empty(), msg.str()); } } bool MockUDPSocket::CheckNetworkParamsMatch(bool init_called, bool bound_to_port, uint16_t port, bool broadcast_set) { return (init_called == m_init_called && bound_to_port == m_bound_to_port && port == m_port && broadcast_set == m_broadcast_set); } void MockUDPSocket::SetInterface(const IPV4Address &iface) { m_interface = iface; } uint8_t* MockUDPSocket::IOQueueToBuffer(IOQueue *ioqueue, unsigned int *size) const { *size = ioqueue->Size(); uint8_t *data = new uint8_t[*size]; *size = ioqueue->Read(data, *size); return data; } } // namespace testing } // namespace ola ola-0.10.5.nojsmin/ola/0000755000175000017500000000000013155164170014236 5ustar wouterwouterola-0.10.5.nojsmin/ola/Makefile.mk0000644000175000017500000000262213134123277016306 0ustar wouterwouter# HEADERS ################################################## # These headers are deprecated and will be removed 6 months after the 0.9.0 # release. DEPRECATED = \ ola/OlaCallbackClient.h \ ola/OlaDevice.h \ ola/StreamingClient.h pkginclude_HEADERS += \ ola/AutoStart.h \ ola/OlaClientWrapper.h \ $(DEPRECATED) # LIBRARIES ################################################## lib_LTLIBRARIES += ola/libola.la ola_libola_la_SOURCES = \ ola/AutoStart.cpp \ ola/ClientRDMAPIShim.cpp \ ola/ClientTypesFactory.h \ ola/ClientTypesFactory.cpp \ ola/Module.cpp \ ola/OlaCallbackClient.cpp \ ola/OlaClient.cpp \ ola/OlaClientCore.h \ ola/OlaClientCore.cpp \ ola/OlaClientWrapper.cpp \ ola/StreamingClient.cpp ola_libola_la_CXXFLAGS = $(COMMON_PROTOBUF_CXXFLAGS) ola_libola_la_LDFLAGS = -version-info 1:1:0 ola_libola_la_LIBADD = common/libolacommon.la # TESTS ################################################## test_programs += ola/OlaClientTester ola_OlaClientTester_SOURCES = ola/OlaClientWrapperTest.cpp \ ola/StreamingClientTest.cpp ola_OlaClientTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) ola_OlaClientTester_LDADD = $(COMMON_TESTING_LIBS) \ $(PLUGIN_LIBS) \ common/libolacommon.la \ olad/libolaserver.la \ ola/libola.la ola-0.10.5.nojsmin/ola/OlaClientCore.cpp0000644000175000017500000010232413023355232017422 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * OlaClientCore.cpp * Implementation of OlaClientCore * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include #include #include #include #include "common/protocol/Ola.pb.h" #include "ola/Callback.h" #include "ola/ClientTypesFactory.h" #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/OlaClientCore.h" #include "ola/client/ClientTypes.h" #include "ola/network/NetworkUtils.h" #include "ola/rdm/RDMCommand.h" #include "ola/rdm/RDMEnums.h" #include "ola/rdm/RDMFrame.h" namespace ola { namespace client { using ola::io::ConnectedDescriptor; using ola::proto::OlaServerService_Stub; using ola::rdm::UID; using ola::rdm::UIDSet; using ola::rpc::RpcChannel; using ola::rpc::RpcController; using std::auto_ptr; using std::string; using std::vector; const char OlaClientCore::NOT_CONNECTED_ERROR[] = "Not connected"; OlaClientCore::OlaClientCore(ConnectedDescriptor *descriptor) : m_descriptor(descriptor), m_connected(false) { } OlaClientCore::~OlaClientCore() { if (m_connected) Stop(); } /* * Setup this client * @return true on success, false on failure */ bool OlaClientCore::Setup() { if (m_connected) return false; m_channel.reset(new RpcChannel(this, m_descriptor)); if (!m_channel.get()) { return false; } m_stub.reset(new OlaServerService_Stub(m_channel.get())); if (!m_stub.get()) { m_channel.reset(); return false; } m_connected = true; return true; } /* * Close the ola connection. * @return true on success, false on failure */ bool OlaClientCore::Stop() { if (m_connected) { m_descriptor->Close(); m_channel.reset(); m_stub.reset(); } m_connected = false; return 0; } /** * Set the close handler. */ void OlaClientCore::SetCloseHandler(ClosedCallback *callback) { if (callback) { m_channel->SetChannelCloseHandler( NewSingleCallback(this, &OlaClientCore::ChannelClosed, callback)); } else { m_channel->SetChannelCloseHandler(NULL); } } void OlaClientCore::SetDMXCallback(RepeatableDMXCallback *callback) { m_dmx_callback.reset(callback); } void OlaClientCore::ReloadPlugins(SetCallback *callback) { ola::proto::PluginReloadRequest request; RpcController *controller = new RpcController(); ola::proto::Ack *reply = new ola::proto::Ack(); if (m_connected) { CompletionCallback *cb = ola::NewSingleCallback( this, &OlaClientCore::HandleAck, controller, reply, callback); m_stub->ReloadPlugins(controller, &request, reply, cb); } else { controller->SetFailed(NOT_CONNECTED_ERROR); HandleAck(controller, reply, callback); } } void OlaClientCore::FetchPluginList(PluginListCallback *callback) { RpcController *controller = new RpcController(); ola::proto::PluginListRequest request; ola::proto::PluginListReply *reply = new ola::proto::PluginListReply(); if (m_connected) { CompletionCallback *cb = NewSingleCallback( this, &OlaClientCore::HandlePluginList, controller, reply, callback); m_stub->GetPlugins(controller, &request, reply, cb); } else { controller->SetFailed(NOT_CONNECTED_ERROR); HandlePluginList(controller, reply, callback); } } void OlaClientCore::FetchPluginDescription( ola_plugin_id plugin_id, PluginDescriptionCallback *callback) { RpcController *controller = new RpcController(); ola::proto::PluginDescriptionRequest request; ola::proto::PluginDescriptionReply *reply = new ola::proto::PluginDescriptionReply(); request.set_plugin_id(plugin_id); if (m_connected) { CompletionCallback *cb = NewSingleCallback( this, &OlaClientCore::HandlePluginDescription, controller, reply, callback); m_stub->GetPluginDescription(controller, &request, reply, cb); } else { controller->SetFailed(NOT_CONNECTED_ERROR); HandlePluginDescription(controller, reply, callback); } } void OlaClientCore::FetchPluginState( ola_plugin_id plugin_id, PluginStateCallback *callback) { RpcController *controller = new RpcController(); ola::proto::PluginStateRequest request; ola::proto::PluginStateReply *reply = new ola::proto::PluginStateReply(); request.set_plugin_id(plugin_id); if (m_connected) { CompletionCallback *cb = NewSingleCallback( this, &OlaClientCore::HandlePluginState, controller, reply, callback); m_stub->GetPluginState(controller, &request, reply, cb); } else { controller->SetFailed(NOT_CONNECTED_ERROR); HandlePluginState(controller, reply, callback); } } void OlaClientCore::FetchDeviceInfo(ola_plugin_id filter, DeviceInfoCallback *callback) { ola::proto::DeviceInfoRequest request; RpcController *controller = new RpcController(); ola::proto::DeviceInfoReply *reply = new ola::proto::DeviceInfoReply(); request.set_plugin_id(filter); if (m_connected) { CompletionCallback *cb = NewSingleCallback( this, &OlaClientCore::HandleDeviceInfo, controller, reply, callback); m_stub->GetDeviceInfo(controller, &request, reply, cb); } else { controller->SetFailed(NOT_CONNECTED_ERROR); HandleDeviceInfo(controller, reply, callback); } } void OlaClientCore::FetchCandidatePorts( unsigned int universe_id, CandidatePortsCallback *callback) { GenericFetchCandidatePorts(universe_id, true, callback); } void OlaClientCore::FetchCandidatePorts(CandidatePortsCallback *callback) { GenericFetchCandidatePorts(0, false, callback); } void OlaClientCore::ConfigureDevice( unsigned int device_alias, const string &msg, ConfigureDeviceCallback *callback) { ola::proto::DeviceConfigRequest request; RpcController *controller = new RpcController(); ola::proto::DeviceConfigReply *reply = new ola::proto::DeviceConfigReply(); string configure_request; request.set_device_alias(device_alias); request.set_data(msg); if (m_connected) { CompletionCallback *cb = NewSingleCallback( this, &OlaClientCore::HandleDeviceConfig, controller, reply, callback); m_stub->ConfigureDevice(controller, &request, reply, cb); } else { controller->SetFailed(NOT_CONNECTED_ERROR); HandleDeviceConfig(controller, reply, callback); } } void OlaClientCore::SetPluginState(ola_plugin_id plugin_id, bool state, SetCallback *callback) { ola::proto::PluginStateChangeRequest request; RpcController *controller = new RpcController(); ola::proto::Ack *reply = new ola::proto::Ack(); request.set_plugin_id(plugin_id); request.set_enabled(state); if (m_connected) { CompletionCallback *cb = ola::NewSingleCallback( this, &OlaClientCore::HandleAck, controller, reply, callback); m_stub->SetPluginState(controller, &request, reply, cb); } else { controller->SetFailed(NOT_CONNECTED_ERROR); HandleAck(controller, reply, callback); } } void OlaClientCore::SetPortPriorityInherit(unsigned int device_alias, unsigned int port, PortDirection port_direction, SetCallback *callback) { ola::proto::PortPriorityRequest request; RpcController *controller = new RpcController(); ola::proto::Ack *reply = new ola::proto::Ack(); request.set_device_alias(device_alias); request.set_port_id(port); request.set_is_output(port_direction == OUTPUT_PORT); request.set_priority_mode(ola::PRIORITY_MODE_INHERIT); if (m_connected) { CompletionCallback *cb = ola::NewSingleCallback( this, &OlaClientCore::HandleAck, controller, reply, callback); m_stub->SetPortPriority(controller, &request, reply, cb); } else { controller->SetFailed(NOT_CONNECTED_ERROR); HandleAck(controller, reply, callback); } } void OlaClientCore::SetPortPriorityOverride(unsigned int device_alias, unsigned int port, PortDirection port_direction, uint8_t value, SetCallback *callback) { ola::proto::PortPriorityRequest request; RpcController *controller = new RpcController(); ola::proto::Ack *reply = new ola::proto::Ack(); request.set_device_alias(device_alias); request.set_port_id(port); request.set_is_output(port_direction == OUTPUT_PORT); request.set_priority_mode(ola::PRIORITY_MODE_STATIC); request.set_priority(value); if (m_connected) { CompletionCallback *cb = ola::NewSingleCallback( this, &OlaClientCore::HandleAck, controller, reply, callback); m_stub->SetPortPriority(controller, &request, reply, cb); } else { controller->SetFailed(NOT_CONNECTED_ERROR); HandleAck(controller, reply, callback); } } void OlaClientCore::FetchUniverseList(UniverseListCallback *callback) { RpcController *controller = new RpcController(); ola::proto::OptionalUniverseRequest request; ola::proto::UniverseInfoReply *reply = new ola::proto::UniverseInfoReply(); if (m_connected) { CompletionCallback *cb = ola::NewSingleCallback( this, &OlaClientCore::HandleUniverseList, controller, reply, callback); m_stub->GetUniverseInfo(controller, &request, reply, cb); } else { controller->SetFailed(NOT_CONNECTED_ERROR); HandleUniverseList(controller, reply, callback); } } void OlaClientCore::FetchUniverseInfo(unsigned int universe_id, UniverseInfoCallback *callback) { RpcController *controller = new RpcController(); ola::proto::OptionalUniverseRequest request; ola::proto::UniverseInfoReply *reply = new ola::proto::UniverseInfoReply(); request.set_universe(universe_id); if (m_connected) { CompletionCallback *cb = ola::NewSingleCallback( this, &OlaClientCore::HandleUniverseInfo, controller, reply, callback); m_stub->GetUniverseInfo(controller, &request, reply, cb); } else { controller->SetFailed(NOT_CONNECTED_ERROR); HandleUniverseInfo(controller, reply, callback); } } void OlaClientCore::SetUniverseName(unsigned int universe, const string &name, SetCallback *callback) { ola::proto::UniverseNameRequest request; RpcController *controller = new RpcController(); ola::proto::Ack *reply = new ola::proto::Ack(); request.set_universe(universe); request.set_name(name); if (m_connected) { CompletionCallback *cb = ola::NewSingleCallback( this, &OlaClientCore::HandleAck, controller, reply, callback); m_stub->SetUniverseName(controller, &request, reply, cb); } else { controller->SetFailed(NOT_CONNECTED_ERROR); HandleAck(controller, reply, callback); } } void OlaClientCore::SetUniverseMergeMode(unsigned int universe, OlaUniverse::merge_mode mode, SetCallback *callback) { ola::proto::MergeModeRequest request; RpcController *controller = new RpcController(); ola::proto::Ack *reply = new ola::proto::Ack(); ola::proto::MergeMode merge_mode = mode == OlaUniverse::MERGE_HTP ? ola::proto::HTP : ola::proto::LTP; request.set_universe(universe); request.set_merge_mode(merge_mode); if (m_connected) { CompletionCallback *cb = ola::NewSingleCallback( this, &OlaClientCore::HandleAck, controller, reply, callback); m_stub->SetMergeMode(controller, &request, reply, cb); } else { controller->SetFailed(NOT_CONNECTED_ERROR); HandleAck(controller, reply, callback); } } void OlaClientCore::Patch(unsigned int device_alias, unsigned int port_id, PortDirection port_direction, PatchAction patch_action, unsigned int universe, SetCallback *callback) { ola::proto::PatchPortRequest request; RpcController *controller = new RpcController(); ola::proto::Ack *reply = new ola::proto::Ack(); ola::proto::PatchAction action = ( patch_action == PATCH ? ola::proto::PATCH : ola::proto::UNPATCH); request.set_universe(universe); request.set_device_alias(device_alias); request.set_port_id(port_id); request.set_is_output(port_direction == OUTPUT_PORT); request.set_action(action); if (m_connected) { CompletionCallback *cb = ola::NewSingleCallback( this, &OlaClientCore::HandleAck, controller, reply, callback); m_stub->PatchPort(controller, &request, reply, cb); } else { controller->SetFailed(NOT_CONNECTED_ERROR); HandleAck(controller, reply, callback); } } void OlaClientCore::RegisterUniverse(unsigned int universe, RegisterAction register_action, SetCallback *callback) { ola::proto::RegisterDmxRequest request; RpcController *controller = new RpcController(); ola::proto::Ack *reply = new ola::proto::Ack(); ola::proto::RegisterAction action = ( register_action == REGISTER ? ola::proto::REGISTER : ola::proto::UNREGISTER); request.set_universe(universe); request.set_action(action); if (m_connected) { CompletionCallback *cb = ola::NewSingleCallback( this, &OlaClientCore::HandleAck, controller, reply, callback); m_stub->RegisterForDmx(controller, &request, reply, cb); } else { controller->SetFailed(NOT_CONNECTED_ERROR); HandleAck(controller, reply, callback); } } void OlaClientCore::SendDMX(unsigned int universe, const DmxBuffer &data, const SendDMXArgs &args) { ola::proto::DmxData request; request.set_universe(universe); request.set_data(data.Get()); request.set_priority(args.priority); if (args.callback) { // Full request RpcController *controller = new RpcController(); ola::proto::Ack *reply = new ola::proto::Ack(); if (m_connected) { CompletionCallback *cb = ola::NewSingleCallback( this, &OlaClientCore::HandleGeneralAck, controller, reply, args.callback); m_stub->UpdateDmxData(controller, &request, reply, cb); } else { controller->SetFailed(NOT_CONNECTED_ERROR); HandleGeneralAck(controller, reply, args.callback); } } else if (m_connected) { // stream data m_stub->StreamDmxData(NULL, &request, NULL, NULL); } } void OlaClientCore::FetchDMX(unsigned int universe, DMXCallback *callback) { ola::proto::UniverseRequest request; RpcController *controller = new RpcController(); ola::proto::DmxData *reply = new ola::proto::DmxData(); request.set_universe(universe); if (m_connected) { CompletionCallback *cb = NewSingleCallback( this, &OlaClientCore::HandleGetDmx, controller, reply, callback); m_stub->GetDmx(controller, &request, reply, cb); } else { controller->SetFailed(NOT_CONNECTED_ERROR); HandleGetDmx(controller, reply, callback); } } void OlaClientCore::RunDiscovery(unsigned int universe, DiscoveryType discovery_type, DiscoveryCallback *callback) { RpcController *controller = new RpcController(); ola::proto::UIDListReply *reply = new ola::proto::UIDListReply(); if (!m_connected) { controller->SetFailed(NOT_CONNECTED_ERROR); HandleUIDList(controller, reply, callback); return; } CompletionCallback *cb = NewSingleCallback( this, &OlaClientCore::HandleUIDList, controller, reply, callback); if (discovery_type == DISCOVERY_CACHED) { ola::proto::UniverseRequest request; request.set_universe(universe); m_stub->GetUIDs(controller, &request, reply, cb); } else { ola::proto::DiscoveryRequest request; request.set_universe(universe); request.set_full(discovery_type == DISCOVERY_FULL); m_stub->ForceDiscovery(controller, &request, reply, cb); } } void OlaClientCore::SetSourceUID(const UID &uid, SetCallback *callback) { ola::proto::UID request; RpcController *controller = new RpcController(); ola::proto::Ack *reply = new ola::proto::Ack(); request.set_esta_id(uid.ManufacturerId()); request.set_device_id(uid.DeviceId()); if (m_connected) { CompletionCallback *cb = ola::NewSingleCallback( this, &OlaClientCore::HandleAck, controller, reply, callback); m_stub->SetSourceUID(controller, &request, reply, cb); } else { controller->SetFailed(NOT_CONNECTED_ERROR); HandleAck(controller, reply, callback); } } void OlaClientCore::RDMGet(unsigned int universe, const ola::rdm::UID &uid, uint16_t sub_device, uint16_t pid, const uint8_t *data, unsigned int data_length, const SendRDMArgs& args) { SendRDMCommand(false, universe, uid, sub_device, pid, data, data_length, args); } void OlaClientCore::RDMSet(unsigned int universe, const ola::rdm::UID &uid, uint16_t sub_device, uint16_t pid, const uint8_t *data, unsigned int data_length, const SendRDMArgs& args) { SendRDMCommand(true, universe, uid, sub_device, pid, data, data_length, args); } void OlaClientCore::SendTimeCode(const ola::timecode::TimeCode &timecode, SetCallback *callback) { if (!timecode.IsValid()) { Result result("Invalid timecode"); OLA_WARN << "Invalid timecode: " << timecode; if (callback) { callback->Run(result); } return; } RpcController *controller = new RpcController(); ola::proto::TimeCode request; ola::proto::Ack *reply = new ola::proto::Ack(); request.set_type(static_cast(timecode.Type())); request.set_hours(timecode.Hours()); request.set_minutes(timecode.Minutes()); request.set_seconds(timecode.Seconds()); request.set_frames(timecode.Frames()); if (m_connected) { CompletionCallback *cb = ola::NewSingleCallback( this, &OlaClientCore::HandleAck, controller, reply, callback); m_stub->SendTimeCode(controller, &request, reply, cb); } else { controller->SetFailed(NOT_CONNECTED_ERROR); HandleAck(controller, reply, callback); } } void OlaClientCore::UpdateDmxData(ola::rpc::RpcController*, const ola::proto::DmxData *request, ola::proto::Ack*, CompletionCallback *done) { if (m_dmx_callback.get()) { DmxBuffer buffer; buffer.Set(request->data()); uint8_t priority = 0; if (request->has_priority()) { priority = request->priority(); } DMXMetadata metadata(request->universe(), priority); m_dmx_callback->Run(metadata, buffer); } done->Run(); } void OlaClientCore::ChannelClosed(ClosedCallback *callback, OLA_UNUSED ola::rpc::RpcSession *session) { callback->Run(); } // The following are RPC callbacks /* * Called once PluginInfo completes */ void OlaClientCore::HandlePluginList(RpcController *controller_ptr, ola::proto::PluginListReply *reply_ptr, PluginListCallback *callback) { auto_ptr controller(controller_ptr); auto_ptr reply(reply_ptr); if (!callback) { return; } Result result(controller->Failed() ? controller->ErrorText() : ""); vector ola_plugins; if (!controller->Failed()) { for (int i = 0; i < reply->plugin_size(); ++i) { ola::proto::PluginInfo plugin_info = reply->plugin(i); ola_plugins.push_back( ClientTypesFactory::PluginFromProtobuf(plugin_info)); } } std::sort(ola_plugins.begin(), ola_plugins.end()); callback->Run(result, ola_plugins); } /* * Called once PluginState completes */ void OlaClientCore::HandlePluginDescription( RpcController *controller_ptr, ola::proto::PluginDescriptionReply *reply_ptr, PluginDescriptionCallback *callback) { auto_ptr controller(controller_ptr); auto_ptr reply(reply_ptr); if (!callback) { return; } Result result(controller->Failed() ? controller->ErrorText() : ""); string description; if (!controller->Failed()) { description = reply->description(); } callback->Run(result, description); } /* * Called once PluginState completes */ void OlaClientCore::HandlePluginState( RpcController *controller_ptr, ola::proto::PluginStateReply *reply_ptr, PluginStateCallback *callback) { auto_ptr controller(controller_ptr); auto_ptr reply(reply_ptr); if (!callback) { return; } Result result(controller->Failed() ? controller->ErrorText() : ""); PluginState plugin_state; if (!controller->Failed()) { plugin_state.name = reply->name(); plugin_state.enabled = reply->enabled(); plugin_state.active = reply->active(); plugin_state.preferences_source = reply->preferences_source(); for (int i = 0; i < reply->conflicts_with_size(); ++i) { ola::proto::PluginInfo plugin_info = reply->conflicts_with(i); plugin_state.conflicting_plugins.push_back( ClientTypesFactory::PluginFromProtobuf(plugin_info)); } } callback->Run(result, plugin_state); } /* * Called once DeviceInfo completes. */ void OlaClientCore::HandleDeviceInfo(RpcController *controller_ptr, ola::proto::DeviceInfoReply *reply_ptr, DeviceInfoCallback *callback) { auto_ptr controller(controller_ptr); auto_ptr reply(reply_ptr); if (!callback) { return; } Result result(controller->Failed() ? controller->ErrorText() : ""); vector ola_devices; if (!controller->Failed()) { for (int i = 0; i < reply->device_size(); ++i) { ola::proto::DeviceInfo device_info = reply->device(i); ola_devices.push_back( ClientTypesFactory::DeviceFromProtobuf(device_info)); } } std::sort(ola_devices.begin(), ola_devices.end()); callback->Run(result, ola_devices); } void OlaClientCore::HandleDeviceConfig(RpcController *controller_ptr, ola::proto::DeviceConfigReply *reply_ptr, ConfigureDeviceCallback *callback) { auto_ptr controller(controller_ptr); auto_ptr reply(reply_ptr); if (!callback) { return; } Result result(controller->Failed() ? controller->ErrorText() : ""); string response_data; if (!controller->Failed()) { response_data = reply->data(); } callback->Run(result, response_data); } void OlaClientCore::HandleAck(RpcController *controller_ptr, ola::proto::Ack *reply_ptr, SetCallback *callback) { auto_ptr controller(controller_ptr); auto_ptr reply(reply_ptr); if (!callback) { return; } Result result(controller->Failed() ? controller->ErrorText() : ""); callback->Run(result); } void OlaClientCore::HandleGeneralAck(RpcController *controller_ptr, ola::proto::Ack *reply_ptr, GeneralSetCallback *callback) { auto_ptr controller(controller_ptr); auto_ptr reply(reply_ptr); if (!callback) { return; } Result result(controller->Failed() ? controller->ErrorText() : ""); callback->Run(result); } void OlaClientCore::HandleUniverseList(RpcController *controller_ptr, ola::proto::UniverseInfoReply *reply_ptr, UniverseListCallback *callback) { auto_ptr controller(controller_ptr); auto_ptr reply(reply_ptr); if (!callback) { return; } Result result(controller->Failed() ? controller->ErrorText() : ""); vector ola_universes; if (!controller->Failed()) { for (int i = 0; i < reply->universe_size(); ++i) { ola::proto::UniverseInfo universe_info = reply->universe(i); ola_universes.push_back( ClientTypesFactory::UniverseFromProtobuf(universe_info)); } } callback->Run(result, ola_universes); } void OlaClientCore::HandleUniverseInfo(RpcController *controller_ptr, ola::proto::UniverseInfoReply *reply_ptr, UniverseInfoCallback *callback) { auto_ptr controller(controller_ptr); auto_ptr reply(reply_ptr); if (!callback) { return; } string error_str(controller->Failed() ? controller->ErrorText() : ""); OlaUniverse null_universe(0, OlaUniverse::MERGE_LTP, "", std::vector(), std::vector(), 0); if (!controller->Failed()) { if (reply->universe_size() == 1) { ola::proto::UniverseInfo universe_info = reply->universe(0); OlaUniverse universe = ClientTypesFactory::UniverseFromProtobuf(universe_info); Result result(error_str); callback->Run(result, universe); return; } else if (reply->universe_size() > 1) { error_str = "Too many universes in response"; } else { error_str = "Universe not found"; } } Result result(error_str); callback->Run(result, null_universe); } void OlaClientCore::HandleGetDmx(RpcController *controller_ptr, ola::proto::DmxData *reply_ptr, DMXCallback *callback) { auto_ptr controller(controller_ptr); auto_ptr reply(reply_ptr); if (!callback) { return; } Result result(controller->Failed() ? controller->ErrorText() : ""); DmxBuffer buffer; uint8_t priority = ola::dmx::SOURCE_PRIORITY_DEFAULT; if (!controller->Failed()) { buffer.Set(reply->data()); priority = reply->priority(); } DMXMetadata metadata(reply->universe(), priority); callback->Run(result, metadata, buffer); } void OlaClientCore::HandleUIDList(RpcController *controller_ptr, ola::proto::UIDListReply *reply_ptr, DiscoveryCallback *callback) { auto_ptr controller(controller_ptr); auto_ptr reply(reply_ptr); if (!callback) { return; } Result result(controller->Failed() ? controller->ErrorText() : ""); UIDSet uids; if (!controller->Failed()) { for (int i = 0; i < reply->uid_size(); ++i) { const ola::proto::UID &proto_uid = reply->uid(i); ola::rdm::UID uid(proto_uid.esta_id(), proto_uid.device_id()); uids.AddUID(uid); } } callback->Run(result, uids); } void OlaClientCore::HandleRDM(RpcController *controller_ptr, ola::proto::RDMResponse *reply_ptr, RDMCallback *callback) { auto_ptr controller(controller_ptr); auto_ptr reply(reply_ptr); if (!callback) { return; } Result result(controller->Failed() ? controller->ErrorText() : ""); RDMMetadata metadata; ola::rdm::RDMResponse *response = NULL; if (!controller->Failed()) { response = BuildRDMResponse(reply.get(), &metadata.response_code); for (int i = 0; i < reply->raw_frame_size(); i++) { const ola::proto::RDMFrame &proto_frame = reply->raw_frame(i); ola::rdm::RDMFrame frame( reinterpret_cast(proto_frame.raw_response().data()), proto_frame.raw_response().size()); frame.timing.response_time = proto_frame.timing().response_delay(); frame.timing.break_time = proto_frame.timing().break_time(); frame.timing.mark_time = proto_frame.timing().mark_time(); frame.timing.data_time = proto_frame.timing().data_time(); metadata.frames.push_back(frame); } } callback->Run(result, metadata, response); } void OlaClientCore::GenericFetchCandidatePorts( unsigned int universe_id, bool include_universe, CandidatePortsCallback *callback) { ola::proto::OptionalUniverseRequest request; RpcController *controller = new RpcController(); ola::proto::DeviceInfoReply *reply = new ola::proto::DeviceInfoReply(); if (include_universe) { request.set_universe(universe_id); } if (m_connected) { CompletionCallback *cb = NewSingleCallback( this, &OlaClientCore::HandleDeviceInfo, controller, reply, callback); m_stub->GetCandidatePorts(controller, &request, reply, cb); } else { controller->SetFailed(NOT_CONNECTED_ERROR); HandleDeviceInfo(controller, reply, callback); } } /* * Send a generic rdm command */ void OlaClientCore::SendRDMCommand(bool is_set, unsigned int universe, const UID &uid, uint16_t sub_device, uint16_t pid, const uint8_t *data, unsigned int data_length, const SendRDMArgs &args) { if (!args.callback) { OLA_WARN << "RDM callback was null, command to " << uid << " won't be sent"; return; } RpcController *controller = new RpcController(); ola::proto::RDMResponse *reply = new ola::proto::RDMResponse(); if (!m_connected) { controller->SetFailed(NOT_CONNECTED_ERROR); HandleRDM(controller, reply, args.callback); return; } ola::proto::RDMRequest request; request.set_universe(universe); ola::proto::UID *pb_uid = request.mutable_uid(); pb_uid->set_esta_id(uid.ManufacturerId()); pb_uid->set_device_id(uid.DeviceId()); request.set_sub_device(sub_device); request.set_param_id(pid); request.set_is_set(is_set); request.set_data(string(reinterpret_cast(data), data_length)); if (args.include_raw_frames) { request.set_include_raw_response(true); } CompletionCallback *cb = NewSingleCallback( this, &OlaClientCore::HandleRDM, controller, reply, args.callback); m_stub->RDMCommand(controller, &request, reply, cb); } /** * This constructs a ola::rdm::RDMResponse object from the information in a * ola::proto::RDMResponse. */ ola::rdm::RDMResponse *OlaClientCore::BuildRDMResponse( ola::proto::RDMResponse *reply, ola::rdm::RDMStatusCode *status_code) { // Get the response code, if it's not RDM_COMPLETED_OK don't bother with the // rest of the response data. *status_code = static_cast( reply->response_code()); if (*status_code != ola::rdm::RDM_COMPLETED_OK) { return NULL; } if (!reply->has_source_uid()) { OLA_WARN << "Missing source UID from RDMResponse"; return NULL; } ola::rdm::UID source_uid(reply->source_uid().esta_id(), reply->source_uid().device_id()); if (!reply->has_dest_uid()) { OLA_WARN << "Missing dest UID from RDMResponse"; return NULL; } ola::rdm::UID dest_uid(reply->dest_uid().esta_id(), reply->dest_uid().device_id()); if (!reply->has_transaction_number()) { OLA_WARN << "Missing transaction number from RDMResponse"; return NULL; } if (!reply->has_command_class()) { OLA_WARN << "Missing command_class from RDMResponse"; return NULL; } ola::rdm::RDMCommand::RDMCommandClass command_class = ola::rdm::RDMCommand::INVALID_COMMAND; switch (reply->command_class()) { case ola::proto::RDM_GET_RESPONSE : command_class = ola::rdm::RDMCommand::GET_COMMAND_RESPONSE; break; case ola::proto::RDM_SET_RESPONSE : command_class = ola::rdm::RDMCommand::SET_COMMAND_RESPONSE; break; default: OLA_WARN << "Unknown command class " << reply->command_class(); return NULL; } return new ola::rdm::RDMResponse( source_uid, dest_uid, reply->transaction_number(), reply->response_type(), reply->message_count(), reply->sub_device(), command_class, reply->param_id(), reinterpret_cast(reply->data().c_str()), reply->data().size()); } } // namespace client } // namespace ola ola-0.10.5.nojsmin/ola/ClientRDMAPIShim.cpp0000644000175000017500000001363713023355232017703 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * ClientRDMAPIShim.cpp * An implemention of RDMAPIImplInterface that uses the OlaClient. * Copyright (C) 2013 Simon Newton */ #include #include #include #include #include #include #include namespace ola { namespace client { using std::string; bool ClientRDMAPIShim::RDMGet(rdm_callback *callback, unsigned int universe, const ola::rdm::UID &uid, uint16_t sub_device, uint16_t pid, const uint8_t *data, unsigned int data_length) { SendRDMArgs args(NewSingleCallback( this, &ClientRDMAPIShim::HandleResponse, callback)); m_client->RDMGet(universe, uid, sub_device, pid, data, data_length, args); return true; } bool ClientRDMAPIShim::RDMGet(rdm_pid_callback *callback, unsigned int universe, const ola::rdm::UID &uid, uint16_t sub_device, uint16_t pid, const uint8_t *data, unsigned int data_length) { SendRDMArgs args(NewSingleCallback( this, &ClientRDMAPIShim::HandleResponseWithPid, callback)); m_client->RDMGet(universe, uid, sub_device, pid, data, data_length, args); return true; } bool ClientRDMAPIShim::RDMSet(rdm_callback *callback, unsigned int universe, const ola::rdm::UID &uid, uint16_t sub_device, uint16_t pid, const uint8_t *data, unsigned int data_length) { SendRDMArgs args(NewSingleCallback( this, &ClientRDMAPIShim::HandleResponse, callback)); m_client->RDMSet(universe, uid, sub_device, pid, data, data_length, args); return true; } void ClientRDMAPIShim::HandleResponse(rdm_callback *callback, const Result &result, const RDMMetadata &metadata, const ola::rdm::RDMResponse *response) { rdm::ResponseStatus response_status; string data; GetResponseStatusAndData(result, metadata.response_code, response, &response_status, &data); callback->Run(response_status, data); } void ClientRDMAPIShim::HandleResponseWithPid( rdm_pid_callback *callback, const Result &result, const RDMMetadata &metadata, const ola::rdm::RDMResponse *response) { rdm::ResponseStatus response_status; string data; GetResponseStatusAndData(result, metadata.response_code, response, &response_status, &data); callback->Run(response_status, response_status.pid_value, data); } void ClientRDMAPIShim::GetResponseStatusAndData( const Result &result, ola::rdm::RDMStatusCode status_code, const ola::rdm::RDMResponse *response, rdm::ResponseStatus *response_status, string *data) { response_status->error = result.Error(); response_status->response_code = ola::rdm::RDM_FAILED_TO_SEND; if (result.Success()) { response_status->response_code = status_code; if (status_code == ola::rdm::RDM_COMPLETED_OK && response) { response_status->response_type = response->PortIdResponseType(); response_status->message_count = response->MessageCount(); response_status->pid_value = response->ParamId(); response_status->set_command = ( response->CommandClass() == ola::rdm::RDMCommand::SET_COMMAND_RESPONSE ? true : false); switch (response->PortIdResponseType()) { case ola::rdm::RDM_ACK: data->append(reinterpret_cast(response->ParamData()), response->ParamDataSize()); break; case ola::rdm::RDM_ACK_TIMER: GetParamFromReply("ack timer", response, response_status); break; case ola::rdm::RDM_NACK_REASON: GetParamFromReply("nack", response, response_status); break; default: OLA_WARN << "Invalid response type 0x" << std::hex << static_cast(response->PortIdResponseType()); response_status->response_type = ola::rdm::RDM_INVALID_RESPONSE; } } } } /** * Extract the uint16_t param for a ACK TIMER or NACK message and add it to the * ResponseStatus. */ void ClientRDMAPIShim::GetParamFromReply(const string &message_type, const ola::rdm::RDMResponse *response, ola::rdm::ResponseStatus *new_status) { uint16_t param; if (response->ParamDataSize() != sizeof(param)) { OLA_WARN << "Invalid PDL size for " << message_type << ", length was " << response->ParamDataSize(); new_status->response_type = ola::rdm::RDM_INVALID_RESPONSE; } else { memcpy(¶m, response->ParamData(), sizeof(param)); new_status->m_param = ola::network::NetworkToHost(param); } } } // namespace client } // namespace ola ola-0.10.5.nojsmin/ola/StreamingClientTest.cpp0000644000175000017500000001231213023355232020664 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * StreamingClientTest.cpp * Test fixture for the StreamingClient class * Copyright (C) 2005 Simon Newton */ #include #include #include #include "ola/DmxBuffer.h" #include "ola/Logging.h" #include "ola/StreamingClient.h" #include "ola/base/Flags.h" #include "ola/network/SocketAddress.h" #include "ola/testing/TestUtils.h" #include "ola/thread/Thread.h" #include "olad/OlaDaemon.h" DECLARE_uint16(rpc_port); static unsigned int TEST_UNIVERSE = 1; using ola::OlaDaemon; using ola::StreamingClient; using ola::network::GenericSocketAddress; using ola::thread::ConditionVariable; using ola::thread::Mutex; using std::auto_ptr; class StreamingClientTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(StreamingClientTest); CPPUNIT_TEST(testSendDMX); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void tearDown(); void testSendDMX(); private: class OlaServerThread *m_server_thread; }; CPPUNIT_TEST_SUITE_REGISTRATION(StreamingClientTest); /* * The thread that the OlaServer runs in. */ class OlaServerThread: public ola::thread::Thread { public: OlaServerThread() : Thread(), m_is_running(false) { } ~OlaServerThread() {} bool Setup(); void *Run(); void Terminate(); void WaitForStart(); GenericSocketAddress RPCAddress() const; private: auto_ptr m_olad; bool m_is_running; Mutex m_mutex; ConditionVariable m_condition; void MarkAsStarted(); }; bool OlaServerThread::Setup() { FLAGS_rpc_port = 0; // pick an unused port ola::OlaServer::Options ola_options; ola_options.http_enable = false; ola_options.http_localhost_only = false; ola_options.http_enable_quit = false; ola_options.http_port = 0; ola_options.http_data_dir = ""; // pick an unused port auto_ptr olad(new OlaDaemon(ola_options, NULL)); if (olad->Init()) { m_olad.reset(olad.release()); return true; } else { return false; } } /* * Run the ola Server */ void *OlaServerThread::Run() { if (m_olad.get()) { m_olad->GetSelectServer()->Execute( ola::NewSingleCallback(this, &OlaServerThread::MarkAsStarted)); m_olad->Run(); m_olad->Shutdown(); } return NULL; } /* * Stop the OLA server */ void OlaServerThread::Terminate() { if (m_olad.get()) { m_olad->GetSelectServer()->Terminate(); } } /** * Block until the OLA Server is running */ void OlaServerThread::WaitForStart() { m_mutex.Lock(); if (!m_is_running) { m_condition.Wait(&m_mutex); } m_mutex.Unlock(); } void OlaServerThread::MarkAsStarted() { m_mutex.Lock(); m_is_running = true; m_mutex.Unlock(); m_condition.Signal(); } GenericSocketAddress OlaServerThread::RPCAddress() const { if (m_olad.get()) { return m_olad->RPCAddress(); } return GenericSocketAddress(); } /* * Startup the Ola server */ void StreamingClientTest::setUp() { ola::InitLogging(ola::OLA_LOG_INFO, ola::OLA_LOG_STDERR); m_server_thread = new OlaServerThread(); if (m_server_thread->Setup()) { m_server_thread->Start(); } else { CPPUNIT_FAIL("Failed to setup OlaDaemon"); } } /* * Stop the ola Server */ void StreamingClientTest::tearDown() { m_server_thread->Terminate(); m_server_thread->Join(); delete m_server_thread; } /* * Check that the SendDMX method works correctly. */ void StreamingClientTest::testSendDMX() { m_server_thread->WaitForStart(); GenericSocketAddress server_address = m_server_thread->RPCAddress(); OLA_ASSERT_EQ(static_cast(AF_INET), server_address.Family()); StreamingClient::Options options; options.auto_start = false; options.server_port = server_address.V4Addr().Port(); StreamingClient ola_client(options); ola::DmxBuffer buffer; buffer.Blackout(); // Setup the client, this connects to the server OLA_ASSERT_TRUE(ola_client.Setup()); // Try it again to make sure it doesn't break OLA_ASSERT_FALSE(ola_client.Setup()); OLA_ASSERT_TRUE(ola_client.SendDmx(TEST_UNIVERSE, buffer)); ola_client.Stop(); // Now reconnect OLA_ASSERT_TRUE(ola_client.Setup()); OLA_ASSERT_TRUE(ola_client.SendDmx(TEST_UNIVERSE, buffer)); ola_client.Stop(); // Now Terminate the server mid flight OLA_ASSERT_TRUE(ola_client.Setup()); OLA_ASSERT_TRUE(ola_client.SendDmx(TEST_UNIVERSE, buffer)); m_server_thread->Terminate(); m_server_thread->Join(); OLA_ASSERT_FALSE(ola_client.SendDmx(TEST_UNIVERSE, buffer)); ola_client.Stop(); OLA_ASSERT_FALSE(ola_client.Setup()); } ola-0.10.5.nojsmin/ola/OlaClientWrapper.cpp0000644000175000017500000000352113023355232020151 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * OlaClientWrapper.cpp * Implementation of the OLA Client * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include namespace ola { namespace client { BaseClientWrapper::BaseClientWrapper() : m_close_callback(NewCallback(&m_ss, &ola::io::SelectServer::Terminate)) { } BaseClientWrapper::~BaseClientWrapper() { Cleanup(); } void BaseClientWrapper::SetCloseCallback(CloseCallback *callback) { m_close_callback.reset(callback); } bool BaseClientWrapper::Setup() { if (!m_socket.get()) { InitSocket(); if (!m_socket.get()) { return false; } } CreateClient(); if (!m_ss.AddReadDescriptor(m_socket.get())) { return false; } return StartupClient(); } bool BaseClientWrapper::Cleanup() { if (m_socket.get()) { m_socket->Close(); m_socket.reset(); } return true; } void BaseClientWrapper::SocketClosed() { OLA_INFO << "Server closed the connection"; m_close_callback->Run(); } } // namespace client } // namespace ola ola-0.10.5.nojsmin/ola/Module.cpp0000644000175000017500000000303313023355232016161 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Module.cpp * Contains the information required to load the StreamingClient as a plugin. * Copyright (C) 2014 Simon Newton */ #include #include #include extern "C" { ola::client::StreamingClientInterface *ola_new_streaming_client( const ola::client::StreamingClient::Options &options) { return new ola::client::StreamingClient(options); } void ola_delete_streaming_client( ola::client::StreamingClientInterface *client) { delete client; } ola::DmxBuffer *ola_new_dmxbuffer() { return new ola::DmxBuffer(); } void ola_delete_dmxbuffer(ola::DmxBuffer *buffer) { delete buffer; } void ola_set_dmxbuffer(ola::DmxBuffer *buffer, const uint8_t *data, unsigned int size) { buffer->Set(data, size); } } ola-0.10.5.nojsmin/ola/StreamingClient.h0000644000175000017500000000225513023355232017476 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * StreamingClient.h * Implementation of Streaming Client * Copyright (C) 2005 Simon Newton */ #ifndef OLA_STREAMINGCLIENT_H_ #define OLA_STREAMINGCLIENT_H_ #include /** * @file * @brief * @deprecated Include instead. */ namespace ola { // For backwards compatability: typedef ola::client::StreamingClient StreamingClient; } // namespace ola #endif // OLA_STREAMINGCLIENT_H_ ola-0.10.5.nojsmin/ola/AutoStart.cpp0000644000175000017500000000710113134123277016667 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * AutoStart.cpp * Connects to the ola server, starting it if it's not already running. * Copyright (C) 2010 Simon Newton */ #include #include #include #ifdef _WIN32 #define VC_EXTRALEAN #include #include #else #include #include #endif // _WIN32 #include #include #include #include namespace ola { namespace client { using ola::network::TCPSocket; /* * Open a connection to the server. */ TCPSocket *ConnectToServer(unsigned short port) { ola::network::IPV4SocketAddress server_address( ola::network::IPV4Address::Loopback(), port); TCPSocket *socket = TCPSocket::Connect(server_address); if (socket) return socket; OLA_INFO << "Attempting to start olad"; #ifdef _WIN32 // On Windows, olad is not (yet) available as a service, so we just launch // it as a normal process STARTUPINFO startup_info; PROCESS_INFORMATION process_information; memset(&startup_info, 0, sizeof(startup_info)); startup_info.cb = sizeof(startup_info); memset(&process_information, 0, sizeof(process_information)); // On unicode systems, cmd_line may be modified by CreateProcess, so we need // to create a copy TCHAR* cmd_line = _tcsdup(TEXT("olad --syslog")); if (!CreateProcess(NULL, cmd_line, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &startup_info, &process_information)) { OLA_WARN << "Could not launch olad " << GetLastError(); _exit(1); } // Don't leak the handles CloseHandle(process_information.hProcess); CloseHandle(process_information.hThread); free(cmd_line); // wait a bit here for the server to come up. Sleep time is in milliseconds. Sleep(1000); #else pid_t pid = fork(); if (pid < 0) { OLA_WARN << "Could not fork: " << strerror(errno); return NULL; } else if (pid == 0) { // fork again so the parent can call waitpid immediately. pid_t pid = fork(); if (pid < 0) { OLA_WARN << "Could not fork: " << strerror(errno); _exit(1); } else if (pid > 0) { _exit(0); } // Try to start the server, we pass --daemon (fork into background) and // --syslog (log to syslog). execlp("olad", "olad", "--daemon", "--syslog", reinterpret_cast(NULL)); OLA_WARN << "Failed to exec: " << strerror(errno); _exit(1); } if (waitpid(pid, NULL, 0) != pid) OLA_WARN << "waitpid error: " << strerror(errno); // wait a bit here for the server to come up sleep(1); #endif // _WIN32 return TCPSocket::Connect(server_address); } } // namespace client } // namespace ola ola-0.10.5.nojsmin/ola/OlaClientWrapperTest.cpp0000644000175000017500000000406013023355232021010 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * OlaClientWrapperTest.cpp * Basic test fixture for the OlaClientWrapper class * Copyright (C) 2016 Peter Newman */ #include #include #include #include "ola/client/ClientWrapper.h" #include "ola/testing/TestUtils.h" using ola::client::OlaClientWrapper; class OlaClientWrapperTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(OlaClientWrapperTest); CPPUNIT_TEST(testNoAutoStartNoOlad); CPPUNIT_TEST_SUITE_END(); public: void testNoAutoStartNoOlad(); }; CPPUNIT_TEST_SUITE_REGISTRATION(OlaClientWrapperTest); /* * Check that the client works correctly with no auto start and without olad * running. */ void OlaClientWrapperTest::testNoAutoStartNoOlad() { // Setup the client OlaClientWrapper ola_client(false); // Setup the client, this tried to connect to the server OLA_ASSERT_FALSE_MSG(ola_client.Setup(), "Check for another instance of olad running"); // Try it again to make sure it still fails OLA_ASSERT_FALSE_MSG(ola_client.Setup(), "Check for another instance of olad running"); // This should be a NOOP OLA_ASSERT_TRUE(ola_client.Cleanup()); // Try for a third time to start OLA_ASSERT_FALSE_MSG(ola_client.Setup(), "Check for another instance of olad running"); } ola-0.10.5.nojsmin/ola/OlaCallbackClient.h0000644000175000017500000002737613023355232017710 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * OlaCallbackClient.h * The legacy callback client. * Copyright (C) 2010 Simon Newton */ #ifndef OLA_OLACALLBACKCLIENT_H_ #define OLA_OLACALLBACKCLIENT_H_ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /** * @file * @brief * @deprecated Include instead. */ namespace ola { namespace client { class OlaClientCore; } enum PatchAction {PATCH, UNPATCH}; enum RegisterAction {REGISTER, UNREGISTER}; enum PortDirection {INPUT_PORT, OUTPUT_PORT}; /** * @brief The legacy callback client. * @deprecated Use ola::client::OlaClient instead. */ class OlaCallbackClient: public ola::rdm::RDMAPIImplInterface { public: struct PluginState { std::string name; bool enabled; bool active; std::string preferences_source; std::vector conflicting_plugins; }; typedef SingleUseCallback2 PluginStateCallback; typedef Callback3 DMXCallback; typedef Callback4 DMXCallbackWithPriority; explicit OlaCallbackClient(ola::io::ConnectedDescriptor *descriptor); ~OlaCallbackClient(); bool Setup(); bool Stop(); void SetCloseHandler(ola::SingleUseCallback0 *callback); // plugin methods bool FetchPluginList( SingleUseCallback2&, const std::string&> *callback); bool FetchPluginDescription( ola_plugin_id plugin_id, SingleUseCallback2 *callback); bool FetchPluginState(ola_plugin_id plugin_id, PluginStateCallback *callback); // device methods bool FetchDeviceInfo( ola_plugin_id filter, SingleUseCallback2&, const std::string&> *callback); bool FetchCandidatePorts( unsigned int universe_id, SingleUseCallback2&, const std::string&> *callback); bool FetchCandidatePorts( SingleUseCallback2&, const std::string&> *callback); bool ConfigureDevice( unsigned int device_alias, const std::string &msg, SingleUseCallback2 *callback); // port methods bool SetPortPriorityInherit( unsigned int device_alias, unsigned int port, PortDirection port_direction, SingleUseCallback1 *callback); bool SetPortPriorityOverride( unsigned int device_alias, unsigned int port, PortDirection port_direction, uint8_t value, SingleUseCallback1 *callback); // universe methods bool FetchUniverseList( SingleUseCallback2&, const std::string &> *callback); bool FetchUniverseInfo( unsigned int universe, SingleUseCallback2 *callback); bool SetUniverseName( unsigned int uni, const std::string &name, SingleUseCallback1 *callback); bool SetUniverseMergeMode( unsigned int uni, OlaUniverse::merge_mode mode, SingleUseCallback1 *callback); // patching bool Patch( unsigned int device_alias, unsigned int port, ola::PortDirection port_direction, ola::PatchAction action, unsigned int uni, SingleUseCallback1 *callback); // DMX methods void SetDmxCallback( Callback3 *callback); // Similar to above, but this also passes the source priority. void SetDmxCallback( Callback4 *callback); bool RegisterUniverse( unsigned int universe, ola::RegisterAction register_action, SingleUseCallback1 *callback); bool SendDmx( unsigned int universe, const DmxBuffer &data, SingleUseCallback1 *callback); bool SendDmx( unsigned int universe, const DmxBuffer &data, Callback1 *callback); // A version of SendDmx that doesn't wait for confirmation bool SendDmx(unsigned int universe, const DmxBuffer &data); bool FetchDmx( unsigned int universe, SingleUseCallback2 *callback); // rdm methods bool FetchUIDList( unsigned int universe, SingleUseCallback2 *callback); bool RunDiscovery( unsigned int universe, bool full, ola::SingleUseCallback2 *callback); bool SetSourceUID(const ola::rdm::UID &uid, ola::SingleUseCallback1 *callback); bool RDMGet(ola::rdm::RDMAPIImplInterface::rdm_callback *callback, unsigned int universe, const ola::rdm::UID &uid, uint16_t sub_device, uint16_t pid, const uint8_t *data, unsigned int data_length); bool RDMGet(ola::rdm::RDMAPIImplInterface::rdm_pid_callback *callback, unsigned int universe, const ola::rdm::UID &uid, uint16_t sub_device, uint16_t pid, const uint8_t *data, unsigned int data_length); bool RDMSet(ola::rdm::RDMAPIImplInterface::rdm_callback *callback, unsigned int universe, const ola::rdm::UID &uid, uint16_t sub_device, uint16_t pid, const uint8_t *data, unsigned int data_length); bool RDMSet(ola::rdm::RDMAPIImplInterface::rdm_pid_callback *callback, unsigned int universe, const ola::rdm::UID &uid, uint16_t sub_device, uint16_t pid, const uint8_t *data, unsigned int data_length); // timecode bool SendTimeCode(ola::SingleUseCallback1 *callback, const ola::timecode::TimeCode &timecode); private: std::auto_ptr m_core; std::auto_ptr m_dmx_callback; std::auto_ptr m_priority_dmx_callback; void HandlePluginList( SingleUseCallback2&, const std::string&> *callback, const client::Result &result, const std::vector &plugins); void HandlePluginDescription( SingleUseCallback2 *callback, const client::Result &result, const std::string &description); void HandlePluginState( PluginStateCallback *callback, const client::Result &result, const client::PluginState &state); void HandleDeviceInfo( SingleUseCallback2&, const std::string&> *callback, const client::Result &result, const std::vector &devices); void HandleConfigureDevice( SingleUseCallback2 *callback, const client::Result &result, const std::string &reply); void HandleUniverseList( SingleUseCallback2&, const std::string &> *callback, const client::Result &result, const std::vector &universes); void HandleUniverseInfo( SingleUseCallback2 *callback, const client::Result &result, const OlaUniverse &universe); void HandleFetchDmx( SingleUseCallback2 *callback, const client::Result &result, const client::DMXMetadata &metadata, const DmxBuffer &data); void HandleDiscovery( ola::SingleUseCallback2 *callback, const client::Result &result, const ola::rdm::UIDSet &uids); void HandleSetCallback( ola::SingleUseCallback1 *callback, const client::Result &result); void HandleRepeatableSetCallback( ola::Callback1 *callback, const client::Result &result); void HandleDMX(const client::DMXMetadata &metadata, const DmxBuffer &data); void HandleRDMResponse( ola::rdm::RDMAPIImplInterface::rdm_callback *callback, const client::Result &result, const client::RDMMetadata &metadata, const ola::rdm::RDMResponse *response); void HandleRDMResponseWithPid( ola::rdm::RDMAPIImplInterface::rdm_pid_callback *callback, const client::Result &result, const client::RDMMetadata &metadata, const ola::rdm::RDMResponse *response); void GetResponseStatusAndData( const client::Result &result, ola::rdm::rdm_response_code response_code, const ola::rdm::RDMResponse *response, rdm::ResponseStatus *response_status, std::string *data); void GetParamFromReply( const std::string &message_type, const ola::rdm::RDMResponse *response, ola::rdm::ResponseStatus *new_status); DISALLOW_COPY_AND_ASSIGN(OlaCallbackClient); }; } // namespace ola #endif // OLA_OLACALLBACKCLIENT_H_ ola-0.10.5.nojsmin/ola/StreamingClient.cpp0000644000175000017500000001107513023355232020031 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * StreamingClient.cpp * Implementation of Streaming Client * Copyright (C) 2005 Simon Newton */ #include // NOLINT(build/include) // ola/StreamingClient.h deprecated #include #include #include #include #include #include #include #include #include #include "common/protocol/Ola.pb.h" #include "common/protocol/OlaService.pb.h" #include "common/rpc/RpcChannel.h" #include "common/rpc/RpcSession.h" namespace ola { namespace client { using ola::io::SelectServer; using ola::network::TCPSocket; using ola::proto::OlaServerService_Stub; using ola::rpc::RpcChannel; StreamingClient::StreamingClient(bool auto_start) : m_auto_start(auto_start), m_server_port(OLA_DEFAULT_PORT), m_socket(NULL), m_ss(NULL), m_channel(NULL), m_stub(NULL), m_socket_closed(false) { } StreamingClient::StreamingClient(const Options &options) : m_auto_start(options.auto_start), m_server_port(options.server_port), m_socket(NULL), m_ss(NULL), m_channel(NULL), m_stub(NULL), m_socket_closed(false) { } StreamingClient::~StreamingClient() { Stop(); } bool StreamingClient::Setup() { if (m_socket || m_channel || m_stub) return false; if (m_auto_start) m_socket = ola::client::ConnectToServer(m_server_port); else m_socket = TCPSocket::Connect( ola::network::IPV4SocketAddress(ola::network::IPV4Address::Loopback(), m_server_port)); if (!m_socket) return false; m_ss = new SelectServer(); m_ss->AddReadDescriptor(m_socket); m_channel = new RpcChannel(NULL, m_socket); if (!m_channel) { delete m_socket; m_socket = NULL; return false; } m_stub = new OlaServerService_Stub(m_channel); if (!m_stub) { delete m_channel; delete m_socket; m_channel = NULL; m_socket = NULL; return false; } m_channel->SetChannelCloseHandler( NewSingleCallback(this, &StreamingClient::ChannelClosed)); return true; } void StreamingClient::Stop() { if (m_stub) delete m_stub; if (m_channel) delete m_channel; if (m_ss) delete m_ss; if (m_socket) delete m_socket; m_channel = NULL; m_socket = NULL; m_ss = NULL; m_stub = NULL; } bool StreamingClient::SendDmx(unsigned int universe, const DmxBuffer &data) { return Send(universe, ola::dmx::SOURCE_PRIORITY_DEFAULT, data); } bool StreamingClient::SendDMX(unsigned int universe, const DmxBuffer &data, const SendArgs &args) { return Send(universe, args.priority, data); } bool StreamingClient::Send(unsigned int universe, uint8_t priority, const DmxBuffer &data) { if (!m_stub || !m_socket->ValidReadDescriptor()) return false; // We select() on the fd here to see if the remove end has closed the // connection. We could skip this and rely on the EPIPE delivered by the // write() below, but that introduces a race condition in the unittests. m_socket_closed = false; m_ss->RunOnce(); if (m_socket_closed) { Stop(); return false; } ola::proto::DmxData request; request.set_universe(universe); request.set_data(data.Get()); request.set_priority(priority); m_stub->StreamDmxData(NULL, &request, NULL, NULL); if (m_socket_closed) { Stop(); return false; } return true; } void StreamingClient::ChannelClosed(OLA_UNUSED ola::rpc::RpcSession *session) { m_socket_closed = true; OLA_WARN << "The RPC socket has been closed, this is more than likely due" << " to a framing error, perhaps you're sending too fast?"; } } // namespace client } // namespace ola ola-0.10.5.nojsmin/ola/OlaDevice.h0000644000175000017500000000254713023355232016245 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * OlaDevice.h * Interface to the OLA Client Device class * Copyright (C) 2005 Simon Newton */ #ifndef OLA_OLADEVICE_H_ #define OLA_OLADEVICE_H_ #include /** * @file * @brief * @deprecated Include instead. */ namespace ola { // For backwards compatability: typedef ola::client::OlaDevice OlaDevice; typedef ola::client::OlaInputPort OlaInputPort; typedef ola::client::OlaOutputPort OlaOutputPort; typedef ola::client::OlaPlugin OlaPlugin; typedef ola::client::OlaPort OlaPort; typedef ola::client::OlaUniverse OlaUniverse; } // namespace ola #endif // OLA_OLADEVICE_H_ ola-0.10.5.nojsmin/ola/OlaClientCore.h0000644000175000017500000003703113023355232017071 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * OlaClientCore.h * The OLA Client Core class * Copyright (C) 2005 Simon Newton */ #ifndef OLA_OLACLIENTCORE_H_ #define OLA_OLACLIENTCORE_H_ #include #include #include "common/protocol/Ola.pb.h" #include "common/protocol/OlaService.pb.h" #include "common/rpc/RpcChannel.h" #include "common/rpc/RpcController.h" #include "ola/Callback.h" #include "ola/DmxBuffer.h" #include "ola/client/CallbackTypes.h" #include "ola/client/ClientArgs.h" #include "ola/client/ClientTypes.h" #include "ola/base/Macro.h" #include "ola/dmx/SourcePriorities.h" #include "ola/io/Descriptor.h" #include "ola/plugin_id.h" #include "ola/rdm/UID.h" #include "ola/rdm/UIDSet.h" #include "ola/timecode/TimeCode.h" namespace ola { namespace rpc { class RpcSession; } namespace client { /** * @brief The low level C++ API to olad. * Clients shouldn't use this directly. Instead use ola::client::OlaClient. */ class OlaClientCore: public ola::proto::OlaClientService { public: typedef ola::SingleUseCallback0 ClosedCallback; explicit OlaClientCore(ola::io::ConnectedDescriptor *descriptor); ~OlaClientCore(); bool Setup(); bool Stop(); void SetCloseHandler(ClosedCallback *callback); /** * @brief Set the callback to be run when new DMX data arrives. * The DMX callback will be run when new data arrives for universes that * have been registered with RegisterUniverse(). Ownership of the callback * is transferred to the OlaClientCore. * @param callback the callback to run upon receiving new DMX data. */ void SetDMXCallback(RepeatableDMXCallback *callback); /** * @brief Trigger a plugin reload. * @param callback the SetCallback to invoke upon completion. */ void ReloadPlugins(SetCallback *callback); /** * @brief Fetch the list of plugins loaded. * @param callback the PluginListCallback to be invoked upon completion. */ void FetchPluginList(PluginListCallback *callback); /** * @brief Fetch the description for a plugin. * @param plugin_id the id of the plugin to fetch the state for. * @param callback the PluginDescriptionCallback to be invoked upon * completion. */ void FetchPluginDescription(ola_plugin_id plugin_id, PluginDescriptionCallback *callback); /** * @brief Fetch the state of a plugin. This returns the state and the list * of plugins this plugin conflicts with. * @param plugin_id the id of the plugin to fetch the state for. * @param callback the PluginStateCallback to be invoked upon completion. */ void FetchPluginState(ola_plugin_id plugin_id, PluginStateCallback *callback); /** * @brief Request a list of the available devices. * @param plugin_filter only fetch devices that belong to the specified * plugin. * @param callback the DeviceInfoCallback to be invoked upon completion. */ void FetchDeviceInfo(ola_plugin_id plugin_filter, DeviceInfoCallback *callback); /** * Request a list of ports that could be patched to new universe. * @param callback the CandidatePortsCallback invoked upon completion. */ void FetchCandidatePorts(CandidatePortsCallback *callback); /** * @brief Request a list of ports that could be patched to a particular * universe. * @param universe_id the id of the universe to fetch the candidate ports * for. * @param callback the CandidatePortsCallback invoked upon completion. */ void FetchCandidatePorts(unsigned int universe_id, CandidatePortsCallback *callback); /** * @brief Send a device config request. * @param device_alias the device alias of the device to configure. * @param msg the blob of data to send to the device. * @param callback the ConfigureDeviceCallback invoked upon completion. */ void ConfigureDevice(unsigned int device_alias, const std::string &msg, ConfigureDeviceCallback *callback); /** * @brief Set the state of a plugin. * @param plugin_id the plugin whose state you want to change * @param state the state to change to. * @param callback the SetCallback to invoke upon completion. */ void SetPluginState(ola_plugin_id plugin_id, bool state, SetCallback *callback); /** * @brief Set the priority for a port to inherit mode. * @param device_alias the device containing the port to change * @param port the port id of the port to change. * @param port_direction the direction of the port. * @param callback the SetCallback to invoke upon completion. */ void SetPortPriorityInherit(unsigned int device_alias, unsigned int port, PortDirection port_direction, SetCallback *callback); /** * @brief Set the priority for a port to override mode * @param device_alias the device containing the port to change * @param port the port id of the port to change. * @param port_direction the direction of the port. * @param value the new port priority value. * @param callback the SetCallback to invoke upon completion. */ void SetPortPriorityOverride(unsigned int device_alias, unsigned int port, PortDirection port_direction, uint8_t value, SetCallback *callback); /** * @brief Request a list of universes. * @param callback the UniverseListCallback to invoke upon completion. */ void FetchUniverseList(UniverseListCallback *callback); /** * @brief Fetch the information for a given universe. * @param universe the id of the universe. * @param callback the UniverseInfoCallback to invoke upon completion. */ void FetchUniverseInfo(unsigned int universe, UniverseInfoCallback *callback); /** * @brief Set the name of a universe. * @param universe the id of the universe * @param name the new name to use. * @param callback the SetCallback to invoke upon completion. */ void SetUniverseName(unsigned int universe, const std::string &name, SetCallback *callback); /** * @brief Set the merge mode of a universe. * @param universe the id of the universe * @param mode the new merge mode * @param callback the SetCallback to invoke upon completion. */ void SetUniverseMergeMode(unsigned int universe, OlaUniverse::merge_mode mode, SetCallback *callback); /** * @brief Patch or unpatch a port from a universe. * @param device_alias the device containing the port to change * @param port the port id of the port to change. * @param port_direction the direction of the port. * @param action OlaClientCore::PATCH or OlaClientCore::UNPATCH. * @param universe universe id to patch the port to. * @param callback the SetCallback to invoke upon completion. */ void Patch(unsigned int device_alias, unsigned int port, PortDirection port_direction, PatchAction action, unsigned int universe, SetCallback *callback); /** * @brief Register our interest in a universe. The callback set by * SetDMXCallback() will be called when new DMX data arrives. * @param universe the id of the universe to register for. * @param register_action the action (register or unregister) * @param callback the SetCallback to invoke upon completion. */ void RegisterUniverse(unsigned int universe, RegisterAction register_action, SetCallback *callback); /** * @brief Send DMX data. * @param universe the universe to send to. * @param data the DmxBuffer with the data * @param args the SendDMXArgs to use for this call. */ void SendDMX(unsigned int universe, const DmxBuffer &data, const SendDMXArgs &args); /** * @brief Fetch the latest DMX data for a universe. * @param universe the universe id to get data for. * @param callback the SetCallback to invoke upon completion. */ void FetchDMX(unsigned int universe, DMXCallback *callback); /** * @brief Trigger discovery for a universe. * @param universe the universe id to run discovery on. * @param discovery_type the type of discovery to run before returning. * @param callback the UIDListCallback to invoke upon completion. */ void RunDiscovery(unsigned int universe, DiscoveryType discovery_type, DiscoveryCallback *callback); /** * @brief Set the source UID for this client. * @param uid the UID to use when sending RDM messages from this client. * @param callback the SetCallback to invoke upon completion. */ void SetSourceUID(const ola::rdm::UID &uid, SetCallback *callback); /** * @brief Send an RDM Get Command. * @param universe the universe to send the command on * @param uid the UID to send the command to * @param sub_device the sub device index * @param pid the PID to address * @param data the optional data to send * @param data_length the length of the data * @param args the RDM arguments which includes the callback to run. */ void RDMGet(unsigned int universe, const ola::rdm::UID &uid, uint16_t sub_device, uint16_t pid, const uint8_t *data, unsigned int data_length, const SendRDMArgs& args); /** * @brief Send an RDM Set Command. * @param universe the universe to send the command on * @param uid the UID to send the command to * @param sub_device the sub device index * @param pid the PID to address * @param data the optional data to send * @param data_length the length of the data * @param args the RDM arguments which includes the callback to run. */ void RDMSet(unsigned int universe, const ola::rdm::UID &uid, uint16_t sub_device, uint16_t pid, const uint8_t *data, unsigned int data_length, const SendRDMArgs& args); /** * @brief Send TimeCode data. * @param timecode The timecode data. * @param callback the SetCallback to invoke when the send completes. */ void SendTimeCode(const ola::timecode::TimeCode &timecode, SetCallback *callback); /** * @brief This is called by the channel when new DMX data arrives. */ void UpdateDmxData(ola::rpc::RpcController* controller, const ola::proto::DmxData* request, ola::proto::Ack* response, CompletionCallback* done); private: ola::io::ConnectedDescriptor *m_descriptor; std::auto_ptr m_dmx_callback; std::auto_ptr m_channel; std::auto_ptr m_stub; int m_connected; void ChannelClosed(ClosedCallback *callback, ola::rpc::RpcSession *session); /** * @brief Called when GetPlugins() completes. */ void HandlePluginList(ola::rpc::RpcController *controller_ptr, ola::proto::PluginListReply *reply_ptr, PluginListCallback *callback); /** * @brief Called when GetPluginDescription() completes. */ void HandlePluginDescription(ola::rpc::RpcController *controller, ola::proto::PluginDescriptionReply *reply, PluginDescriptionCallback *callback); /** * @brief Called when GetPluginState() completes. */ void HandlePluginState(ola::rpc::RpcController *controller, ola::proto::PluginStateReply *reply, PluginStateCallback *callback); /** * @brief Called when GetDeviceInfo() completes. */ void HandleDeviceInfo(ola::rpc::RpcController *controller, ola::proto::DeviceInfoReply *reply, DeviceInfoCallback *callback); /** * @brief Called when ConfigureDevice() completes. */ void HandleDeviceConfig(ola::rpc::RpcController *controller, ola::proto::DeviceConfigReply *reply, ConfigureDeviceCallback *callback); /** * @brief Called when a Set* request completes. */ void HandleAck(ola::rpc::RpcController *controller, ola::proto::Ack *reply, SetCallback *callback); /** * @brief Called when a Set* request completes. */ void HandleGeneralAck(ola::rpc::RpcController *controller, ola::proto::Ack *reply, GeneralSetCallback *callback); /** * @brief Called when a GetUniverseInfo() request completes. */ void HandleUniverseList(ola::rpc::RpcController *controller, ola::proto::UniverseInfoReply *reply, UniverseListCallback *callback); /** * @brief Called when a GetUniverseInfo() request completes. */ void HandleUniverseInfo(ola::rpc::RpcController *controller, ola::proto::UniverseInfoReply *reply, UniverseInfoCallback *callback); /** * @brief Called when a GetDmx() request completes. */ void HandleGetDmx(ola::rpc::RpcController *controller, ola::proto::DmxData *reply, DMXCallback *callback); /** * @brief Called when a RunDiscovery() request completes. */ void HandleUIDList(ola::rpc::RpcController *controller_ptr, ola::proto::UIDListReply *reply_ptr, DiscoveryCallback *callback); /** * @brief Called when a RDM request completes. */ void HandleRDM(ola::rpc::RpcController *controller, ola::proto::RDMResponse *reply, RDMCallback *callback); /** * @brief Fetch a list of candidate ports, with or without a universe */ void GenericFetchCandidatePorts(unsigned int universe_id, bool include_universe, CandidatePortsCallback *callback); /** * @brief Sends a RDM command to the server. */ void SendRDMCommand(bool is_set, unsigned int universe, const ola::rdm::UID &uid, uint16_t sub_device, uint16_t pid, const uint8_t *data, unsigned int data_length, const SendRDMArgs &args); /** * @brief Builds a RDMResponse from the server's RDM reply message. */ ola::rdm::RDMResponse *BuildRDMResponse( ola::proto::RDMResponse *reply, ola::rdm::RDMStatusCode *status_code); static const char NOT_CONNECTED_ERROR[]; DISALLOW_COPY_AND_ASSIGN(OlaClientCore); }; } // namespace client } // namespace ola #endif // OLA_OLACLIENTCORE_H_ ola-0.10.5.nojsmin/ola/OlaClient.cpp0000644000175000017500000001565313023355232016621 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * OlaClient.cpp * Implementation of OlaClient * Copyright (C) 2010 Simon Newton */ #include "ola/client/OlaClient.h" #include #include #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/OlaClientCore.h" #include "ola/OlaDevice.h" #include "ola/rdm/RDMAPI.h" #include "ola/rdm/RDMAPIImplInterface.h" #include "ola/rdm/RDMEnums.h" namespace ola { namespace client { using std::string; using std::vector; using ola::rdm::RDMAPIImplInterface; using ola::io::ConnectedDescriptor; OlaClient::OlaClient(ConnectedDescriptor *descriptor) : m_core(new OlaClientCore(descriptor)) { } OlaClient::~OlaClient() { } bool OlaClient::Setup() { return m_core->Setup(); } bool OlaClient::Stop() { return m_core->Stop(); } void OlaClient::SetCloseHandler(ola::SingleUseCallback0 *callback) { m_core->SetCloseHandler(callback); } void OlaClient::SetDMXCallback(RepeatableDMXCallback *callback) { m_core->SetDMXCallback(callback); } void OlaClient::ReloadPlugins(SetCallback *callback) { m_core->ReloadPlugins(callback); } void OlaClient::FetchPluginList(PluginListCallback *callback) { m_core->FetchPluginList(callback); } void OlaClient::FetchPluginDescription(ola_plugin_id plugin_id, PluginDescriptionCallback *callback) { m_core->FetchPluginDescription(plugin_id, callback); } void OlaClient::FetchPluginState(ola_plugin_id plugin_id, PluginStateCallback *callback) { m_core->FetchPluginState(plugin_id, callback); } void OlaClient::FetchDeviceInfo(ola_plugin_id plugin_filter, DeviceInfoCallback *callback) { m_core->FetchDeviceInfo(plugin_filter, callback); } void OlaClient::FetchCandidatePorts(CandidatePortsCallback *callback) { m_core->FetchCandidatePorts(callback); } void OlaClient::FetchCandidatePorts(unsigned int universe_id, CandidatePortsCallback *callback) { m_core->FetchCandidatePorts(universe_id, callback); } void OlaClient::ConfigureDevice(unsigned int device_alias, const string &msg, ConfigureDeviceCallback *callback) { m_core->ConfigureDevice(device_alias, msg, callback); } void OlaClient::SetPluginState(ola_plugin_id plugin_id, bool state, SetCallback *callback) { m_core->SetPluginState(plugin_id, state, callback); } void OlaClient::SetPortPriorityInherit(unsigned int device_alias, unsigned int port, PortDirection port_direction, SetCallback *callback) { m_core->SetPortPriorityInherit(device_alias, port, port_direction, callback); } void OlaClient::SetPortPriorityOverride(unsigned int device_alias, unsigned int port, PortDirection port_direction, uint8_t value, SetCallback *callback) { m_core->SetPortPriorityOverride(device_alias, port, port_direction, value, callback); } void OlaClient::FetchUniverseList(UniverseListCallback *callback) { m_core->FetchUniverseList(callback); } void OlaClient::FetchUniverseInfo(unsigned int universe, UniverseInfoCallback *callback) { m_core->FetchUniverseInfo(universe, callback); } void OlaClient::SetUniverseName(unsigned int universe, const string &name, SetCallback *callback) { m_core->SetUniverseName(universe, name, callback); } void OlaClient::SetUniverseMergeMode(unsigned int universe, OlaUniverse::merge_mode mode, SetCallback *callback) { m_core->SetUniverseMergeMode(universe, mode, callback); } void OlaClient::Patch(unsigned int device_alias, unsigned int port, PortDirection port_direction, PatchAction action, unsigned int universe, SetCallback *callback) { m_core->Patch(device_alias, port, port_direction, action, universe, callback); } void OlaClient::RegisterUniverse(unsigned int universe, RegisterAction register_action, SetCallback *callback) { m_core->RegisterUniverse(universe, register_action, callback); } void OlaClient::SendDMX(unsigned int universe, const DmxBuffer &data, const SendDMXArgs &args) { m_core->SendDMX(universe, data, args); } void OlaClient::FetchDMX(unsigned int universe, DMXCallback *callback) { m_core->FetchDMX(universe, callback); } void OlaClient::RunDiscovery(unsigned int universe, DiscoveryType discovery_type, DiscoveryCallback *callback) { m_core->RunDiscovery(universe, discovery_type, callback); } void OlaClient::SetSourceUID(const ola::rdm::UID &uid, SetCallback *callback) { m_core->SetSourceUID(uid, callback); } void OlaClient::SendTimeCode(const ola::timecode::TimeCode &timecode, SetCallback *callback) { m_core->SendTimeCode(timecode, callback); } void OlaClient::RDMGet(unsigned int universe, const ola::rdm::UID &uid, uint16_t sub_device, uint16_t pid, const uint8_t *data, unsigned int data_length, const SendRDMArgs& args) { m_core->RDMGet(universe, uid, sub_device, pid, data, data_length, args); } void OlaClient::RDMSet(unsigned int universe, const ola::rdm::UID &uid, uint16_t sub_device, uint16_t pid, const uint8_t *data, unsigned int data_length, const SendRDMArgs& args) { m_core->RDMSet(universe, uid, sub_device, pid, data, data_length, args); } } // namespace client } // namespace ola ola-0.10.5.nojsmin/ola/OlaCallbackClient.cpp0000644000175000017500000004416213023355232020233 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * OlaCallbackClient.cpp * Implementation of OlaCallbackClient * Copyright (C) 2010 Simon Newton */ #include "ola/OlaCallbackClient.h" #include #include #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/OlaClientCore.h" #include "ola/OlaDevice.h" #include "ola/client/Result.h" #include "ola/network/NetworkUtils.h" #include "ola/rdm/RDMAPI.h" #include "ola/rdm/RDMAPIImplInterface.h" #include "ola/rdm/RDMEnums.h" namespace ola { using ola::client::RDMMetadata; using ola::client::Result; using ola::client::SendRDMArgs; using ola::io::ConnectedDescriptor; using ola::rdm::RDMAPIImplInterface; using std::string; using std::vector; OlaCallbackClient::OlaCallbackClient(ConnectedDescriptor *descriptor) : m_core(new client::OlaClientCore(descriptor)) { m_core->SetDMXCallback(NewCallback(this, &OlaCallbackClient::HandleDMX)); } OlaCallbackClient::~OlaCallbackClient() {} bool OlaCallbackClient::Setup() { return m_core->Setup(); } bool OlaCallbackClient::Stop() { return m_core->Stop(); } void OlaCallbackClient::SetCloseHandler( ola::SingleUseCallback0 *callback) { m_core->SetCloseHandler(callback); } bool OlaCallbackClient::FetchPluginList( SingleUseCallback2&, const string&> *callback) { m_core->FetchPluginList( NewSingleCallback(this, &OlaCallbackClient::HandlePluginList, callback)); return true; } bool OlaCallbackClient::FetchPluginDescription( ola_plugin_id plugin_id, SingleUseCallback2 *callback) { m_core->FetchPluginDescription( plugin_id, NewSingleCallback(this, &OlaCallbackClient::HandlePluginDescription, callback)); return true; } bool OlaCallbackClient::FetchPluginState(ola_plugin_id plugin_id, PluginStateCallback *callback) { m_core->FetchPluginState( plugin_id, NewSingleCallback(this, &OlaCallbackClient::HandlePluginState, callback)); return true; } bool OlaCallbackClient::FetchDeviceInfo( ola_plugin_id filter, SingleUseCallback2&, const string&> *callback) { m_core->FetchDeviceInfo( filter, NewSingleCallback(this, &OlaCallbackClient::HandleDeviceInfo, callback)); return true; } bool OlaCallbackClient::FetchCandidatePorts( unsigned int universe_id, SingleUseCallback2&, const string&> *callback) { m_core->FetchCandidatePorts( universe_id, NewSingleCallback(this, &OlaCallbackClient::HandleDeviceInfo, callback)); return true; } bool OlaCallbackClient::FetchCandidatePorts( SingleUseCallback2&, const string&> *callback) { m_core->FetchCandidatePorts( NewSingleCallback(this, &OlaCallbackClient::HandleDeviceInfo, callback)); return true; } bool OlaCallbackClient::ConfigureDevice( unsigned int device_alias, const string &msg, SingleUseCallback2 *callback) { m_core->ConfigureDevice( device_alias, msg, NewSingleCallback(this, &OlaCallbackClient::HandleConfigureDevice, callback)); return true; } bool OlaCallbackClient::SetPortPriorityInherit( unsigned int device_alias, unsigned int port, PortDirection port_direction, SingleUseCallback1 *callback) { m_core->SetPortPriorityInherit( device_alias, port, port_direction == INPUT_PORT ? client::INPUT_PORT: client::OUTPUT_PORT, NewSingleCallback(this, &OlaCallbackClient::HandleSetCallback, callback)); return true; } bool OlaCallbackClient::SetPortPriorityOverride( unsigned int device_alias, unsigned int port, PortDirection port_direction, uint8_t value, SingleUseCallback1 *callback) { m_core->SetPortPriorityOverride( device_alias, port, port_direction == INPUT_PORT ? client::INPUT_PORT: client::OUTPUT_PORT, value, NewSingleCallback(this, &OlaCallbackClient::HandleSetCallback, callback)); return true; } bool OlaCallbackClient::FetchUniverseList( SingleUseCallback2&, const string&> *callback) { m_core->FetchUniverseList( NewSingleCallback(this, &OlaCallbackClient::HandleUniverseList, callback)); return true; } bool OlaCallbackClient::FetchUniverseInfo( unsigned int universe, SingleUseCallback2 *callback) { m_core->FetchUniverseInfo( universe, NewSingleCallback(this, &OlaCallbackClient::HandleUniverseInfo, callback)); return true; } bool OlaCallbackClient::SetUniverseName( unsigned int uni, const string &name, SingleUseCallback1 *callback) { m_core->SetUniverseName( uni, name, NewSingleCallback(this, &OlaCallbackClient::HandleSetCallback, callback)); return true; } bool OlaCallbackClient::SetUniverseMergeMode( unsigned int uni, OlaUniverse::merge_mode mode, SingleUseCallback1 *callback) { m_core->SetUniverseMergeMode( uni, mode, NewSingleCallback(this, &OlaCallbackClient::HandleSetCallback, callback)); return true; } bool OlaCallbackClient::Patch( unsigned int device_alias, unsigned int port, ola::PortDirection port_direction, ola::PatchAction action, unsigned int universe, ola::SingleUseCallback1 *callback) { m_core->Patch( device_alias, port, port_direction == INPUT_PORT ? client::INPUT_PORT: client::OUTPUT_PORT, action == PATCH ? client::PATCH : client::UNPATCH, universe, NewSingleCallback(this, &OlaCallbackClient::HandleSetCallback, callback)); return true; } void OlaCallbackClient::SetDmxCallback( ola::Callback3 *callback) { m_dmx_callback.reset(callback); } void OlaCallbackClient::SetDmxCallback( ola::Callback4 *callback) { m_priority_dmx_callback.reset(callback); } bool OlaCallbackClient::RegisterUniverse( unsigned int universe, ola::RegisterAction register_action, SingleUseCallback1 *callback) { m_core->RegisterUniverse( universe, register_action == REGISTER ? client::REGISTER : client::UNREGISTER, NewSingleCallback(this, &OlaCallbackClient::HandleSetCallback, callback)); return true; } bool OlaCallbackClient::SendDmx( unsigned int universe, const DmxBuffer &data, SingleUseCallback1 *callback) { client::SendDMXArgs args( NewSingleCallback(this, &OlaCallbackClient::HandleSetCallback, callback)); m_core->SendDMX(universe, data, args); return true; } bool OlaCallbackClient::SendDmx( unsigned int universe, const DmxBuffer &data, Callback1 *callback) { client::SendDMXArgs args( NewSingleCallback(this, &OlaCallbackClient::HandleRepeatableSetCallback, callback)); m_core->SendDMX(universe, data, args); return true; } bool OlaCallbackClient::SendDmx(unsigned int universe, const DmxBuffer &data) { client::SendDMXArgs args; m_core->SendDMX(universe, data, args); return true; } bool OlaCallbackClient::FetchDmx( unsigned int universe, SingleUseCallback2 *callback) { m_core->FetchDMX( universe, NewSingleCallback(this, &OlaCallbackClient::HandleFetchDmx, callback)); return true; } bool OlaCallbackClient::FetchUIDList( unsigned int universe, SingleUseCallback2 *callback) { m_core->RunDiscovery( universe, client::DISCOVERY_CACHED, NewSingleCallback(this, &OlaCallbackClient::HandleDiscovery, callback)); return true; } bool OlaCallbackClient::RunDiscovery( unsigned int universe, bool full, ola::SingleUseCallback2 *callback) { m_core->RunDiscovery( universe, full ? client::DISCOVERY_FULL : client::DISCOVERY_INCREMENTAL, NewSingleCallback(this, &OlaCallbackClient::HandleDiscovery, callback)); return true; } bool OlaCallbackClient::SetSourceUID( const ola::rdm::UID &uid, ola::SingleUseCallback1 *callback) { m_core->SetSourceUID( uid, NewSingleCallback(this, &OlaCallbackClient::HandleSetCallback, callback)); return true; } bool OlaCallbackClient::RDMGet( ola::rdm::RDMAPIImplInterface::rdm_callback *callback, unsigned int universe, const ola::rdm::UID &uid, uint16_t sub_device, uint16_t pid, const uint8_t *data, unsigned int data_length) { SendRDMArgs args(NewSingleCallback( this, &OlaCallbackClient::HandleRDMResponse, callback)); m_core->RDMGet(universe, uid, sub_device, pid, data, data_length, args); return true; } bool OlaCallbackClient::RDMGet( ola::rdm::RDMAPIImplInterface::rdm_pid_callback *callback, unsigned int universe, const ola::rdm::UID &uid, uint16_t sub_device, uint16_t pid, const uint8_t *data, unsigned int data_length) { SendRDMArgs args(NewSingleCallback( this, &OlaCallbackClient::HandleRDMResponseWithPid, callback)); m_core->RDMGet(universe, uid, sub_device, pid, data, data_length, args); return true; } bool OlaCallbackClient::RDMSet( ola::rdm::RDMAPIImplInterface::rdm_callback *callback, unsigned int universe, const ola::rdm::UID &uid, uint16_t sub_device, uint16_t pid, const uint8_t *data, unsigned int data_length) { SendRDMArgs args(NewSingleCallback( this, &OlaCallbackClient::HandleRDMResponse, callback)); m_core->RDMSet(universe, uid, sub_device, pid, data, data_length, args); return true; } bool OlaCallbackClient::RDMSet( ola::rdm::RDMAPIImplInterface::rdm_pid_callback *callback, unsigned int universe, const ola::rdm::UID &uid, uint16_t sub_device, uint16_t pid, const uint8_t *data, unsigned int data_length) { SendRDMArgs args(NewSingleCallback( this, &OlaCallbackClient::HandleRDMResponseWithPid, callback)); m_core->RDMSet(universe, uid, sub_device, pid, data, data_length, args); return true; } bool OlaCallbackClient::SendTimeCode( ola::SingleUseCallback1 *callback, const ola::timecode::TimeCode &timecode) { m_core->SendTimeCode( timecode, NewSingleCallback(this, &OlaCallbackClient::HandleSetCallback, callback)); return true; } // Handlers // ------------------------------------------------------- void OlaCallbackClient::HandlePluginList( SingleUseCallback2&, const string&> *callback, const client::Result &result, const vector &plugins) { callback->Run(plugins, result.Error()); } void OlaCallbackClient::HandlePluginDescription( SingleUseCallback2 *callback, const client::Result &result, const string &description) { callback->Run(description, result.Error()); } void OlaCallbackClient::HandlePluginState( PluginStateCallback *callback, const client::Result &result, const client::PluginState &core_state) { PluginState state; state.name = core_state.name; state.enabled = core_state.enabled; state.active = core_state.active; state.preferences_source = core_state.preferences_source; state.conflicting_plugins = core_state.conflicting_plugins; callback->Run(state, result.Error()); } void OlaCallbackClient::HandleDeviceInfo( SingleUseCallback2&, const string&> *callback, const client::Result &result, const vector &devices) { callback->Run(devices, result.Error()); } void OlaCallbackClient::HandleConfigureDevice( SingleUseCallback2 *callback, const client::Result &result, const string &reply) { callback->Run(reply, result.Error()); } void OlaCallbackClient::HandleUniverseList( SingleUseCallback2&, const string &> *callback, const client::Result &result, const vector &universes) { callback->Run(universes, result.Error()); } void OlaCallbackClient::HandleUniverseInfo( SingleUseCallback2 *callback, const client::Result &result, const OlaUniverse &universe) { // There was a bug in the API and universe isn't const. OlaUniverse new_universe( universe.Id(), universe.MergeMode(), universe.Name(), universe.InputPorts(), universe.OutputPorts(), universe.RDMDeviceCount()); callback->Run(new_universe, result.Error()); } void OlaCallbackClient::HandleFetchDmx( SingleUseCallback2 *callback, const client::Result &result, const client::DMXMetadata&, const DmxBuffer &data) { callback->Run(data, result.Error()); } void OlaCallbackClient::HandleDiscovery( ola::SingleUseCallback2 *callback, const client::Result &result, const ola::rdm::UIDSet &uids) { callback->Run(uids, result.Error()); } void OlaCallbackClient::HandleSetCallback( ola::SingleUseCallback1 *callback, const Result &result) { if (callback) { callback->Run(result.Error()); } } void OlaCallbackClient::HandleRepeatableSetCallback( ola::Callback1 *callback, const Result &result) { callback->Run(result.Error()); } void OlaCallbackClient::HandleDMX(const client::DMXMetadata &metadata, const DmxBuffer &data) { if (m_dmx_callback.get()) { m_dmx_callback->Run(metadata.universe, data, ""); } if (m_priority_dmx_callback.get()) { m_priority_dmx_callback->Run(metadata.universe, metadata.priority, data, ""); } } void OlaCallbackClient::HandleRDMResponse( ola::rdm::RDMAPIImplInterface::rdm_callback *callback, const Result &result, const RDMMetadata &metadata, const ola::rdm::RDMResponse *response) { rdm::ResponseStatus response_status; string data; GetResponseStatusAndData(result, metadata.response_code, response, &response_status, &data); callback->Run(response_status, data); } void OlaCallbackClient::HandleRDMResponseWithPid( ola::rdm::RDMAPIImplInterface::rdm_pid_callback *callback, const Result &result, const RDMMetadata &metadata, const ola::rdm::RDMResponse *response) { rdm::ResponseStatus response_status; string data; GetResponseStatusAndData(result, metadata.response_code, response, &response_status, &data); callback->Run(response_status, response_status.pid_value, data); } void OlaCallbackClient::GetResponseStatusAndData( const Result &result, ola::rdm::rdm_response_code response_code, const ola::rdm::RDMResponse *response, rdm::ResponseStatus *response_status, string *data) { response_status->error = result.Error(); response_status->response_code = ola::rdm::RDM_FAILED_TO_SEND; if (result.Success()) { response_status->response_code = response_code; if (response_code == ola::rdm::RDM_COMPLETED_OK && response) { response_status->response_type = response->PortIdResponseType(); response_status->message_count = response->MessageCount(); response_status->pid_value = response->ParamId(); response_status->set_command = ( response->CommandClass() == ola::rdm::RDMCommand::SET_COMMAND_RESPONSE ? true : false); switch (response->PortIdResponseType()) { case ola::rdm::RDM_ACK: data->append(reinterpret_cast(response->ParamData()), response->ParamDataSize()); break; case ola::rdm::RDM_ACK_TIMER: GetParamFromReply("ack timer", response, response_status); break; case ola::rdm::RDM_NACK_REASON: GetParamFromReply("nack", response, response_status); break; default: OLA_WARN << "Invalid response type 0x" << std::hex << static_cast(response->PortIdResponseType()); response_status->response_type = ola::rdm::RDM_INVALID_RESPONSE; } } } } void OlaCallbackClient::GetParamFromReply( const string &message_type, const ola::rdm::RDMResponse *response, ola::rdm::ResponseStatus *new_status) { uint16_t param; if (response->ParamDataSize() != sizeof(param)) { OLA_WARN << "Invalid PDL size for " << message_type << ", length was " << response->ParamDataSize(); new_status->response_type = ola::rdm::RDM_INVALID_RESPONSE; } else { memcpy(¶m, response->ParamData(), sizeof(param)); new_status->m_param = ola::network::NetworkToHost(param); } } } // namespace ola ola-0.10.5.nojsmin/ola/OlaClientWrapper.h0000644000175000017500000000245013023355232017616 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * OlaClientWrapper.h * This provides a helpful wrapper for the OlaClient & OlaCallbackClient * classes. * Copyright (C) 2005 Simon Newton */ #ifndef OLA_OLACLIENTWRAPPER_H_ #define OLA_OLACLIENTWRAPPER_H_ #include #include namespace ola { /** * @brief A ClientWrapper that uses the OlaCallbackClient. * @deprecated Use ola::client::OlaClientWrapper instead. */ typedef ola::client::GenericClientWrapper OlaCallbackClientWrapper; } // namespace ola #endif // OLA_OLACLIENTWRAPPER_H_ ola-0.10.5.nojsmin/ola/AutoStart.h0000644000175000017500000000225713023355232016336 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * AutoStart.h * Connects to the ola server, starting it if it's not already running. * Copyright (C) 2010 Simon Newton */ #ifndef OLA_AUTOSTART_H_ #define OLA_AUTOSTART_H_ #include #include namespace ola { namespace client { /* * Open a connection to the server. */ ola::network::TCPSocket *ConnectToServer(unsigned short port); } // namespace client } // namespace ola #endif // OLA_AUTOSTART_H_ ola-0.10.5.nojsmin/ola/ClientTypesFactory.cpp0000644000175000017500000001102713023355232020531 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * ClientTypesFactory.cpp * Copyright (C) 2015 Simon Marchi */ #include #include "ola/ClientTypesFactory.h" namespace ola { namespace client { using std::vector; /* * Create an OlaPlugin object from a protobuf. */ OlaPlugin ClientTypesFactory::PluginFromProtobuf( const ola::proto::PluginInfo &plugin_info) { return OlaPlugin(plugin_info.plugin_id(), plugin_info.name(), plugin_info.active(), plugin_info.enabled()); } /* * Create an OlaInputPort object from a protobuf. */ OlaInputPort ClientTypesFactory::InputPortFromProtobuf( const ola::proto::PortInfo &port_info) { return OlaInputPort(port_info.port_id(), port_info.universe(), port_info.active(), port_info.description(), static_cast( port_info.priority_capability()), static_cast( port_info.priority_mode()), port_info.priority(), port_info.supports_rdm()); } /* * Create an OlaOutputPort object from a protobuf. */ OlaOutputPort ClientTypesFactory::OutputPortFromProtobufOut( const ola::proto::PortInfo &port_info) { return OlaOutputPort(port_info.port_id(), port_info.universe(), port_info.active(), port_info.description(), static_cast( port_info.priority_capability()), static_cast( port_info.priority_mode()), port_info.priority(), port_info.supports_rdm()); } /* * Create an OlaDevice object from a protobuf. */ OlaDevice ClientTypesFactory::DeviceFromProtobuf( const ola::proto::DeviceInfo &device_info) { vector input_ports; for (int i = 0; i < device_info.input_port_size(); ++i) { ola::proto::PortInfo port_info = device_info.input_port(i); input_ports.push_back( ClientTypesFactory::InputPortFromProtobuf(port_info)); } vector output_ports; for (int i = 0; i < device_info.output_port_size(); ++i) { ola::proto::PortInfo port_info = device_info.output_port(i); output_ports.push_back( ClientTypesFactory::OutputPortFromProtobufOut(port_info)); } return OlaDevice(device_info.device_id(), device_info.device_alias(), device_info.device_name(), device_info.plugin_id(), input_ports, output_ports); } /* * Create an OlaUniverse object from a protobuf. */ OlaUniverse ClientTypesFactory::UniverseFromProtobuf( const ola::proto::UniverseInfo &universe_info) { OlaUniverse::merge_mode merge_mode = universe_info.merge_mode() == ola::proto::HTP ? OlaUniverse::MERGE_HTP: OlaUniverse::MERGE_LTP; vector input_ports; for (int j = 0; j < universe_info.input_ports_size(); ++j) { ola::proto::PortInfo port_info = universe_info.input_ports(j); input_ports.push_back( ClientTypesFactory::InputPortFromProtobuf(port_info)); } vector output_ports; for (int j = 0; j < universe_info.output_ports_size(); ++j) { ola::proto::PortInfo port_info = universe_info.output_ports(j); output_ports.push_back( ClientTypesFactory::OutputPortFromProtobufOut(port_info)); } return OlaUniverse(universe_info.universe(), merge_mode, universe_info.name(), input_ports, output_ports, universe_info.rdm_devices()); } } // namespace client } // namespace ola ola-0.10.5.nojsmin/ola/ClientTypesFactory.h0000644000175000017500000000332613023355232020201 0ustar wouterwouter/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * ClientTypesFactory.h * This provides convenience functions to create data objects from * corresponding protocol buffer objects. * Copyright (C) 2015 Simon Marchi */ #ifndef OLA_CLIENTTYPESFACTORY_H_ #define OLA_CLIENTTYPESFACTORY_H_ #include #include namespace ola { namespace client { /** * @brief Creates OlaPlugin types from protocol buffer objects. */ class ClientTypesFactory { public: static OlaPlugin PluginFromProtobuf( const ola::proto::PluginInfo &plugin_info); static OlaInputPort InputPortFromProtobuf( const ola::proto::PortInfo &port_info); static OlaOutputPort OutputPortFromProtobufOut( const ola::proto::PortInfo &port_info); static OlaDevice DeviceFromProtobuf( const ola::proto::DeviceInfo &device_info); static OlaUniverse UniverseFromProtobuf( const ola::proto::UniverseInfo &universe_info); }; } // namespace client } // namespace ola #endif // OLA_CLIENTTYPESFACTORY_H_ ola-0.10.5.nojsmin/plugins/0000755000175000017500000000000013155164170015144 5ustar wouterwouterola-0.10.5.nojsmin/plugins/dummy/0000755000175000017500000000000013155164170016277 5ustar wouterwouterola-0.10.5.nojsmin/plugins/dummy/DummyPortTest.cpp0000644000175000017500000006541613023355232021612 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DummyPortTest.cpp * Test class for the dummy responders * Copyright (C) 2005 Simon Newton */ #include #include #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #include #include #include "common/rdm/TestHelper.h" #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/network/NetworkUtils.h" #include "ola/rdm/OpenLightingEnums.h" #include "ola/rdm/RDMAPI.h" #include "ola/rdm/RDMCommand.h" #include "ola/rdm/RDMControllerInterface.h" #include "ola/rdm/UID.h" #include "ola/rdm/UIDSet.h" #include "ola/testing/TestUtils.h" #include "plugins/dummy/DummyPort.h" namespace ola { namespace plugin { namespace dummy { using ola::network::HostToNetwork; using ola::rdm::RDMGetRequest; using ola::rdm::RDMGetResponse; using ola::rdm::RDMReply; using ola::rdm::RDMRequest; using ola::rdm::RDMResponse; using ola::rdm::RDMSetRequest; using ola::rdm::RDMSetResponse; using ola::rdm::UID; using ola::rdm::UIDSet; using std::min; using std::string; using std::vector; class MockDummyPort: public DummyPort { public: MockDummyPort() : DummyPort(NULL, DummyPort::Options(), 0) { } }; class DummyPortTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(DummyPortTest); CPPUNIT_TEST(testRDMDiscovery); CPPUNIT_TEST(testUnknownPid); CPPUNIT_TEST(testSupportedParams); CPPUNIT_TEST(testDeviceInfo); CPPUNIT_TEST(testSoftwareVersion); CPPUNIT_TEST(testDmxAddress); CPPUNIT_TEST(testIdentifyDevice); CPPUNIT_TEST(testParamDescription); CPPUNIT_TEST(testOlaManufacturerPidCodeVersion); CPPUNIT_TEST(testSlotInfo); CPPUNIT_TEST_SUITE_END(); public: DummyPortTest() : TestFixture(), m_expected_uid(0x7a70, 0xffffff00), m_test_source(1, 2) { ola::InitLogging(ola::OLA_LOG_INFO, ola::OLA_LOG_STDERR); } void setUp() { m_expected_response = NULL; m_got_uids = false; } void HandleRDMResponse(RDMReply *reply); void SetExpectedResponse(ola::rdm::RDMStatusCode code, const RDMResponse *response); void Verify() { OLA_ASSERT_FALSE(m_expected_response); } void testRDMDiscovery(); void testUnknownPid(); void testSupportedParams(); void testDeviceInfo(); void testSoftwareVersion(); void testDmxAddress(); void testIdentifyDevice(); void testParamDescription(); void testOlaManufacturerPidCodeVersion(); void testSlotInfo(); private: UID m_expected_uid; UID m_test_source; MockDummyPort m_port; ola::rdm::RDMStatusCode m_expected_code; const RDMResponse *m_expected_response; bool m_got_uids; void VerifyUIDs(const UIDSet &uids); void checkSubDeviceOutOfRange(uint16_t pid); void checkSubDeviceOutOfRange(ola::rdm::rdm_pid pid) { checkSubDeviceOutOfRange(static_cast(pid)); } void checkSubDeviceOutOfRange(ola::rdm::rdm_ola_manufacturer_pid pid) { checkSubDeviceOutOfRange(static_cast(pid)); } void checkMalformedRequest(uint16_t pid, ola::rdm::rdm_nack_reason expected_response = ola::rdm::NR_FORMAT_ERROR); void checkMalformedRequest(ola::rdm::rdm_pid pid, ola::rdm::rdm_nack_reason expected_response = ola::rdm::NR_FORMAT_ERROR) { checkMalformedRequest(static_cast(pid), expected_response); } void checkMalformedRequest(ola::rdm::rdm_ola_manufacturer_pid pid, ola::rdm::rdm_nack_reason expected_response = ola::rdm::NR_FORMAT_ERROR) { checkMalformedRequest(static_cast(pid), expected_response); } void checkSetRequest(uint16_t pid); void checkSetRequest(ola::rdm::rdm_pid pid) { checkSetRequest(static_cast(pid)); } void checkSetRequest(ola::rdm::rdm_ola_manufacturer_pid pid) { checkSetRequest(static_cast(pid)); } void checkNoBroadcastResponse(uint16_t pid); void checkNoBroadcastResponse(ola::rdm::rdm_pid pid) { checkNoBroadcastResponse(static_cast(pid)); } void checkNoBroadcastResponse(ola::rdm::rdm_ola_manufacturer_pid pid) { checkNoBroadcastResponse(static_cast(pid)); } }; CPPUNIT_TEST_SUITE_REGISTRATION(DummyPortTest); void DummyPortTest::HandleRDMResponse(RDMReply *reply) { OLA_ASSERT_EQ(m_expected_code, reply->StatusCode()); if (m_expected_response) { OLA_ASSERT_TRUE(*m_expected_response == *reply->Response()); } else { OLA_ASSERT_NULL(reply->Response()); } delete m_expected_response; m_expected_response = NULL; } void DummyPortTest::SetExpectedResponse(ola::rdm::RDMStatusCode code, const RDMResponse *response) { m_expected_code = code; m_expected_response = response; } /* * Check that RDM discovery works */ void DummyPortTest::testRDMDiscovery() { m_port.RunFullDiscovery(NewSingleCallback(this, &DummyPortTest::VerifyUIDs)); OLA_ASSERT(m_got_uids); } /* * Check that unknown pids fail */ void DummyPortTest::testUnknownPid() { UID source(1, 2); RDMRequest *request = new RDMGetRequest( source, m_expected_uid, 0, // transaction # 1, // port id 0, // sub device ola::rdm::PID_COMMS_STATUS, // param id NULL, // data 0); // data length RDMResponse *response = NackWithReason( request, ola::rdm::NR_UNKNOWN_PID); SetExpectedResponse(ola::rdm::RDM_COMPLETED_OK, response); m_port.SendRDMRequest( request, NewSingleCallback(this, &DummyPortTest::HandleRDMResponse)); Verify(); } /* * Check that the supported params command works */ void DummyPortTest::testSupportedParams() { RDMRequest *request = new RDMGetRequest( m_test_source, m_expected_uid, 0, // transaction # 1, // port id 0, // sub device ola::rdm::PID_SUPPORTED_PARAMETERS, // param id NULL, // data 0); // data length uint16_t supported_params[] = { ola::rdm::PID_PRODUCT_DETAIL_ID_LIST, ola::rdm::PID_DEVICE_MODEL_DESCRIPTION, ola::rdm::PID_MANUFACTURER_LABEL, ola::rdm::PID_DEVICE_LABEL, ola::rdm::PID_FACTORY_DEFAULTS, ola::rdm::PID_DMX_PERSONALITY, ola::rdm::PID_DMX_PERSONALITY_DESCRIPTION, ola::rdm::PID_SLOT_INFO, ola::rdm::PID_SLOT_DESCRIPTION, ola::rdm::PID_DEFAULT_SLOT_VALUE, #ifdef HAVE_GETLOADAVG ola::rdm::PID_SENSOR_DEFINITION, ola::rdm::PID_SENSOR_VALUE, ola::rdm::PID_RECORD_SENSORS, #endif // HAVE_GETLOADAVG ola::rdm::PID_LAMP_STRIKES, ola::rdm::PID_REAL_TIME_CLOCK, ola::rdm::PID_LIST_INTERFACES, ola::rdm::PID_INTERFACE_LABEL, ola::rdm::PID_INTERFACE_HARDWARE_ADDRESS_TYPE1, ola::rdm::PID_IPV4_CURRENT_ADDRESS, ola::rdm::PID_IPV4_DEFAULT_ROUTE, ola::rdm::PID_DNS_NAME_SERVER, ola::rdm::PID_DNS_HOSTNAME, ola::rdm::PID_DNS_DOMAIN_NAME, ola::rdm::OLA_MANUFACTURER_PID_CODE_VERSION, }; for (unsigned int i = 0; i < sizeof(supported_params) / 2; i++) supported_params[i] = HostToNetwork(supported_params[i]); RDMResponse *response = GetResponseFromData( request, reinterpret_cast(&supported_params), sizeof(supported_params)); SetExpectedResponse(ola::rdm::RDM_COMPLETED_OK, response); m_port.SendRDMRequest( request, NewSingleCallback(this, &DummyPortTest::HandleRDMResponse)); Verify(); checkSubDeviceOutOfRange(ola::rdm::PID_SUPPORTED_PARAMETERS); checkMalformedRequest(ola::rdm::PID_SUPPORTED_PARAMETERS); checkSetRequest(ola::rdm::PID_SUPPORTED_PARAMETERS); checkNoBroadcastResponse(ola::rdm::PID_SUPPORTED_PARAMETERS); } /* * Check that the device info command works */ void DummyPortTest::testDeviceInfo() { RDMRequest *request = new RDMGetRequest( m_test_source, m_expected_uid, 0, // transaction # 1, // port id 0, // sub device ola::rdm::PID_DEVICE_INFO, // param id NULL, // data 0); // data length ola::rdm::DeviceDescriptor device_descriptor; device_descriptor.protocol_version_high = 1; device_descriptor.protocol_version_low = 0; device_descriptor.device_model = HostToNetwork( static_cast(ola::rdm::OLA_DUMMY_DEVICE_MODEL)); device_descriptor.product_category = HostToNetwork( static_cast(ola::rdm::PRODUCT_CATEGORY_OTHER)); device_descriptor.software_version = HostToNetwork(static_cast(3)); device_descriptor.dmx_footprint = HostToNetwork(static_cast(5)); device_descriptor.current_personality = 2; device_descriptor.personality_count = 4; device_descriptor.dmx_start_address = HostToNetwork(static_cast(1)); device_descriptor.sub_device_count = 0; #ifdef HAVE_GETLOADAVG device_descriptor.sensor_count = 3; #else device_descriptor.sensor_count = 0; #endif // HAVE_GETLOADAVG RDMResponse *response = GetResponseFromData( request, reinterpret_cast(&device_descriptor), sizeof(device_descriptor)); SetExpectedResponse(ola::rdm::RDM_COMPLETED_OK, response); m_port.SendRDMRequest( request, NewSingleCallback(this, &DummyPortTest::HandleRDMResponse)); Verify(); checkSubDeviceOutOfRange(ola::rdm::PID_DEVICE_INFO); checkMalformedRequest(ola::rdm::PID_DEVICE_INFO); checkSetRequest(ola::rdm::PID_DEVICE_INFO); checkNoBroadcastResponse(ola::rdm::PID_DEVICE_INFO); } /* * Check that the software version command works */ void DummyPortTest::testSoftwareVersion() { RDMRequest *request = new RDMGetRequest( m_test_source, m_expected_uid, 0, // transaction # 1, // port id 0, // sub device ola::rdm::PID_SOFTWARE_VERSION_LABEL, // param id NULL, // data 0); // data length const string version = "Dummy Software Version"; RDMResponse *response = GetResponseFromData( request, reinterpret_cast(version.data()), version.size()); SetExpectedResponse(ola::rdm::RDM_COMPLETED_OK, response); m_port.SendRDMRequest( request, NewSingleCallback(this, &DummyPortTest::HandleRDMResponse)); Verify(); checkSubDeviceOutOfRange(ola::rdm::PID_SOFTWARE_VERSION_LABEL); checkMalformedRequest(ola::rdm::PID_SOFTWARE_VERSION_LABEL); checkSetRequest(ola::rdm::PID_SOFTWARE_VERSION_LABEL); checkNoBroadcastResponse(ola::rdm::PID_SOFTWARE_VERSION_LABEL); } /* * Check that the dmx address command works */ void DummyPortTest::testDmxAddress() { RDMRequest *request = new RDMGetRequest( m_test_source, m_expected_uid, 0, // transaction # 1, // port id 0, // sub device ola::rdm::PID_DMX_START_ADDRESS, // param id NULL, // data 0); // data length uint16_t dmx_address = HostToNetwork(static_cast(1)); RDMResponse *response = GetResponseFromData( request, reinterpret_cast(&dmx_address), sizeof(dmx_address)); SetExpectedResponse(ola::rdm::RDM_COMPLETED_OK, response); m_port.SendRDMRequest( request, NewSingleCallback(this, &DummyPortTest::HandleRDMResponse)); Verify(); // now attempt to set it dmx_address = HostToNetwork(static_cast(99)); request = new RDMSetRequest( m_test_source, m_expected_uid, 0, // transaction # 1, // port id 0, // sub device ola::rdm::PID_DMX_START_ADDRESS, // param id reinterpret_cast(&dmx_address), sizeof(dmx_address)); response = GetResponseFromData(request, NULL, 0); SetExpectedResponse(ola::rdm::RDM_COMPLETED_OK, response); m_port.SendRDMRequest( request, NewSingleCallback(this, &DummyPortTest::HandleRDMResponse)); Verify(); // now check it updated request = new RDMGetRequest( m_test_source, m_expected_uid, 0, // transaction # 1, // port id 0, // sub device ola::rdm::PID_DMX_START_ADDRESS, // param id NULL, // data 0); // data length dmx_address = HostToNetwork(static_cast(99)); response = GetResponseFromData( request, reinterpret_cast(&dmx_address), sizeof(dmx_address)); SetExpectedResponse(ola::rdm::RDM_COMPLETED_OK, response); m_port.SendRDMRequest( request, NewSingleCallback(this, &DummyPortTest::HandleRDMResponse)); Verify(); // check that broadcasting changes the address dmx_address = HostToNetwork(static_cast(48)); UID broadcast_uid = UID::VendorcastAddress(OPEN_LIGHTING_ESTA_CODE); request = new RDMSetRequest( m_test_source, broadcast_uid, 0, // transaction # 1, // port id 0, // sub device ola::rdm::PID_DMX_START_ADDRESS, // param id reinterpret_cast(&dmx_address), sizeof(dmx_address)); // no response expected SetExpectedResponse(ola::rdm::RDM_WAS_BROADCAST, NULL); m_port.SendRDMRequest( request, NewSingleCallback(this, &DummyPortTest::HandleRDMResponse)); Verify(); // now check it updated request = new RDMGetRequest( m_test_source, m_expected_uid, 0, // transaction # 1, // port id 0, // sub device ola::rdm::PID_DMX_START_ADDRESS, // param id NULL, // data 0); // data length dmx_address = HostToNetwork(static_cast(48)); response = GetResponseFromData( request, reinterpret_cast(&dmx_address), sizeof(dmx_address)); SetExpectedResponse(ola::rdm::RDM_COMPLETED_OK, response); m_port.SendRDMRequest( request, NewSingleCallback(this, &DummyPortTest::HandleRDMResponse)); Verify(); checkSubDeviceOutOfRange(ola::rdm::PID_DMX_START_ADDRESS); checkMalformedRequest(ola::rdm::PID_DMX_START_ADDRESS); checkNoBroadcastResponse(ola::rdm::PID_DMX_START_ADDRESS); } /* * Check that the identify mode works */ void DummyPortTest::testIdentifyDevice() { RDMRequest *request = new RDMGetRequest( m_test_source, m_expected_uid, 0, // transaction # 1, // port id 0, // sub device ola::rdm::PID_IDENTIFY_DEVICE, // param id NULL, // data 0); // data length uint8_t mode = 0; RDMResponse *response = GetResponseFromData( request, &mode, sizeof(mode)); SetExpectedResponse(ola::rdm::RDM_COMPLETED_OK, response); m_port.SendRDMRequest( request, NewSingleCallback(this, &DummyPortTest::HandleRDMResponse)); Verify(); // now attempt to set it uint8_t new_mode = 1; request = new RDMSetRequest( m_test_source, m_expected_uid, 0, // transaction # 1, // port id 0, // sub device ola::rdm::PID_IDENTIFY_DEVICE, // param id &new_mode, sizeof(new_mode)); response = GetResponseFromData(request, NULL, 0); SetExpectedResponse(ola::rdm::RDM_COMPLETED_OK, response); m_port.SendRDMRequest( request, NewSingleCallback(this, &DummyPortTest::HandleRDMResponse)); Verify(); // now check it updated request = new RDMGetRequest( m_test_source, m_expected_uid, 0, // transaction # 1, // port id 0, // sub device ola::rdm::PID_IDENTIFY_DEVICE, // param id NULL, // data 0); // data length mode = 1; response = GetResponseFromData( request, &mode, sizeof(mode)); SetExpectedResponse(ola::rdm::RDM_COMPLETED_OK, response); m_port.SendRDMRequest( request, NewSingleCallback(this, &DummyPortTest::HandleRDMResponse)); Verify(); // check that broadcasting changes the identify new_mode = 0; UID broadcast_uid = UID::VendorcastAddress(OPEN_LIGHTING_ESTA_CODE); request = new RDMSetRequest( m_test_source, broadcast_uid, 0, // transaction # 1, // port id 0, // sub device ola::rdm::PID_IDENTIFY_DEVICE, // param id &new_mode, sizeof(new_mode)); // no response expected SetExpectedResponse(ola::rdm::RDM_WAS_BROADCAST, NULL); m_port.SendRDMRequest( request, NewSingleCallback(this, &DummyPortTest::HandleRDMResponse)); Verify(); // now check it updated request = new RDMGetRequest( m_test_source, m_expected_uid, 0, // transaction # 1, // port id 0, // sub device ola::rdm::PID_IDENTIFY_DEVICE, // param id NULL, // data 0); // data length mode = 0; response = GetResponseFromData( request, &mode, sizeof(mode)); SetExpectedResponse(ola::rdm::RDM_COMPLETED_OK, response); m_port.SendRDMRequest( request, NewSingleCallback(this, &DummyPortTest::HandleRDMResponse)); Verify(); checkSubDeviceOutOfRange(ola::rdm::PID_IDENTIFY_DEVICE); checkMalformedRequest(ola::rdm::PID_IDENTIFY_DEVICE); checkNoBroadcastResponse(ola::rdm::PID_IDENTIFY_DEVICE); } /* * Check that the param description command works */ void DummyPortTest::testParamDescription() { uint16_t param_id = HostToNetwork( static_cast(ola::rdm::OLA_MANUFACTURER_PID_CODE_VERSION)); RDMRequest *request = new RDMGetRequest( m_test_source, m_expected_uid, 0, // transaction # 1, // port id 0, // sub device ola::rdm::PID_PARAMETER_DESCRIPTION, // param id reinterpret_cast(¶m_id), // data sizeof(param_id)); // data length PACK( struct parameter_description_s { uint16_t pid; uint8_t pdl_size; uint8_t data_type; uint8_t command_class; uint8_t type; uint8_t unit; uint8_t prefix; uint32_t min_value; uint32_t default_value; uint32_t max_value; char description[ola::rdm::MAX_RDM_STRING_LENGTH]; }); struct parameter_description_s param_description; param_description.pid = HostToNetwork( static_cast(ola::rdm::OLA_MANUFACTURER_PID_CODE_VERSION)); param_description.pdl_size = HostToNetwork( static_cast(ola::rdm::MAX_RDM_STRING_LENGTH)); param_description.data_type = HostToNetwork( static_cast(ola::rdm::DS_ASCII)); param_description.command_class = HostToNetwork( static_cast(ola::rdm::CC_GET)); param_description.type = 0; param_description.unit = HostToNetwork( static_cast(ola::rdm::UNITS_NONE)); param_description.prefix = HostToNetwork( static_cast(ola::rdm::PREFIX_NONE)); param_description.min_value = 0; param_description.default_value = 0; param_description.max_value = 0; const string description("Code Version"); size_t str_len = std::min(sizeof(param_description.description), description.size()); strncpy(param_description.description, description.c_str(), str_len); unsigned int param_data_length = ( sizeof(param_description) - sizeof(param_description.description) + str_len); RDMResponse *response = GetResponseFromData( request, reinterpret_cast(¶m_description), param_data_length); SetExpectedResponse(ola::rdm::RDM_COMPLETED_OK, response); m_port.SendRDMRequest( request, NewSingleCallback(this, &DummyPortTest::HandleRDMResponse)); Verify(); // Alternative PID // This PID should be one the device won't respond to for the check to work uint16_t unknown_param_id = HostToNetwork(static_cast(0xFFDF)); request = new RDMGetRequest( m_test_source, m_expected_uid, 0, // transaction # 1, // port id 0, // sub device ola::rdm::PID_PARAMETER_DESCRIPTION, // param id reinterpret_cast(&unknown_param_id), // data sizeof(unknown_param_id)); // data length response = NackWithReason(request, ola::rdm::NR_DATA_OUT_OF_RANGE); SetExpectedResponse(ola::rdm::RDM_COMPLETED_OK, response); m_port.SendRDMRequest( request, NewSingleCallback(this, &DummyPortTest::HandleRDMResponse)); Verify(); checkSubDeviceOutOfRange(ola::rdm::PID_PARAMETER_DESCRIPTION); // We don't get the normal format error here, as we're expecting data anyway checkMalformedRequest(ola::rdm::PID_PARAMETER_DESCRIPTION, ola::rdm::NR_DATA_OUT_OF_RANGE); checkSetRequest(ola::rdm::PID_PARAMETER_DESCRIPTION); checkNoBroadcastResponse(ola::rdm::PID_PARAMETER_DESCRIPTION); } /* * Check that the OLA manufacturer PID code version works */ void DummyPortTest::testOlaManufacturerPidCodeVersion() { RDMRequest *request = new RDMGetRequest( m_test_source, m_expected_uid, 0, // transaction # 1, // port id 0, // sub device ola::rdm::OLA_MANUFACTURER_PID_CODE_VERSION, // param id NULL, // data 0); // data length const string code_version = VERSION; RDMResponse *response = GetResponseFromData( request, reinterpret_cast(code_version.data()), code_version.size()); SetExpectedResponse(ola::rdm::RDM_COMPLETED_OK, response); m_port.SendRDMRequest( request, NewSingleCallback(this, &DummyPortTest::HandleRDMResponse)); Verify(); checkSubDeviceOutOfRange(ola::rdm::OLA_MANUFACTURER_PID_CODE_VERSION); checkMalformedRequest(ola::rdm::OLA_MANUFACTURER_PID_CODE_VERSION); checkSetRequest(ola::rdm::OLA_MANUFACTURER_PID_CODE_VERSION); checkNoBroadcastResponse(ola::rdm::OLA_MANUFACTURER_PID_CODE_VERSION); } /* * Check that the slot info command works */ void DummyPortTest::testSlotInfo() { RDMRequest *request = new RDMGetRequest( m_test_source, m_expected_uid, 0, // transaction # 1, // port id 0, // sub device ola::rdm::PID_SLOT_INFO, // param id NULL, // data 0); // data length PACK( struct slot_info_struct { uint16_t offset; uint8_t type; uint16_t label; }); PACK( struct slot_infos_s { slot_info_struct slot_info_s[5]; }); slot_infos_s slot_infos = { { {HostToNetwork(static_cast(0)), static_cast(ola::rdm::ST_PRIMARY), HostToNetwork(static_cast(ola::rdm::SD_INTENSITY))}, {HostToNetwork(static_cast(1)), static_cast(ola::rdm::ST_SEC_FINE), HostToNetwork(static_cast(0))}, {HostToNetwork(static_cast(2)), static_cast(ola::rdm::ST_PRIMARY), HostToNetwork(static_cast(ola::rdm::SD_PAN))}, {HostToNetwork(static_cast(3)), static_cast(ola::rdm::ST_PRIMARY), HostToNetwork(static_cast(ola::rdm::SD_TILT))}, {HostToNetwork(static_cast(4)), static_cast(ola::rdm::ST_PRIMARY), HostToNetwork(static_cast(ola::rdm::SD_UNDEFINED))} }}; RDMResponse *response = GetResponseFromData( request, reinterpret_cast(&slot_infos), sizeof(slot_infos)); SetExpectedResponse(ola::rdm::RDM_COMPLETED_OK, response); m_port.SendRDMRequest( request, NewSingleCallback(this, &DummyPortTest::HandleRDMResponse)); Verify(); checkSubDeviceOutOfRange(ola::rdm::PID_SLOT_INFO); checkMalformedRequest(ola::rdm::PID_SLOT_INFO); checkSetRequest(ola::rdm::PID_SLOT_INFO); checkNoBroadcastResponse(ola::rdm::PID_SLOT_INFO); } void DummyPortTest::VerifyUIDs(const UIDSet &uids) { UIDSet expected_uids; for (unsigned int i = 0; i < 6; i++) { UID uid(OPEN_LIGHTING_ESTA_CODE, 0xffffff00 + i); expected_uids.AddUID(uid); } OLA_ASSERT_EQ(expected_uids, uids); m_got_uids = true; } void DummyPortTest::checkSubDeviceOutOfRange(uint16_t pid) { // a request with a non-0 subdevice RDMRequest *request = new RDMGetRequest( m_test_source, m_expected_uid, 0, // transaction # 1, // port id 1, // sub device pid, NULL, // data 0); // data length RDMResponse *response = NackWithReason( request, ola::rdm::NR_SUB_DEVICE_OUT_OF_RANGE); SetExpectedResponse(ola::rdm::RDM_COMPLETED_OK, response); m_port.SendRDMRequest( request, NewSingleCallback(this, &DummyPortTest::HandleRDMResponse)); Verify(); } void DummyPortTest::checkMalformedRequest(uint16_t pid, ola::rdm::rdm_nack_reason expected_response) { // a malformed request uint16_t bad_data = 0; RDMRequest *request = new RDMGetRequest( m_test_source, m_expected_uid, 0, // transaction # 1, // port id 0, // sub device pid, reinterpret_cast(&bad_data), // data sizeof(bad_data)); // data length RDMResponse *response = NackWithReason( request, expected_response); SetExpectedResponse(ola::rdm::RDM_COMPLETED_OK, response); m_port.SendRDMRequest( request, NewSingleCallback(this, &DummyPortTest::HandleRDMResponse)); Verify(); } void DummyPortTest::checkSetRequest(uint16_t pid) { // a set request RDMRequest *request = new RDMSetRequest( m_test_source, m_expected_uid, 0, // transaction # 1, // port id 0, // sub device pid, NULL, // data 0); // data length RDMResponse *response = NackWithReason( request, ola::rdm::NR_UNSUPPORTED_COMMAND_CLASS); SetExpectedResponse(ola::rdm::RDM_COMPLETED_OK, response); m_port.SendRDMRequest( request, NewSingleCallback(this, &DummyPortTest::HandleRDMResponse)); Verify(); } void DummyPortTest::checkNoBroadcastResponse(uint16_t pid) { // a broadcast request UID broadcast_uid = UID::AllDevices(); RDMRequest *request = new RDMGetRequest( m_test_source, broadcast_uid, 0, // transaction # 1, // port id 0, // sub device pid, // param id NULL, // data 0); // data length // we don't expect any response to this SetExpectedResponse(ola::rdm::RDM_WAS_BROADCAST, NULL); m_port.SendRDMRequest( request, NewSingleCallback(this, &DummyPortTest::HandleRDMResponse)); Verify(); broadcast_uid = UID::VendorcastAddress(OPEN_LIGHTING_ESTA_CODE); request = new RDMGetRequest( m_test_source, broadcast_uid, 0, // transaction # 1, // port id 0, // sub device pid, // param id NULL, // data 0); // data length // we don't expect any response to this SetExpectedResponse(ola::rdm::RDM_WAS_BROADCAST, NULL); m_port.SendRDMRequest( request, NewSingleCallback(this, &DummyPortTest::HandleRDMResponse)); Verify(); } } // namespace dummy } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/dummy/Makefile.mk0000644000175000017500000000213113023355232020335 0ustar wouterwouter# LIBRARIES ################################################## if USE_DUMMY lib_LTLIBRARIES += plugins/dummy/liboladummy.la plugins_dummy_liboladummy_la_SOURCES = \ plugins/dummy/DummyDevice.cpp \ plugins/dummy/DummyDevice.h \ plugins/dummy/DummyPlugin.cpp \ plugins/dummy/DummyPlugin.h \ plugins/dummy/DummyPort.cpp \ plugins/dummy/DummyPort.h plugins_dummy_liboladummy_la_LIBADD = \ common/libolacommon.la \ olad/plugin_api/libolaserverplugininterface.la # TESTS ################################################## test_programs += plugins/dummy/DummyPluginTester plugins_dummy_DummyPluginTester_SOURCES = plugins/dummy/DummyPortTest.cpp plugins_dummy_DummyPluginTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) # it's unclear to me why liboladummyresponder has to be included here # but if it isn't, the test breaks with gcc 4.6.1 plugins_dummy_DummyPluginTester_LDADD = \ $(COMMON_TESTING_LIBS) \ $(top_builddir)/olad/plugin_api/libolaserverplugininterface.la \ $(top_builddir)/olad/libolaserver.la \ plugins/dummy/liboladummy.la \ common/libolacommon.la endif ola-0.10.5.nojsmin/plugins/dummy/DummyPort.h0000644000175000017500000000662413023355232020413 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DummyPort.h * The interface to the Dummy port * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_DUMMY_DUMMYPORT_H_ #define PLUGINS_DUMMY_DUMMYPORT_H_ #include #include #include #include #include "ola/Constants.h" #include "ola/DmxBuffer.h" #include "ola/rdm/RDMControllerInterface.h" #include "ola/rdm/RDMEnums.h" #include "ola/rdm/UID.h" #include "olad/Port.h" namespace ola { namespace plugin { namespace dummy { class DummyPort: public BasicOutputPort { public: struct Options { public: Options() : number_of_dimmers(1), dimmer_sub_device_count(4), number_of_moving_lights(1), number_of_dummy_responders(1), number_of_ack_timer_responders(0), number_of_advanced_dimmers(1), number_of_sensor_responders(1), number_of_network_responders(1) { } uint8_t number_of_dimmers; uint16_t dimmer_sub_device_count; uint8_t number_of_moving_lights; uint8_t number_of_dummy_responders; uint8_t number_of_ack_timer_responders; uint8_t number_of_advanced_dimmers; uint8_t number_of_sensor_responders; uint8_t number_of_network_responders; }; /** * Create a new DummyPort * @param parent the parent device for this port * @param options the config for the DummyPort such as the number of fake RDM * devices to create * @param id the ID of this port */ DummyPort(class DummyDevice *parent, const Options &options, unsigned int id); virtual ~DummyPort(); bool WriteDMX(const DmxBuffer &buffer, uint8_t priority); std::string Description() const { return "Dummy Port"; } void RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback); void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback); /* * Handle an RDM Request */ void SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *callback); private: typedef struct { unsigned int expected_count; unsigned int current_count; bool failed; ola::rdm::RDMCallback *callback; } broadcast_request_tracker; typedef std::map ResponderMap; DmxBuffer m_buffer; ResponderMap m_responders; void RunDiscovery(ola::rdm::RDMDiscoveryCallback *callback); void HandleBroadcastAck(broadcast_request_tracker *tracker, ola::rdm::RDMReply *reply); // See https://wiki.openlighting.org/index.php/Open_Lighting_Allocations // Do not change. static const unsigned int kStartAddress = 0xffffff00; }; } // namespace dummy } // namespace plugin } // namespace ola #endif // PLUGINS_DUMMY_DUMMYPORT_H_ ola-0.10.5.nojsmin/plugins/dummy/DummyPlugin.cpp0000644000175000017500000001666613023355232021267 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DummyPlugin.cpp * The Dummy plugin for ola, contains a single dummy device * Copyright (C) 2005 Simon Newton */ #include #include #include #include "ola/StringUtils.h" #include "olad/PluginAdaptor.h" #include "olad/Preferences.h" #include "plugins/dummy/DummyDevice.h" #include "plugins/dummy/DummyPort.h" #include "plugins/dummy/DummyPlugin.h" namespace ola { namespace plugin { namespace dummy { using std::string; const char DummyPlugin::ACK_TIMER_COUNT_KEY[] = "ack_timer_count"; const char DummyPlugin::ADVANCED_DIMMER_KEY[] = "advanced_dimmer_count"; const uint8_t DummyPlugin::DEFAULT_DEVICE_COUNT = 1; // 0 for now, since the web UI doesn't handle it. const uint8_t DummyPlugin::DEFAULT_ACK_TIMER_DEVICE_COUNT = 0; const uint16_t DummyPlugin::DEFAULT_SUBDEVICE_COUNT = 4; const char DummyPlugin::DEVICE_NAME[] = "Dummy Device"; const char DummyPlugin::DIMMER_COUNT_KEY[] = "dimmer_count"; const char DummyPlugin::DIMMER_SUBDEVICE_COUNT_KEY[] = "dimmer_subdevice_count"; const char DummyPlugin::DUMMY_DEVICE_COUNT_KEY[] = "dummy_device_count"; const char DummyPlugin::MOVING_LIGHT_COUNT_KEY[] = "moving_light_count"; const char DummyPlugin::NETWORK_COUNT_KEY[] = "network_device_count"; const char DummyPlugin::PLUGIN_NAME[] = "Dummy"; const char DummyPlugin::PLUGIN_PREFIX[] = "dummy"; const char DummyPlugin::SENSOR_COUNT_KEY[] = "sensor_device_count"; /* * Start the plugin * * Lets keep it simple, one device for this plugin. */ bool DummyPlugin::StartHook() { DummyPort::Options options; if (!StringToInt(m_preferences->GetValue(DUMMY_DEVICE_COUNT_KEY) , &options.number_of_dummy_responders)) { options.number_of_dummy_responders = DEFAULT_DEVICE_COUNT; } if (!StringToInt(m_preferences->GetValue(DIMMER_COUNT_KEY) , &options.number_of_dimmers)) { options.number_of_dimmers = DEFAULT_DEVICE_COUNT; } if (!StringToInt(m_preferences->GetValue(DIMMER_SUBDEVICE_COUNT_KEY) , &options.dimmer_sub_device_count)) { options.dimmer_sub_device_count = DEFAULT_SUBDEVICE_COUNT; } if (!StringToInt(m_preferences->GetValue(MOVING_LIGHT_COUNT_KEY) , &options.number_of_moving_lights)) { options.number_of_moving_lights = DEFAULT_DEVICE_COUNT; } if (!StringToInt(m_preferences->GetValue(ACK_TIMER_COUNT_KEY) , &options.number_of_ack_timer_responders)) { options.number_of_ack_timer_responders = DEFAULT_ACK_TIMER_DEVICE_COUNT; } if (!StringToInt(m_preferences->GetValue(ADVANCED_DIMMER_KEY) , &options.number_of_advanced_dimmers)) { options.number_of_advanced_dimmers = DEFAULT_DEVICE_COUNT; } if (!StringToInt(m_preferences->GetValue(SENSOR_COUNT_KEY) , &options.number_of_sensor_responders)) { options.number_of_sensor_responders = DEFAULT_DEVICE_COUNT; } if (!StringToInt(m_preferences->GetValue(NETWORK_COUNT_KEY) , &options.number_of_network_responders)) { options.number_of_network_responders = DEFAULT_DEVICE_COUNT; } std::auto_ptr device( new DummyDevice(this, DEVICE_NAME, options)); if (!device->Start()) { return false; } m_device = device.release(); m_plugin_adaptor->RegisterDevice(m_device); return true; } /* * Stop the plugin * @return true on success, false on failure */ bool DummyPlugin::StopHook() { if (m_device) { m_plugin_adaptor->UnregisterDevice(m_device); bool ret = m_device->Stop(); delete m_device; return ret; } return true; } string DummyPlugin::Description() const { return "Dummy Plugin\n" "----------------------------\n" "\n" "The plugin creates a single device with one port. When used as an output\n" "port it prints the first two bytes of dmx data to stdout.\n" "\n" "The Dummy plugin can also emulate a range of RDM devices. It supports the\n" "following RDM device types:\n" " * Dummy Device (original)\n" " * Dimmer Rack, with a configurable number of sub-devices\n" " * Moving Light\n" " * Advanced Dimmer Rack, with E1.37-1 PIDs\n" " * A device that responds with ack timers\n" " * Sensor Device, with a number of sensors implemented\n" " * Network Device, with E1.37-2 PIDs\n" "\n" "The number of each device is configurable.\n" "\n" "--- Config file : ola-dummy.conf ---\n" "\n" "ack_timer_count = 0\n" "The number of ack timer responders to create.\n" "\n" "advanced_dimmer_count = 0\n" "The number of E1.37-1 dimmer responders to create.\n" "\n" "dimmer_count = 1\n" "The number of dimmer devices to create.\n" "\n" "dimmer_subdevice_count = 1\n" "The number of sub-devices each dimmer device should have.\n" "\n" "dummy_device_count = 1\n" "The number of dummy devices to create.\n" "\n" "moving_light_count = 1\n" "The number of moving light devices to create.\n" "\n" "sensor_device_count = 1\n" "The number of sensor-only devices to create.\n" "\n" "network_device_count = 1\n" "The number of network E1.37-2 devices to create.\n" "\n"; } /** * Set the default preferences for the dummy plugin. */ bool DummyPlugin::SetDefaultPreferences() { if (!m_preferences) { return false; } bool save = false; save |= m_preferences->SetDefaultValue(DUMMY_DEVICE_COUNT_KEY, UIntValidator(0, 254), DEFAULT_DEVICE_COUNT); save |= m_preferences->SetDefaultValue(DIMMER_COUNT_KEY, UIntValidator(0, 254), DEFAULT_DEVICE_COUNT); save |= m_preferences->SetDefaultValue(DIMMER_SUBDEVICE_COUNT_KEY, UIntValidator(0, 255), DEFAULT_SUBDEVICE_COUNT); save |= m_preferences->SetDefaultValue(MOVING_LIGHT_COUNT_KEY, UIntValidator(0, 254), DEFAULT_DEVICE_COUNT); save |= m_preferences->SetDefaultValue(ACK_TIMER_COUNT_KEY, UIntValidator(0, 254), DEFAULT_ACK_TIMER_DEVICE_COUNT); save |= m_preferences->SetDefaultValue(ADVANCED_DIMMER_KEY, UIntValidator(0, 254), DEFAULT_DEVICE_COUNT); save |= m_preferences->SetDefaultValue(SENSOR_COUNT_KEY, UIntValidator(0, 254), DEFAULT_DEVICE_COUNT); save |= m_preferences->SetDefaultValue(NETWORK_COUNT_KEY, IntValidator(0, 254), DEFAULT_DEVICE_COUNT); if (save) { m_preferences->Save(); } return true; } } // namespace dummy } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/dummy/DummyPlugin.h0000644000175000017500000000446513023355232020726 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DummyPlugin.h * Interface for the dummyplugin class * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_DUMMY_DUMMYPLUGIN_H_ #define PLUGINS_DUMMY_DUMMYPLUGIN_H_ #include #include #include "olad/Plugin.h" #include "ola/plugin_id.h" namespace ola { namespace plugin { namespace dummy { class DummyDevice; class DummyPlugin: public Plugin { public: explicit DummyPlugin(PluginAdaptor *plugin_adaptor): Plugin(plugin_adaptor), m_device(NULL) {} std::string Name() const { return PLUGIN_NAME; } std::string Description() const; ola_plugin_id Id() const { return OLA_PLUGIN_DUMMY; } std::string PluginPrefix() const { return PLUGIN_PREFIX; } private: bool StartHook(); bool StopHook(); bool SetDefaultPreferences(); DummyDevice *m_device; // the dummy device static const char ACK_TIMER_COUNT_KEY[]; static const char ADVANCED_DIMMER_KEY[]; static const uint8_t DEFAULT_DEVICE_COUNT; static const uint8_t DEFAULT_ACK_TIMER_DEVICE_COUNT; static const uint16_t DEFAULT_SUBDEVICE_COUNT; static const char DEVICE_NAME[]; static const char DIMMER_COUNT_KEY[]; static const char DIMMER_SUBDEVICE_COUNT_KEY[]; static const char DUMMY_DEVICE_COUNT_KEY[]; static const char MOVING_LIGHT_COUNT_KEY[]; static const char NETWORK_COUNT_KEY[]; static const char PLUGIN_NAME[]; static const char PLUGIN_PREFIX[]; static const char SENSOR_COUNT_KEY[]; static const char SUBDEVICE_COUNT_KEY[]; }; } // namespace dummy } // namespace plugin } // namespace ola #endif // PLUGINS_DUMMY_DUMMYPLUGIN_H_ ola-0.10.5.nojsmin/plugins/dummy/DummyPort.cpp0000644000175000017500000001435013023355232020741 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DummyPort.cpp * The Dummy Port for ola * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include #include "ola/Logging.h" #include "ola/rdm/AckTimerResponder.h" #include "ola/rdm/AdvancedDimmerResponder.h" #include "ola/rdm/DimmerResponder.h" #include "ola/rdm/DummyResponder.h" #include "ola/rdm/MovingLightResponder.h" #include "ola/rdm/NetworkResponder.h" #include "ola/rdm/SensorResponder.h" #include "ola/rdm/UIDAllocator.h" #include "ola/rdm/UIDSet.h" #include "ola/stl/STLUtils.h" #include "plugins/dummy/DummyDevice.h" #include "plugins/dummy/DummyPort.h" namespace ola { namespace plugin { namespace dummy { using ola::rdm::DimmerResponder; using ola::rdm::DummyResponder; using ola::rdm::RDMDiscoveryCallback; using ola::rdm::RunRDMCallback; using ola::rdm::UID; using std::auto_ptr; using std::map; using std::ostringstream; using std::string; using std::vector; /** * A count number of responders of type T. */ template void AddResponders(map *responders, ola::rdm::UIDAllocator *uid_allocator, unsigned int count) { for (unsigned int i = 0; i < count; i++) { auto_ptr uid(uid_allocator->AllocateNext()); if (!uid.get()) { OLA_WARN << "Insufficient UIDs to create Dummy RDM devices"; break; } STLReplaceAndDelete(responders, *uid, new T(*uid)); } } DummyPort::DummyPort(DummyDevice *parent, const Options &options, unsigned int id) : BasicOutputPort(parent, id, true, true) { UID first_uid(OPEN_LIGHTING_ESTA_CODE, DummyPort::kStartAddress); ola::rdm::UIDAllocator allocator(first_uid); for (unsigned int i = 0; i < options.number_of_dummy_responders; i++) { auto_ptr uid(allocator.AllocateNext()); if (!uid.get()) { OLA_WARN << "Insufficient UIDs to create dummy RDM devices"; break; } STLReplaceAndDelete(&m_responders, *uid, new DummyResponder(*uid)); } for (unsigned int i = 0; i < options.number_of_dimmers; i++) { auto_ptr uid(allocator.AllocateNext()); if (!uid.get()) { OLA_WARN << "Insufficient UIDs to create dummy RDM devices"; break; } STLReplaceAndDelete( &m_responders, *uid, new DimmerResponder(*uid, options.dimmer_sub_device_count)); } AddResponders( &m_responders, &allocator, options.number_of_moving_lights); AddResponders( &m_responders, &allocator, options.number_of_ack_timer_responders); AddResponders( &m_responders, &allocator, options.number_of_advanced_dimmers); AddResponders( &m_responders, &allocator, options.number_of_sensor_responders); AddResponders( &m_responders, &allocator, options.number_of_network_responders); } bool DummyPort::WriteDMX(const DmxBuffer &buffer, uint8_t priority) { (void) priority; m_buffer = buffer; ostringstream str; string data = buffer.Get(); str << "Dummy port: got " << buffer.Size() << " bytes: "; for (unsigned int i = 0; i < 10 && i < data.size(); i++) str << "0x" << std::hex << 0 + (uint8_t) data.at(i) << " "; OLA_INFO << str.str(); return true; } void DummyPort::RunFullDiscovery(RDMDiscoveryCallback *callback) { RunDiscovery(callback); } void DummyPort::RunIncrementalDiscovery(RDMDiscoveryCallback *callback) { RunDiscovery(callback); } void DummyPort::SendRDMRequest(ola::rdm::RDMRequest *request_ptr, ola::rdm::RDMCallback *callback) { auto_ptr request(request_ptr); UID dest = request->DestinationUID(); if (dest.IsBroadcast()) { if (m_responders.empty()) { RunRDMCallback(callback, ola::rdm::RDM_WAS_BROADCAST); } else { broadcast_request_tracker *tracker = new broadcast_request_tracker; tracker->expected_count = m_responders.size(); tracker->current_count = 0; tracker->failed = false; tracker->callback = callback; for (ResponderMap::iterator i = m_responders.begin(); i != m_responders.end(); i++) { i->second->SendRDMRequest( request->Duplicate(), NewSingleCallback(this, &DummyPort::HandleBroadcastAck, tracker)); } } } else { ola::rdm::RDMControllerInterface *controller = STLFindOrNull( m_responders, dest); if (controller) { controller->SendRDMRequest(request.release(), callback); } else { RunRDMCallback(callback, ola::rdm::RDM_UNKNOWN_UID); } } } void DummyPort::RunDiscovery(RDMDiscoveryCallback *callback) { ola::rdm::UIDSet uid_set; for (ResponderMap::iterator i = m_responders.begin(); i != m_responders.end(); i++) { uid_set.AddUID(i->first); } callback->Run(uid_set); } void DummyPort::HandleBroadcastAck(broadcast_request_tracker *tracker, ola::rdm::RDMReply *reply) { tracker->current_count++; if (reply->StatusCode() != ola::rdm::RDM_WAS_BROADCAST) { tracker->failed = true; } if (tracker->current_count == tracker->expected_count) { // all ports have completed RunRDMCallback( tracker->callback, tracker->failed ? ola::rdm::RDM_FAILED_TO_SEND : ola::rdm::RDM_WAS_BROADCAST); delete tracker; } } DummyPort::~DummyPort() { STLDeleteValues(&m_responders); } } // namespace dummy } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/dummy/DummyDevice.h0000644000175000017500000000276613023355232020671 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DummyDevice.h * Interface for the dummy device * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_DUMMY_DUMMYDEVICE_H_ #define PLUGINS_DUMMY_DUMMYDEVICE_H_ #include #include "olad/Device.h" #include "plugins/dummy/DummyPort.h" namespace ola { class AbstractPlugin; namespace plugin { namespace dummy { class DummyDevice: public Device { public: DummyDevice( AbstractPlugin *owner, const std::string &name, const DummyPort::Options &port_options) : Device(owner, name), m_port_options(port_options) { } std::string DeviceId() const { return "1"; } protected: const DummyPort::Options m_port_options; bool StartHook(); }; } // namespace dummy } // namespace plugin } // namespace ola #endif // PLUGINS_DUMMY_DUMMYDEVICE_H_ ola-0.10.5.nojsmin/plugins/dummy/DummyDevice.cpp0000644000175000017500000000240413023355232021211 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DummyDevice.cpp * A dummy device * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include "plugins/dummy/DummyDevice.h" #include "plugins/dummy/DummyPort.h" namespace ola { namespace plugin { namespace dummy { /* * Start this device */ bool DummyDevice::StartHook() { DummyPort *port = new DummyPort(this, m_port_options, 0); if (!AddPort(port)) { delete port; return false; } return true; } } // namespace dummy } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/shownet/0000755000175000017500000000000013155164170016633 5ustar wouterwouterola-0.10.5.nojsmin/plugins/shownet/Makefile.mk0000644000175000017500000000204713023355232020677 0ustar wouterwouter# LIBRARIES ################################################## if USE_SHOWNET lib_LTLIBRARIES += plugins/shownet/libolashownet.la plugins_shownet_libolashownet_la_SOURCES = \ plugins/shownet/ShowNetPlugin.cpp \ plugins/shownet/ShowNetDevice.cpp \ plugins/shownet/ShowNetPort.cpp \ plugins/shownet/ShowNetNode.cpp \ plugins/shownet/ShowNetPlugin.h \ plugins/shownet/ShowNetDevice.h \ plugins/shownet/ShowNetPort.h \ plugins/shownet/ShowNetPackets.h \ plugins/shownet/ShowNetNode.h plugins_shownet_libolashownet_la_LIBADD = \ common/libolacommon.la \ olad/plugin_api/libolaserverplugininterface.la # TESTS ################################################## test_programs += plugins/shownet/ShowNetTester plugins_shownet_ShowNetTester_SOURCES = \ plugins/shownet/ShowNetNode.cpp \ plugins/shownet/ShowNetNodeTest.cpp plugins_shownet_ShowNetTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) plugins_shownet_ShowNetTester_LDADD = $(COMMON_TESTING_LIBS) \ common/libolacommon.la endif ola-0.10.5.nojsmin/plugins/shownet/ShowNetPort.cpp0000644000175000017500000000601013023355232021563 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ShowNetPort.cpp * The ShowNet plugin for ola * Copyright (C) 2005 Simon Newton */ #include #include #include "ola/Callback.h" #include "ola/Constants.h" #include "ola/Logging.h" #include "plugins/shownet/ShowNetDevice.h" #include "plugins/shownet/ShowNetPort.h" namespace ola { namespace plugin { namespace shownet { using std::string; string ShowNetInputPort::Description() const { std::ostringstream str; str << "ShowNet " << PortId() * DMX_UNIVERSE_SIZE + 1 << "-" << (PortId() + 1) * DMX_UNIVERSE_SIZE; return str.str(); } /* * Check for loops. */ bool ShowNetInputPort::PreSetUniverse(OLA_UNUSED Universe *old_universe, OLA_UNUSED Universe *new_universe) { AbstractDevice *device = GetDevice(); OutputPort *output_port = device->GetOutputPort(PortId()); if (output_port && output_port->GetUniverse()) { OLA_WARN << "Avoiding possible shownet loop on " << Description(); return false; } return true; } /* * We intecept this to setup/remove the dmx handler */ void ShowNetInputPort::PostSetUniverse(Universe *old_universe, Universe *new_universe) { if (old_universe) m_node->RemoveHandler(PortId()); if (new_universe) m_node->SetHandler( PortId(), &m_buffer, ola::NewCallback(this, &ShowNetInputPort::DmxChanged)); } string ShowNetOutputPort::Description() const { std::ostringstream str; str << "ShowNet " << PortId() * DMX_UNIVERSE_SIZE + 1 << "-" << (PortId() + 1) * DMX_UNIVERSE_SIZE; return str.str(); } /* * Check for loops. */ bool ShowNetOutputPort::PreSetUniverse(OLA_UNUSED Universe *old_universe, OLA_UNUSED Universe *new_universe) { AbstractDevice *device = GetDevice(); InputPort *input_port = device->GetInputPort(PortId()); if (input_port && input_port->GetUniverse()) { OLA_WARN << "Avoiding possible shownet loop on " << Description(); return false; } return true; } bool ShowNetOutputPort::WriteDMX(const DmxBuffer &buffer, OLA_UNUSED uint8_t priority) { return !m_node->SendDMX(PortId(), buffer); } } // namespace shownet } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/shownet/ShowNetPlugin.cpp0000644000175000017500000000616513023355232022110 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ShowNetPlugin.cpp * The ShowNet plugin for ola * Copyright (C) 2005 Simon Newton */ #include #include "olad/PluginAdaptor.h" #include "olad/Preferences.h" #include "plugins/shownet/ShowNetDevice.h" #include "plugins/shownet/ShowNetPlugin.h" namespace ola { namespace plugin { namespace shownet { using std::string; const char ShowNetPlugin::SHOWNET_NODE_NAME[] = "ola-ShowNet"; const char ShowNetPlugin::PLUGIN_NAME[] = "ShowNet"; const char ShowNetPlugin::PLUGIN_PREFIX[] = "shownet"; const char ShowNetPlugin::SHOWNET_NAME_KEY[] = "name"; /* * Start the plugin */ bool ShowNetPlugin::StartHook() { m_device = new ShowNetDevice(this, m_preferences, m_plugin_adaptor); if (!m_device->Start()) { delete m_device; return false; } m_plugin_adaptor->RegisterDevice(m_device); return true; } /* * Stop the plugin * @return true on success, false on failure */ bool ShowNetPlugin::StopHook() { if (m_device) { m_plugin_adaptor->UnregisterDevice(m_device); bool ret = m_device->Stop(); delete m_device; return ret; } return true; } /* * return the description for this plugin * */ string ShowNetPlugin::Description() const { return "Strand ShowNet Plugin\n" "----------------------------\n" "\n" "This plugin creates a single device with 8 input and 8 output ports.\n" "\n" "The ports correspond to the DMX channels used in the shownet protocol.\n" "For example the first input and output port 0 is channels 1 - 512 and\n" "the second input and output ports are channels 513 - 1024.\n" "\n" "--- Config file : ola-shownet.conf ---\n" "\n" "ip = [a.b.c.d|]\n" "The ip address or interface name to bind to. If not specified it will\n" "use the first non-loopback interface.\n" "\n" "name = ola-ShowNet\n" "The name of the node.\n" "\n"; } /* * Set default preferences */ bool ShowNetPlugin::SetDefaultPreferences() { if (!m_preferences) { return false; } bool save = false; save |= m_preferences->SetDefaultValue(ShowNetDevice::IP_KEY, StringValidator(true), ""); save |= m_preferences->SetDefaultValue(SHOWNET_NAME_KEY, StringValidator(), SHOWNET_NODE_NAME); if (save) { m_preferences->Save(); } if (m_preferences->GetValue(SHOWNET_NAME_KEY).empty()) { return false; } return true; } } // namespace shownet } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/shownet/ShowNetNode.cpp0000644000175000017500000002434713023355232021541 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ShowNetNode.cpp * A ShowNet node * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include "ola/Logging.h" #include "ola/base/Array.h" #include "ola/network/IPV4Address.h" #include "ola/network/NetworkUtils.h" #include "ola/stl/STLUtils.h" #include "ola/strings/Utils.h" #include "plugins/shownet/ShowNetNode.h" namespace ola { namespace plugin { namespace shownet { using std::string; using std::map; using ola::network::HostToLittleEndian; using ola::network::HostToNetwork; using ola::network::IPV4Address; using ola::network::IPV4SocketAddress; using ola::network::LittleEndianToHost; using ola::network::NetworkToHost; using ola::network::UDPSocket; using ola::Callback0; /* * Create a new node * @param ip_address the IP address to prefer to listen on, if NULL we choose * one. */ ShowNetNode::ShowNetNode(const std::string &ip_address) : m_running(false), m_packet_count(0), m_node_name(), m_preferred_ip(ip_address), m_socket(NULL) { } /* * Cleanup */ ShowNetNode::~ShowNetNode() { Stop(); std::map::iterator iter; for (iter = m_handlers.begin(); iter != m_handlers.end(); ++iter) { delete iter->second.closure; } m_handlers.clear(); } /* * Start this node */ bool ShowNetNode::Start() { if (m_running) return false; ola::network::InterfacePicker *picker = ola::network::InterfacePicker::NewPicker(); if (!picker->ChooseInterface(&m_interface, m_preferred_ip)) { delete picker; OLA_INFO << "Failed to find an interface"; return false; } delete picker; if (!InitNetwork()) return false; m_running = true; return true; } /* * Stop this node */ bool ShowNetNode::Stop() { if (!m_running) return false; if (m_socket) { delete m_socket; m_socket = NULL; } m_running = false; return true; } /* * Set the node name * @param name the new node name */ void ShowNetNode::SetName(const string &name) { m_node_name = name; } /* * Send some DMX data * @param universe the id of the universe to send * @param buffer the DMX data * @return true if it was send successfully, false otherwise */ bool ShowNetNode::SendDMX(unsigned int universe, const ola::DmxBuffer &buffer) { if (!m_running) return false; if (universe >= SHOWNET_MAX_UNIVERSES) { OLA_WARN << "Universe index out of bounds, should be between 0 and" << SHOWNET_MAX_UNIVERSES << "), was " << universe; return false; } shownet_packet packet; unsigned int size = BuildCompressedPacket(&packet, universe, buffer); unsigned int bytes_sent = m_socket->SendTo( reinterpret_cast(&packet), size, IPV4SocketAddress(m_interface.bcast_address, SHOWNET_PORT)); if (bytes_sent != size) { OLA_WARN << "Only sent " << bytes_sent << " of " << size; return false; } m_packet_count++; return true; } /* * Set the closure to be called when we receive data for this universe. * @param universe the universe to register the handler for * @param handler the Callback0 to call when there is data for this universe. * Ownership of the closure is transferred to the node. */ bool ShowNetNode::SetHandler(unsigned int universe, DmxBuffer *buffer, Callback0 *closure) { if (!closure) return false; map::iterator iter = m_handlers.find(universe); if (iter == m_handlers.end()) { universe_handler handler; handler.buffer = buffer; handler.closure = closure; m_handlers[universe] = handler; } else { Callback0 *old_closure = iter->second.closure; iter->second.closure = closure; delete old_closure; } return true; } /* * Remove the handler for this universe * @param universe the universe handler to remove * @param true if removed, false if it didn't exist */ bool ShowNetNode::RemoveHandler(unsigned int universe) { map::iterator iter = m_handlers.find(universe); if (iter != m_handlers.end()) { Callback0 *old_closure = iter->second.closure; m_handlers.erase(iter); delete old_closure; return true; } return false; } /* * Called when there is data on this socket */ void ShowNetNode::SocketReady() { shownet_packet packet; ssize_t packet_size = sizeof(packet); ola::network::IPV4SocketAddress source; if (!m_socket->RecvFrom(reinterpret_cast(&packet), &packet_size, &source)) return; // skip packets sent by us if (source.Host() != m_interface.ip_address) HandlePacket(&packet, packet_size); } /* * Handle a shownet packet */ bool ShowNetNode::HandlePacket(const shownet_packet *packet, unsigned int packet_size) { unsigned int header_size = sizeof(*packet) - sizeof(packet->data); if (packet_size <= header_size) { OLA_WARN << "Skipping small shownet packet received, size=" << packet_size; return false; } if (NetworkToHost(packet->type) != COMPRESSED_DMX_PACKET) { OLA_INFO << "Skipping a packet that isn't a compressed shownet packet"; return false; } const shownet_compressed_dmx *dmx_packet = &packet->data.compressed_dmx; return HandleCompressedPacket(dmx_packet, packet_size - header_size); } bool ShowNetNode::HandleCompressedPacket(const shownet_compressed_dmx *packet, unsigned int packet_size) { uint16_t index_block = LittleEndianToHost(packet->indexBlock[0]); if (index_block < MAGIC_INDEX_OFFSET) { OLA_WARN << "Strange ShowNet packet, indexBlock[0] is " << index_block << ", please contact the developers!"; return false; } uint16_t net_slot = LittleEndianToHost(packet->netSlot[0]); // We only handle data from the first slot // enc_length is the size of the received (optionally encoded) DMX data int enc_len = LittleEndianToHost(packet->indexBlock[1]) - index_block; if (enc_len < 1 || net_slot == 0) { OLA_WARN << "Invalid shownet packet, enc_len=" << enc_len << ", netSlot=" << net_slot; return false; } // the offset into packet.data of the actual data unsigned int data_offset = index_block - MAGIC_INDEX_OFFSET; unsigned int received_data_size = packet_size - ( sizeof(packet) - SHOWNET_COMPRESSED_DATA_LENGTH); if (data_offset + enc_len > received_data_size) { OLA_WARN << "Not enough shownet data: offset=" << data_offset << ", enc_len=" << enc_len << ", received_bytes=" << received_data_size; return false; } uint16_t slot_size = LittleEndianToHost(packet->slotSize[0]); if (!slot_size) { OLA_WARN << "Malformed shownet packet, slotSize=" << slot_size; return false; } unsigned int start_channel = (net_slot - 1) % DMX_UNIVERSE_SIZE; unsigned int universe_id = (net_slot - 1) / DMX_UNIVERSE_SIZE; universe_handler *handler = STLFind(&m_handlers, universe_id); if (!handler) { OLA_DEBUG << "Not interested in universe " << universe_id << ", skipping "; return false; } if (slot_size != enc_len) { m_encoder.Decode(start_channel, packet->data + data_offset, enc_len, handler->buffer); } else { handler->buffer->SetRange(start_channel, packet->data + data_offset, enc_len); } handler->closure->Run(); return true; } /* * Populate a shownet data packet */ unsigned int ShowNetNode::BuildCompressedPacket(shownet_packet *packet, unsigned int universe, const DmxBuffer &buffer) { memset(packet, 0, sizeof(*packet)); packet->type = HostToNetwork(static_cast(COMPRESSED_DMX_PACKET)); memcpy(packet->ip, &m_interface.ip_address, sizeof(packet->ip)); shownet_compressed_dmx *compressed_dmx = &packet->data.compressed_dmx; compressed_dmx->netSlot[0] = HostToLittleEndian( static_cast(universe * DMX_UNIVERSE_SIZE + 1)); compressed_dmx->slotSize[0] = HostToLittleEndian( static_cast(buffer.Size())); unsigned int enc_len = sizeof(packet->data); if (!m_encoder.Encode(buffer, compressed_dmx->data, &enc_len)) OLA_WARN << "Failed to encode all data (used " << enc_len << " bytes"; compressed_dmx->indexBlock[0] = HostToLittleEndian( static_cast(MAGIC_INDEX_OFFSET)); compressed_dmx->indexBlock[1] = HostToLittleEndian( static_cast(MAGIC_INDEX_OFFSET + enc_len)); compressed_dmx->sequence = HostToNetwork(m_packet_count); strings::CopyToFixedLengthBuffer(m_node_name, compressed_dmx->name, arraysize(compressed_dmx->name)); return (sizeof(*packet) - sizeof(packet->data)) + (sizeof(*compressed_dmx) - SHOWNET_COMPRESSED_DATA_LENGTH + enc_len); } /* * Setup the networking compoents. */ bool ShowNetNode::InitNetwork() { m_socket = new UDPSocket(); if (!m_socket->Init()) { OLA_WARN << "Socket init failed"; delete m_socket; return false; } if (!m_socket->Bind(IPV4SocketAddress(IPV4Address::WildCard(), SHOWNET_PORT))) { delete m_socket; return false; } if (!m_socket->EnableBroadcast()) { OLA_WARN << "Failed to enable broadcasting"; delete m_socket; return false; } m_socket->SetOnData(NewCallback(this, &ShowNetNode::SocketReady)); return true; } } // namespace shownet } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/shownet/ShowNetDevice.cpp0000644000175000017500000000532613023355232022047 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ShowNetDevice.cpp * ShowNet device * Copyright (C) 2005 Simon Newton */ #include #include #include "ola/Logging.h" #include "ola/network/NetworkUtils.h" #include "olad/Plugin.h" #include "olad/PluginAdaptor.h" #include "olad/Preferences.h" #include "plugins/shownet/ShowNetDevice.h" #include "plugins/shownet/ShowNetNode.h" #include "plugins/shownet/ShowNetPort.h" namespace ola { namespace plugin { namespace shownet { using std::ostringstream; const char ShowNetDevice::SHOWNET_DEVICE_NAME[] = "ShowNet"; const char ShowNetDevice::IP_KEY[] = "ip"; /* * Create a new device */ ShowNetDevice::ShowNetDevice(ola::Plugin *owner, Preferences *preferences, PluginAdaptor *plugin_adaptor): Device(owner, SHOWNET_DEVICE_NAME), m_preferences(preferences), m_plugin_adaptor(plugin_adaptor), m_node(NULL) {} /* * Start this device */ bool ShowNetDevice::StartHook() { m_node = new ShowNetNode(m_preferences->GetValue(IP_KEY)); m_node->SetName(m_preferences->GetValue("name")); if (!m_node->Start()) { delete m_node; m_node = NULL; DeleteAllPorts(); return false; } ostringstream str; str << SHOWNET_DEVICE_NAME << " [" << m_node->GetInterface().ip_address << "]"; SetName(str.str()); for (unsigned int i = 0; i < ShowNetNode::SHOWNET_MAX_UNIVERSES; i++) { ShowNetInputPort *input_port = new ShowNetInputPort( this, i, m_plugin_adaptor, m_node); AddPort(input_port); ShowNetOutputPort *output_port = new ShowNetOutputPort(this, i, m_node); AddPort(output_port); } m_plugin_adaptor->AddReadDescriptor(m_node->GetSocket()); return true; } /* * Stop this device */ void ShowNetDevice::PrePortStop() { m_plugin_adaptor->RemoveReadDescriptor(m_node->GetSocket()); } /* * Stop this device */ void ShowNetDevice::PostPortStop() { m_node->Stop(); delete m_node; m_node = NULL; } } // namespace shownet } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/shownet/ShowNetNodeTest.cpp0000644000175000017500000002424613023355232022377 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ShowNetNodeTest.cpp * Test fixture for the ShowNetNode class * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include #include "ola/Callback.h" #include "ola/Constants.h" #include "ola/DmxBuffer.h" #include "ola/Logging.h" #include "ola/network/NetworkUtils.h" #include "ola/testing/TestUtils.h" #include "plugins/shownet/ShowNetNode.h" namespace ola { namespace plugin { namespace shownet { using ola::DmxBuffer; using ola::network::HostToNetwork; using ola::network::NetworkToHost; using std::string; namespace { // HostToLittleEndian is overloaded, so to avoid lots of casts we provide this // function. uint16_t ToLittleEndian(uint16_t value) { return ola::network::HostToLittleEndian(value); } } // namespace class ShowNetNodeTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(ShowNetNodeTest); CPPUNIT_TEST(testHandlePacket); CPPUNIT_TEST(testExtractPacket); CPPUNIT_TEST(testPopulatePacket); CPPUNIT_TEST(testSendAndReceive); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void testHandlePacket(); void testExtractPacket(); void testPopulatePacket(); void testSendAndReceive(); void UpdateData(unsigned int universe); void SendAndReceiveForUniverse(unsigned int universe); private: int m_handler_called; std::auto_ptr m_node; static const uint8_t EXPECTED_PACKET[]; static const uint8_t EXPECTED_PACKET2[]; }; CPPUNIT_TEST_SUITE_REGISTRATION(ShowNetNodeTest); // Start slot 1 const uint8_t ShowNetNodeTest::EXPECTED_PACKET[] = { 0x80, 0x8f, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, // net slots 3, 0, 0, 0, 0, 0, 0, 0, // slot sizes 11, 0, 15, 0, 0, 0, 0, 0, 0, 0, // index blocks 0, 0, 0, 0, 0, 0, 'f', 'o', 'o', 'b', 'a', 'r', 'b', 'a', 'z', 3, 'a', 'b', 'c', }; // Start slot 513 const uint8_t ShowNetNodeTest::EXPECTED_PACKET2[] = { 0x80, 0x8f, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, // net slots 3, 0, 0, 0, 0, 0, 0, 0, // slot sizes 11, 0, 15, 0, 0, 0, 0, 0, 0, 0, // index blocks 0, 0, 0, 0, 0, 0, 'f', 'o', 'o', 'b', 'a', 'r', 'b', 'a', 'z', 3, 'a', 'b', 'c', }; void ShowNetNodeTest::setUp() { m_handler_called = 0; m_node.reset(new ShowNetNode("")); } /* * Called when there is new data */ void ShowNetNodeTest::UpdateData(unsigned int) { m_handler_called++; } /* * Test the packet handling code */ void ShowNetNodeTest::testHandlePacket() { unsigned int universe = 0; const uint8_t ENCODED_DATA[] = {4, 1, 2, 4, 3}; const uint8_t EXPECTED_DATA[] = {1, 2, 4, 3}; DmxBuffer expected_dmx(EXPECTED_DATA, sizeof(EXPECTED_DATA)); shownet_packet packet; shownet_compressed_dmx *compressed_dmx = &packet.data.compressed_dmx; memset(&packet, 0, sizeof(packet)); memcpy(compressed_dmx->data, ENCODED_DATA, sizeof(ENCODED_DATA)); DmxBuffer received_data; m_node->SetHandler( universe, &received_data, ola::NewCallback(this, &ShowNetNodeTest::UpdateData, universe)); // short packets OLA_ASSERT_EQ(false, m_node->HandlePacket(&packet, 0)); OLA_ASSERT_EQ(0, m_handler_called); OLA_ASSERT_EQ(false, m_node->HandlePacket(&packet, 5)); OLA_ASSERT_EQ(0, m_handler_called); // invalid header OLA_ASSERT_EQ(false, m_node->HandlePacket(&packet, sizeof(packet))); OLA_ASSERT_EQ(0, m_handler_called); // add a header packet.type = HostToNetwork(static_cast(COMPRESSED_DMX_PACKET)); OLA_ASSERT_EQ(false, m_node->HandlePacket(&packet, sizeof(packet))); OLA_ASSERT_EQ(0, m_handler_called); // add invalid indexBlocks compressed_dmx->indexBlock[0] = ToLittleEndian(4); OLA_ASSERT_EQ(false, m_node->HandlePacket(&packet, sizeof(packet))); OLA_ASSERT_EQ(0, m_handler_called); // invalid block length compressed_dmx->indexBlock[0] = ToLittleEndian(ShowNetNode::MAGIC_INDEX_OFFSET); OLA_ASSERT_EQ(false, m_node->HandlePacket(&packet, sizeof(packet))); OLA_ASSERT_EQ(0, m_handler_called); // add a valid netslot compressed_dmx->netSlot[0] = ToLittleEndian(1); // universe 0 OLA_ASSERT_EQ(false, m_node->HandlePacket(&packet, sizeof(packet))); OLA_ASSERT_EQ(0, m_handler_called); // valid block length, but not enough data unsigned int header_size = sizeof(packet) - sizeof(packet.data); compressed_dmx->indexBlock[1] = ToLittleEndian(ShowNetNode::MAGIC_INDEX_OFFSET); OLA_ASSERT_EQ(false, m_node->HandlePacket(&packet, header_size + sizeof(ENCODED_DATA))); OLA_ASSERT_EQ(0, m_handler_called); // now do a block length larger than the packet compressed_dmx->indexBlock[1] = ToLittleEndian( 100 + ShowNetNode::MAGIC_INDEX_OFFSET); OLA_ASSERT_EQ(false, m_node->HandlePacket(&packet, header_size + sizeof(ENCODED_DATA))); OLA_ASSERT_EQ(0, m_handler_called); // test invalid slot size compressed_dmx->indexBlock[1] = ToLittleEndian( ShowNetNode::MAGIC_INDEX_OFFSET + sizeof(ENCODED_DATA)); OLA_ASSERT_EQ(false, m_node->HandlePacket(&packet, header_size + sizeof(ENCODED_DATA))); OLA_ASSERT_EQ(0, m_handler_called); // check a valid packet, but different universe compressed_dmx->netSlot[0] = ToLittleEndian(513); // universe 1 compressed_dmx->slotSize[0] = ToLittleEndian(sizeof(EXPECTED_DATA)); OLA_ASSERT_EQ(false, m_node->HandlePacket(&packet, header_size + sizeof(ENCODED_DATA))); OLA_ASSERT_EQ(0, m_handler_called); // now check with the correct universe compressed_dmx->netSlot[0] = ToLittleEndian(1); // universe 0 OLA_ASSERT_EQ(true, m_node->HandlePacket(&packet, header_size + sizeof(ENCODED_DATA))); OLA_ASSERT_EQ(1, m_handler_called); OLA_ASSERT_EQ(0, memcmp(expected_dmx.GetRaw(), received_data.GetRaw(), expected_dmx.Size())); } void ShowNetNodeTest::testExtractPacket() { unsigned int universe = 10; DmxBuffer received_data; m_node->SetHandler( universe, &received_data, ola::NewCallback(this, &ShowNetNodeTest::UpdateData, universe)); // Packets from https://code.google.com/p/open-lighting/issues/detail?id=218 const uint8_t packet1[] = { 0x80, 0x8f, 0x01, 0xb6, 0xc0, 0xa8, // header 0x01, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // net slots 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // slot sizes 0x0b, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // index blocks 0x00, 0x71, 0x00, 0x00, 0x00, 0x04, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x00, 0x00, 0x00, 0x00, // name 0x05, 0x11, 0x4e, 0x32, 0x3c, 0x05, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xfe, 0x00 }; DmxBuffer expected_data1; expected_data1.Blackout(); const uint8_t expected_dmx_data1[] = {17, 78, 50, 60, 5}; expected_data1.SetRange(0, expected_dmx_data1, sizeof(expected_dmx_data1)); OLA_ASSERT_TRUE(m_node->HandlePacket( reinterpret_cast(packet1), sizeof(packet1))); OLA_ASSERT_EQ(1, m_handler_called); OLA_ASSERT_DATA_EQUALS(expected_data1.GetRaw(), expected_data1.Size(), received_data.GetRaw(), received_data.Size()); } /* * Check the packet construction code. */ void ShowNetNodeTest::testPopulatePacket() { unsigned int universe = 0; const string NAME = "foobarbaz"; const string DMX_DATA = "abc"; DmxBuffer buffer(DMX_DATA); shownet_packet packet; m_node->SetName(NAME); unsigned int size = m_node->BuildCompressedPacket(&packet, universe, buffer); OLA_ASSERT_DATA_EQUALS(EXPECTED_PACKET, sizeof(EXPECTED_PACKET), reinterpret_cast(&packet), size); // now send for a different universe universe = 1; size = m_node->BuildCompressedPacket(&packet, universe, buffer); OLA_ASSERT_DATA_EQUALS(EXPECTED_PACKET2, sizeof(EXPECTED_PACKET2), reinterpret_cast(&packet), size); } /* * Check that we can decode the packets we send. */ void ShowNetNodeTest::testSendAndReceive() { SendAndReceiveForUniverse(0); SendAndReceiveForUniverse(1); SendAndReceiveForUniverse(2); } /* * Send and receive some packets on this universe. */ void ShowNetNodeTest::SendAndReceiveForUniverse(unsigned int universe) { const uint8_t TEST_DATA[] = {1, 2, 2, 3, 0, 0, 0, 1, 3, 3, 3, 1, 2}; const uint8_t TEST_DATA2[] = {0, 0, 0, 0, 6, 5, 4, 3, 3, 3}; DmxBuffer zero_buffer; zero_buffer.Blackout(); DmxBuffer buffer1(TEST_DATA, sizeof(TEST_DATA)); DmxBuffer buffer2(TEST_DATA2, sizeof(TEST_DATA2)); unsigned int size; shownet_packet packet; DmxBuffer received_data; m_node->SetHandler( universe, &received_data, ola::NewCallback(this, &ShowNetNodeTest::UpdateData, universe)); // zero first size = m_node->BuildCompressedPacket(&packet, universe, zero_buffer); m_node->HandlePacket(&packet, size); OLA_ASSERT(received_data == zero_buffer); // send a test packet size = m_node->BuildCompressedPacket(&packet, universe, buffer1); m_node->HandlePacket(&packet, size); OLA_ASSERT_EQ( 0, memcmp(buffer1.GetRaw(), received_data.GetRaw(), buffer1.Size())); // send another test packet size = m_node->BuildCompressedPacket(&packet, universe, buffer2); m_node->HandlePacket(&packet, size); OLA_ASSERT_EQ( 0, memcmp(buffer2.GetRaw(), received_data.GetRaw(), buffer2.Size())); // check that we don't mix up universes size = m_node->BuildCompressedPacket(&packet, universe + 1, buffer1); m_node->HandlePacket(&packet, size); OLA_ASSERT_EQ( 0, memcmp(buffer2.GetRaw(), received_data.GetRaw(), buffer2.Size())); } } // namespace shownet } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/shownet/ShowNetNode.h0000644000175000017500000000617613023355232021206 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ShowNetNode.h * Header file for the ShowNetNode class * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_SHOWNET_SHOWNETNODE_H_ #define PLUGINS_SHOWNET_SHOWNETNODE_H_ #include #include #include "ola/Callback.h" #include "ola/DmxBuffer.h" #include "ola/base/Macro.h" #include "ola/dmx/RunLengthEncoder.h" #include "ola/network/InterfacePicker.h" #include "ola/network/Socket.h" #include "plugins/shownet/ShowNetPackets.h" namespace ola { namespace plugin { namespace shownet { class ShowNetNode { public: explicit ShowNetNode(const std::string &ip_address); virtual ~ShowNetNode(); bool Start(); bool Stop(); void SetName(const std::string &name); bool SendDMX(unsigned int universe, const ola::DmxBuffer &buffer); bool SetHandler(unsigned int universe, DmxBuffer *buffer, ola::Callback0 *handler); bool RemoveHandler(unsigned int universe); const ola::network::Interface &GetInterface() const { return m_interface; } ola::network::UDPSocket* GetSocket() { return m_socket; } void SocketReady(); static const uint16_t SHOWNET_MAX_UNIVERSES = 8; friend class ShowNetNodeTest; private: typedef struct { DmxBuffer *buffer; Callback0 *closure; } universe_handler; bool m_running; uint16_t m_packet_count; std::string m_node_name; std::string m_preferred_ip; std::map m_handlers; ola::network::Interface m_interface; ola::dmx::RunLengthEncoder m_encoder; ola::network::UDPSocket *m_socket; bool HandlePacket(const shownet_packet *packet, unsigned int size); bool HandleCompressedPacket(const shownet_compressed_dmx *packet, unsigned int packet_size); unsigned int BuildCompressedPacket(shownet_packet *packet, unsigned int universe, const DmxBuffer &buffer); bool InitNetwork(); static const uint16_t SHOWNET_PORT = 2501; // In the shownet spec, the pass(2) and name(9) fields are combined with the // compressed data. This means the indicies referenced in indexBlocks are // off by 11. static const uint16_t MAGIC_INDEX_OFFSET = 11; DISALLOW_COPY_AND_ASSIGN(ShowNetNode); }; } // namespace shownet } // namespace plugin } // namespace ola #endif // PLUGINS_SHOWNET_SHOWNETNODE_H_ ola-0.10.5.nojsmin/plugins/shownet/ShowNetDevice.h0000644000175000017500000000333413023355232021511 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ShowNetDevice.h * Interface for the ShowNet device * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_SHOWNET_SHOWNETDEVICE_H_ #define PLUGINS_SHOWNET_SHOWNETDEVICE_H_ #include #include "olad/Device.h" #include "olad/Plugin.h" namespace ola { namespace plugin { namespace shownet { class ShowNetDevice: public ola::Device { public: ShowNetDevice(Plugin *owner, class Preferences *preferences, class PluginAdaptor *plugin_adaptor); ~ShowNetDevice() {} bool AllowMultiPortPatching() const { return true; } std::string DeviceId() const { return "1"; } static const char IP_KEY[]; protected: bool StartHook(); void PrePortStop(); void PostPortStop(); private: class Preferences *m_preferences; class PluginAdaptor *m_plugin_adaptor; class ShowNetNode *m_node; static const char SHOWNET_DEVICE_NAME[]; }; } // namespace shownet } // namespace plugin } // namespace ola #endif // PLUGINS_SHOWNET_SHOWNETDEVICE_H_ ola-0.10.5.nojsmin/plugins/shownet/ShowNetPort.h0000644000175000017500000000434713023355232021243 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ShowNetPort.h * The ShowNet plugin for ola * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_SHOWNET_SHOWNETPORT_H_ #define PLUGINS_SHOWNET_SHOWNETPORT_H_ #include #include "olad/Port.h" #include "plugins/shownet/ShowNetDevice.h" #include "plugins/shownet/ShowNetNode.h" namespace ola { namespace plugin { namespace shownet { class ShowNetInputPort: public BasicInputPort { public: ShowNetInputPort(ShowNetDevice *parent, unsigned int id, class PluginAdaptor *plugin_adaptor, ShowNetNode *node): BasicInputPort(parent, id, plugin_adaptor), m_node(node) {} ~ShowNetInputPort() {} std::string Description() const; const ola::DmxBuffer &ReadDMX() const { return m_buffer; } bool PreSetUniverse(Universe *old_universe, Universe *new_universe); void PostSetUniverse(Universe *old_universe, Universe *new_universe); private: DmxBuffer m_buffer; ShowNetNode *m_node; }; class ShowNetOutputPort: public BasicOutputPort { public: ShowNetOutputPort(ShowNetDevice *parent, unsigned int id, ShowNetNode *node): BasicOutputPort(parent, id), m_node(node) {} ~ShowNetOutputPort() {} bool PreSetUniverse(Universe *old_universe, Universe *new_universe); std::string Description() const; bool WriteDMX(const ola::DmxBuffer &buffer, uint8_t priority); private: ShowNetNode *m_node; }; } // namespace shownet } // namespace plugin } // namespace ola #endif // PLUGINS_SHOWNET_SHOWNETPORT_H_ ola-0.10.5.nojsmin/plugins/shownet/ShowNetPackets.h0000644000175000017500000000620013023355232021677 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ShowNetPackets.h * Datagram definitions for the ShowNet protocol. * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_SHOWNET_SHOWNETPACKETS_H_ #define PLUGINS_SHOWNET_SHOWNETPACKETS_H_ /** * @namespace ola::plugin::shownet * Some reference info: * https://code.google.com/p/open-lighting/issues/detail?id=218 */ #include "ola/Constants.h" #include "ola/network/IPV4Address.h" #include "ola/network/MACAddress.h" namespace ola { namespace plugin { namespace shownet { enum { SHOWNET_MAC_LENGTH = ola::network::MACAddress::LENGTH }; enum { SHOWNET_NAME_LENGTH = 9 }; enum { SHOWNET_SPARE_LENGTH = 22 }; // Assume this is 512. enum { SHOWNET_DMX_DATA_LENGTH = DMX_UNIVERSE_SIZE }; enum { SHOWNET_COMPRESSED_DATA_LENGTH = 1269 }; enum ShowNetPacketType { DMX_PACKET = 0x202f, COMPRESSED_DMX_PACKET = 0x808f, }; // The old style Shownet DMX packet. Type 0x202f . Apparently this isn't used // much. PACK( struct shownet_dmx_s { uint16_t port; uint16_t slot_length; uint16_t pool_size; uint16_t h_slot; uint32_t sequence; uint8_t priority; // 0 = not used uint8_t universe; // 0 = not used uint16_t spare[SHOWNET_SPARE_LENGTH]; uint8_t dmx_data[SHOWNET_DMX_DATA_LENGTH]; }); typedef struct shownet_dmx_s shownet_dmx; // The 'new' style, compressed shownet packet. Type 0x808f // Each packet can contain up to 4 'blocks' of DMX data. PACK( struct shownet_compressed_dmx_s { uint16_t netSlot[4]; // start channel of each slot (hSlot) uint16_t slotSize[4]; // size of each slot uint16_t indexBlock[5]; // index into data of each slot uint16_t sequence; // not used in n21+ code. uint8_t priority; // not used in n21+ code, 0 = not used uint8_t universe; // not used in n21+ code, 0 = not used uint8_t pass[2]; // something to do with the channels that have // passwords. PasswordNumChans ? char name[SHOWNET_NAME_LENGTH]; // name of console uint8_t data[SHOWNET_COMPRESSED_DATA_LENGTH]; // RLE data. }); typedef struct shownet_compressed_dmx_s shownet_compressed_dmx; // The union of all packets. typedef struct { uint16_t type; // packet type uint8_t ip[ola::network::IPV4Address::LENGTH]; // ip of sender union { shownet_dmx dmx; shownet_compressed_dmx compressed_dmx; } data; } shownet_packet; } // namespace shownet } // namespace plugin } // namespace ola #endif // PLUGINS_SHOWNET_SHOWNETPACKETS_H_ ola-0.10.5.nojsmin/plugins/shownet/ShowNetPlugin.h0000644000175000017500000000347613023355232021557 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ShowNetPlugin.h * Interface for the ShowNet plugin class * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_SHOWNET_SHOWNETPLUGIN_H_ #define PLUGINS_SHOWNET_SHOWNETPLUGIN_H_ #include #include "olad/Plugin.h" #include "ola/plugin_id.h" namespace ola { namespace plugin { namespace shownet { class ShowNetDevice; class ShowNetPlugin: public Plugin { public: explicit ShowNetPlugin(PluginAdaptor *plugin_adaptor): Plugin(plugin_adaptor), m_device(NULL) {} ~ShowNetPlugin() {} std::string Name() const { return PLUGIN_NAME; } ola_plugin_id Id() const { return OLA_PLUGIN_SHOWNET; } std::string Description() const; std::string PluginPrefix() const { return PLUGIN_PREFIX; } private: bool StartHook(); bool StopHook(); bool SetDefaultPreferences(); ShowNetDevice *m_device; static const char SHOWNET_NODE_NAME[]; static const char PLUGIN_NAME[]; static const char PLUGIN_PREFIX[]; static const char SHOWNET_NAME_KEY[]; }; } // namespace shownet } // namespace plugin } // namespace ola #endif // PLUGINS_SHOWNET_SHOWNETPLUGIN_H_ ola-0.10.5.nojsmin/plugins/Makefile.mk0000644000175000017500000000144613023355232017212 0ustar wouterwouterinclude plugins/artnet/Makefile.mk include plugins/dummy/Makefile.mk include plugins/espnet/Makefile.mk include plugins/ftdidmx/Makefile.mk include plugins/gpio/Makefile.mk include plugins/karate/Makefile.mk include plugins/kinet/Makefile.mk include plugins/milinst/Makefile.mk include plugins/opendmx/Makefile.mk include plugins/openpixelcontrol/Makefile.mk include plugins/osc/Makefile.mk include plugins/pathport/Makefile.mk include plugins/renard/Makefile.mk include plugins/sandnet/Makefile.mk include plugins/shownet/Makefile.mk include plugins/spi/Makefile.mk include plugins/stageprofi/Makefile.mk include plugins/usbdmx/Makefile.mk if !USING_WIN32 include plugins/usbpro/Makefile.mk include plugins/dmx4linux/Makefile.mk include plugins/e131/Makefile.mk include plugins/uartdmx/Makefile.mk endif ola-0.10.5.nojsmin/plugins/e131/0000755000175000017500000000000013155164170015615 5ustar wouterwouterola-0.10.5.nojsmin/plugins/e131/E131Port.h0000644000175000017500000000632613023355232017246 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E131Port.h * The E1.31 port for OLA * Copyright (C) 2007 Simon Newton */ #ifndef PLUGINS_E131_E131PORT_H_ #define PLUGINS_E131_E131PORT_H_ #include #include "olad/Port.h" #include "plugins/e131/E131Device.h" #include "libs/acn/E131Node.h" namespace ola { namespace plugin { namespace e131 { class E131PortHelper { public: bool PreSetUniverse(Universe *old_universe, Universe *new_universe); std::string Description(Universe *universe) const; private: static const unsigned int MAX_E131_UNIVERSE = 63999; }; class E131InputPort: public BasicInputPort { public: E131InputPort(E131Device *parent, int id, ola::acn::E131Node *node, class PluginAdaptor *plugin_adaptor) : BasicInputPort(parent, id, plugin_adaptor), m_node(node), m_priority(ola::dmx::SOURCE_PRIORITY_DEFAULT) { SetPriorityMode(PRIORITY_MODE_INHERIT); } bool PreSetUniverse(Universe *old_universe, Universe *new_universe) { return m_helper.PreSetUniverse(old_universe, new_universe); } void PostSetUniverse(Universe *old_universe, Universe *new_universe); std::string Description() const { return m_helper.Description(GetUniverse()); } const ola::DmxBuffer &ReadDMX() const { return m_buffer; } bool SupportsPriorities() const { return true; } uint8_t InheritedPriority() const { return m_priority; } private: ola::DmxBuffer m_buffer; ola::acn::E131Node *m_node; E131PortHelper m_helper; uint8_t m_priority; }; class E131OutputPort: public BasicOutputPort { public: E131OutputPort(E131Device *parent, int id, ola::acn::E131Node *node) : BasicOutputPort(parent, id), m_preview_on(false), m_node(node) { m_last_priority = GetPriority(); } ~E131OutputPort(); bool PreSetUniverse(Universe *old_universe, Universe *new_universe) { return m_helper.PreSetUniverse(old_universe, new_universe); } void PostSetUniverse(Universe *old_universe, Universe *new_universe); std::string Description() const { return m_helper.Description(GetUniverse()); } bool WriteDMX(const ola::DmxBuffer &buffer, uint8_t priority); void SetPreviewMode(bool preview_mode) { m_preview_on = preview_mode; } bool PreviewMode() const { return m_preview_on; } bool SupportsPriorities() const { return true; } private: bool m_preview_on; uint8_t m_last_priority; ola::DmxBuffer m_buffer; ola::acn::E131Node *m_node; E131PortHelper m_helper; }; } // namespace e131 } // namespace plugin } // namespace ola #endif // PLUGINS_E131_E131PORT_H_ ola-0.10.5.nojsmin/plugins/e131/Makefile.mk0000644000175000017500000000117413134123277017666 0ustar wouterwouterinclude plugins/e131/messages/Makefile.mk # LIBRARIES ################################################## if USE_E131 lib_LTLIBRARIES += plugins/e131/libolae131.la plugins_e131_libolae131_la_SOURCES = \ plugins/e131/E131Device.cpp \ plugins/e131/E131Device.h \ plugins/e131/E131Plugin.cpp \ plugins/e131/E131Plugin.h \ plugins/e131/E131Port.cpp \ plugins/e131/E131Port.h plugins_e131_libolae131_la_CXXFLAGS = $(COMMON_PROTOBUF_CXXFLAGS) plugins_e131_libolae131_la_LIBADD = \ olad/plugin_api/libolaserverplugininterface.la \ plugins/e131/messages/libolae131conf.la \ libs/acn/libolae131core.la endif ola-0.10.5.nojsmin/plugins/e131/messages/0000755000175000017500000000000013134123611017414 5ustar wouterwouterola-0.10.5.nojsmin/plugins/e131/messages/E131ConfigMessages.proto0000644000175000017500000000462313023355232023740 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E131ConfigMessages.proto * Defines the protocol buffers used to configure the Artnet device * Copyright (C) 2005 Simon Newton */ package ola.plugin.e131; /* * Controls the preview bit for output ports. */ message PreviewModeRequest { required int32 port_id = 1; required bool preview_mode = 2; required bool input_port = 3; } message InputPortInfo { required int32 port_id = 1; required bool preview_mode = 2; } message OutputPortInfo { required int32 port_id = 1; required bool preview_mode = 2; } /* * Contains the status of input & output ports */ message PortInfoReply { repeated InputPortInfo input_port = 1; repeated OutputPortInfo output_port = 2; } /** * The SourceList request message. */ message SourceListRequest { // No options for now. } message SourceEntry { // The CID of the source required string cid = 1; // The IP address of the source required string ip_address = 2; // The name of the source optional string source_name = 3; // The universes reported by the source. repeated int32 universe = 4; } message SourceListReply { // True if discovery wasn't enabled optional bool unsupported = 1 [ default = true ]; repeated SourceEntry source = 2; } /* * A generic request */ message Request { enum RequestType { E131_PORT_INFO = 1; E131_PREVIEW_MODE = 2; E131_SOURCES_LIST = 3; } required RequestType type = 1; optional PreviewModeRequest preview_mode = 2; optional SourceListRequest source_list = 3; } message Reply { enum ReplyType { E131_PORT_INFO = 1; E131_SOURCES_LIST = 2; } required ReplyType type = 1; optional PortInfoReply port_info = 2; optional SourceListReply source_list = 3; } ola-0.10.5.nojsmin/plugins/e131/messages/Makefile.mk0000644000175000017500000000233413023355232021467 0ustar wouterwouter# The E1.31 plugin config messages. This needs to be available to client # programs. EXTRA_DIST += plugins/e131/messages/E131ConfigMessages.proto # pkg-config ################################################## pkgconfig_DATA += plugins/e131/messages/libolae131conf.pc # LIBRARIES ################################################## if USE_E131 lib_LTLIBRARIES += plugins/e131/messages/libolae131conf.la e131includedir = $(includedir)/ola/e131 nodist_e131include_HEADERS = \ plugins/e131/messages/E131ConfigMessages.pb.h built_sources += plugins/e131/messages/E131ConfigMessages.pb.cc \ plugins/e131/messages/E131ConfigMessages.pb.h nodist_plugins_e131_messages_libolae131conf_la_SOURCES = \ plugins/e131/messages/E131ConfigMessages.pb.cc plugins_e131_messages_libolae131conf_la_CXXFLAGS = $(COMMON_PROTOBUF_CXXFLAGS) plugins_e131_messages_libolae131conf_la_LIBADD = $(libprotobuf_LIBS) plugins/e131/messages/E131ConfigMessages.pb.cc plugins/e131/messages/E131ConfigMessages.pb.h: plugins/e131/messages/Makefile.mk plugins/e131/messages/E131ConfigMessages.proto $(PROTOC) --cpp_out plugins/e131/messages/ --proto_path $(srcdir)/plugins/e131/messages/ $(srcdir)/plugins/e131/messages/E131ConfigMessages.proto endif ola-0.10.5.nojsmin/plugins/e131/messages/libolae131conf.pc.in0000644000175000017500000000040613023355232023052 0ustar wouterwouterprefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libolae131conf Version: @VERSION@ Description: Open Lighting Architecture - E1.31 Config Messages Requires: protobuf Libs: -L${libdir} -lolae131conf Cflags: -I${includedir} ola-0.10.5.nojsmin/plugins/e131/E131Plugin.cpp0000644000175000017500000001551413023355232020112 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E131Plugin.cpp * The E1.31 plugin for ola * Copyright (C) 2007 Simon Newton */ #include #include #include "ola/Logging.h" #include "ola/network/NetworkUtils.h" #include "ola/StringUtils.h" #include "ola/acn/CID.h" #include "olad/PluginAdaptor.h" #include "olad/Preferences.h" #include "plugins/e131/E131Device.h" #include "plugins/e131/E131Plugin.h" namespace ola { namespace plugin { namespace e131 { using ola::acn::CID; using std::string; const char E131Plugin::CID_KEY[] = "cid"; const unsigned int E131Plugin::DEFAULT_DSCP_VALUE = 0; const char E131Plugin::DSCP_KEY[] = "dscp"; const char E131Plugin::DRAFT_DISCOVERY_KEY[] = "draft_discovery"; const char E131Plugin::IGNORE_PREVIEW_DATA_KEY[] = "ignore_preview"; const char E131Plugin::INPUT_PORT_COUNT_KEY[] = "input_ports"; const char E131Plugin::IP_KEY[] = "ip"; const char E131Plugin::OUTPUT_PORT_COUNT_KEY[] = "output_ports"; const char E131Plugin::PLUGIN_NAME[] = "E1.31 (sACN)"; const char E131Plugin::PLUGIN_PREFIX[] = "e131"; const char E131Plugin::PREPEND_HOSTNAME_KEY[] = "prepend_hostname"; const char E131Plugin::REVISION_0_2[] = "0.2"; const char E131Plugin::REVISION_0_46[] = "0.46"; const char E131Plugin::REVISION_KEY[] = "revision"; const unsigned int E131Plugin::DEFAULT_PORT_COUNT = 5; /* * Start the plugin */ bool E131Plugin::StartHook() { CID cid = CID::FromString(m_preferences->GetValue(CID_KEY)); string ip_addr = m_preferences->GetValue(IP_KEY); E131Device::E131DeviceOptions options; options.use_rev2 = (m_preferences->GetValue(REVISION_KEY) == REVISION_0_2); options.ignore_preview = m_preferences->GetValueAsBool( IGNORE_PREVIEW_DATA_KEY); options.enable_draft_discovery = m_preferences->GetValueAsBool( DRAFT_DISCOVERY_KEY); if (m_preferences->GetValueAsBool(PREPEND_HOSTNAME_KEY)) { std::ostringstream str; str << ola::network::Hostname() << "-" << m_plugin_adaptor->InstanceName(); options.source_name = str.str(); } else { options.source_name = m_plugin_adaptor->InstanceName(); } unsigned int dscp; if (!StringToInt(m_preferences->GetValue(DSCP_KEY), &dscp)) { OLA_WARN << "Can't convert dscp value " << m_preferences->GetValue(DSCP_KEY) << " to int"; options.dscp = 0; } else { // shift 2 bits left options.dscp = dscp << 2; } if (!StringToInt(m_preferences->GetValue(INPUT_PORT_COUNT_KEY), &options.input_ports)) { OLA_WARN << "Invalid value for input_ports"; } if (!StringToInt(m_preferences->GetValue(OUTPUT_PORT_COUNT_KEY), &options.output_ports)) { OLA_WARN << "Invalid value for input_ports"; } m_device = new E131Device(this, cid, ip_addr, m_plugin_adaptor, options); if (!m_device->Start()) { delete m_device; return false; } m_plugin_adaptor->RegisterDevice(m_device); return true; } /* * Stop the plugin * @return true on success, false on failure */ bool E131Plugin::StopHook() { if (m_device) { m_plugin_adaptor->UnregisterDevice(m_device); bool ret = m_device->Stop(); delete m_device; return ret; } return true; } /* * Return the description for this plugin */ string E131Plugin::Description() const { return "E1.31 (Streaming DMX over ACN) Plugin\n" "----------------------------\n" "\n" "This plugin creates a single device with a configurable number of input \n" "and output ports.\n" "\n" "Each port can be assigned to a different E1.31 Universe.\n" "\n" "--- Config file : ola-e131.conf ---\n" "\n" "cid = 00010203-0405-0607-0809-0A0B0C0D0E0F\n" "The CID to use for this device.\n" "\n" "dscp = [int]\n" "The DSCP value to tag the packets with, range is 0 to 63.\n" "\n" "draft_discovery = [bool]\n" "Enable the draft (2014) E1.31 discovery protocol.\n" "\n" "ignore_preview = [true|false]\n" "Ignore preview data.\n" "\n" "input_ports = [int]\n" "The number of input ports to create up to a max of 32.\n" "\n" "ip = [a.b.c.d|]\n" "The ip address or interface name to bind to. If not specified it will\n" "use the first non-loopback interface.\n" "\n" "output_ports = [int]\n" "The number of output ports to create up to a max of 32.\n" "\n" "prepend_hostname = [true|false]\n" "Prepend the hostname to the source name when sending packets.\n" "\n" "revision = [0.2|0.46]\n" "Select which revision of the standard to use when sending data. 0.2 is the\n" " standardized revision, 0.46 (default) is the ANSI standard version.\n" "\n"; } /* * Load the plugin prefs and default to sensible values * */ bool E131Plugin::SetDefaultPreferences() { if (!m_preferences) return false; bool save = false; CID cid = CID::FromString(m_preferences->GetValue(CID_KEY)); if (cid.IsNil()) { cid = CID::Generate(); m_preferences->SetValue(CID_KEY, cid.ToString()); save = true; } save |= m_preferences->SetDefaultValue( DSCP_KEY, UIntValidator(0, 63), DEFAULT_DSCP_VALUE); save |= m_preferences->SetDefaultValue( DRAFT_DISCOVERY_KEY, BoolValidator(), false); save |= m_preferences->SetDefaultValue( IGNORE_PREVIEW_DATA_KEY, BoolValidator(), true); save |= m_preferences->SetDefaultValue( INPUT_PORT_COUNT_KEY, UIntValidator(0, 512), DEFAULT_PORT_COUNT); save |= m_preferences->SetDefaultValue( OUTPUT_PORT_COUNT_KEY, UIntValidator(0, 512), DEFAULT_PORT_COUNT); save |= m_preferences->SetDefaultValue(IP_KEY, StringValidator(true), ""); save |= m_preferences->SetDefaultValue( PREPEND_HOSTNAME_KEY, BoolValidator(), true); std::set revision_values; revision_values.insert(REVISION_0_2); revision_values.insert(REVISION_0_46); save |= m_preferences->SetDefaultValue( REVISION_KEY, SetValidator(revision_values), REVISION_0_46); if (save) { m_preferences->Save(); } // check if this saved correctly // we don't want to use it if null string revision = m_preferences->GetValue(REVISION_KEY); if (m_preferences->GetValue(CID_KEY).empty() || (revision != REVISION_0_2 && revision != REVISION_0_46)) { return false; } return true; } } // namespace e131 } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/e131/E131Device.h0000644000175000017500000000546013023355232017517 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E131Device.h * Interface for the E1.31 device * Copyright (C) 2007 Simon Newton */ #ifndef PLUGINS_E131_E131DEVICE_H_ #define PLUGINS_E131_E131DEVICE_H_ #include #include #include #include "libs/acn/E131Node.h" #include "ola/acn/CID.h" #include "olad/Device.h" #include "olad/Plugin.h" #include "plugins/e131/messages/E131ConfigMessages.pb.h" namespace ola { namespace plugin { namespace e131 { class E131InputPort; class E131OutputPort; class E131Device: public ola::Device { public: struct E131DeviceOptions : public ola::acn::E131Node::Options { public: E131DeviceOptions() : ola::acn::E131Node::Options(), input_ports(0), output_ports(0) { } unsigned int input_ports; unsigned int output_ports; }; E131Device(ola::Plugin *owner, const ola::acn::CID &cid, std::string ip_addr, class PluginAdaptor *plugin_adaptor, const E131DeviceOptions &options); std::string DeviceId() const { return "1"; } void Configure(ola::rpc::RpcController *controller, const std::string &request, std::string *response, ConfigureCallback *done); protected: bool StartHook(); void PrePortStop(); void PostPortStop(); private: class PluginAdaptor *m_plugin_adaptor; std::auto_ptr m_node; const E131DeviceOptions m_options; std::vector m_input_ports; std::vector m_output_ports; std::string m_ip_addr; ola::acn::CID m_cid; void HandlePreviewMode(const ola::plugin::e131::Request *request, std::string *response); void HandlePortStatusRequest(std::string *response); void HandleSourceListRequest(const ola::plugin::e131::Request *request, std::string *response); E131InputPort *GetE131InputPort(unsigned int port_id); E131OutputPort *GetE131OutputPort(unsigned int port_id); static const char DEVICE_NAME[]; }; } // namespace e131 } // namespace plugin } // namespace ola #endif // PLUGINS_E131_E131DEVICE_H_ ola-0.10.5.nojsmin/plugins/e131/E131Port.cpp0000644000175000017500000000577613023355232017611 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E131Port.cpp * The E1.31 plugin for ola * Copyright (C) 2007 Simon Newton */ #include #include "ola/Logging.h" #include "olad/Universe.h" #include "plugins/e131/E131Port.h" #include "plugins/e131/E131Device.h" namespace ola { namespace plugin { namespace e131 { using std::string; bool E131PortHelper::PreSetUniverse(Universe *old_universe, Universe *new_universe) { if (new_universe && (new_universe->UniverseId() == 0 || new_universe->UniverseId() > MAX_E131_UNIVERSE)) { OLA_WARN << "Universe id " << new_universe->UniverseId() << " is 0 or > " << MAX_E131_UNIVERSE; return false; } (void) old_universe; return true; } string E131PortHelper::Description(Universe *universe) const { std::ostringstream str; if (universe) str << "E1.31 Universe " << universe->UniverseId(); return str.str(); } /* * Set the universe for an input port. */ void E131InputPort::PostSetUniverse(Universe *old_universe, Universe *new_universe) { if (old_universe) m_node->RemoveHandler(old_universe->UniverseId()); if (new_universe) m_node->SetHandler( new_universe->UniverseId(), &m_buffer, &m_priority, NewCallback(this, &E131InputPort::DmxChanged)); } E131OutputPort::~E131OutputPort() { Universe *universe = GetUniverse(); if (universe) { m_node->TerminateStream(universe->UniverseId(), m_last_priority); } } /* * Set the universe for an output port. */ void E131OutputPort::PostSetUniverse(Universe *old_universe, Universe *new_universe) { if (old_universe) { m_node->TerminateStream(old_universe->UniverseId(), m_last_priority); } if (new_universe) { m_node->StartStream(new_universe->UniverseId()); } } /* * Write data to this port. */ bool E131OutputPort::WriteDMX(const DmxBuffer &buffer, uint8_t priority) { Universe *universe = GetUniverse(); if (!universe) return false; m_last_priority = (GetPriorityMode() == PRIORITY_MODE_STATIC) ? GetPriority() : priority; return m_node->SendDMX(universe->UniverseId(), buffer, m_last_priority, m_preview_on); } } // namespace e131 } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/e131/E131Device.cpp0000644000175000017500000001654613023355232020061 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E131Device.cpp * An E1.31 device * Copyright (C) 2007 Simon Newton * * Ids 0-3 : Input ports (recv dmx) * Ids 4-7 : Output ports (send dmx) */ #include #include #include #include #include #include #include "common/rpc/RpcController.h" #include "ola/CallbackRunner.h" #include "ola/Logging.h" #include "ola/network/NetworkUtils.h" #include "olad/Plugin.h" #include "olad/PluginAdaptor.h" #include "olad/Preferences.h" #include "plugins/e131/E131Device.h" #include "plugins/e131/E131Port.h" #include "libs/acn/E131Node.h" namespace ola { namespace plugin { namespace e131 { const char E131Device::DEVICE_NAME[] = "E1.31 (DMX over ACN)"; using ola::acn::E131Node; using ola::rpc::RpcController; using std::ostringstream; using std::set; using std::string; using std::vector; /* * Create a new device */ E131Device::E131Device(Plugin *owner, const ola::acn::CID &cid, string ip_addr, PluginAdaptor *plugin_adaptor, const E131DeviceOptions &options) : Device(owner, DEVICE_NAME), m_plugin_adaptor(plugin_adaptor), m_options(options), m_ip_addr(ip_addr), m_cid(cid) { } /* * Start this device */ bool E131Device::StartHook() { m_node.reset(new E131Node(m_plugin_adaptor, m_ip_addr, m_options, m_cid)); if (!m_node->Start()) { m_node.reset(); DeleteAllPorts(); return false; } ostringstream str; str << DEVICE_NAME << " [" << m_node->GetInterface().ip_address << "]"; SetName(str.str()); for (unsigned int i = 0; i < m_options.input_ports; i++) { E131InputPort *input_port = new E131InputPort( this, i, m_node.get(), m_plugin_adaptor); AddPort(input_port); m_input_ports.push_back(input_port); } for (unsigned int i = 0; i < m_options.output_ports; i++) { E131OutputPort *output_port = new E131OutputPort( this, i, m_node.get()); AddPort(output_port); m_output_ports.push_back(output_port); } m_plugin_adaptor->AddReadDescriptor(m_node->GetSocket()); return true; } /* * Stop this device */ void E131Device::PrePortStop() { m_plugin_adaptor->RemoveReadDescriptor(m_node->GetSocket()); } /* * Stop this device */ void E131Device::PostPortStop() { m_node->Stop(); m_node.reset(); } /* * Handle device config messages * @param controller An RpcController * @param request the request data * @param response the response to return * @param done the closure to call once the request is complete */ void E131Device::Configure(RpcController *controller, const string &request, string *response, ConfigureCallback *done) { CallbackRunner runner(done); Request request_pb; if (!request_pb.ParseFromString(request)) { controller->SetFailed("Invalid Request"); return; } switch (request_pb.type()) { case ola::plugin::e131::Request::E131_PORT_INFO: HandlePortStatusRequest(response); break; case ola::plugin::e131::Request::E131_PREVIEW_MODE: HandlePreviewMode(&request_pb, response); break; case ola::plugin::e131::Request::E131_SOURCES_LIST: HandleSourceListRequest(&request_pb, response); break; default: controller->SetFailed("Invalid Request"); } } /* * Handle a preview mode request. */ void E131Device::HandlePreviewMode(const Request *request, string *response) { if (request->has_preview_mode()) { const ola::plugin::e131::PreviewModeRequest preview_request = request->preview_mode(); unsigned int port_id = preview_request.port_id(); bool preview_mode = preview_request.preview_mode(); if (preview_request.input_port()) { E131InputPort *e131_port = GetE131InputPort(port_id); if (e131_port) { // TODO(simon): figure out what to do here (void) e131_port; } } else { E131OutputPort *e131_port = GetE131OutputPort(port_id); if (e131_port) { e131_port->SetPreviewMode(preview_mode); } } } HandlePortStatusRequest(response); } /* * Handle an options request */ void E131Device::HandlePortStatusRequest(string *response) { ola::plugin::e131::Reply reply; reply.set_type(ola::plugin::e131::Reply::E131_PORT_INFO); ola::plugin::e131::PortInfoReply *port_reply = reply.mutable_port_info(); vector::iterator input_iter = m_input_ports.begin(); for (; input_iter != m_input_ports.end(); ++input_iter) { ola::plugin::e131::InputPortInfo *input_port = port_reply->add_input_port(); input_port->set_port_id((*input_iter)->PortId()); input_port->set_preview_mode(m_options.ignore_preview); } vector::iterator output_iter = m_output_ports.begin(); for (; output_iter != m_output_ports.end(); ++output_iter) { ola::plugin::e131::OutputPortInfo *output_port = port_reply->add_output_port(); output_port->set_port_id((*output_iter)->PortId()); output_port->set_preview_mode((*output_iter)->PreviewMode()); } reply.SerializeToString(response); } void E131Device::HandleSourceListRequest(const Request *request, string *response) { typedef std::vector KnownControllerList; (void) request; ola::plugin::e131::Reply reply; reply.set_type(ola::plugin::e131::Reply::E131_SOURCES_LIST); ola::plugin::e131::SourceListReply *sources_reply = reply.mutable_source_list(); if (!m_options.enable_draft_discovery) { sources_reply->set_unsupported(true); } else { sources_reply->set_unsupported(false); KnownControllerList controllers; m_node->GetKnownControllers(&controllers); KnownControllerList::const_iterator iter = controllers.begin(); for (; iter != controllers.end(); ++iter) { ola::plugin::e131::SourceEntry *entry = sources_reply->add_source(); entry->set_cid(iter->cid.ToString()); entry->set_ip_address(iter->ip_address.ToString()); entry->set_source_name(iter->source_name); set::const_iterator uni_iter = iter->universes.begin(); for (; uni_iter != iter->universes.end(); ++uni_iter) { entry->add_universe(*uni_iter); } } } reply.SerializeToString(response); } E131InputPort *E131Device::GetE131InputPort(unsigned int port_id) { return (port_id < m_input_ports.size()) ? m_input_ports[port_id] : NULL; } E131OutputPort *E131Device::GetE131OutputPort(unsigned int port_id) { return (port_id < m_output_ports.size()) ? m_output_ports[port_id] : NULL; } } // namespace e131 } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/e131/E131Plugin.h0000644000175000017500000000435513023355232017560 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * E131Plugin.h * Interface for the E1.131 plugin class * Copyright (C) 2007 Simon Newton */ #ifndef PLUGINS_E131_E131PLUGIN_H_ #define PLUGINS_E131_E131PLUGIN_H_ #include #include "olad/Plugin.h" #include "ola/plugin_id.h" namespace ola { namespace plugin { namespace e131 { class E131Device; class E131Plugin: public ola::Plugin { public: explicit E131Plugin(ola::PluginAdaptor *plugin_adaptor): ola::Plugin(plugin_adaptor), m_device(NULL) {} ~E131Plugin() {} std::string Name() const { return PLUGIN_NAME; } ola_plugin_id Id() const { return OLA_PLUGIN_E131; } std::string Description() const; std::string PluginPrefix() const { return PLUGIN_PREFIX; } private: bool StartHook(); bool StopHook(); bool SetDefaultPreferences(); E131Device *m_device; static const char CID_KEY[]; static const unsigned int DEFAULT_DSCP_VALUE; static const unsigned int DEFAULT_PORT_COUNT; static const char DRAFT_DISCOVERY_KEY[]; static const char DSCP_KEY[]; static const char IGNORE_PREVIEW_DATA_KEY[]; static const char INPUT_PORT_COUNT_KEY[]; static const char IP_KEY[]; static const char OUTPUT_PORT_COUNT_KEY[]; static const char PLUGIN_NAME[]; static const char PLUGIN_PREFIX[]; static const char PREPEND_HOSTNAME_KEY[]; static const char REVISION_0_2[]; static const char REVISION_0_46[]; static const char REVISION_KEY[]; }; } // namespace e131 } // namespace plugin } // namespace ola #endif // PLUGINS_E131_E131PLUGIN_H_ ola-0.10.5.nojsmin/plugins/milinst/0000755000175000017500000000000013155164170016623 5ustar wouterwouterola-0.10.5.nojsmin/plugins/milinst/MilInstPort.h0000644000175000017500000000306313023355232021215 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * MilInstPort.h * The MilInst plugin for ola * Copyright (C) 2013 Peter Newman */ #ifndef PLUGINS_MILINST_MILINSTPORT_H_ #define PLUGINS_MILINST_MILINSTPORT_H_ #include #include "plugins/milinst/MilInstDevice.h" #include "plugins/milinst/MilInstWidget.h" namespace ola { namespace plugin { namespace milinst { class MilInstOutputPort: public BasicOutputPort { public: MilInstOutputPort(MilInstDevice *parent, unsigned int id, MilInstWidget *widget) : BasicOutputPort(parent, id), m_widget(widget) {} bool WriteDMX(const DmxBuffer &buffer, uint8_t priority); std::string Description() const { return m_widget->Description(); } private: MilInstWidget *m_widget; }; } // namespace milinst } // namespace plugin } // namespace ola #endif // PLUGINS_MILINST_MILINSTPORT_H_ ola-0.10.5.nojsmin/plugins/milinst/MilInstWidget1463.h0000644000175000017500000000323513023355232022033 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * MilInstWidget1463.h * Interface for the MilInst 1-463 device * Copyright (C) 2013 Peter Newman */ #ifndef PLUGINS_MILINST_MILINSTWIDGET1463_H_ #define PLUGINS_MILINST_MILINSTWIDGET1463_H_ #include #include "plugins/milinst/MilInstWidget.h" namespace ola { namespace plugin { namespace milinst { class MilInstWidget1463: public MilInstWidget { public: explicit MilInstWidget1463(const std::string &path): MilInstWidget(path) {} ~MilInstWidget1463() {} bool Connect(); bool DetectDevice(); bool SendDmx(const DmxBuffer &buffer) const; std::string Type() { return "Milford Instruments 1-463 Widget"; } protected: int SetChannel(unsigned int chan, uint8_t val) const; int Send112(const DmxBuffer &buffer) const; // This interface can only transmit 112 channels enum { DMX_MAX_TRANSMIT_CHANNELS = 112 }; }; } // namespace milinst } // namespace plugin } // namespace ola #endif // PLUGINS_MILINST_MILINSTWIDGET1463_H_ ola-0.10.5.nojsmin/plugins/milinst/Makefile.mk0000644000175000017500000000141713023355232020667 0ustar wouterwouter# LIBRARIES ################################################## if USE_MILINST lib_LTLIBRARIES += plugins/milinst/libolamilinst.la plugins_milinst_libolamilinst_la_SOURCES = \ plugins/milinst/MilInstDevice.cpp \ plugins/milinst/MilInstDevice.h \ plugins/milinst/MilInstPlugin.cpp \ plugins/milinst/MilInstPlugin.h \ plugins/milinst/MilInstPort.cpp \ plugins/milinst/MilInstPort.h \ plugins/milinst/MilInstWidget.cpp \ plugins/milinst/MilInstWidget.h \ plugins/milinst/MilInstWidget1463.cpp \ plugins/milinst/MilInstWidget1463.h \ plugins/milinst/MilInstWidget1553.cpp \ plugins/milinst/MilInstWidget1553.h plugins_milinst_libolamilinst_la_LIBADD = \ common/libolacommon.la \ olad/plugin_api/libolaserverplugininterface.la endif ola-0.10.5.nojsmin/plugins/milinst/MilInstPort.cpp0000644000175000017500000000217113023355232021547 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * MilInstPort.cpp * The MilInst plugin for ola * Copyright (C) 2013 Peter Newman */ #include "plugins/milinst/MilInstPort.h" namespace ola { namespace plugin { namespace milinst { bool MilInstOutputPort::WriteDMX(const DmxBuffer &buffer, OLA_UNUSED uint8_t priority) { return m_widget->SendDmx(buffer); } } // namespace milinst } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/milinst/MilInstPlugin.cpp0000644000175000017500000001106113023355232022057 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * MilInstPlugin.cpp * The Milford Instruments plugin for ola * Copyright (C) 2013 Peter Newman */ #include #include #include "ola/Logging.h" #include "olad/PluginAdaptor.h" #include "olad/Preferences.h" #include "plugins/milinst/MilInstDevice.h" #include "plugins/milinst/MilInstPlugin.h" namespace ola { namespace plugin { namespace milinst { using ola::io::ConnectedDescriptor; using std::string; using std::vector; // Blank default path, so we don't start using a serial port without being asked const char MilInstPlugin::MILINST_DEVICE_PATH[] = ""; const char MilInstPlugin::PLUGIN_NAME[] = "Milford Instruments"; const char MilInstPlugin::PLUGIN_PREFIX[] = "milinst"; const char MilInstPlugin::DEVICE_KEY[] = "device"; /* * Start the plugin */ bool MilInstPlugin::StartHook() { vector device_names; vector::iterator it; MilInstDevice *device; // fetch device listing device_names = m_preferences->GetMultipleValue(DEVICE_KEY); for (it = device_names.begin(); it != device_names.end(); ++it) { if (it->empty()) { OLA_DEBUG << "No path configured for device, please set one in " "ola-milinst.conf"; continue; } device = new MilInstDevice(this, m_preferences, *it); OLA_DEBUG << "Adding device " << *it; if (!device->Start()) { delete device; continue; } OLA_DEBUG << "Started device " << *it; m_plugin_adaptor->AddReadDescriptor(device->GetSocket()); m_plugin_adaptor->RegisterDevice(device); m_devices.push_back(device); } return true; } /* * Stop the plugin * @return true on success, false on failure */ bool MilInstPlugin::StopHook() { vector::iterator iter; for (iter = m_devices.begin(); iter != m_devices.end(); ++iter) { m_plugin_adaptor->RemoveReadDescriptor((*iter)->GetSocket()); DeleteDevice(*iter); } m_devices.clear(); return true; } /* * Return the description for this plugin */ string MilInstPlugin::Description() const { return "Milford Instruments Plugin\n" "----------------------------\n" "\n" "This plugin creates devices with one output port. It currently supports the " "1-463 DMX Protocol Converter and 1-553 512 Channel Serial to DMX " "Transmitter.\n" "\n" "--- Config file : ola-milinst.conf ---\n" "\n" "device = /dev/ttyS0\n" "The device to use as a path for the serial port. Multiple devices are " "supported.\n" "--- Per Device Settings ---\n" "-type = [1-463 | 1-553]\n" "The type of interface.\n" "\n" "--- 1-553 Specific Per Device Settings ---\n" "-baudrate = [9600 | 19200]\n" "The baudrate to connect at.\n" "\n" "-channels = [128 | 256 | 512]\n" "The number of channels to send.\n" "\n"; } /* * Called when the file descriptor is closed. */ int MilInstPlugin::SocketClosed(ConnectedDescriptor *socket) { vector::iterator iter; for (iter = m_devices.begin(); iter != m_devices.end(); ++iter) { if ((*iter)->GetSocket() == socket) { break; } } if (iter == m_devices.end()) { OLA_WARN << "unknown fd"; return -1; } DeleteDevice(*iter); m_devices.erase(iter); return 0; } /* * load the plugin prefs and default to sensible values * */ bool MilInstPlugin::SetDefaultPreferences() { if (!m_preferences) { return false; } bool save = false; save |= m_preferences->SetDefaultValue(DEVICE_KEY, StringValidator(), MILINST_DEVICE_PATH); if (save) { m_preferences->Save(); } // Just check key exists, as we've set it to "" if (!m_preferences->HasKey(DEVICE_KEY)) { return false; } return true; } /* * Cleanup a single device */ void MilInstPlugin::DeleteDevice(MilInstDevice *device) { m_plugin_adaptor->UnregisterDevice(device); device->Stop(); delete device; } } // namespace milinst } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/milinst/MilInstDevice.h0000644000175000017500000000346513023355232021476 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * MilInstDevice.h * Interface for the milinst device * Copyright (C) 2013 Peter Newman */ #ifndef PLUGINS_MILINST_MILINSTDEVICE_H_ #define PLUGINS_MILINST_MILINSTDEVICE_H_ #include #include #include "olad/Device.h" namespace ola { class AbstractPlugin; namespace plugin { namespace milinst { class MilInstDevice: public ola::Device { public: MilInstDevice(AbstractPlugin *owner, class Preferences *preferences, const std::string &dev_path); ~MilInstDevice(); std::string DeviceId() const { return m_path; } ola::io::ConnectedDescriptor *GetSocket() const; protected: bool StartHook(); void PrePortStop(); private: std::string m_path; class Preferences *m_preferences; std::auto_ptr m_widget; static const char MILINST_DEVICE_NAME[]; // Per device options std::string DeviceTypeKey() const; void SetDeviceDefaults(); static const char TYPE_1463[]; static const char TYPE_1553[]; }; } // namespace milinst } // namespace plugin } // namespace ola #endif // PLUGINS_MILINST_MILINSTDEVICE_H_ ola-0.10.5.nojsmin/plugins/milinst/MilInstWidget.cpp0000644000175000017500000000376313023355232022056 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * MilInstWidget.cpp * This is the base widget class * Copyright (C) 2013 Peter Newman */ #include #include "ola/Logging.h" #include "ola/io/IOUtils.h" #include "plugins/milinst/MilInstWidget.h" namespace ola { namespace plugin { namespace milinst { using std::string; /* * New widget */ MilInstWidget::~MilInstWidget() { if (m_socket) { m_socket->Close(); delete m_socket; } } /* * Connect to the widget */ int MilInstWidget::ConnectToWidget(const string &path, speed_t speed) { struct termios newtio; if (path.empty()) { OLA_DEBUG << "No path configured for device, please set one in " "ola-milinst.conf"; return -1; } int fd; if (!ola::io::Open(path, O_RDWR | O_NONBLOCK | O_NOCTTY, &fd)) { return -1; } memset(&newtio, 0, sizeof(newtio)); // Clear struct for new port settings tcgetattr(fd, &newtio); newtio.c_cflag |= (CLOCAL | CREAD); // Enable read newtio.c_cflag |= CS8; // 8n1 newtio.c_cflag &= ~CRTSCTS; // No flow control cfsetispeed(&newtio, speed); cfsetospeed(&newtio, speed); tcsetattr(fd, TCSANOW, &newtio); return fd; } /* * Disconnect from the widget */ int MilInstWidget::Disconnect() { m_socket->Close(); return 0; } } // namespace milinst } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/milinst/MilInstWidget1463.cpp0000644000175000017500000000554613023355232022375 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * MilInstWidget1463.cpp * The MilInst 1-463 Widget. * Copyright (C) 2013 Peter Newman */ #include #include "ola/Logging.h" #include "plugins/milinst/MilInstWidget1463.h" namespace ola { namespace plugin { namespace milinst { /* * Connect to the widget */ bool MilInstWidget1463::Connect() { OLA_DEBUG << "Connecting to " << m_path; int fd = ConnectToWidget(m_path); if (fd < 0) return false; m_socket = new ola::io::DeviceDescriptor(fd); OLA_DEBUG << "Connected to " << m_path; return true; } /* * Check if this is actually a MilInst device * @return true if this is a milinst, false otherwise */ bool MilInstWidget1463::DetectDevice() { // This device doesn't do two way comms, so just return true return true; } /* * Send a DMX msg. */ bool MilInstWidget1463::SendDmx(const DmxBuffer &buffer) const { // TODO(Peter): Probably add offset in here to send higher channels shifted // down int bytes_sent = Send112(buffer); OLA_DEBUG << "Sending DMX, sent " << bytes_sent << " bytes"; // Should this confirm we've sent more than 0 bytes and return false if not? return true; } //----------------------------------------------------------------------------- // Private methods used for communicating with the widget /* * Set a single channel */ int MilInstWidget1463::SetChannel(unsigned int chan, uint8_t val) const { uint8_t msg[2]; msg[0] = chan; msg[1] = val; OLA_DEBUG << "Setting " << chan << " to " << static_cast(val); return m_socket->Send(msg, sizeof(msg)); } /* * Send 112 channels worth of data * @param buffer a DmxBuffer with the data */ int MilInstWidget1463::Send112(const DmxBuffer &buffer) const { unsigned int channels = std::min((unsigned int) DMX_MAX_TRANSMIT_CHANNELS, buffer.Size()); uint8_t msg[channels * 2]; for (unsigned int i = 0; i <= channels; i++) { msg[i * 2] = i + 1; msg[(i * 2) + 1] = buffer.Get(i); OLA_DEBUG << "Setting " << (i + 1) << " to " << static_cast(buffer.Get(i)); } return m_socket->Send(msg, (channels * 2)); } } // namespace milinst } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/milinst/MilInstPlugin.h0000644000175000017500000000367213023355232021535 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * MilInstPlugin.h * Interface for the Milford Instruments plugin class * Copyright (C) 2013 Peter Newman */ #ifndef PLUGINS_MILINST_MILINSTPLUGIN_H_ #define PLUGINS_MILINST_MILINSTPLUGIN_H_ #include #include #include "ola/io/Descriptor.h" #include "olad/Plugin.h" namespace ola { namespace plugin { namespace milinst { class MilInstDevice; class MilInstPlugin: public Plugin { public: explicit MilInstPlugin(PluginAdaptor *plugin_adaptor) : Plugin(plugin_adaptor) {} ~MilInstPlugin() {} std::string Name() const { return PLUGIN_NAME; } ola_plugin_id Id() const { return OLA_PLUGIN_MILINST; } std::string Description() const; int SocketClosed(ola::io::ConnectedDescriptor *socket); std::string PluginPrefix() const { return PLUGIN_PREFIX; } private: bool StartHook(); bool StopHook(); bool SetDefaultPreferences(); void DeleteDevice(MilInstDevice *device); std::vector m_devices; // list of our devices static const char MILINST_DEVICE_PATH[]; static const char PLUGIN_NAME[]; static const char PLUGIN_PREFIX[]; static const char DEVICE_KEY[]; }; } // namespace milinst } // namespace plugin } // namespace ola #endif // PLUGINS_MILINST_MILINSTPLUGIN_H_ ola-0.10.5.nojsmin/plugins/milinst/MilInstWidget1553.h0000644000175000017500000000402713023355232022033 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * MilInstWidget1553.h * Interface for the MilInst 1-553 device * Copyright (C) 2013 Peter Newman */ #ifndef PLUGINS_MILINST_MILINSTWIDGET1553_H_ #define PLUGINS_MILINST_MILINSTWIDGET1553_H_ #include #include "plugins/milinst/MilInstWidget.h" namespace ola { namespace plugin { namespace milinst { class MilInstWidget1553: public MilInstWidget { public: explicit MilInstWidget1553(const std::string &path, Preferences *preferences); ~MilInstWidget1553() {} bool Connect(); bool DetectDevice(); bool SendDmx(const DmxBuffer &buffer) const; std::string Type() { return "Milford Instruments 1-553 Widget"; } void SocketReady(); protected: int SetChannel(unsigned int chan, uint8_t val) const; int Send(const DmxBuffer &buffer) const; static const uint8_t MILINST_1553_LOAD_COMMAND = 0x01; static const speed_t DEFAULT_BAUDRATE; static const uint16_t CHANNELS_128; static const uint16_t CHANNELS_256; static const uint16_t CHANNELS_512; static const uint16_t DEFAULT_CHANNELS; private: class Preferences *m_preferences; uint16_t m_channels; // Per widget options std::string BaudRateKey() const; std::string ChannelsKey() const; void SetWidgetDefaults(); }; } // namespace milinst } // namespace plugin } // namespace ola #endif // PLUGINS_MILINST_MILINSTWIDGET1553_H_ ola-0.10.5.nojsmin/plugins/milinst/MilInstDevice.cpp0000644000175000017500000000667513023355232022037 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * MilInstDevice.cpp * MilInst device * Copyright (C) 2013 Peter Newman */ #include #include #include "ola/Logging.h" #include "olad/Preferences.h" #include "plugins/milinst/MilInstPort.h" #include "plugins/milinst/MilInstWidget1463.h" #include "plugins/milinst/MilInstWidget1553.h" #include "plugins/milinst/MilInstDevice.h" namespace ola { namespace plugin { namespace milinst { using ola::AbstractPlugin; using ola::io::ConnectedDescriptor; using std::set; using std::string; const char MilInstDevice::MILINST_DEVICE_NAME[] = "Milford Instruments Device"; const char MilInstDevice::TYPE_1463[] = "1-463"; const char MilInstDevice::TYPE_1553[] = "1-553"; /* * Create a new device * * @param owner the plugin that owns this device * @param name the device name * @param dev_path path to the pro widget */ MilInstDevice::MilInstDevice(AbstractPlugin *owner, Preferences *preferences, const string &dev_path) : Device(owner, MILINST_DEVICE_NAME), m_path(dev_path), m_preferences(preferences) { SetDeviceDefaults(); string type = m_preferences->GetValue(DeviceTypeKey()); OLA_DEBUG << "Got type " << type; if (type.compare(TYPE_1553) == 0) { m_widget.reset(new MilInstWidget1553(m_path, m_preferences)); } else { m_widget.reset(new MilInstWidget1463(m_path)); } } /* * Destroy this device */ MilInstDevice::~MilInstDevice() { // Stub destructor for compatibility with MilInstWidget subclasses } /* * Start this device */ bool MilInstDevice::StartHook() { if (!m_widget.get()) { return false; } if (!m_widget->Connect()) { OLA_WARN << "Failed to connect to " << m_path; return false; } if (!m_widget->DetectDevice()) { OLA_WARN << "No device found at " << m_path; return false; } MilInstOutputPort *port = new MilInstOutputPort(this, 0, m_widget.get()); AddPort(port); return true; } /* * Stop this device */ void MilInstDevice::PrePortStop() { // disconnect from widget m_widget->Disconnect(); } /* * return the sd for this device */ ConnectedDescriptor *MilInstDevice::GetSocket() const { return m_widget->GetSocket(); } string MilInstDevice::DeviceTypeKey() const { return m_path + "-type"; } void MilInstDevice::SetDeviceDefaults() { bool save = false; set valid_types; valid_types.insert(TYPE_1463); valid_types.insert(TYPE_1553); // Set generic device options save |= m_preferences->SetDefaultValue(DeviceTypeKey(), SetValidator(valid_types), TYPE_1463); if (save) { m_preferences->Save(); } } } // namespace milinst } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/milinst/MilInstWidget1553.cpp0000644000175000017500000001264113023355232022367 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * MilInstWidget1553.cpp * The MilInst 1-553 Widget. * Copyright (C) 2013 Peter Newman */ #include #include #include #include "ola/io/Serial.h" #include "ola/Logging.h" #include "ola/StringUtils.h" #include "ola/util/Utils.h" #include "olad/Preferences.h" #include "plugins/milinst/MilInstWidget1553.h" namespace ola { namespace plugin { namespace milinst { using std::set; using std::string; const speed_t MilInstWidget1553::DEFAULT_BAUDRATE = B9600; const uint16_t MilInstWidget1553::CHANNELS_128 = 128; const uint16_t MilInstWidget1553::CHANNELS_256 = 256; const uint16_t MilInstWidget1553::CHANNELS_512 = 512; const uint16_t MilInstWidget1553::DEFAULT_CHANNELS = CHANNELS_128; MilInstWidget1553::MilInstWidget1553(const string &path, Preferences *preferences) : MilInstWidget(path), m_preferences(preferences) { SetWidgetDefaults(); if (!StringToInt(m_preferences->GetValue(ChannelsKey()), &m_channels)) { OLA_DEBUG << "Invalid channels, defaulting to " << DEFAULT_CHANNELS; m_channels = DEFAULT_CHANNELS; } } /* * Connect to the widget */ bool MilInstWidget1553::Connect() { OLA_DEBUG << "Connecting to " << m_path; speed_t baudrate; uint32_t baudrate_int; if (!StringToInt(m_preferences->GetValue(BaudRateKey()), &baudrate_int) || !ola::io::UIntToSpeedT(baudrate_int, &baudrate)) { OLA_DEBUG << "Invalid baudrate, defaulting to 9600"; baudrate = DEFAULT_BAUDRATE; } int fd = ConnectToWidget(m_path, baudrate); if (fd < 0) { return false; } m_socket = new ola::io::DeviceDescriptor(fd); m_socket->SetOnData( NewCallback(this, &MilInstWidget1553::SocketReady)); OLA_DEBUG << "Connected to " << m_path; return true; } /* * Called when there is data to read */ void MilInstWidget1553::SocketReady() { while (m_socket->DataRemaining() > 0) { uint8_t byte = 0x00; unsigned int data_read; int ret = m_socket->Receive(&byte, 1, data_read); if (ret == -1 || data_read != 1) { } else { OLA_DEBUG << "Received byte " << static_cast(byte); } } } /* * Check if this is actually a MilInst device * @return true if this is a milinst, false otherwise */ bool MilInstWidget1553::DetectDevice() { // TODO(Peter): Fixme, check channel count or something! return true; } /* * Send a DMX msg. */ bool MilInstWidget1553::SendDmx(const DmxBuffer &buffer) const { // TODO(Peter): Probably add offset in here to send higher channels shifted // down int bytes_sent = Send(buffer); OLA_DEBUG << "Sending DMX, sent " << bytes_sent << " bytes"; // Should this confirm we've sent more than 0 bytes and return false if not? return true; } //----------------------------------------------------------------------------- // Private methods used for communicating with the widget /* * Set a single channel */ int MilInstWidget1553::SetChannel(unsigned int chan, uint8_t val) const { uint8_t msg[4]; msg[0] = MILINST_1553_LOAD_COMMAND; ola::utils::SplitUInt16(chan, &msg[1], &msg[2]); msg[3] = val; OLA_DEBUG << "Setting " << chan << " to " << static_cast(val); return m_socket->Send(msg, sizeof(msg)); } /* * Send data * @param buffer a DmxBuffer with the data */ int MilInstWidget1553::Send(const DmxBuffer &buffer) const { unsigned int channels = std::min(static_cast(m_channels), buffer.Size()); uint8_t msg[3 + channels]; msg[0] = MILINST_1553_LOAD_COMMAND; ola::utils::SplitUInt16(1, &msg[1], &msg[2]); buffer.Get(msg + 3, &channels); return m_socket->Send(msg, sizeof(msg)); } string MilInstWidget1553::BaudRateKey() const { return m_path + "-baudrate"; } string MilInstWidget1553::ChannelsKey() const { return m_path + "-channels"; } void MilInstWidget1553::SetWidgetDefaults() { bool save = false; set valid_baudrates; valid_baudrates.insert(ola::io::BAUD_RATE_9600); valid_baudrates.insert(ola::io::BAUD_RATE_19200); set valid_channels; valid_channels.insert(CHANNELS_128); valid_channels.insert(CHANNELS_256); valid_channels.insert(CHANNELS_512); // Set 1-553 widget options save |= m_preferences->SetDefaultValue( BaudRateKey(), SetValidator(valid_baudrates), ola::io::BAUD_RATE_9600); // TODO(Peter): Fix me, default to 512 once we can set the channel count or it // behaves properly when sending higher channel counts when limited save |= m_preferences->SetDefaultValue( ChannelsKey(), SetValidator(valid_channels), DEFAULT_CHANNELS); if (save) { m_preferences->Save(); } } } // namespace milinst } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/milinst/MilInstWidget.h0000644000175000017500000000411613023355232021514 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * MilInstWidget.h * Interface for the milinst widget * Copyright (C) 2013 Peter Newman */ #ifndef PLUGINS_MILINST_MILINSTWIDGET_H_ #define PLUGINS_MILINST_MILINSTWIDGET_H_ #include #include #include #include "ola/io/SelectServer.h" #include "ola/DmxBuffer.h" namespace ola { namespace plugin { namespace milinst { class MilInstWidget { public: static int ConnectToWidget(const std::string &path, speed_t speed = B9600); explicit MilInstWidget(const std::string &path) : m_enabled(false), m_path(path), m_socket(NULL) {} virtual ~MilInstWidget(); // these methods are for communicating with the device virtual bool Connect() = 0; int Disconnect(); ola::io::ConnectedDescriptor *GetSocket() { return m_socket; } std::string GetPath() { return m_path; } virtual std::string Type() = 0; std::string Description() { std::ostringstream str; str << GetPath() << ", " << Type(); return str.str(); } virtual bool SendDmx(const DmxBuffer &buffer) const = 0; virtual bool DetectDevice() = 0; protected: virtual int SetChannel(unsigned int chan, uint8_t val) const = 0; // instance variables bool m_enabled; const std::string m_path; ola::io::ConnectedDescriptor *m_socket; }; } // namespace milinst } // namespace plugin } // namespace ola #endif // PLUGINS_MILINST_MILINSTWIDGET_H_ ola-0.10.5.nojsmin/plugins/pathport/0000755000175000017500000000000013155164170017005 5ustar wouterwouterola-0.10.5.nojsmin/plugins/pathport/PathportNode.h0000644000175000017500000001055713023355232021570 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * PathportNode.h * Header file for the PathportNode class * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_PATHPORT_PATHPORTNODE_H_ #define PLUGINS_PATHPORT_PATHPORTNODE_H_ #include #include #include "ola/Callback.h" #include "ola/DmxBuffer.h" #include "ola/network/IPV4Address.h" #include "ola/network/InterfacePicker.h" #include "ola/network/Socket.h" #include "plugins/pathport/PathportPackets.h" namespace ola { namespace plugin { namespace pathport { class PathportNode { public: explicit PathportNode(const std::string &preferred_ip, uint32_t device_id, uint8_t dscp); ~PathportNode(); bool Start(); bool Stop(); const ola::network::Interface &GetInterface() const { return m_interface; } ola::network::UDPSocket *GetSocket() { return &m_socket; } void SocketReady(ola::network::UDPSocket *socket); bool SetHandler(uint8_t universe, DmxBuffer *buffer, Callback0 *closure); bool RemoveHandler(uint8_t universe); bool SendArpReply(); bool SendDMX(unsigned int universe, const DmxBuffer &buffer); // apparently pathport supports up to 128 universes, the spec only says 64 static const uint8_t MAX_UNIVERSES = 127; private: typedef struct { DmxBuffer *buffer; Callback0 *closure; } universe_handler; enum { XDMX_DATA_FLAT = 0x0101, XDMX_DATA_RELEASE = 0x0103 }; enum { NODE_MANUF_PATHWAY_CONNECTIVITY = 0, NODE_MANUF_INTERACTIVE_TECH = 0x10, NODE_MANUF_ENTERTAINMENT_TECH = 0x11, NODE_MANUF_MA_LIGHTING = 0x12, NODE_MANUF_HIGH_END_SYSTEMS = 0x13, NODE_MANUF_CRESTRON_ELECTRONICS = 0x14, NODE_MANUF_LEVITON = 0x15, NODE_MANUF_FLYING_PIG = 0x16, NODE_MANUF_HORIZON = 0x17, NODE_MANUF_ZP_TECH = 0x28, // ola }; enum { NODE_CLASS_DMX_NODE = 0, NODE_CLASS_MANAGER = 1, NODE_CLASS_DIMMER = 2, NODE_CLASS_CONTROLLER = 3, NODE_CLASS_FIXTURE = 4, NODE_CLASS_EFFECTS_UNIT = 5, }; enum { NODE_DEVICE_PATHPORT = 0, NODE_DEVICE_DMX_MANAGER_PLUS = 1, NODE_DEVICE_ONEPORT = 2, }; typedef std::map universe_handlers; bool InitNetwork(); void PopulateHeader(pathport_packet_header *header, uint32_t destination); bool ValidateHeader(const pathport_packet_header &header); void HandleDmxData(const pathport_pdu_data &packet, unsigned int size); bool SendArpRequest(uint32_t destination = PATHPORT_ID_BROADCAST); bool SendPacket(const pathport_packet_s &packet, unsigned int size, ola::network::IPV4Address dest); bool m_running; uint8_t m_dscp; std::string m_preferred_ip; uint32_t m_device_id; // the pathport device id uint16_t m_sequence_number; universe_handlers m_handlers; ola::network::Interface m_interface; ola::network::UDPSocket m_socket; ola::network::IPV4Address m_config_addr; ola::network::IPV4Address m_status_addr; ola::network::IPV4Address m_data_addr; static const uint16_t PATHPORT_PORT = 0xed0; static const uint16_t PATHPORT_PROTOCOL = 0xed01; static const uint32_t PATHPORT_CONFIG_GROUP = 0xefffed02; static const uint32_t PATHPORT_DATA_GROUP = 0xefffed01; static const uint32_t PATHPORT_ID_BROADCAST = 0xffffffff; static const uint32_t PATHPORT_STATUS_GROUP = 0xefffedff; static const uint8_t MAJOR_VERSION = 2; static const uint8_t MINOR_VERSION = 0; }; } // namespace pathport } // namespace plugin } // namespace ola #endif // PLUGINS_PATHPORT_PATHPORTNODE_H_ ola-0.10.5.nojsmin/plugins/pathport/Makefile.mk0000644000175000017500000000123713023355232021051 0ustar wouterwouter# LIBRARIES ################################################## if USE_PATHPORT lib_LTLIBRARIES += plugins/pathport/libolapathport.la plugins_pathport_libolapathport_la_SOURCES = \ plugins/pathport/PathportDevice.cpp \ plugins/pathport/PathportDevice.h \ plugins/pathport/PathportNode.cpp \ plugins/pathport/PathportNode.h \ plugins/pathport/PathportPackets.h \ plugins/pathport/PathportPlugin.cpp \ plugins/pathport/PathportPlugin.h \ plugins/pathport/PathportPort.cpp \ plugins/pathport/PathportPort.h plugins_pathport_libolapathport_la_LIBADD = \ common/libolacommon.la \ olad/plugin_api/libolaserverplugininterface.la endif ola-0.10.5.nojsmin/plugins/pathport/PathportPackets.h0000644000175000017500000000736313023355232022276 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * PathportPackets.h * Datagram definitions for libpathport * Copyright (C) 2006 Simon Newton */ #ifndef PLUGINS_PATHPORT_PATHPORTPACKETS_H_ #define PLUGINS_PATHPORT_PATHPORTPACKETS_H_ #include #include #include "ola/network/IPV4Address.h" namespace ola { namespace plugin { namespace pathport { /* * Pathport opcodes */ // We can't use the PACK macro for enums #ifdef _WIN32 #pragma pack(push, 1) #endif // _WIN32 enum pathport_packet_type_e { PATHPORT_DATA = 0x0100, PATHPORT_PATCH = 0x0200, PATHPORT_PATCHREP = 0x0210, PATHPORT_GET = 0x0222, PATHPORT_GET_REPLY = 0x0223, PATHPORT_ARP_REQUEST = 0x0301, PATHPORT_ARP_REPLY = 0x0302, PATHPORT_SET = 0x0400, #ifdef _WIN32 }; #pragma pack(pop) #else } __attribute__((packed)); #endif // _WIN32 typedef enum pathport_packet_type_e pathport_packet_type_t; /* * Pathport xDmx */ PACK( struct pathport_pdu_data_s { uint16_t type; uint16_t channel_count; uint8_t universe; // not used, set to 0 uint8_t start_code; uint16_t offset; uint8_t data[0]; }); typedef struct pathport_pdu_data_s pathport_pdu_data; /* * Pathport get request */ PACK( struct pathport_pdu_get_s { uint16_t params[0]; }); typedef struct pathport_pdu_get_s pathport_pdu_get; /* * Pathport get reply */ PACK( struct pathport_pdu_getrep_s { uint8_t params[0]; }); typedef struct pathport_pdu_getrep_s pathport_pdu_getrep; struct pathport_pdu_getrep_alv_s { uint16_t type; uint16_t len; uint8_t val[0]; }; typedef struct pathport_pdu_getrep_alv_s pathport_pdu_getrep_alv; /* * Pathport arp reply */ PACK( struct pathport_pdu_arp_reply_s { uint32_t id; uint8_t ip[ola::network::IPV4Address::LENGTH]; uint8_t manufacturer_code; // manufacturer code uint8_t device_class; // device class uint8_t device_type; // device type uint8_t component_count; // number of dmx components }); typedef struct pathport_pdu_arp_reply_s pathport_pdu_arp_reply; PACK( struct pathport_pdu_header_s { uint16_t type; // pdu type uint16_t len; // length }); typedef struct pathport_pdu_header_s pathport_pdu_header; /* * PDU Header */ PACK( struct pathport_packet_pdu_s { pathport_pdu_header head; union { pathport_pdu_data data; pathport_pdu_get get; pathport_pdu_getrep getrep; pathport_pdu_arp_reply arp_reply; } d; // pdu data }); typedef struct pathport_packet_pdu_s pathport_packet_pdu; /* * A complete Pathport packet */ PACK( struct pathport_packet_header_s { uint16_t protocol; uint8_t version_major; uint8_t version_minor; uint16_t sequence; uint8_t reserved[6]; // set to 0 uint32_t source; // src id uint32_t destination; // dst id }); typedef struct pathport_packet_header_s pathport_packet_header; /* * The complete pathport packet */ PACK( struct pathport_packet_s { pathport_packet_header header; union { uint8_t data[1480]; // 1500 - header size pathport_packet_pdu pdu; } d; }); } // namespace pathport } // namespace plugin } // namespace ola #endif // PLUGINS_PATHPORT_PATHPORTPACKETS_H_ ola-0.10.5.nojsmin/plugins/pathport/PathportPort.cpp0000644000175000017500000000460613023355232022160 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * PathportPort.cpp * The Pathport plugin for ola * Copyright (C) 2005 Simon Newton */ #include #include #include "ola/Logging.h" #include "ola/Constants.h" #include "plugins/pathport/PathportPort.h" namespace ola { namespace plugin { namespace pathport { using std::string; string PathportPortHelper::Description(const Universe *universe) const { if (!universe) { return ""; } std::ostringstream str; str << "Pathport xDMX " << DMX_UNIVERSE_SIZE * universe->UniverseId() << " - " << DMX_UNIVERSE_SIZE * (1 + universe->UniverseId()) - 1; return str.str(); } // Don't allow us to patch ports out of range bool PathportPortHelper::PreSetUniverse(Universe *new_universe) { if (new_universe && new_universe->UniverseId() > PathportNode::MAX_UNIVERSES) { OLA_WARN << "Pathport universes need to be between 0 and " << PathportNode::MAX_UNIVERSES; return false; } return true; } void PathportInputPort::PostSetUniverse(Universe *old_universe, Universe *new_universe) { if (old_universe) { m_node->RemoveHandler(old_universe->UniverseId()); } if (new_universe) { m_node->SetHandler( new_universe->UniverseId(), &m_buffer, NewCallback(this, &PathportInputPort::DmxChanged)); } } bool PathportOutputPort::WriteDMX(const DmxBuffer &buffer, OLA_UNUSED uint8_t priority) { if (GetUniverse()) { return m_node->SendDMX(GetUniverse()->UniverseId(), buffer); } return true; } } // namespace pathport } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/pathport/PathportPlugin.cpp0000644000175000017500000001026513023355232022470 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * PathportPlugin.cpp * The Pathport plugin for ola * Copyright (C) 2005 Simon Newton */ #include #include #include "ola/Logging.h" #include "ola/StringUtils.h" #include "ola/math/Random.h" #include "olad/PluginAdaptor.h" #include "olad/Preferences.h" #include "plugins/pathport/PathportDevice.h" #include "plugins/pathport/PathportPlugin.h" namespace ola { namespace plugin { namespace pathport { using std::string; const char PathportPlugin::PLUGIN_NAME[] = "Pathport"; const char PathportPlugin::PLUGIN_PREFIX[] = "pathport"; const unsigned int PathportPlugin::DEFAULT_DSCP_VALUE = 0; /* * Start the plugin * For now we just have one device. */ bool PathportPlugin::StartHook() { m_device = new PathportDevice(this, m_preferences, m_plugin_adaptor); if (!m_device) { return false; } if (!m_device->Start()) { delete m_device; return false; } m_plugin_adaptor->RegisterDevice(m_device); return true; } /* * Stop the plugin * @return true on success, false on failure */ bool PathportPlugin::StopHook() { if (m_device) { m_plugin_adaptor->UnregisterDevice(m_device); bool ret = m_device->Stop(); delete m_device; return ret; } return true; } /* * Return the description for this plugin */ string PathportPlugin::Description() const { return "Pathway Pathport Plugin\n" "----------------------------\n" "\n" "This plugin creates a single device with 5 input and 5 output ports.\n" "\n" "The universe the port is patched to corresponds with the DMX channels used \n" "in the PathPort protocol. For example universe 0 is xDMX channels 0 - 511, \n" "universe 1 is xDMX channels 512 - 1023.\n" "\n" "--- Config file : ola-pathport.conf ---\n" "\n" "dscp = \n" "Set the DSCP value for the packets. Range is 0-63.\n" "\n" "ip = [a.b.c.d|]\n" "The ip address or interface name to bind to. If not specified it will\n" "use the first non-loopback interface.\n" "\n" "name = ola-Pathport\n" "The name of the node.\n" "\n" "node-id = \n" "The pathport id of the node.\n" "\n"; } /* * Load the plugin prefs and default to sensible values */ bool PathportPlugin::SetDefaultPreferences() { bool save = false; if (!m_preferences) { return false; } save |= m_preferences->SetDefaultValue(PathportDevice::K_DSCP_KEY, UIntValidator(0, 63), DEFAULT_DSCP_VALUE); save |= m_preferences->SetDefaultValue(PathportDevice::K_NODE_IP_KEY, StringValidator(true), ""); save |= m_preferences->SetDefaultValue(PathportDevice::K_NODE_NAME_KEY, StringValidator(), PathportDevice::K_DEFAULT_NODE_NAME); // Generate a new node id in case we need it uint32_t product_id = ((OLA_MANUFACTURER_CODE << 24) + ola::math::Random(0, (1 << 24) - 1)); save |= m_preferences->SetDefaultValue(PathportDevice::K_NODE_ID_KEY, UIntValidator(0, UINT_MAX), product_id); if (save) { m_preferences->Save(); } if (m_preferences->GetValue(PathportDevice::K_NODE_NAME_KEY).empty() || m_preferences->GetValue(PathportDevice::K_NODE_ID_KEY).empty()) { return false; } return true; } } // namespace pathport } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/pathport/PathportPort.h0000644000175000017500000000547113023355232021626 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * PathportPort.h * The Pathport plugin for ola * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_PATHPORT_PATHPORTPORT_H_ #define PLUGINS_PATHPORT_PATHPORTPORT_H_ #include #include "ola/DmxBuffer.h" #include "olad/Port.h" #include "plugins/pathport/PathportDevice.h" namespace ola { namespace plugin { namespace pathport { class PathportPortHelper { public: PathportPortHelper() {} std::string Description(const Universe *universe) const; bool PreSetUniverse(Universe *new_universe); }; class PathportInputPort: public BasicInputPort { public: PathportInputPort(PathportDevice *parent, unsigned int id, class PluginAdaptor *plugin_adaptor, PathportNode *node): BasicInputPort(parent, id, plugin_adaptor), m_node(node) {} ~PathportInputPort() {} std::string Description() const { return m_helper.Description(GetUniverse()); } const DmxBuffer &ReadDMX() const { return m_buffer; } bool PreSetUniverse(OLA_UNUSED Universe *old_universe, Universe *new_universe) { return m_helper.PreSetUniverse(new_universe); } void PostSetUniverse(Universe *old_universe, Universe *new_universe); private: PathportPortHelper m_helper; PathportNode *m_node; DmxBuffer m_buffer; }; class PathportOutputPort: public BasicOutputPort { public: PathportOutputPort(PathportDevice *parent, unsigned int id, PathportNode *node): BasicOutputPort(parent, id), m_node(node) {} ~PathportOutputPort() {} std::string Description() const { return m_helper.Description(GetUniverse()); } bool WriteDMX(const DmxBuffer &buffer, uint8_t priority); bool PreSetUniverse(OLA_UNUSED Universe *old_universe, Universe *new_universe) { return m_helper.PreSetUniverse(new_universe); } private: PathportPortHelper m_helper; PathportNode *m_node; }; } // namespace pathport } // namespace plugin } // namespace ola #endif // PLUGINS_PATHPORT_PATHPORTPORT_H_ ola-0.10.5.nojsmin/plugins/pathport/PathportDevice.h0000644000175000017500000000413213023355232022072 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * PathportDevice.h * Interface for the pathport device * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_PATHPORT_PATHPORTDEVICE_H_ #define PLUGINS_PATHPORT_PATHPORTDEVICE_H_ #include #include "olad/Device.h" #include "ola/io/SelectServer.h" #include "plugins/pathport/PathportNode.h" namespace ola { namespace plugin { namespace pathport { class PathportDevice: public ola::Device { public: PathportDevice(class PathportPlugin *owner, class Preferences *preferences, class PluginAdaptor *plugin_adaptor); std::string DeviceId() const { return "1"; } PathportNode *GetNode() const { return m_node; } bool SendArpReply(); static const char K_DEFAULT_NODE_NAME[]; static const char K_DSCP_KEY[]; static const char K_NODE_ID_KEY[]; static const char K_NODE_IP_KEY[]; static const char K_NODE_NAME_KEY[]; protected: bool StartHook(); void PrePortStop(); void PostPortStop(); private: class Preferences *m_preferences; class PluginAdaptor *m_plugin_adaptor; PathportNode *m_node; ola::thread::timeout_id m_timeout_id; static const char PATHPORT_DEVICE_NAME[]; static const uint32_t PORTS_PER_DEVICE = 8; static const int ADVERTISTMENT_PERIOD_MS = 6000; }; } // namespace pathport } // namespace plugin } // namespace ola #endif // PLUGINS_PATHPORT_PATHPORTDEVICE_H_ ola-0.10.5.nojsmin/plugins/pathport/PathportDevice.cpp0000644000175000017500000001003313134123277022427 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * PathportDevice.cpp * Pathport device * Copyright (C) 2005 Simon Newton */ #include #include #include "ola/Logging.h" #include "ola/StringUtils.h" #include "ola/network/NetworkUtils.h" #include "olad/PluginAdaptor.h" #include "olad/Preferences.h" #include "olad/Universe.h" #include "plugins/pathport/PathportDevice.h" #include "plugins/pathport/PathportPort.h" #include "plugins/pathport/PathportPlugin.h" namespace ola { namespace plugin { namespace pathport { using std::ostringstream; using std::vector; const char PathportDevice::K_DEFAULT_NODE_NAME[] = "ola-Pathport"; const char PathportDevice::K_DSCP_KEY[] = "dscp"; const char PathportDevice::K_NODE_ID_KEY[] = "node-id"; const char PathportDevice::K_NODE_IP_KEY[] = "ip"; const char PathportDevice::K_NODE_NAME_KEY[] = "name"; const char PathportDevice::PATHPORT_DEVICE_NAME[] = "Pathport"; /* * Create a new device */ PathportDevice::PathportDevice(PathportPlugin *owner, Preferences *prefs, PluginAdaptor *plugin_adaptor) : Device(owner, PATHPORT_DEVICE_NAME), m_preferences(prefs), m_plugin_adaptor(plugin_adaptor), m_node(NULL), m_timeout_id(ola::thread::INVALID_TIMEOUT) { } /* * Start this device */ bool PathportDevice::StartHook() { vector sockets; vector::iterator iter; uint32_t product_id; if (!StringToInt(m_preferences->GetValue(K_NODE_ID_KEY), &product_id)) { OLA_WARN << "Invalid node Id " << m_preferences->GetValue(K_NODE_ID_KEY); } unsigned int dscp; if (!StringToInt(m_preferences->GetValue(K_DSCP_KEY), &dscp)) { OLA_WARN << "Can't convert dscp value " << m_preferences->GetValue(K_DSCP_KEY) << " to int"; dscp = 0; } else { // shift 2 bits left dscp = dscp << 2; } m_node = new PathportNode(m_preferences->GetValue(K_NODE_IP_KEY), product_id, dscp); if (!m_node->Start()) { delete m_node; m_node = NULL; return false; } ostringstream str; str << PATHPORT_DEVICE_NAME << " [" << m_node->GetInterface().ip_address << "]"; SetName(str.str()); for (unsigned int i = 0; i < PORTS_PER_DEVICE; i++) { PathportInputPort *port = new PathportInputPort( this, i, m_plugin_adaptor, m_node); AddPort(port); } for (unsigned int i = 0; i < PORTS_PER_DEVICE; i++) { PathportOutputPort *port = new PathportOutputPort(this, i, m_node); AddPort(port); } m_plugin_adaptor->AddReadDescriptor(m_node->GetSocket()); m_timeout_id = m_plugin_adaptor->RegisterRepeatingTimeout( ADVERTISTMENT_PERIOD_MS, NewCallback(this, &PathportDevice::SendArpReply)); return true; } /* * Stop this device */ void PathportDevice::PrePortStop() { m_plugin_adaptor->RemoveReadDescriptor(m_node->GetSocket()); if (m_timeout_id != ola::thread::INVALID_TIMEOUT) { m_plugin_adaptor->RemoveTimeout(m_timeout_id); m_timeout_id = ola::thread::INVALID_TIMEOUT; } } /* * Stop this device */ void PathportDevice::PostPortStop() { m_node->Stop(); delete m_node; } bool PathportDevice::SendArpReply() { OLA_DEBUG << "Sending pathport arp reply"; if (m_node) m_node->SendArpReply(); return true; } } // namespace pathport } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/pathport/PathportPlugin.h0000644000175000017500000000361713023355232022140 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * PathportPlugin.h * Interface for the pathport plugin class * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_PATHPORT_PATHPORTPLUGIN_H_ #define PLUGINS_PATHPORT_PATHPORTPLUGIN_H_ #include #include #include "olad/Plugin.h" #include "ola/plugin_id.h" namespace ola { namespace plugin { namespace pathport { class PathportPlugin: public ola::Plugin { public: explicit PathportPlugin(class ola::PluginAdaptor *plugin_adaptor) : Plugin(plugin_adaptor), m_device(NULL) {} std::string Name() const { return PLUGIN_NAME; } std::string Description() const; ola_plugin_id Id() const { return OLA_PLUGIN_PATHPORT; } std::string PluginPrefix() const { return PLUGIN_PREFIX; } private: bool StartHook(); bool StopHook(); bool SetDefaultPreferences(); class PathportDevice *m_device; static const unsigned int DEFAULT_DSCP_VALUE; static const char PLUGIN_NAME[]; static const char PLUGIN_PREFIX[]; // 0x28 is assigned to the OLA project static const uint8_t OLA_MANUFACTURER_CODE = 0x28; }; } // namespace pathport } // namespace plugin } // namespace ola #endif // PLUGINS_PATHPORT_PATHPORTPLUGIN_H_ ola-0.10.5.nojsmin/plugins/pathport/PathportNode.cpp0000644000175000017500000003047513023355232022124 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * PathportNode.cpp * A SandNet node * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include #include "ola/Logging.h" #include "ola/Constants.h" #include "ola/network/IPV4Address.h" #include "ola/network/NetworkUtils.h" #include "plugins/pathport/PathportNode.h" namespace ola { namespace plugin { namespace pathport { using std::string; using std::map; using std::vector; using ola::network::HostToNetwork; using ola::network::IPV4Address; using ola::network::IPV4SocketAddress; using ola::network::NetworkToHost; using ola::network::UDPSocket; using ola::Callback0; /* * Create a new node * @param ip_address the IP address to prefer to listen on, if NULL we choose * one. */ PathportNode::PathportNode(const string &ip_address, uint32_t device_id, uint8_t dscp) : m_running(false), m_dscp(dscp), m_preferred_ip(ip_address), m_device_id(device_id), m_sequence_number(1) { } /* * Cleanup */ PathportNode::~PathportNode() { Stop(); universe_handlers::iterator iter; for (iter = m_handlers.begin(); iter != m_handlers.end(); ++iter) { delete iter->second.closure; } m_handlers.clear(); } /* * Start this node */ bool PathportNode::Start() { if (m_running) return false; ola::network::InterfacePicker *picker = ola::network::InterfacePicker::NewPicker(); if (!picker->ChooseInterface(&m_interface, m_preferred_ip)) { delete picker; OLA_INFO << "Failed to find an interface"; return false; } delete picker; m_config_addr = IPV4Address(HostToNetwork(PATHPORT_CONFIG_GROUP)); m_status_addr = IPV4Address(HostToNetwork(PATHPORT_STATUS_GROUP)); m_data_addr = IPV4Address(HostToNetwork(PATHPORT_DATA_GROUP)); if (!InitNetwork()) return false; m_socket.SetTos(m_dscp); m_running = true; SendArpReply(); return true; } /* * Stop this node */ bool PathportNode::Stop() { if (!m_running) return false; m_socket.Close(); m_running = false; return true; } /* * Called when there is data on this socket */ void PathportNode::SocketReady(UDPSocket *socket) { pathport_packet_s packet; ssize_t packet_size = sizeof(packet); IPV4SocketAddress source; if (!socket->RecvFrom(reinterpret_cast(&packet), &packet_size, &source)) return; // skip packets sent by us if (source.Host() == m_interface.ip_address) return; if (packet_size < static_cast(sizeof(packet.header))) { OLA_WARN << "Small pathport packet received, discarding"; return; } packet_size -= static_cast(sizeof(packet.header)); // Validate header if (!ValidateHeader(packet.header)) { OLA_WARN << "Invalid pathport packet"; return; } uint32_t destination = NetworkToHost(packet.header.destination); if (destination != m_device_id && destination != PATHPORT_ID_BROADCAST && destination != PATHPORT_STATUS_GROUP && destination != PATHPORT_CONFIG_GROUP && destination != PATHPORT_DATA_GROUP) { ola::network::IPV4Address addr(destination); OLA_WARN << "pathport destination not set to us: " << addr; return; } // TODO(simon): Handle multiple pdus here pathport_packet_pdu *pdu = &packet.d.pdu; if (packet_size < static_cast(sizeof(pathport_pdu_header))) { OLA_WARN << "Pathport packet too small to fit a pdu header"; return; } packet_size -= sizeof(pathport_pdu_header); switch (NetworkToHost(pdu->head.type)) { case PATHPORT_DATA: HandleDmxData(pdu->d.data, packet_size); break; case PATHPORT_ARP_REQUEST: SendArpReply(); break; case PATHPORT_ARP_REPLY: OLA_DEBUG << "Got pathport arp reply"; break; default: OLA_INFO << "Unhandled pathport packet with id: " << NetworkToHost(pdu->head.type); } } /* * Set the closure to be called when we receive data for this universe. * @param universe the universe to register the handler for * @param handler the Callback0 to call when there is data for this universe. * Ownership of the closure is transferred to the node. */ bool PathportNode::SetHandler(uint8_t universe, DmxBuffer *buffer, Callback0 *closure) { if (!closure) return false; universe_handlers::iterator iter = m_handlers.find(universe); if (iter == m_handlers.end()) { universe_handler handler; handler.buffer = buffer; handler.closure = closure; m_handlers[universe] = handler; } else { Callback0 *old_closure = iter->second.closure; iter->second.closure = closure; delete old_closure; } return true; } /* * Remove the handler for this universe * @param universe the universe handler to remove * @param true if removed, false if it didn't exist */ bool PathportNode::RemoveHandler(uint8_t universe) { universe_handlers::iterator iter = m_handlers.find(universe); if (iter != m_handlers.end()) { Callback0 *old_closure = iter->second.closure; m_handlers.erase(iter); delete old_closure; return true; } return false; } /* * Send an arp reply */ bool PathportNode::SendArpReply() { if (!m_running) return false; pathport_packet_s packet; // Should this go to status or config? PopulateHeader(&packet.header, PATHPORT_STATUS_GROUP); pathport_packet_pdu *pdu = &packet.d.pdu; pdu->head.type = HostToNetwork((uint16_t) PATHPORT_ARP_REPLY); pdu->head.len = HostToNetwork((uint16_t) sizeof(pathport_pdu_arp_reply)); pdu->d.arp_reply.id = HostToNetwork(m_device_id); m_interface.ip_address.Get(pdu->d.arp_reply.ip); pdu->d.arp_reply.manufacturer_code = NODE_MANUF_ZP_TECH; pdu->d.arp_reply.device_class = NODE_CLASS_DMX_NODE; pdu->d.arp_reply.device_type = NODE_DEVICE_PATHPORT; pdu->d.arp_reply.component_count = 1; unsigned int length = sizeof(pathport_packet_header) + sizeof(pathport_pdu_header) + sizeof(pathport_pdu_arp_reply); return SendPacket(packet, length, m_config_addr); } /* * Send some DMX data * @param buffer the DMX data * @return true if it was send successfully, false otherwise */ bool PathportNode::SendDMX(unsigned int universe, const DmxBuffer &buffer) { if (!m_running) return false; if (universe > MAX_UNIVERSES) { OLA_WARN << "attempt to send to universe " << universe; return false; } pathport_packet_s packet; // pad to a multiple of 4 bytes unsigned int padded_size = (buffer.Size() + 3) & ~3; PopulateHeader(&packet.header, PATHPORT_DATA_GROUP); pathport_packet_pdu *pdu = &packet.d.pdu; pdu->head.type = HostToNetwork((uint16_t) PATHPORT_DATA); pdu->head.len = HostToNetwork( (uint16_t) (padded_size + sizeof(pathport_pdu_data))); pdu->d.data.type = HostToNetwork((uint16_t) XDMX_DATA_FLAT); pdu->d.data.channel_count = HostToNetwork((uint16_t) buffer.Size()); pdu->d.data.universe = 0; pdu->d.data.start_code = 0; pdu->d.data.offset = HostToNetwork( (uint16_t) (DMX_UNIVERSE_SIZE * universe)); unsigned int length = padded_size; buffer.Get(pdu->d.data.data, &length); // pad data to multiple of 4 bytes length = sizeof(pathport_packet_header) + sizeof(pathport_pdu_header) + sizeof(pathport_pdu_data) + padded_size; return SendPacket(packet, length, m_data_addr); } /* * Setup the networking compoents. */ bool PathportNode::InitNetwork() { if (!m_socket.Init()) { OLA_WARN << "Socket init failed"; return false; } if (!m_socket.Bind(IPV4SocketAddress(IPV4Address::WildCard(), PATHPORT_PORT))) { m_socket.Close(); return false; } if (!m_socket.SetMulticastInterface(m_interface.ip_address)) { m_socket.Close(); return false; } if (!m_socket.JoinMulticast(m_interface.ip_address, m_config_addr)) { OLA_WARN << "Failed to join multicast to: " << m_config_addr; m_socket.Close(); return false; } if (!m_socket.JoinMulticast(m_interface.ip_address, m_data_addr)) { OLA_WARN << "Failed to join multicast to: " << m_data_addr; m_socket.Close(); return false; } if (!m_socket.JoinMulticast(m_interface.ip_address, m_status_addr)) { OLA_WARN << "Failed to join multicast to: " << m_status_addr; m_socket.Close(); return false; } m_socket.SetOnData( NewCallback(this, &PathportNode::SocketReady, &m_socket)); return true; } /* * Fill in a pathport header structure */ void PathportNode::PopulateHeader(pathport_packet_header *header, uint32_t destination) { header->protocol = HostToNetwork(PATHPORT_PROTOCOL); header->version_major = MAJOR_VERSION; header->version_minor = MINOR_VERSION; header->sequence = HostToNetwork(m_sequence_number); memset(header->reserved, 0, sizeof(header->reserved)); header->source = HostToNetwork(m_device_id); header->destination = HostToNetwork(destination); } /* * Check a pathport header structure is valid. */ bool PathportNode::ValidateHeader(const pathport_packet_header &header) { return ( header.protocol == HostToNetwork(PATHPORT_PROTOCOL) && header.version_major == MAJOR_VERSION && header.version_minor == MINOR_VERSION); } /* * Handle new DMX data */ void PathportNode::HandleDmxData(const pathport_pdu_data &packet, unsigned int size) { if (size < sizeof(pathport_pdu_data)) { OLA_WARN << "Small pathport data packet received, ignoring"; return; } // Don't handle release messages yet if (NetworkToHost(packet.type) != XDMX_DATA_FLAT) return; if (packet.start_code) { OLA_INFO << "Non-0 start code packet received, ignoring"; return; } unsigned int offset = NetworkToHost(packet.offset) % DMX_UNIVERSE_SIZE; unsigned int universe = NetworkToHost(packet.offset) / DMX_UNIVERSE_SIZE; const uint8_t *dmx_data = packet.data; unsigned int data_size = std::min( NetworkToHost(packet.channel_count), (uint16_t) (size - sizeof(pathport_pdu_data))); while (data_size > 0 && universe <= MAX_UNIVERSES) { unsigned int channels_for_this_universe = std::min(data_size, DMX_UNIVERSE_SIZE - offset); universe_handlers::iterator iter = m_handlers.find(universe); if (iter != m_handlers.end()) { iter->second.buffer->SetRange(offset, dmx_data, channels_for_this_universe); iter->second.closure->Run(); } data_size -= channels_for_this_universe; dmx_data += channels_for_this_universe; offset = 0; universe++; } } /* * @param destination the destination to target */ bool PathportNode::SendArpRequest(uint32_t destination) { if (!m_running) return false; pathport_packet_s packet; PopulateHeader(&packet.header, destination); packet.d.pdu.head.type = HostToNetwork((uint16_t) PATHPORT_ARP_REQUEST); packet.d.pdu.head.len = 0; unsigned int length = sizeof(pathport_packet_header) + sizeof(pathport_pdu_header); return SendPacket(packet, length, m_status_addr); } /* * Send a packet */ bool PathportNode::SendPacket(const pathport_packet_s &packet, unsigned int size, IPV4Address destination) { ssize_t bytes_sent = m_socket.SendTo( reinterpret_cast(&packet), size, IPV4SocketAddress(destination, PATHPORT_PORT)); if (bytes_sent != static_cast(size)) { OLA_INFO << "Only sent " << bytes_sent << " of " << size; return false; } return true; } } // namespace pathport } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/stageprofi/0000755000175000017500000000000013155164170017307 5ustar wouterwouterola-0.10.5.nojsmin/plugins/stageprofi/Makefile.mk0000644000175000017500000000140713023355232021352 0ustar wouterwouter# LIBRARIES ################################################## if USE_STAGEPROFI lib_LTLIBRARIES += plugins/stageprofi/libolastageprofi.la plugins_stageprofi_libolastageprofi_la_SOURCES = \ plugins/stageprofi/StageProfiDetector.cpp \ plugins/stageprofi/StageProfiDetector.h \ plugins/stageprofi/StageProfiDevice.cpp \ plugins/stageprofi/StageProfiDevice.h \ plugins/stageprofi/StageProfiPlugin.cpp \ plugins/stageprofi/StageProfiPlugin.h \ plugins/stageprofi/StageProfiPort.cpp \ plugins/stageprofi/StageProfiPort.h \ plugins/stageprofi/StageProfiWidget.cpp \ plugins/stageprofi/StageProfiWidget.h plugins_stageprofi_libolastageprofi_la_LIBADD = \ common/libolacommon.la \ olad/plugin_api/libolaserverplugininterface.la endif ola-0.10.5.nojsmin/plugins/stageprofi/StageProfiPort.cpp0000644000175000017500000000322413023355232022717 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * StageProfiPort.cpp * The StageProfi plugin for ola * Copyright (C) 2006 Simon Newton */ #include "plugins/stageprofi/StageProfiPort.h" #include #include #include "ola/base/Macro.h" #include "plugins/stageprofi/StageProfiDevice.h" #include "plugins/stageprofi/StageProfiWidget.h" namespace ola { namespace plugin { namespace stageprofi { StageProfiOutputPort::StageProfiOutputPort(StageProfiDevice *parent, unsigned int id, StageProfiWidget *widget) : BasicOutputPort(parent, id), m_widget(widget) { } bool StageProfiOutputPort::WriteDMX(const DmxBuffer &buffer, OLA_UNUSED uint8_t priority) { return m_widget->SendDmx(buffer); } std::string StageProfiOutputPort::Description() const { return m_widget->GetPath(); } } // namespace stageprofi } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/stageprofi/StageProfiDetector.cpp0000644000175000017500000001346013023355232023547 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * StageProfiDetector.cpp * Detects StageProfi devices as they are attached. * Copyright (C) 2014 Simon Newton */ #include "plugins/stageprofi/StageProfiDetector.h" #include #include #include #include #include #include #include #include #include #include "ola/Callback.h" #include "ola/Clock.h" #include "ola/Logging.h" #include "ola/file/Util.h" #include "ola/io/Descriptor.h" #include "ola/io/IOUtils.h" #include "ola/io/SelectServerInterface.h" #include "ola/io/Serial.h" #include "ola/network/IPV4Address.h" #include "ola/network/SocketAddress.h" #include "ola/stl/STLUtils.h" namespace ola { namespace plugin { namespace stageprofi { using ola::TimeInterval; using ola::io::ConnectedDescriptor; using ola::io::SelectServerInterface; using ola::network::IPV4Address; using ola::network::IPV4SocketAddress; using ola::thread::INVALID_TIMEOUT; using std::set; using std::string; using std::vector; bool EndpointFromString(const string &widget_path, IPV4SocketAddress *socket_addr) { static const uint16_t STAGEPROFI_PORT = 10001; IPV4Address ip_address; if (!IPV4Address::FromString(widget_path, &ip_address)) { OLA_WARN << "Invalid StageProfi device: " << widget_path; return false; } *socket_addr = ola::network::IPV4SocketAddress(ip_address, STAGEPROFI_PORT); return true; } StageProfiDetector::StageProfiDetector(SelectServerInterface *ss, const vector &widget_paths, WidgetCallback *callback) : m_ss(ss), m_callback(callback), m_timeout_id(INVALID_TIMEOUT), m_backoff(TimeInterval(1, 0), TimeInterval(300, 0)), m_socket_factory(NewCallback(this, &StageProfiDetector::SocketConnected)), m_tcp_connector(ss, &m_socket_factory, TimeInterval(3, 0)) { if (!callback) { OLA_FATAL << "No WidgetCallback provided"; return; } set paths(widget_paths.begin(), widget_paths.end()); set::const_iterator iter = paths.begin(); for (; iter != paths.end(); ++iter) { if (iter->empty()) { continue; } if (iter->at(0) == ola::file::PATH_SEPARATOR) { STLReplace(&m_usb_widgets, *iter, NULL); } else { IPV4SocketAddress socket_addr; if (EndpointFromString(*iter, &socket_addr)) { m_tcp_connector.AddEndpoint(socket_addr, &m_backoff); } } } } StageProfiDetector::~StageProfiDetector() { Stop(); } void StageProfiDetector::Start() { if (m_timeout_id == INVALID_TIMEOUT) { m_timeout_id = m_ss->RegisterRepeatingTimeout( ola::TimeInterval(5, 0), NewCallback(this, &StageProfiDetector::RunDiscovery)); } } void StageProfiDetector::Stop() { if (m_timeout_id != INVALID_TIMEOUT) { m_ss->RemoveTimeout(m_timeout_id); m_timeout_id = INVALID_TIMEOUT; } } void StageProfiDetector::ReleaseWidget(const std::string &widget_path) { // It's important not to add the widget_path if it doesn't already exist in // the map. DescriptorMap::iterator iter = m_usb_widgets.find(widget_path); if (iter != m_usb_widgets.end()) { ola::io::ReleaseUUCPLock(widget_path); iter->second = NULL; return; } iter = m_tcp_widgets.find(widget_path); if (iter != m_tcp_widgets.end()) { iter->second = NULL; IPV4SocketAddress socket_addr; if (EndpointFromString(widget_path, &socket_addr)) { m_tcp_connector.Disconnect(socket_addr); } } } bool StageProfiDetector::RunDiscovery() { DescriptorMap::iterator iter = m_usb_widgets.begin(); for (; iter != m_usb_widgets.end(); ++iter) { if (iter->second) { continue; } ConnectedDescriptor *descriptor = ConnectToUSB(iter->first); if (descriptor) { iter->second = descriptor; if (m_callback.get()) { m_callback->Run(iter->first, descriptor); } } } return true; } ConnectedDescriptor* StageProfiDetector::ConnectToUSB( const string &widget_path) { struct termios newtio; int fd; if (!ola::io::AcquireUUCPLockAndOpen(widget_path, O_RDWR | O_NONBLOCK | O_NOCTTY, &fd)) { return NULL; } memset(&newtio, 0, sizeof(newtio)); // clear struct for new port settings tcgetattr(fd, &newtio); cfsetospeed(&newtio, B38400); tcsetattr(fd, TCSANOW, &newtio); return new ola::io::DeviceDescriptor(fd); } void StageProfiDetector::SocketConnected(ola::network::TCPSocket *socket) { ola::network::GenericSocketAddress socket_addr = socket->GetPeerAddress(); if (socket_addr.Family() != AF_INET) { delete socket; return; } IPV4SocketAddress v4_socket_addr = socket_addr.V4Addr(); string key = v4_socket_addr.Host().ToString(); OLA_INFO << "Connected to " << v4_socket_addr; DescriptorMap::iterator iter = STLLookupOrInsertNull(&m_tcp_widgets, key); if (iter->second) { OLA_WARN << "Duplicate socket for " << key; delete socket; return; } if (m_callback.get()) { m_callback->Run(key, socket); } } } // namespace stageprofi } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/stageprofi/StageProfiPlugin.h0000644000175000017500000000442713023355232022704 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * StageProfiPlugin.h * Interface for the stageprofi plugin class * Copyright (C) 2006 Simon Newton */ #ifndef PLUGINS_STAGEPROFI_STAGEPROFIPLUGIN_H_ #define PLUGINS_STAGEPROFI_STAGEPROFIPLUGIN_H_ #include #include #include #include "olad/Plugin.h" #include "ola/network/Socket.h" #include "ola/plugin_id.h" #include "plugins/stageprofi/StageProfiDetector.h" namespace ola { namespace plugin { namespace stageprofi { class StageProfiDevice; class StageProfiPlugin: public Plugin { public: explicit StageProfiPlugin(PluginAdaptor *plugin_adaptor) : Plugin(plugin_adaptor) {} ~StageProfiPlugin(); std::string Name() const { return PLUGIN_NAME; } ola_plugin_id Id() const { return OLA_PLUGIN_STAGEPROFI; } std::string Description() const; std::string PluginPrefix() const { return PLUGIN_PREFIX; } private: typedef std::map DeviceMap; DeviceMap m_devices; std::auto_ptr m_detector; bool StartHook(); bool StopHook(); bool SetDefaultPreferences(); void NewWidget(const std::string &widget_path, ola::io::ConnectedDescriptor *descriptor); void DeviceRemoved(std::string widget_path); void DeleteDevice(StageProfiDevice *device); static const char STAGEPROFI_DEVICE_PATH[]; static const char STAGEPROFI_DEVICE_NAME[]; static const char PLUGIN_NAME[]; static const char PLUGIN_PREFIX[]; static const char DEVICE_KEY[]; }; } // namespace stageprofi } // namespace plugin } // namespace ola #endif // PLUGINS_STAGEPROFI_STAGEPROFIPLUGIN_H_ ola-0.10.5.nojsmin/plugins/stageprofi/StageProfiPort.h0000644000175000017500000000353513023355232022371 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * StageProfiPort.h * The StageProfi plugin for ola * Copyright (C) 2006 Simon Newton */ #ifndef PLUGINS_STAGEPROFI_STAGEPROFIPORT_H_ #define PLUGINS_STAGEPROFI_STAGEPROFIPORT_H_ #include #include "ola/DmxBuffer.h" #include "olad/Port.h" #include "plugins/stageprofi/StageProfiDevice.h" namespace ola { namespace plugin { namespace stageprofi { class StageProfiWidget; /** * @brief An OutputPort for the StageProfi Device. */ class StageProfiOutputPort: public BasicOutputPort { public: /** * @brief Create a new StageProfi Output Port. * @param parent the StageProfiDevice this port belongs to * @param id the port-id. * @param widget the StageProfiWidget to use for this port, ownership is not * transferred. */ StageProfiOutputPort(StageProfiDevice *parent, unsigned int id, StageProfiWidget *widget); bool WriteDMX(const DmxBuffer &buffer, uint8_t priority); std::string Description() const; private: StageProfiWidget *m_widget; }; } // namespace stageprofi } // namespace plugin } // namespace ola #endif // PLUGINS_STAGEPROFI_STAGEPROFIPORT_H_ ola-0.10.5.nojsmin/plugins/stageprofi/StageProfiDevice.h0000644000175000017500000000364613023355232022647 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * StageProfiDevice.h * Interface for the stageprofi device * Copyright (C) 2006 Simon Newton */ #ifndef PLUGINS_STAGEPROFI_STAGEPROFIDEVICE_H_ #define PLUGINS_STAGEPROFI_STAGEPROFIDEVICE_H_ #include #include #include "ola/network/Socket.h" #include "olad/Device.h" namespace ola { class AbstractPlugin; namespace plugin { namespace stageprofi { class StageProfiWidget; class StageProfiDevice: public Device { public: /** * @brief Create a new StageProfi device. * @param owner the Plugin that owns this device * @param widget The StageProfiWidget to use for this device. * @param name the device name */ StageProfiDevice(AbstractPlugin *owner, StageProfiWidget *widget, const std::string &name); /** * @brief Destructor. */ ~StageProfiDevice(); // TODO(simon): I don't think this get us full stickiness because USB devices // may appear as different devices. std::string DeviceId() const; protected: bool StartHook(); private: std::string m_path; std::auto_ptr m_widget; }; } // namespace stageprofi } // namespace plugin } // namespace ola #endif // PLUGINS_STAGEPROFI_STAGEPROFIDEVICE_H_ ola-0.10.5.nojsmin/plugins/stageprofi/StageProfiDevice.cpp0000644000175000017500000000346413023355232023200 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * StageProfiDevice.cpp * StageProfi device * Copyright (C) 2006 Simon Newton */ #include "plugins/stageprofi/StageProfiDevice.h" #include #include "ola/Logging.h" #include "plugins/stageprofi/StageProfiPort.h" #include "plugins/stageprofi/StageProfiWidget.h" namespace ola { namespace plugin { namespace stageprofi { using ola::AbstractPlugin; using ola::io::ConnectedDescriptor; using std::string; StageProfiDevice::StageProfiDevice(AbstractPlugin *owner, StageProfiWidget *widget, const string &name) : Device(owner, name), m_widget(widget) { } StageProfiDevice::~StageProfiDevice() { // Stub destructor for compatibility with StageProfiWidget subclasses } string StageProfiDevice::DeviceId() const { return m_widget->GetPath(); } bool StageProfiDevice::StartHook() { if (!m_widget.get()) return false; StageProfiOutputPort *port = new StageProfiOutputPort( this, 0, m_widget.get()); AddPort(port); return true; } } // namespace stageprofi } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/stageprofi/StageProfiPlugin.cpp0000644000175000017500000001146213023355232023234 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * StageProfiPlugin.cpp * The StageProfi plugin for ola * Copyright (C) 2006 Simon Newton */ #include "plugins/stageprofi/StageProfiPlugin.h" #include #include #include #include #include "ola/Logging.h" #include "ola/stl/STLUtils.h" #include "olad/PluginAdaptor.h" #include "ola/network/IPV4Address.h" #include "ola/network/TCPSocket.h" #include "olad/Preferences.h" #include "plugins/stageprofi/StageProfiDetector.h" #include "plugins/stageprofi/StageProfiDevice.h" #include "plugins/stageprofi/StageProfiWidget.h" namespace ola { namespace plugin { namespace stageprofi { using ola::io::ConnectedDescriptor; using std::auto_ptr; using std::string; using std::vector; const char StageProfiPlugin::STAGEPROFI_DEVICE_PATH[] = "/dev/ttyUSB0"; const char StageProfiPlugin::STAGEPROFI_DEVICE_NAME[] = "StageProfi Device"; const char StageProfiPlugin::PLUGIN_NAME[] = "StageProfi"; const char StageProfiPlugin::PLUGIN_PREFIX[] = "stageprofi"; const char StageProfiPlugin::DEVICE_KEY[] = "device"; namespace { void DeleteStageProfiDevice(StageProfiDevice *device) { delete device; } } // namespace StageProfiPlugin::~StageProfiPlugin() { } bool StageProfiPlugin::StartHook() { vector device_names = m_preferences->GetMultipleValue(DEVICE_KEY); m_detector.reset(new StageProfiDetector( m_plugin_adaptor, device_names, NewCallback(this, &StageProfiPlugin::NewWidget))); m_detector->Start(); return true; } bool StageProfiPlugin::StopHook() { m_detector->Stop(); DeviceMap::iterator iter = m_devices.begin(); for (; iter != m_devices.end(); ++iter) { DeleteDevice(iter->second); } m_devices.clear(); return true; } string StageProfiPlugin::Description() const { return "StageProfi Plugin\n" "----------------------------\n" "\n" "This plugin creates devices with one output port.\n" "\n" "--- Config file : ola-stageprofi.conf ---\n" "\n" "device = /dev/ttyUSB0\n" "device = 192.168.1.250\n" "The device to use either as a path for the USB version or an IP address\n" "for the LAN version. Multiple devices are supported.\n" "\n"; } bool StageProfiPlugin::SetDefaultPreferences() { if (!m_preferences) { return false; } bool save = false; save |= m_preferences->SetDefaultValue(DEVICE_KEY, StringValidator(), STAGEPROFI_DEVICE_PATH); if (save) { m_preferences->Save(); } if (m_preferences->GetValue(DEVICE_KEY).empty()) { return false; } return true; } void StageProfiPlugin::NewWidget(const std::string &widget_path, ConnectedDescriptor *descriptor) { OLA_INFO << "New StageProfiWidget: " << widget_path; DeviceMap::iterator iter = STLLookupOrInsertNull(&m_devices, widget_path); if (iter->second) { OLA_WARN << "Pre-existing StageProfiDevice for " << widget_path; return; } auto_ptr device(new StageProfiDevice( this, new StageProfiWidget( m_plugin_adaptor, descriptor, widget_path, NewSingleCallback(this, &StageProfiPlugin::DeviceRemoved, widget_path)), STAGEPROFI_DEVICE_NAME)); if (!device->Start()) { OLA_INFO << "Failed to start StageProfiDevice"; return; } m_plugin_adaptor->RegisterDevice(device.get()); iter->second = device.release(); } void StageProfiPlugin::DeviceRemoved(std::string widget_path) { OLA_INFO << "StageProfi device " << widget_path << " was removed"; StageProfiDevice *device = STLReplacePtr(&m_devices, widget_path, NULL); if (device) { // Since this is called within the call stack of the StageProfiWidget // itself, we need to schedule deletion for later. m_plugin_adaptor->UnregisterDevice(device); device->Stop(); m_plugin_adaptor->Execute( NewSingleCallback(DeleteStageProfiDevice, device)); } m_detector->ReleaseWidget(widget_path); } void StageProfiPlugin::DeleteDevice(StageProfiDevice *device) { if (device) { m_plugin_adaptor->UnregisterDevice(device); device->Stop(); delete device; } } } // namespace stageprofi } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/stageprofi/StageProfiDetector.h0000644000175000017500000000456713023355232023224 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * StageProfiDetector.h * Detects StageProfi devices as they are attached. * Copyright (C) 2014 Simon Newton */ #ifndef PLUGINS_STAGEPROFI_STAGEPROFIDETECTOR_H_ #define PLUGINS_STAGEPROFI_STAGEPROFIDETECTOR_H_ #include #include #include #include #include "ola/Callback.h" #include "ola/io/SelectServerInterface.h" #include "ola/io/Descriptor.h" #include "ola/network/AdvancedTCPConnector.h" #include "ola/util/Backoff.h" namespace ola { namespace plugin { namespace stageprofi { class StageProfiWidget; class StageProfiDetector { public: typedef ola::Callback2 WidgetCallback; StageProfiDetector(ola::io::SelectServerInterface *ss, const std::vector &widget_paths, WidgetCallback *callback); ~StageProfiDetector(); void Start(); void Stop(); void ReleaseWidget(const std::string &widget_path); private: typedef std::map DescriptorMap; ola::io::SelectServerInterface *m_ss; std::auto_ptr m_callback; ola::thread::timeout_id m_timeout_id; DescriptorMap m_usb_widgets; DescriptorMap m_tcp_widgets; ola::ExponentialBackoffPolicy m_backoff; // TCP members ola::network::TCPSocketFactory m_socket_factory; ola::network::AdvancedTCPConnector m_tcp_connector; bool RunDiscovery(); ola::io::ConnectedDescriptor* ConnectToUSB(const std::string &widget_path); void SocketConnected(ola::network::TCPSocket *socket); }; } // namespace stageprofi } // namespace plugin } // namespace ola #endif // PLUGINS_STAGEPROFI_STAGEPROFIDETECTOR_H_ ola-0.10.5.nojsmin/plugins/stageprofi/StageProfiWidget.cpp0000644000175000017500000001122413023355232023215 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * StageProfiWidget.cpp * This is the base widget class * Copyright (C) 2006 Simon Newton */ #define __STDC_LIMIT_MACROS // for UINT8_MAX & friends #include "plugins/stageprofi/StageProfiWidget.h" #include #include #include #include #include "ola/Callback.h" #include "ola/Logging.h" #include "ola/base/Array.h" #include "ola/util/Utils.h" namespace ola { namespace plugin { namespace stageprofi { using ola::io::ConnectedDescriptor; using ola::TimeInterval; using ola::thread::INVALID_TIMEOUT; using std::string; enum stageprofi_packet_type_e { ID_GETDMX = 0xFE, ID_SETDMX = 0xFF, ID_SETLO = 0xE0, ID_SETHI = 0xE1, }; typedef enum stageprofi_packet_type_e stageprofi_packet_type; StageProfiWidget::StageProfiWidget(io::SelectServerInterface *ss, ConnectedDescriptor *descriptor, const string &widget_path, DisconnectCallback *disconnect_cb) : m_ss(ss), m_descriptor(descriptor), m_widget_path(widget_path), m_disconnect_cb(disconnect_cb), m_timeout_id(INVALID_TIMEOUT), m_got_response(false) { m_descriptor->SetOnData( NewCallback(this, &StageProfiWidget::SocketReady)); m_ss->AddReadDescriptor(m_descriptor.get()); m_timeout_id = m_ss->RegisterSingleTimeout( TimeInterval(1, 0), ola::NewSingleCallback(this, &StageProfiWidget::DiscoveryTimeout)); SendQueryPacket(); } StageProfiWidget::~StageProfiWidget() { if (m_timeout_id != INVALID_TIMEOUT) { m_ss->RemoveTimeout(m_timeout_id); } if (m_descriptor.get()) { m_ss->RemoveReadDescriptor(m_descriptor.get()); } if (m_disconnect_cb) { delete m_disconnect_cb; } } bool StageProfiWidget::SendDmx(const DmxBuffer &buffer) { if (!m_got_response) { return false; } uint16_t index = 0; while (index < buffer.Size()) { unsigned int size = std::min((unsigned int) DMX_MSG_LEN, buffer.Size() - index); bool ok = Send255(index, buffer.GetRaw() + index, size); if (!ok) { OLA_INFO << "Failed to send StageProfi message, closing socket"; RunDisconnectHandler(); } index += size; } return true; } /* * Called when there is data to read. */ void StageProfiWidget::SocketReady() { while (m_descriptor->DataRemaining() > 0) { uint8_t byte = 0x00; unsigned int data_read; while (byte != 'G') { int ret = m_descriptor->Receive(&byte, 1, data_read); if (ret == -1 || data_read != 1) { return; } } m_got_response = true; } } void StageProfiWidget::DiscoveryTimeout() { if (!m_got_response) { OLA_INFO << "No response from StageProfiWidget"; RunDisconnectHandler(); } } /* * @brief Send 255 channels worth of data * @param start the start channel for the data * @param buf a pointer to the data * @param len the length of the data */ bool StageProfiWidget::Send255(uint16_t start, const uint8_t *buf, unsigned int length) const { uint8_t msg[DMX_MSG_LEN + DMX_HEADER_SIZE]; unsigned int len = std::min((unsigned int) DMX_MSG_LEN, length); msg[0] = ID_SETDMX; ola::utils::SplitUInt16(start, &msg[2], &msg[1]); msg[3] = len; memcpy(msg + DMX_HEADER_SIZE, buf, len); // This needs to be an int, as m_descriptor->Send() below returns an int const int bytes_to_send = len + DMX_HEADER_SIZE; return m_descriptor->Send(msg, bytes_to_send) == bytes_to_send; } void StageProfiWidget::SendQueryPacket() { uint8_t query[] = {'C', '?'}; ssize_t bytes_sent = m_descriptor->Send(query, arraysize(query)); OLA_DEBUG << "Sending StageprofiWidget query: C? returned " << bytes_sent; } void StageProfiWidget::RunDisconnectHandler() { if (m_disconnect_cb) { m_disconnect_cb->Run(); m_disconnect_cb = NULL; } } } // namespace stageprofi } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/stageprofi/StageProfiWidget.h0000644000175000017500000000512513023355232022665 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * StageProfiWidget.h * This is the base widget class * Copyright (C) 2006 Simon Newton */ #ifndef PLUGINS_STAGEPROFI_STAGEPROFIWIDGET_H_ #define PLUGINS_STAGEPROFI_STAGEPROFIWIDGET_H_ #include #include #include "ola/DmxBuffer.h" #include "ola/Callback.h" #include "ola/io/Descriptor.h" #include "ola/io/SelectServerInterface.h" namespace ola { namespace plugin { namespace stageprofi { class StageProfiWidget { public: typedef ola::SingleUseCallback0 DisconnectCallback; /** * @brief Create a new StageProfiWidget. * @param ss The SelectServer. * @param descriptor The descriptor to use for the widget. Ownership is * transferred. * @param widget_path the path to the widget. * @param disconnect_cb Called if the widget is disconnected. */ StageProfiWidget(ola::io::SelectServerInterface *ss, ola::io::ConnectedDescriptor *descriptor, const std::string &widget_path, DisconnectCallback *disconnect_cb); /** * @brief Destructor. */ ~StageProfiWidget(); /** * @brief Return the path for this widget. * @returns Either a filesystem path, or an IP address. */ std::string GetPath() const { return m_widget_path; } bool SendDmx(const DmxBuffer &buffer); private: enum { DMX_MSG_LEN = 255 }; enum { DMX_HEADER_SIZE = 4}; ola::io::SelectServerInterface *m_ss; std::auto_ptr m_descriptor; const std::string m_widget_path; DisconnectCallback *m_disconnect_cb; ola::thread::timeout_id m_timeout_id; bool m_got_response; void SocketReady(); void DiscoveryTimeout(); bool Send255(uint16_t start, const uint8_t *buf, unsigned int len) const; void SendQueryPacket(); void RunDisconnectHandler(); }; } // namespace stageprofi } // namespace plugin } // namespace ola #endif // PLUGINS_STAGEPROFI_STAGEPROFIWIDGET_H_ ola-0.10.5.nojsmin/plugins/dmx4linux/0000755000175000017500000000000013155164170017100 5ustar wouterwouterola-0.10.5.nojsmin/plugins/dmx4linux/Makefile.mk0000644000175000017500000000114513023355232021142 0ustar wouterwouter# LIBRARIES ################################################## if USE_DMX4LINUX lib_LTLIBRARIES += plugins/dmx4linux/liboladmx4linux.la plugins_dmx4linux_liboladmx4linux_la_SOURCES = \ plugins/dmx4linux/Dmx4LinuxDevice.cpp \ plugins/dmx4linux/Dmx4LinuxDevice.h \ plugins/dmx4linux/Dmx4LinuxPlugin.cpp \ plugins/dmx4linux/Dmx4LinuxPlugin.h \ plugins/dmx4linux/Dmx4LinuxPort.cpp \ plugins/dmx4linux/Dmx4LinuxPort.h \ plugins/dmx4linux/Dmx4LinuxSocket.h plugins_dmx4linux_liboladmx4linux_la_LIBADD = \ common/libolacommon.la \ olad/plugin_api/libolaserverplugininterface.la endif ola-0.10.5.nojsmin/plugins/dmx4linux/Dmx4LinuxPlugin.h0000644000175000017500000000532213023355232022261 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Dmx4LinuxPlugin.h * Interface for the dmx4linux plugin class * Copyright (C) 2006 Simon Newton */ #ifndef PLUGINS_DMX4LINUX_DMX4LINUXPLUGIN_H_ #define PLUGINS_DMX4LINUX_DMX4LINUXPLUGIN_H_ #include #include #include "ola/DmxBuffer.h" #include "olad/Plugin.h" #include "ola/network/Socket.h" #include "ola/plugin_id.h" #include "plugins/dmx4linux/Dmx4LinuxPort.h" #include "plugins/dmx4linux/Dmx4LinuxSocket.h" namespace ola { namespace plugin { namespace dmx4linux { class Dmx4LinuxDevice; class Dmx4LinuxPlugin: public ola::Plugin { public: explicit Dmx4LinuxPlugin(PluginAdaptor *plugin_adaptor): Plugin(plugin_adaptor), m_in_descriptor(NULL), m_out_descriptor(NULL), m_in_devices_count(0), m_in_buffer(NULL) {} ~Dmx4LinuxPlugin(); string Name() const { return PLUGIN_NAME; } string Description() const; ola_plugin_id Id() const { return OLA_PLUGIN_DMX4LINUX; } int SocketReady(); string PluginPrefix() const { return PLUGIN_PREFIX; } private: bool StartHook(); bool StopHook(); bool SetDefaultPreferences(); bool SetupDescriptors(); int CleanupDescriptors(); bool SetupDevice(string family, int d4l_uni, int dir); bool SetupDevices(); vector m_devices; // list of out devices vector m_in_ports; // list of in ports string m_out_dev; // path to the dmx output device string m_in_dev; // path to the dmx input device Dmx4LinuxSocket *m_in_descriptor; Dmx4LinuxSocket *m_out_descriptor; int m_in_devices_count; // number of input devices uint8_t *m_in_buffer; // input buffer static const char DMX4LINUX_OUT_DEVICE[]; static const char DMX4LINUX_IN_DEVICE[]; static const char OUT_DEV_KEY[]; static const char IN_DEV_KEY[]; static const char PLUGIN_NAME[]; static const char PLUGIN_PREFIX[]; }; } // namespace dmx4linux } // namespace plugin } // namespace ola #endif // PLUGINS_DMX4LINUX_DMX4LINUXPLUGIN_H_ ola-0.10.5.nojsmin/plugins/dmx4linux/Dmx4LinuxSocket.h0000644000175000017500000000250513023355232022253 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Dmx4LinuxSocket.h * Interface for the dmx4linux socket class * Copyright (C) 2006 Simon Newton */ #ifndef PLUGINS_DMX4LINUX_DMX4LINUXSOCKET_H_ #define PLUGINS_DMX4LINUX_DMX4LINUXSOCKET_H_ #include "ola/network/Socket.h" namespace ola { namespace plugin { namespace dmx4linux { class Dmx4LinuxSocket: public ola::network::DeviceDescriptor { public: explicit Dmx4LinuxSocket(int fd): ola::network::DeviceDescriptor(fd) {} protected: virtual bool IsClosed() const {return false;} }; } // namespace dmx4linux } // namespace plugin } // namespace ola #endif // PLUGINS_DMX4LINUX_DMX4LINUXSOCKET_H_ ola-0.10.5.nojsmin/plugins/dmx4linux/Dmx4LinuxDevice.h0000644000175000017500000000261313023355232022222 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Dmx4LinuxDevice.h * Interface for the dmx4linux device * Copyright (C) 2006 Simon Newton */ #ifndef PLUGINS_DMX4LINUX_DMX4LINUXDEVICE_H_ #define PLUGINS_DMX4LINUX_DMX4LINUXDEVICE_H_ #include #include "olad/Device.h" namespace ola { namespace plugin { namespace dmx4linux { class Dmx4LinuxDevice: public ola::Device { public: Dmx4LinuxDevice(class Dmx4LinuxPlugin *owner, const string &name, const string &device_id); string DeviceId() const { return m_device_id; } private: string m_device_id; }; } // namespace dmx4linux } // namespace plugin } // namespace ola #endif // PLUGINS_DMX4LINUX_DMX4LINUXDEVICE_H_ ola-0.10.5.nojsmin/plugins/dmx4linux/Dmx4LinuxPort.h0000644000175000017500000000475213023355232021755 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Dmx4LinuxPort.h * The Dmx4Linux plugin for ola * Copyright (C) 2006 Simon Newton */ #ifndef PLUGINS_DMX4LINUX_DMX4LINUXPORT_H_ #define PLUGINS_DMX4LINUX_DMX4LINUXPORT_H_ #include #include "ola/Constants.h" #include "ola/DmxBuffer.h" #include "plugins/dmx4linux/Dmx4LinuxDevice.h" #include "plugins/dmx4linux/Dmx4LinuxSocket.h" namespace ola { namespace plugin { namespace dmx4linux { /* * A Dmx4Linux output port, we only have 1 port per device so the port id is * always 0. */ class Dmx4LinuxOutputPort: public BasicOutputPort { public: Dmx4LinuxOutputPort(Dmx4LinuxDevice *parent, Dmx4LinuxSocket *socket, int d4l_universe) : BasicOutputPort(parent, 0), m_socket(socket), m_d4l_universe(d4l_universe) { } bool WriteDMX(const DmxBuffer &buffer, uint8_t priority); string Description() const { return ""; } private: Dmx4LinuxSocket *m_socket; int m_d4l_universe; // dmx4linux universe that this maps to }; /* * A Dmx4Linux input port, we only have 1 port per device so the port id is * always 0. */ class Dmx4LinuxInputPort: public BasicInputPort { public: explicit Dmx4LinuxInputPort(Dmx4LinuxDevice *parent, class PluginAdaptor *plugin_adaptor) : BasicInputPort(parent, 0, plugin_adaptor) { m_read_buffer.SetRangeToValue(0, 0, DMX_UNIVERSE_SIZE); } /** * Read operation * @return a DmxBufer with the data */ const DmxBuffer &ReadDMX() const; /** * Process new Data */ bool UpdateData(const uint8_t *in_buffer, unsigned int length); string Description() const { return ""; } private: DmxBuffer m_read_buffer; }; } // namespace dmx4linux } // namespace plugin } // namespace ola #endif // PLUGINS_DMX4LINUX_DMX4LINUXPORT_H_ ola-0.10.5.nojsmin/plugins/dmx4linux/Dmx4LinuxPlugin.cpp0000644000175000017500000001717213023355232022622 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Dmx4LinuxPlugin.cpp * The Dmx4Linux plugin for ola * Copyright (C) 2006 Simon Newton */ #include #include #include #include #include #include #include #include #include #include #include #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/StringUtils.h" #include "olad/PluginAdaptor.h" #include "olad/Preferences.h" #include "plugins/dmx4linux/Dmx4LinuxDevice.h" #include "plugins/dmx4linux/Dmx4LinuxPlugin.h" #include "plugins/dmx4linux/Dmx4LinuxPort.h" #include "plugins/dmx4linux/Dmx4LinuxSocket.h" namespace ola { namespace plugin { namespace dmx4linux { const char Dmx4LinuxPlugin::DMX4LINUX_OUT_DEVICE[] = "/dev/dmx"; const char Dmx4LinuxPlugin::DMX4LINUX_IN_DEVICE[] = "/dev/dmxin"; const char Dmx4LinuxPlugin::IN_DEV_KEY[] = "in_device"; const char Dmx4LinuxPlugin::OUT_DEV_KEY[] = "out_device"; const char Dmx4LinuxPlugin::PLUGIN_NAME[] = "Dmx4Linux"; const char Dmx4LinuxPlugin::PLUGIN_PREFIX[] = "dmx4linux"; Dmx4LinuxPlugin::~Dmx4LinuxPlugin() { CleanupDescriptors(); } /* * Start the plugin */ bool Dmx4LinuxPlugin::StartHook() { if (!SetupDescriptors()) { return false; } if (!SetupDevices()) { CleanupDescriptors(); return false; } if (!m_devices.empty()) { m_in_descriptor->SetOnData( ola::NewCallback(this, &Dmx4LinuxPlugin::SocketReady)); m_plugin_adaptor->AddReadDescriptor(m_in_descriptor); return true; } else { CleanupDescriptors(); return false; } } /* * Stop the plugin * @return true on success, false on failure */ bool Dmx4LinuxPlugin::StopHook() { vector::iterator it; m_plugin_adaptor->RemoveReadDescriptor(m_in_descriptor); for (it = m_devices.begin(); it != m_devices.end(); ++it) { m_plugin_adaptor->UnregisterDevice(*it); (*it)->Stop(); delete *it; } CleanupDescriptors(); m_devices.clear(); m_in_ports.clear(); return 0; } /* * Return the description for this plugin */ string Dmx4LinuxPlugin::Description() const { return "DMX 4 Linux Plugin\n" "----------------------------\n" "\n" "This plugin exposes DMX 4 Linux devices.\n" "\n" "--- Config file : ola-dmx4linux.conf ---\n" "\n" "in_device = /dev/dmxin\n" "out_device = /dev/dmx\n"; } /* * Called when there is input for us */ int Dmx4LinuxPlugin::SocketReady() { vector::iterator iter; unsigned int data_read, offset; int ret; if (lseek(m_in_descriptor->ReadDescriptor(), 0, SEEK_SET) != 0) { OLA_WARN << "Failed to seek: " << strerror(errno); return -1; } ret = m_in_descriptor->Receive(m_in_buffer, DMX_UNIVERSE_SIZE * m_in_devices_count, data_read); iter = m_in_ports.begin(); offset = 0; while (offset < data_read && iter != m_in_ports.end()) { (*iter)->UpdateData(m_in_buffer + offset, data_read - offset); iter++; } return 0; } /* * load the plugin prefs and default to sensible values */ bool Dmx4LinuxPlugin::SetDefaultPreferences() { bool save = false; if (!m_preferences) { return false; } save |= m_preferences->SetDefaultValue(IN_DEV_KEY, StringValidator(), DMX4LINUX_IN_DEVICE); save |= m_preferences->SetDefaultValue(OUT_DEV_KEY, StringValidator(), DMX4LINUX_OUT_DEVICE); if (save) { m_preferences->Save(); } if (m_preferences->GetValue(IN_DEV_KEY).empty() || m_preferences->GetValue(OUT_DEV_KEY).empty()) { return false; } m_in_dev = m_preferences->GetValue(IN_DEV_KEY); m_out_dev = m_preferences->GetValue(OUT_DEV_KEY); return true; } /* * Open the input and output fds */ bool Dmx4LinuxPlugin::SetupDescriptors() { if (!m_in_descriptor && !m_out_descriptor) { int fd = open(m_out_dev.c_str(), O_WRONLY); if (fd < 0) { OLA_WARN << "Failed to open " << m_out_dev << " " << strerror(errno); return false; } m_out_descriptor = new Dmx4LinuxSocket(fd); fd = open(m_in_dev.c_str(), O_RDONLY | O_NONBLOCK); if (fd < 0) { OLA_WARN << "Failed to open " << m_in_dev << " " << strerror(errno); CleanupDescriptors(); return false; } m_in_descriptor = new Dmx4LinuxSocket(fd); return true; } return false; } /* * Close all fds */ int Dmx4LinuxPlugin::CleanupDescriptors() { if (m_in_descriptor) { delete m_in_descriptor; m_in_descriptor = NULL; } if (m_out_descriptor) { delete m_out_descriptor; m_out_descriptor = NULL; } if (m_in_buffer) { delete[] m_in_buffer; m_in_buffer = NULL; } return 0; } /* * setup a single device * @param family the dmx4linux family * @param d4l_uni the dmx4linux universe * @param dir in|out */ bool Dmx4LinuxPlugin::SetupDevice(string family, int d4l_uni, int dir) { string device_id = IntToString((d4l_uni << 1) + dir); string name = string("dmx4linux_"); name.append(family); name.append(dir ? "_in_" : "_out_"); name.append(IntToString(d4l_uni)); OLA_INFO << "Dmx4LinuxPlugin creates a device : name = " << name << " / uni = " << d4l_uni << " / dir = " << dir; Dmx4LinuxDevice *dev = new Dmx4LinuxDevice(this, name, device_id); dev->Start(); if (dir == DMX_DIRECTION_INPUT) { Dmx4LinuxInputPort *port = new Dmx4LinuxInputPort( dev, m_plugin_adaptor); m_in_ports.push_back(port); dev->AddPort(port); } else { Dmx4LinuxOutputPort *port = new Dmx4LinuxOutputPort(dev, m_out_descriptor, d4l_uni); dev->AddPort(port); } m_plugin_adaptor->RegisterDevice(dev); m_devices.push_back(dev); return true; } /* * Find all the devices connected and setup ports for them. */ bool Dmx4LinuxPlugin::SetupDevices() { struct dmx_capabilities cap; struct dmx_info info; if (ioctl(m_in_descriptor->ReadDescriptor(), DMX_IOCTL_GET_INFO, &info) < 0) { OLA_WARN << "failed to fetch universe list"; return false; } if (info.max_in_universes > 0) { m_in_devices_count = info.max_in_universes; m_in_buffer = new uint8_t[DMX_UNIVERSE_SIZE * info.max_in_universes]; } for (int i = 0; i < info.max_in_universes; i++) { cap.direction = DMX_DIRECTION_INPUT; cap.universe = i; if (ioctl(m_in_descriptor->ReadDescriptor(), DMX_IOCTL_GET_CAP, &cap) >= 0) { if (cap.maxSlots > 0) { SetupDevice(cap.family, cap.universe, cap.direction); } } } for (int i = 0; i < info.max_out_universes; i++) { cap.direction = DMX_DIRECTION_OUTPUT; cap.universe = i; if (ioctl(m_in_descriptor->ReadDescriptor(), DMX_IOCTL_GET_CAP, &cap) >= 0) { if (cap.maxSlots > 0) { SetupDevice(cap.family, cap.universe, cap.direction); } } } return true; } } // namespace dmx4linux } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/dmx4linux/Dmx4LinuxPort.cpp0000644000175000017500000000403513023355232022302 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Dmx4LinuxPort.cpp * The DMX 4 Linux plugin * Copyright (C) 2006 Simon Newton */ #include #include #include #include #include "plugins/dmx4linux/Dmx4LinuxPort.h" #include "plugins/dmx4linux/Dmx4LinuxDevice.h" namespace ola { namespace plugin { namespace dmx4linux { bool Dmx4LinuxOutputPort::WriteDMX(const DmxBuffer &buffer, uint8_t priority) { int offset = DMX_UNIVERSE_SIZE * m_d4l_universe; if (lseek(m_socket->WriteDescriptor(), offset, SEEK_SET) == offset) { ssize_t r = m_socket->Send(buffer.GetRaw(), buffer.Size()); if ((uint) r != buffer.Size()) { OLA_WARN << "only wrote " << r << "/" << buffer.Size() << " bytes: " << strerror(errno); return false; } } else { OLA_WARN << "failed to seek: " << strerror(errno); return false; } return true; } const DmxBuffer &Dmx4LinuxInputPort::ReadDMX() const { return m_read_buffer; } bool Dmx4LinuxInputPort::UpdateData(const uint8_t *in_buffer, unsigned int length) { DmxBuffer tmp_buffer = DmxBuffer(in_buffer, length); if (!(tmp_buffer == m_read_buffer)) { m_read_buffer.Set(tmp_buffer); DmxChanged(); } return true; } } // namespace dmx4linux } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/dmx4linux/Dmx4LinuxDevice.cpp0000644000175000017500000000264213023355232022557 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Dmx4LinuxDevice.cpp * Dmx4Linux device * Copyright (C) 2006 Simon Newton * */ #include #include "plugins/dmx4linux/Dmx4LinuxPlugin.h" #include "plugins/dmx4linux/Dmx4LinuxDevice.h" namespace ola { namespace plugin { namespace dmx4linux { using ola::Device; /* * Create a new device * @param owner the plugin that owns this device * @param name the device name * @param device_id the device id */ Dmx4LinuxDevice::Dmx4LinuxDevice(Dmx4LinuxPlugin *owner, const string &name, const string &device_id): Device(owner, name), m_device_id(device_id) { } } // namespace dmx4linux } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/spi/0000755000175000017500000000000013155164170015737 5ustar wouterwouterola-0.10.5.nojsmin/plugins/spi/SPIBackend.cpp0000644000175000017500000003070713023355232020350 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SPIBackend.cpp * The backend for SPI output. These are the classes which write the data to * the SPI bus. * Copyright (C) 2013 Simon Newton */ #include #include #include #include #include #include #include #include #include #include #include "ola/Logging.h" #include "ola/io/IOUtils.h" #include "ola/network/SocketCloser.h" #include "ola/stl/STLUtils.h" #include "plugins/spi/SPIBackend.h" namespace ola { namespace plugin { namespace spi { using ola::thread::MutexLocker; using std::string; using std::vector; const char SPIBackendInterface::SPI_DROP_VAR[] = "spi-drops"; const char SPIBackendInterface::SPI_DROP_VAR_KEY[] = "device"; uint8_t *HardwareBackend::OutputData::Resize(unsigned int length) { if (length < m_size) { m_size = length; return m_data; } else if (length == m_size) { return m_data; } if (length <= m_actual_size) { m_size = length; return m_data; } delete[] m_data; m_data = new uint8_t[length]; if (m_data) { m_size = m_data ? length : 0; m_actual_size = m_size; memset(m_data, 0, length); } return m_data; } void HardwareBackend::OutputData::SetPending() { m_write_pending = true; } void HardwareBackend::OutputData::SetLatchBytes(unsigned int latch_bytes) { m_latch_bytes = latch_bytes; } HardwareBackend::OutputData& HardwareBackend::OutputData::operator=( const HardwareBackend::OutputData &other) { if (this != &other) { uint8_t *data = Resize(other.m_size + other.m_latch_bytes); if (data) { memcpy(data, other.m_data, other.m_size); memset(data + other.m_size, 0, other.m_latch_bytes); m_write_pending = true; } else { m_write_pending = false; } } return *this; } HardwareBackend::HardwareBackend(const Options &options, SPIWriterInterface *writer, ExportMap *export_map) : m_spi_writer(writer), m_drop_map(NULL), m_output_count(1 << options.gpio_pins.size()), m_exit(false), m_gpio_pins(options.gpio_pins) { SetupOutputs(&m_output_data); if (export_map) { m_drop_map = export_map->GetUIntMapVar(SPI_DROP_VAR, SPI_DROP_VAR_KEY); (*m_drop_map)[m_spi_writer->DevicePath()] = 0; } } HardwareBackend::~HardwareBackend() { { MutexLocker lock(&m_mutex); m_exit = true; } m_cond_var.Signal(); Join(); STLDeleteElements(&m_output_data); CloseGPIOFDs(); } bool HardwareBackend::Init() { if (!(m_spi_writer->Init() && SetupGPIO())) { return false; } if (!Start()) { CloseGPIOFDs(); return false; } return true; } uint8_t *HardwareBackend::Checkout(uint8_t output_id, unsigned int length, unsigned int latch_bytes) { if (output_id >= m_output_count) { return NULL; } m_mutex.Lock(); uint8_t *output = m_output_data[output_id]->Resize(length); if (!output) { m_mutex.Unlock(); } m_output_data[output_id]->SetLatchBytes(latch_bytes); // We return with the Mutex locked, the caller must then call Commit() // coverity[LOCK] return output; } void HardwareBackend::Commit(uint8_t output) { if (output >= m_output_count) { return; } OutputData *output_data = m_output_data[output]; if (output_data->IsPending() && m_drop_map) { // There was already another write pending which we're now stomping on (*m_drop_map)[m_spi_writer->DevicePath()]++; } output_data->SetPending(); m_mutex.Unlock(); m_cond_var.Signal(); } void *HardwareBackend::Run() { Outputs outputs; SetupOutputs(&outputs); while (true) { m_mutex.Lock(); if (m_exit) { m_mutex.Unlock(); STLDeleteElements(&outputs); return NULL; } bool action_pending = false; Outputs::const_iterator iter = m_output_data.begin(); for (; iter != m_output_data.end(); ++iter) { if ((*iter)->IsPending()) { action_pending = true; break; } } if (!action_pending) { m_cond_var.Wait(&m_mutex); } if (m_exit) { m_mutex.Unlock(); STLDeleteElements(&outputs); return NULL; } for (unsigned int i = 0; i < m_output_data.size(); i++) { if (m_output_data[i]->IsPending()) { // take a copy *outputs[i] = *m_output_data[i]; m_output_data[i]->ResetPending(); } } m_mutex.Unlock(); for (unsigned int i = 0; i < outputs.size(); i++) { if (outputs[i]->IsPending()) { WriteOutput(i, outputs[i]); outputs[i]->ResetPending(); } } } } void HardwareBackend::SetupOutputs(Outputs *outputs) { for (unsigned int i = 0; i < m_output_count; i++) { outputs->push_back(new OutputData()); } } void HardwareBackend::WriteOutput(uint8_t output_id, OutputData *output) { const string on("1"); const string off("0"); for (unsigned int i = 0; i < m_gpio_fds.size(); i++) { uint8_t pin = output_id & (1 << i); if (i >= m_gpio_pin_state.size()) { m_gpio_pin_state.push_back(!pin); } if (m_gpio_pin_state[i] != pin) { const string &data = pin ? on : off; if (write(m_gpio_fds[i], data.c_str(), data.size()) < 0) { OLA_WARN << "Failed to toggle SPI GPIO pin " << static_cast(m_gpio_pins[i]) << ": " << strerror(errno); return; } m_gpio_pin_state[i] = pin; } } m_spi_writer->WriteSPIData(output->GetData(), output->Size()); } bool HardwareBackend::SetupGPIO() { /** * This relies on the pins being exported: * echo N > /sys/class/gpio/export * That requires root access. */ const string direction("out"); bool failed = false; vector::const_iterator iter = m_gpio_pins.begin(); for (; iter != m_gpio_pins.end(); ++iter) { std::ostringstream str; str << "/sys/class/gpio/gpio" << static_cast(*iter) << "/value"; int fd; if (ola::io::Open(str.str(), O_RDWR, &fd)) { m_gpio_fds.push_back(fd); } else { failed = true; break; } // Set dir str.str(""); str << "/sys/class/gpio/gpio" << static_cast(*iter) << "/direction"; if (!ola::io::Open(str.str(), O_RDWR, &fd)) { failed = true; break; } if (write(fd, direction.c_str(), direction.size()) < 0) { OLA_WARN << "Failed to enable output on " << str.str() << " : " << strerror(errno); failed = true; } close(fd); } if (failed) { CloseGPIOFDs(); return false; } return true; } void HardwareBackend::CloseGPIOFDs() { GPIOFds::iterator iter = m_gpio_fds.begin(); for (; iter != m_gpio_fds.end(); ++iter) { close(*iter); } m_gpio_fds.clear(); } SoftwareBackend::SoftwareBackend(const Options &options, SPIWriterInterface *writer, ExportMap *export_map) : m_spi_writer(writer), m_drop_map(NULL), m_write_pending(false), m_exit(false), m_sync_output(options.sync_output), m_output_sizes(options.outputs, 0), m_latch_bytes(options.outputs, 0), m_output(NULL), m_length(0) { if (export_map) { m_drop_map = export_map->GetUIntMapVar(SPI_DROP_VAR, SPI_DROP_VAR_KEY); (*m_drop_map)[m_spi_writer->DevicePath()] = 0; } } SoftwareBackend::~SoftwareBackend() { { MutexLocker lock(&m_mutex); m_exit = true; } m_cond_var.Signal(); Join(); delete[] m_output; } bool SoftwareBackend::Init() { if (!m_spi_writer->Init()) { return false; } if (!Start()) { return false; } return true; } uint8_t *SoftwareBackend::Checkout(uint8_t output, unsigned int length, unsigned int latch_bytes) { if (output >= m_output_sizes.size()) { OLA_WARN << "Invalid SPI output " << static_cast(output); return NULL; } m_mutex.Lock(); unsigned int leading = 0; unsigned int trailing = 0; for (uint8_t i = 0; i < m_output_sizes.size(); i++) { if (i < output) { leading += m_output_sizes[i]; } else if (i > output) { trailing += m_output_sizes[i]; } } m_latch_bytes[output] = latch_bytes; const unsigned int total_latch_bytes = std::accumulate( m_latch_bytes.begin(), m_latch_bytes.end(), 0); const unsigned int required_size = ( leading + length + trailing + total_latch_bytes); // Check if the current buffer is large enough to hold our data. if (required_size != m_length) { // The length changed uint8_t *new_output = new uint8_t[required_size]; memcpy(new_output, m_output, leading); memset(new_output + leading, 0, length); memcpy(new_output + leading + length, m_output + leading, trailing); memset(new_output + leading + length + trailing, 0, total_latch_bytes); delete[] m_output; m_output = new_output; m_length = required_size; m_output_sizes[output] = length; } return m_output + leading; } void SoftwareBackend::Commit(uint8_t output) { if (output >= m_output_sizes.size()) { OLA_WARN << "Invalid SPI output " << static_cast(output); return; } bool should_write = m_sync_output < 0 || output == m_sync_output; if (should_write) { if (m_write_pending && m_drop_map) { // There was already another write pending which we're now stomping on (*m_drop_map)[m_spi_writer->DevicePath()]++; } m_write_pending = should_write; } m_mutex.Unlock(); if (should_write) { m_cond_var.Signal(); } } void *SoftwareBackend::Run() { uint8_t *output_data = NULL; unsigned int length = 0; while (true) { m_mutex.Lock(); if (m_exit) { m_mutex.Unlock(); delete output_data; return NULL; } if (!m_write_pending) { m_cond_var.Wait(&m_mutex); } if (m_exit) { m_mutex.Unlock(); delete[] output_data; return NULL; } bool write_pending = m_write_pending; m_write_pending = false; if (write_pending) { if (length < m_length) { delete[] output_data; output_data = new uint8_t[m_length]; length = m_length; } // TODO(simon) Add an actual size here length = m_length; memcpy(output_data, m_output, m_length); } m_mutex.Unlock(); if (write_pending) { m_spi_writer->WriteSPIData(output_data, length); } } } FakeSPIBackend::FakeSPIBackend(unsigned int outputs) { for (unsigned int i = 0; i < outputs; i++) { m_outputs.push_back(new Output()); } } FakeSPIBackend::~FakeSPIBackend() { STLDeleteElements(&m_outputs); } uint8_t *FakeSPIBackend::Checkout(uint8_t output_id, unsigned int length, unsigned int latch_bytes) { if (output_id >= m_outputs.size()) { return NULL; } Output *output = m_outputs[output_id]; if (output->length != length + latch_bytes) { delete[] output->data; output->data = new uint8_t[length + latch_bytes]; memset(output->data, 0, length + latch_bytes); output->length = length + latch_bytes; } return output->data; } void FakeSPIBackend::Commit(uint8_t output) { if (output >= m_outputs.size()) { return; } m_outputs[output]->writes++; } const uint8_t *FakeSPIBackend::GetData(uint8_t output_id, unsigned int *length) { if (output_id >= m_outputs.size()) { return NULL; } Output *output = m_outputs[output_id]; *length = output->length; return output->data; } unsigned int FakeSPIBackend::Writes(uint8_t output) const { if (output >= m_outputs.size()) { return 0; } return m_outputs[output]->writes; } } // namespace spi } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/spi/SPIPlugin.cpp0000644000175000017500000001473713023355232020264 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SPIPlugin.cpp * The SPI plugin for ola * Copyright (C) 2013 Simon Newton */ #include #include #include #include "ola/Logging.h" #include "ola/StringUtils.h" #include "ola/file/Util.h" #include "ola/rdm/UID.h" #include "ola/rdm/UIDAllocator.h" #include "olad/PluginAdaptor.h" #include "olad/Preferences.h" #include "plugins/spi/SPIDevice.h" #include "plugins/spi/SPIPlugin.h" namespace ola { namespace plugin { namespace spi { using ola::rdm::UID; using std::auto_ptr; using std::string; using std::vector; const char SPIPlugin::DEFAULT_BASE_UID[] = "7a70:00000100"; const char SPIPlugin::DEFAULT_SPI_DEVICE_PREFIX[] = "spidev"; const char SPIPlugin::PLUGIN_NAME[] = "SPI"; const char SPIPlugin::PLUGIN_PREFIX[] = "spi"; const char SPIPlugin::SPI_BASE_UID_KEY[] = "base_uid"; const char SPIPlugin::SPI_DEVICE_PREFIX_KEY[] = "device_prefix"; /* * Start the plugin * For now we just have one device. */ bool SPIPlugin::StartHook() { const string uid_str = m_preferences->GetValue(SPI_BASE_UID_KEY); auto_ptr base_uid(UID::FromString(uid_str)); if (!base_uid.get()) { OLA_WARN << "Invalid UID " << uid_str << ", defaulting to " << DEFAULT_BASE_UID; base_uid.reset(UID::FromString(DEFAULT_BASE_UID)); if (!base_uid.get()) { OLA_WARN << "Invalid UID " << DEFAULT_BASE_UID; return false; } } vector spi_files; vector spi_prefixes = m_preferences->GetMultipleValue( SPI_DEVICE_PREFIX_KEY); if (!ola::file::FindMatchingFiles("/dev", spi_prefixes, &spi_files)) { return false; } ola::rdm::UIDAllocator uid_allocator(*base_uid); vector::const_iterator iter = spi_files.begin(); for (; iter != spi_files.end(); ++iter) { SPIDevice *device = new SPIDevice(this, m_preferences, m_plugin_adaptor, *iter, &uid_allocator); if (!device) { continue; } if (!device->Start()) { delete device; continue; } m_devices.push_back(device); m_plugin_adaptor->RegisterDevice(device); } return true; } /* * Stop the plugin * @return true on success, false on failure */ bool SPIPlugin::StopHook() { vector::iterator iter = m_devices.begin(); bool ok = true; for (; iter != m_devices.end(); ++iter) { m_plugin_adaptor->UnregisterDevice(*iter); ok &= (*iter)->Stop(); delete *iter; } return ok; } /* * Return the description for this plugin */ string SPIPlugin::Description() const { return "SPI Plugin\n" "----------------------------\n" "\n" "This plugin enables control of LED pixel strings using SPI. Each SPI output\n" "is represented as an OLA Device. Devices can have multiple Ports, each of\n" "which controls a pixel string. Each Port can use a different\n" "personality (pixel type) and DMX start address, this allows a combination\n" "of various strings lengths & pixel hardware types. The start address and\n" "personality settings are controllable via RDM (each Port appears as a RDM\n" "responder).\n" "\n" "To support multiple ports per SPI output, we use an SPI-Backend. Two\n" "backends are supported right now, a software backend which concatenates\n" "all the pixel data into a single buffer and a hardware multiplexer backend\n" "which uses the GPIO pins to control an off-host multiplexer. It's\n" "recommended to use the hardware multiplexer.\n" "\n" "--- Config file : ola-spi.conf ---\n" "\n" "base_uid = \n" "The starting UID to use for the SPI RDM , e.g. 7a70:00000100.\n" "\n" "device_prefix = \n" "The prefix of files to match in /dev. Usually set to 'spidev'. Each match\n" "will instantiate a Device.\n" "\n" "--- Per Device Settings ---\n" "-spi-speed = \n" "The speed of the SPI bus, range is 0 - 32000000 Hz.\n" "\n" "-ce-high = \n" "The mode of the CE pin. Set to false this pulls the CE pin low when writing\n" "data. Set to true this will pull the pin high when writing.\n" "\n" "-backend = [software | hardware]\n" "The backend to use to multiplex the SPI data.\n" "\n" "-gpio-pin = \n" "The GPIO pins to use for the hardware multiplexer. Add one line for each\n" "pin. The number of ports will be 2 ** (# of pins).\n" "\n" "-ports = \n" "If the software backend is used, this defines the number of ports which\n" "will be created.\n" "\n" "-sync-ports = \n" "Controls which port triggers a flush (write) of the SPI data. If set to -1\n" "the SPI data is written when any port changes. This can result in a lot of\n" "data writes (slow) and partial frames. If set to -2, the last port is used.\n" "\n" "--- Per Port Settings ---\n" "Ports are indexed from 0.\n" "\n" "--dmx-address = \n" "The DMX address to use. e.g. spidev0.1-0-dmx-address = 1\n" "\n" "--device-label = \n" "The RDM device label to use.\n" "\n" "--personality = \n" "The RDM personality to use.\n" "\n" "--pixel-count = \n" "The number of pixels for this port. e.g. spidev0.1-1-pixel-count = 20.\n" "\n"; } /* * Load the plugin prefs and default to sensible values */ bool SPIPlugin::SetDefaultPreferences() { bool save = false; if (!m_preferences) { return false; } save |= m_preferences->SetDefaultValue(SPI_DEVICE_PREFIX_KEY, StringValidator(), DEFAULT_SPI_DEVICE_PREFIX); save |= m_preferences->SetDefaultValue(SPI_BASE_UID_KEY, StringValidator(), DEFAULT_BASE_UID); if (save) { m_preferences->Save(); } if (m_preferences->GetValue(SPI_DEVICE_PREFIX_KEY).empty()) { return false; } return true; } } // namespace spi } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/spi/Makefile.mk0000644000175000017500000000252013023355232017777 0ustar wouterwouter# LIBRARIES ################################################## if USE_SPI # This is a library which isn't coupled to olad lib_LTLIBRARIES += plugins/spi/libolaspicore.la plugins/spi/libolaspi.la plugins_spi_libolaspicore_la_SOURCES = \ plugins/spi/SPIBackend.cpp \ plugins/spi/SPIBackend.h \ plugins/spi/SPIOutput.cpp \ plugins/spi/SPIOutput.h \ plugins/spi/SPIWriter.cpp \ plugins/spi/SPIWriter.h plugins_spi_libolaspicore_la_LIBADD = common/libolacommon.la plugins_spi_libolaspi_la_SOURCES = \ plugins/spi/SPIDevice.cpp \ plugins/spi/SPIDevice.h \ plugins/spi/SPIPlugin.cpp \ plugins/spi/SPIPlugin.h \ plugins/spi/SPIPort.cpp \ plugins/spi/SPIPort.h plugins_spi_libolaspi_la_LIBADD = \ common/libolacommon.la \ olad/plugin_api/libolaserverplugininterface.la \ plugins/spi/libolaspicore.la # TESTS ################################################## test_programs += plugins/spi/SPITester plugins_spi_SPITester_SOURCES = \ plugins/spi/SPIBackendTest.cpp \ plugins/spi/SPIOutputTest.cpp \ plugins/spi/FakeSPIWriter.cpp \ plugins/spi/FakeSPIWriter.h plugins_spi_SPITester_CXXFLAGS = $(COMMON_TESTING_FLAGS) plugins_spi_SPITester_LDADD = $(COMMON_TESTING_LIBS) \ plugins/spi/libolaspicore.la \ common/libolacommon.la endif ola-0.10.5.nojsmin/plugins/spi/SPIPort.cpp0000644000175000017500000000550313023355232017741 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SPIPort.cpp * The SPI plugin for ola * Copyright (C) 2013 Simon Newton */ #include #include "ola/Constants.h" #include "ola/rdm/RDMCommand.h" #include "ola/rdm/UID.h" #include "plugins/spi/SPIBackend.h" #include "plugins/spi/SPIPort.h" namespace ola { namespace plugin { namespace spi { using ola::rdm::RDMCallback; using ola::rdm::RDMDiscoveryCallback; using ola::rdm::RDMRequest; using ola::rdm::UID; using std::string; SPIOutputPort::SPIOutputPort(SPIDevice *parent, SPIBackendInterface *backend, const UID &uid, const SPIOutput::Options &options) : BasicOutputPort(parent, options.output_number, true), m_spi_output(uid, backend, options) { } string SPIOutputPort::GetDeviceLabel() const { return m_spi_output.GetDeviceLabel(); } bool SPIOutputPort::SetDeviceLabel(const string &device_label) { return m_spi_output.SetDeviceLabel(device_label); } uint8_t SPIOutputPort::GetPersonality() const { return m_spi_output.GetPersonality(); } bool SPIOutputPort::SetPersonality(uint16_t personality) { return m_spi_output.SetPersonality(personality); } uint16_t SPIOutputPort::GetStartAddress() const { return m_spi_output.GetStartAddress(); } bool SPIOutputPort::SetStartAddress(uint16_t address) { return m_spi_output.SetStartAddress(address); } unsigned int SPIOutputPort::PixelCount() const { return m_spi_output.PixelCount(); } string SPIOutputPort::Description() const { return m_spi_output.Description(); } bool SPIOutputPort::WriteDMX(const DmxBuffer &buffer, uint8_t) { return m_spi_output.WriteDMX(buffer); } void SPIOutputPort::RunFullDiscovery(RDMDiscoveryCallback *callback) { return m_spi_output.RunFullDiscovery(callback); } void SPIOutputPort::RunIncrementalDiscovery(RDMDiscoveryCallback *callback) { return m_spi_output.RunIncrementalDiscovery(callback); } void SPIOutputPort::SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *callback) { return m_spi_output.SendRDMRequest(request, callback); } } // namespace spi } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/spi/FakeSPIWriter.cpp0000644000175000017500000000456113023355232021063 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * FakeSPIWriter.cpp * The SPIWriter used for testing. * Copyright (C) 2013 Simon Newton */ #include #include #include #include "ola/Logging.h" #include "ola/testing/TestUtils.h" #include "plugins/spi/FakeSPIWriter.h" namespace ola { namespace plugin { namespace spi { using ola::thread::MutexLocker; bool FakeSPIWriter::WriteSPIData(const uint8_t *data, unsigned int length) { { MutexLocker lock(&m_mutex); if (m_last_write_size != length) { delete[] m_data; m_data = new uint8_t[length]; } memcpy(m_data, data, length); m_writes++; m_write_pending = true; m_last_write_size = length; } m_cond_var.Signal(); MutexLocker lock(&m_write_lock); return true; } void FakeSPIWriter::BlockWriter() { m_write_lock.Lock(); } void FakeSPIWriter::UnblockWriter() { m_write_lock.Unlock(); } void FakeSPIWriter::ResetWrite() { MutexLocker lock(&m_mutex); m_write_pending = false; } void FakeSPIWriter::WaitForWrite() { MutexLocker lock(&m_mutex); if (m_write_pending) return; m_cond_var.Wait(&m_mutex); } unsigned int FakeSPIWriter::WriteCount() const { MutexLocker lock(&m_mutex); return m_writes; } unsigned int FakeSPIWriter::LastWriteSize() const { MutexLocker lock(&m_mutex); return m_last_write_size; } void FakeSPIWriter::CheckDataMatches( const ola::testing::SourceLine &source_line, const uint8_t *expected, unsigned int length) { MutexLocker lock(&m_mutex); ola::testing::ASSERT_DATA_EQUALS(source_line, expected, length, m_data, m_last_write_size); } } // namespace spi } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/spi/SPIBackendTest.cpp0000644000175000017500000002556313023355232021214 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SPIBackendTest.cpp * Test fixture for the SPIBackendTests. * Copyright (C) 2013 Simon Newton */ #include #include #include "ola/base/Array.h" #include "ola/DmxBuffer.h" #include "ola/ExportMap.h" #include "ola/Logging.h" #include "ola/testing/TestUtils.h" #include "plugins/spi/FakeSPIWriter.h" #include "plugins/spi/SPIBackend.h" using ola::DmxBuffer; using ola::ExportMap; using ola::plugin::spi::FakeSPIWriter; using ola::plugin::spi::HardwareBackend; using ola::plugin::spi::SoftwareBackend; using ola::plugin::spi::SPIBackendInterface; using ola::UIntMap; class SPIBackendTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(SPIBackendTest); CPPUNIT_TEST(testHardwareDrops); CPPUNIT_TEST(testHardwareVariousFrameLengths); CPPUNIT_TEST(testInvalidOutputs); CPPUNIT_TEST(testSoftwareDrops); CPPUNIT_TEST(testSoftwareVariousFrameLengths); CPPUNIT_TEST_SUITE_END(); public: SPIBackendTest(); void setUp(); unsigned int DropCount(); bool SendSomeData(SPIBackendInterface *backend, uint8_t output, const uint8_t *data, unsigned int length, unsigned int checkout_size, unsigned int latch_bytes = 0); void testHardwareDrops(); void testHardwareVariousFrameLengths(); void testInvalidOutputs(); void testSoftwareDrops(); void testSoftwareVariousFrameLengths(); private: ExportMap m_export_map; FakeSPIWriter m_writer; unsigned int m_total_size; static const uint8_t DATA1[]; static const uint8_t DATA2[]; static const uint8_t DATA3[]; static const uint8_t EXPECTED1[]; static const uint8_t EXPECTED2[]; static const uint8_t EXPECTED3[]; static const uint8_t EXPECTED4[]; static const char DEVICE_NAME[]; static const char SPI_DROP_VAR[]; static const char SPI_DROP_VAR_KEY[]; }; const uint8_t SPIBackendTest::DATA1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; const uint8_t SPIBackendTest::DATA2[] = { 0xa, 0xb, 0xc, 0xd, 0xe, 0xf }; const uint8_t SPIBackendTest::DATA3[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf }; const uint8_t SPIBackendTest::EXPECTED1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0 }; const uint8_t SPIBackendTest::EXPECTED2[] = { 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0 }; const uint8_t SPIBackendTest::EXPECTED3[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 0, 0, 0, }; const uint8_t SPIBackendTest::EXPECTED4[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; const char SPIBackendTest::DEVICE_NAME[] = "Fake Device"; const char SPIBackendTest::SPI_DROP_VAR[] = "spi-drops"; const char SPIBackendTest::SPI_DROP_VAR_KEY[] = "device"; CPPUNIT_TEST_SUITE_REGISTRATION(SPIBackendTest); SPIBackendTest::SPIBackendTest() : CppUnit::TestFixture(), m_writer(DEVICE_NAME) { m_total_size = arraysize(DATA3); } void SPIBackendTest::setUp() { ola::InitLogging(ola::OLA_LOG_INFO, ola::OLA_LOG_STDERR); } unsigned int SPIBackendTest::DropCount() { UIntMap *drop_map = m_export_map.GetUIntMapVar(SPI_DROP_VAR, SPI_DROP_VAR_KEY); return (*drop_map)[DEVICE_NAME]; } bool SPIBackendTest::SendSomeData(SPIBackendInterface *backend, uint8_t output, const uint8_t *data, unsigned int length, unsigned int checkout_size, unsigned int latch_bytes) { uint8_t *buffer = backend->Checkout(output, checkout_size, latch_bytes); if (!buffer) return false; memcpy(buffer, data, length); backend->Commit(output); return true; } /** * Check that we increment the exported variable when we drop frames. */ void SPIBackendTest::testHardwareDrops() { HardwareBackend backend(HardwareBackend::Options(), &m_writer, &m_export_map); OLA_ASSERT(backend.Init()); m_writer.BlockWriter(); OLA_ASSERT_EQ(0u, DropCount()); OLA_ASSERT(SendSomeData(&backend, 0, DATA1, arraysize(DATA1), m_total_size)); m_writer.WaitForWrite(); // now we know the writer is blocked OLA_ASSERT_EQ(1u, m_writer.WriteCount()); OLA_ASSERT(SendSomeData(&backend, 0, DATA1, arraysize(DATA1), m_total_size)); OLA_ASSERT(SendSomeData(&backend, 0, DATA1, arraysize(DATA1), m_total_size)); OLA_ASSERT_EQ(1u, DropCount()); m_writer.ResetWrite(); m_writer.UnblockWriter(); m_writer.WaitForWrite(); OLA_ASSERT_EQ(2u, m_writer.WriteCount()); } /** * Check that we handle the case of frame lengths changing. */ void SPIBackendTest::testHardwareVariousFrameLengths() { HardwareBackend backend(HardwareBackend::Options(), &m_writer, &m_export_map); OLA_ASSERT(backend.Init()); OLA_ASSERT(SendSomeData(&backend, 0, DATA1, arraysize(DATA1), m_total_size)); m_writer.WaitForWrite(); OLA_ASSERT_EQ(1u, m_writer.WriteCount()); m_writer.CheckDataMatches(OLA_SOURCELINE(), EXPECTED1, arraysize(EXPECTED1)); m_writer.ResetWrite(); OLA_ASSERT(SendSomeData(&backend, 0, DATA1, arraysize(DATA1), m_total_size)); m_writer.WaitForWrite(); OLA_ASSERT_EQ(2u, m_writer.WriteCount()); m_writer.CheckDataMatches(OLA_SOURCELINE(), EXPECTED1, arraysize(EXPECTED1)); m_writer.ResetWrite(); OLA_ASSERT(SendSomeData(&backend, 0, DATA2, arraysize(DATA2), m_total_size)); m_writer.WaitForWrite(); OLA_ASSERT_EQ(3u, m_writer.WriteCount()); m_writer.CheckDataMatches(OLA_SOURCELINE(), EXPECTED2, arraysize(EXPECTED2)); m_writer.ResetWrite(); OLA_ASSERT(SendSomeData(&backend, 0, DATA1, arraysize(DATA1), m_total_size)); m_writer.WaitForWrite(); OLA_ASSERT_EQ(4u, m_writer.WriteCount()); m_writer.CheckDataMatches(OLA_SOURCELINE(), EXPECTED1, arraysize(EXPECTED1)); m_writer.ResetWrite(); OLA_ASSERT(SendSomeData(&backend, 0, DATA3, arraysize(DATA3), m_total_size)); m_writer.WaitForWrite(); OLA_ASSERT_EQ(5u, m_writer.WriteCount()); m_writer.CheckDataMatches(OLA_SOURCELINE(), DATA3, arraysize(DATA3)); m_writer.ResetWrite(); // now test the latch bytes OLA_ASSERT( SendSomeData(&backend, 0, DATA1, arraysize(DATA1), m_total_size, 4)); m_writer.WaitForWrite(); OLA_ASSERT_EQ(6u, m_writer.WriteCount()); m_writer.CheckDataMatches(OLA_SOURCELINE(), EXPECTED3, arraysize(EXPECTED3)); m_writer.ResetWrite(); OLA_ASSERT( SendSomeData(&backend, 0, DATA3, arraysize(DATA3), m_total_size, 4)); m_writer.WaitForWrite(); OLA_ASSERT_EQ(7u, m_writer.WriteCount()); m_writer.CheckDataMatches(OLA_SOURCELINE(), EXPECTED3, arraysize(EXPECTED3)); m_writer.ResetWrite(); } /** * Check we can't send to invalid outputs. */ void SPIBackendTest::testInvalidOutputs() { // HardwareBackend HardwareBackend hw_backend(HardwareBackend::Options(), &m_writer, &m_export_map); OLA_ASSERT(hw_backend.Init()); OLA_ASSERT_FALSE( SendSomeData(&hw_backend, 1, DATA1, arraysize(DATA1), m_total_size)); OLA_ASSERT_EQ(0u, m_writer.WriteCount()); // SoftwareBackend SoftwareBackend sw_backend(SoftwareBackend::Options(), &m_writer, &m_export_map); OLA_ASSERT(sw_backend.Init()); OLA_ASSERT_FALSE( SendSomeData(&sw_backend, 1, DATA1, arraysize(DATA1), m_total_size)); OLA_ASSERT_EQ(0u, m_writer.WriteCount()); } /** * Check that we increment the exported variable when we drop frames. */ void SPIBackendTest::testSoftwareDrops() { SoftwareBackend backend(SoftwareBackend::Options(), &m_writer, &m_export_map); OLA_ASSERT(backend.Init()); m_writer.BlockWriter(); OLA_ASSERT_EQ(0u, DropCount()); OLA_ASSERT(SendSomeData(&backend, 0, DATA1, arraysize(DATA1), m_total_size)); m_writer.WaitForWrite(); // now we know the writer is blocked OLA_ASSERT_EQ(1u, m_writer.WriteCount()); OLA_ASSERT(SendSomeData(&backend, 0, DATA1, arraysize(DATA1), m_total_size)); OLA_ASSERT(SendSomeData(&backend, 0, DATA1, arraysize(DATA1), m_total_size)); OLA_ASSERT_EQ(1u, DropCount()); m_writer.ResetWrite(); m_writer.UnblockWriter(); m_writer.WaitForWrite(); OLA_ASSERT_EQ(2u, m_writer.WriteCount()); } /** * Check that we handle the case of frame lengths changing. */ void SPIBackendTest::testSoftwareVariousFrameLengths() { SoftwareBackend backend(SoftwareBackend::Options(), &m_writer, &m_export_map); OLA_ASSERT(backend.Init()); OLA_ASSERT(SendSomeData(&backend, 0, DATA1, arraysize(DATA1), m_total_size)); m_writer.WaitForWrite(); OLA_ASSERT_EQ(1u, m_writer.WriteCount()); m_writer.CheckDataMatches(OLA_SOURCELINE(), EXPECTED1, arraysize(EXPECTED1)); m_writer.ResetWrite(); OLA_ASSERT(SendSomeData(&backend, 0, DATA1, arraysize(DATA1), m_total_size)); m_writer.WaitForWrite(); OLA_ASSERT_EQ(2u, m_writer.WriteCount()); m_writer.CheckDataMatches(OLA_SOURCELINE(), EXPECTED1, arraysize(EXPECTED1)); m_writer.ResetWrite(); OLA_ASSERT(SendSomeData(&backend, 0, DATA2, arraysize(DATA2), m_total_size)); m_writer.WaitForWrite(); OLA_ASSERT_EQ(3u, m_writer.WriteCount()); m_writer.CheckDataMatches(OLA_SOURCELINE(), EXPECTED2, arraysize(EXPECTED2)); m_writer.ResetWrite(); OLA_ASSERT(SendSomeData(&backend, 0, DATA1, arraysize(DATA1), m_total_size)); m_writer.WaitForWrite(); OLA_ASSERT_EQ(4u, m_writer.WriteCount()); m_writer.CheckDataMatches(OLA_SOURCELINE(), EXPECTED1, arraysize(EXPECTED1)); m_writer.ResetWrite(); OLA_ASSERT(SendSomeData(&backend, 0, DATA3, arraysize(DATA3), m_total_size)); m_writer.WaitForWrite(); OLA_ASSERT_EQ(5u, m_writer.WriteCount()); m_writer.CheckDataMatches(OLA_SOURCELINE(), DATA3, arraysize(DATA3)); m_writer.ResetWrite(); // now test the latch bytes OLA_ASSERT( SendSomeData(&backend, 0, DATA1, arraysize(DATA1), m_total_size, 4)); m_writer.WaitForWrite(); OLA_ASSERT_EQ(6u, m_writer.WriteCount()); m_writer.CheckDataMatches(OLA_SOURCELINE(), EXPECTED4, arraysize(EXPECTED4)); m_writer.ResetWrite(); OLA_ASSERT( SendSomeData(&backend, 0, DATA3, arraysize(DATA3), m_total_size, 4)); m_writer.WaitForWrite(); OLA_ASSERT_EQ(7u, m_writer.WriteCount()); m_writer.CheckDataMatches(OLA_SOURCELINE(), EXPECTED3, arraysize(EXPECTED3)); m_writer.ResetWrite(); } ola-0.10.5.nojsmin/plugins/spi/SPIOutput.cpp0000644000175000017500000006505413023355232020324 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SPIOutput.cpp * An RDM-controllable SPI device. Takes up to one universe of DMX. * Copyright (C) 2013 Simon Newton * * The LPD8806 code was based on * https://github.com/adafruit/LPD8806/blob/master/LPD8806.cpp */ #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #include #include #include #include #include #include "ola/base/Array.h" #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/file/Util.h" #include "ola/network/NetworkUtils.h" #include "ola/rdm/OpenLightingEnums.h" #include "ola/rdm/RDMCommand.h" #include "ola/rdm/RDMEnums.h" #include "ola/rdm/ResponderHelper.h" #include "ola/rdm/ResponderLoadSensor.h" #include "ola/rdm/ResponderSensor.h" #include "ola/rdm/UID.h" #include "ola/rdm/UIDSet.h" #include "ola/stl/STLUtils.h" #include "plugins/spi/SPIBackend.h" #include "plugins/spi/SPIOutput.h" namespace ola { namespace plugin { namespace spi { using ola::file::FilenameFromPathOrPath; using ola::network::HostToNetwork; using ola::network::NetworkToHost; using ola::rdm::LoadSensor; using ola::rdm::NR_DATA_OUT_OF_RANGE; using ola::rdm::NR_FORMAT_ERROR; using ola::rdm::Personality; using ola::rdm::PersonalityCollection; using ola::rdm::PersonalityManager; using ola::rdm::RDMCallback; using ola::rdm::RDMCommand; using ola::rdm::RDMRequest; using ola::rdm::RDMResponse; using ola::rdm::ResponderHelper; using ola::rdm::UID; using ola::rdm::UIDSet; using std::auto_ptr; using std::min; using std::string; using std::vector; const uint16_t SPIOutput::SPI_DELAY = 0; const uint8_t SPIOutput::SPI_BITS_PER_WORD = 8; const uint8_t SPIOutput::SPI_MODE = 0; /** * These constants are used to determine the number of DMX Slots per pixel * The p9813 uses another byte preceding each of the three bytes as a kind * of header. */ const uint16_t SPIOutput::WS2801_SLOTS_PER_PIXEL = 3; const uint16_t SPIOutput::LPD8806_SLOTS_PER_PIXEL = 3; const uint16_t SPIOutput::P9813_SLOTS_PER_PIXEL = 3; const uint16_t SPIOutput::APA102_SLOTS_PER_PIXEL = 3; // Number of bytes that each pixel uses on the SPI wires // (if it differs from 1:1 with colors) const uint16_t SPIOutput::P9813_SPI_BYTES_PER_PIXEL = 4; const uint16_t SPIOutput::APA102_SPI_BYTES_PER_PIXEL = 4; const uint16_t SPIOutput::APA102_START_FRAME_BYTES = 4; SPIOutput::RDMOps *SPIOutput::RDMOps::instance = NULL; const ola::rdm::ResponderOps::ParamHandler SPIOutput::PARAM_HANDLERS[] = { { ola::rdm::PID_DEVICE_INFO, &SPIOutput::GetDeviceInfo, NULL}, { ola::rdm::PID_PRODUCT_DETAIL_ID_LIST, &SPIOutput::GetProductDetailList, NULL}, { ola::rdm::PID_DEVICE_MODEL_DESCRIPTION, &SPIOutput::GetDeviceModelDescription, NULL}, { ola::rdm::PID_MANUFACTURER_LABEL, &SPIOutput::GetManufacturerLabel, NULL}, { ola::rdm::PID_DEVICE_LABEL, &SPIOutput::GetDeviceLabel, &SPIOutput::SetDeviceLabel}, { ola::rdm::PID_SOFTWARE_VERSION_LABEL, &SPIOutput::GetSoftwareVersionLabel, NULL}, { ola::rdm::PID_DMX_PERSONALITY, &SPIOutput::GetDmxPersonality, &SPIOutput::SetDmxPersonality}, { ola::rdm::PID_DMX_PERSONALITY_DESCRIPTION, &SPIOutput::GetPersonalityDescription, NULL}, { ola::rdm::PID_DMX_START_ADDRESS, &SPIOutput::GetDmxStartAddress, &SPIOutput::SetDmxStartAddress}, { ola::rdm::PID_IDENTIFY_DEVICE, &SPIOutput::GetIdentify, &SPIOutput::SetIdentify}, #ifdef HAVE_GETLOADAVG { ola::rdm::PID_SENSOR_DEFINITION, &SPIOutput::GetSensorDefinition, NULL}, { ola::rdm::PID_SENSOR_VALUE, &SPIOutput::GetSensorValue, &SPIOutput::SetSensorValue}, { ola::rdm::PID_RECORD_SENSORS, NULL, &SPIOutput::RecordSensor}, #endif // HAVE_GETLOADAVG { ola::rdm::PID_LIST_INTERFACES, &SPIOutput::GetListInterfaces, NULL}, { ola::rdm::PID_INTERFACE_LABEL, &SPIOutput::GetInterfaceLabel, NULL}, { ola::rdm::PID_INTERFACE_HARDWARE_ADDRESS_TYPE1, &SPIOutput::GetInterfaceHardwareAddressType1, NULL}, { ola::rdm::PID_IPV4_CURRENT_ADDRESS, &SPIOutput::GetIPV4CurrentAddress, NULL}, { ola::rdm::PID_IPV4_DEFAULT_ROUTE, &SPIOutput::GetIPV4DefaultRoute, NULL}, { ola::rdm::PID_DNS_HOSTNAME, &SPIOutput::GetDNSHostname, NULL}, { ola::rdm::PID_DNS_DOMAIN_NAME, &SPIOutput::GetDNSDomainName, NULL}, { ola::rdm::PID_DNS_NAME_SERVER, &SPIOutput::GetDNSNameServer, NULL}, { 0, NULL, NULL}, }; SPIOutput::SPIOutput(const UID &uid, SPIBackendInterface *backend, const Options &options) : m_backend(backend), m_output_number(options.output_number), m_uid(uid), m_pixel_count(options.pixel_count), m_device_label(options.device_label), m_start_address(1), m_identify_mode(false) { m_spi_device_name = FilenameFromPathOrPath(m_backend->DevicePath()); PersonalityCollection::PersonalityList personalities; personalities.push_back(Personality(m_pixel_count * WS2801_SLOTS_PER_PIXEL, "WS2801 Individual Control")); personalities.push_back(Personality(WS2801_SLOTS_PER_PIXEL, "WS2801 Combined Control")); personalities.push_back(Personality(m_pixel_count * LPD8806_SLOTS_PER_PIXEL, "LPD8806 Individual Control")); personalities.push_back(Personality(LPD8806_SLOTS_PER_PIXEL, "LPD8806 Combined Control")); personalities.push_back(Personality(m_pixel_count * P9813_SLOTS_PER_PIXEL, "P9813 Individual Control")); personalities.push_back(Personality(P9813_SLOTS_PER_PIXEL, "P9813 Combined Control")); personalities.push_back(Personality(m_pixel_count * APA102_SLOTS_PER_PIXEL, "APA102 Individual Control")); personalities.push_back(Personality(APA102_SLOTS_PER_PIXEL, "APA102 Combined Control")); m_personality_collection.reset(new PersonalityCollection(personalities)); m_personality_manager.reset(new PersonalityManager( m_personality_collection.get())); m_personality_manager->SetActivePersonality(1); #ifdef HAVE_GETLOADAVG m_sensors.push_back(new LoadSensor(ola::system::LOAD_AVERAGE_1_MIN, "Load Average 1 minute")); m_sensors.push_back(new LoadSensor(ola::system::LOAD_AVERAGE_5_MINS, "Load Average 5 minutes")); m_sensors.push_back(new LoadSensor(ola::system::LOAD_AVERAGE_15_MINS, "Load Average 15 minutes")); #endif // HAVE_GETLOADAVG m_network_manager.reset(new ola::rdm::NetworkManager()); } SPIOutput::~SPIOutput() { STLDeleteElements(&m_sensors); } string SPIOutput::GetDeviceLabel() const { return m_device_label; } bool SPIOutput::SetDeviceLabel(const string &device_label) { m_device_label = device_label; return true; } uint8_t SPIOutput::GetPersonality() const { return m_personality_manager->ActivePersonalityNumber(); } bool SPIOutput::SetPersonality(uint16_t personality) { return m_personality_manager->SetActivePersonality(personality); } uint16_t SPIOutput::GetStartAddress() const { return m_start_address; } bool SPIOutput::SetStartAddress(uint16_t address) { uint16_t footprint = m_personality_manager->ActivePersonalityFootprint(); uint16_t end_address = DMX_UNIVERSE_SIZE - footprint + 1; if (address == 0 || address > end_address || footprint == 0) { return false; } m_start_address = address; return true; } string SPIOutput::Description() const { std::ostringstream str; str << m_spi_device_name << ", output " << static_cast(m_output_number) << ", " << m_personality_manager->ActivePersonalityDescription() << ", " << m_personality_manager->ActivePersonalityFootprint() << " slots @ " << m_start_address << ". (" << m_uid << ")"; return str.str(); } /* * Send DMX data over SPI. */ bool SPIOutput::WriteDMX(const DmxBuffer &buffer) { if (m_identify_mode) return true; return InternalWriteDMX(buffer); } void SPIOutput::RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { UIDSet uids; uids.AddUID(m_uid); callback->Run(uids); } void SPIOutput::RunIncrementalDiscovery( ola::rdm::RDMDiscoveryCallback *callback) { UIDSet uids; uids.AddUID(m_uid); callback->Run(uids); } void SPIOutput::SendRDMRequest(RDMRequest *request, RDMCallback *callback) { RDMOps::Instance()->HandleRDMRequest(this, m_uid, ola::rdm::ROOT_RDM_DEVICE, request, callback); } bool SPIOutput::InternalWriteDMX(const DmxBuffer &buffer) { switch (m_personality_manager->ActivePersonalityNumber()) { case 1: IndividualWS2801Control(buffer); break; case 2: CombinedWS2801Control(buffer); break; case 3: IndividualLPD8806Control(buffer); break; case 4: CombinedLPD8806Control(buffer); break; case 5: IndividualP9813Control(buffer); break; case 6: CombinedP9813Control(buffer); break; case 7: IndividualAPA102Control(buffer); break; case 8: CombinedAPA102Control(buffer); break; default: break; } return true; } void SPIOutput::IndividualWS2801Control(const DmxBuffer &buffer) { // We always check out the entire string length, even if we only have data // for part of it const unsigned int output_length = m_pixel_count * LPD8806_SLOTS_PER_PIXEL; uint8_t *output = m_backend->Checkout(m_output_number, output_length); if (!output) return; unsigned int new_length = output_length; buffer.GetRange(m_start_address - 1, output, &new_length); m_backend->Commit(m_output_number); } void SPIOutput::CombinedWS2801Control(const DmxBuffer &buffer) { unsigned int pixel_data_length = WS2801_SLOTS_PER_PIXEL; uint8_t pixel_data[WS2801_SLOTS_PER_PIXEL]; buffer.GetRange(m_start_address - 1, pixel_data, &pixel_data_length); if (pixel_data_length != WS2801_SLOTS_PER_PIXEL) { OLA_INFO << "Insufficient DMX data, required " << WS2801_SLOTS_PER_PIXEL << ", got " << pixel_data_length; return; } const unsigned int length = m_pixel_count * WS2801_SLOTS_PER_PIXEL; uint8_t *output = m_backend->Checkout(m_output_number, length); if (!output) return; for (unsigned int i = 0; i < m_pixel_count; i++) { memcpy(output + (i * WS2801_SLOTS_PER_PIXEL), pixel_data, pixel_data_length); } m_backend->Commit(m_output_number); } void SPIOutput::IndividualLPD8806Control(const DmxBuffer &buffer) { const uint8_t latch_bytes = (m_pixel_count + 31) / 32; const unsigned int first_slot = m_start_address - 1; // 0 offset if (buffer.Size() - first_slot < LPD8806_SLOTS_PER_PIXEL) { // not even 3 bytes of data, don't bother updating return; } // We always check out the entire string length, even if we only have data // for part of it const unsigned int output_length = m_pixel_count * LPD8806_SLOTS_PER_PIXEL; uint8_t *output = m_backend->Checkout(m_output_number, output_length, latch_bytes); if (!output) return; const unsigned int length = std::min(m_pixel_count * LPD8806_SLOTS_PER_PIXEL, buffer.Size() - first_slot); for (unsigned int i = 0; i < length / LPD8806_SLOTS_PER_PIXEL; i++) { // Convert RGB to GRB unsigned int offset = first_slot + i * LPD8806_SLOTS_PER_PIXEL; uint8_t r = buffer.Get(offset); uint8_t g = buffer.Get(offset + 1); uint8_t b = buffer.Get(offset + 2); output[i * LPD8806_SLOTS_PER_PIXEL] = 0x80 | (g >> 1); output[i * LPD8806_SLOTS_PER_PIXEL + 1] = 0x80 | (r >> 1); output[i * LPD8806_SLOTS_PER_PIXEL + 2] = 0x80 | (b >> 1); } m_backend->Commit(m_output_number); } void SPIOutput::CombinedLPD8806Control(const DmxBuffer &buffer) { const uint8_t latch_bytes = (m_pixel_count + 31) / 32; unsigned int pixel_data_length = LPD8806_SLOTS_PER_PIXEL; uint8_t pixel_data[LPD8806_SLOTS_PER_PIXEL]; buffer.GetRange(m_start_address - 1, pixel_data, &pixel_data_length); if (pixel_data_length != LPD8806_SLOTS_PER_PIXEL) { OLA_INFO << "Insufficient DMX data, required " << LPD8806_SLOTS_PER_PIXEL << ", got " << pixel_data_length; return; } // The leds are GRB format so convert here uint8_t temp = pixel_data[1]; pixel_data[1] = pixel_data[0]; pixel_data[0] = temp; const unsigned int length = m_pixel_count * LPD8806_SLOTS_PER_PIXEL; uint8_t *output = m_backend->Checkout(m_output_number, length, latch_bytes); if (!output) return; for (unsigned int i = 0; i < m_pixel_count; i++) { for (unsigned int j = 0; j < LPD8806_SLOTS_PER_PIXEL; j++) { output[i * LPD8806_SLOTS_PER_PIXEL + j] = 0x80 | (pixel_data[j] >> 1); } } m_backend->Commit(m_output_number); } void SPIOutput::IndividualP9813Control(const DmxBuffer &buffer) { // We need 4 bytes of zeros in the beginning and 8 bytes at // the end const uint8_t latch_bytes = 3 * P9813_SPI_BYTES_PER_PIXEL; const unsigned int first_slot = m_start_address - 1; // 0 offset if (buffer.Size() - first_slot < P9813_SLOTS_PER_PIXEL) { // not even 3 bytes of data, don't bother updating return; } // We always check out the entire string length, even if we only have data // for part of it const unsigned int output_length = m_pixel_count * P9813_SPI_BYTES_PER_PIXEL; uint8_t *output = m_backend->Checkout(m_output_number, output_length, latch_bytes); if (!output) return; for (unsigned int i = 0; i < m_pixel_count; i++) { // Convert RGB to P9813 Pixel unsigned int offset = first_slot + i * P9813_SLOTS_PER_PIXEL; // We need to avoid the first 4 bytes of the buffer since that acts as a // start of frame delimiter unsigned int spi_offset = (i + 1) * P9813_SPI_BYTES_PER_PIXEL; uint8_t r = 0; uint8_t b = 0; uint8_t g = 0; if (buffer.Size() - offset >= P9813_SLOTS_PER_PIXEL) { r = buffer.Get(offset); g = buffer.Get(offset + 1); b = buffer.Get(offset + 2); } output[spi_offset] = P9813CreateFlag(r, g, b); output[spi_offset + 1] = b; output[spi_offset + 2] = g; output[spi_offset + 3] = r; } m_backend->Commit(m_output_number); } void SPIOutput::CombinedP9813Control(const DmxBuffer &buffer) { const uint8_t latch_bytes = 3 * P9813_SPI_BYTES_PER_PIXEL; const unsigned int first_slot = m_start_address - 1; // 0 offset if (buffer.Size() - first_slot < P9813_SLOTS_PER_PIXEL) { OLA_INFO << "Insufficient DMX data, required " << P9813_SLOTS_PER_PIXEL << ", got " << buffer.Size() - first_slot; return; } uint8_t pixel_data[P9813_SPI_BYTES_PER_PIXEL]; pixel_data[3] = buffer.Get(first_slot); // Get Red pixel_data[2] = buffer.Get(first_slot + 1); // Get Green pixel_data[1] = buffer.Get(first_slot + 2); // Get Blue pixel_data[0] = P9813CreateFlag(pixel_data[3], pixel_data[2], pixel_data[1]); const unsigned int length = m_pixel_count * P9813_SPI_BYTES_PER_PIXEL; uint8_t *output = m_backend->Checkout(m_output_number, length, latch_bytes); if (!output) return; for (unsigned int i = 0; i < m_pixel_count; i++) { memcpy(&output[(i + 1) * P9813_SPI_BYTES_PER_PIXEL], pixel_data, P9813_SPI_BYTES_PER_PIXEL); } m_backend->Commit(m_output_number); } /** * For more information please visit: * https://github.com/CoolNeon/elinux-tcl/blob/master/README.txt */ uint8_t SPIOutput::P9813CreateFlag(uint8_t red, uint8_t green, uint8_t blue) { uint8_t flag = 0; flag = (red & 0xc0) >> 6; flag |= (green & 0xc0) >> 4; flag |= (blue & 0xc0) >> 2; return ~flag; } void SPIOutput::IndividualAPA102Control(const DmxBuffer &buffer) { // some detailed information on the protocol: // https://cpldcpu.wordpress.com/2014/11/30/understanding-the-apa102-superled/ // Data-Struct // StartFrame: 4 bytes = 32 bits zeros (APA102_START_FRAME_BYTES) // LEDFrame: 1 byte FF ; 3 bytes color info (Blue, Green, Red) // EndFrame: (n/2)bits; n = pixel_count // calculate DMX-start-address const unsigned int first_slot = m_start_address - 1; // 0 offset // only do something if at least 1 pixel can be updated.. if (buffer.Size() - first_slot < APA102_SLOTS_PER_PIXEL) { OLA_INFO << "Insufficient DMX data, required " << APA102_SLOTS_PER_PIXEL << ", got " << buffer.Size() - first_slot; return; } // We always check out the entire string length, even if we only have data // for part of it uint16_t output_length = (m_pixel_count * APA102_SPI_BYTES_PER_PIXEL); // only add the APA102_START_FRAME_BYTES on the first port!! if (m_output_number == 0) { output_length += APA102_START_FRAME_BYTES; } uint8_t *output = m_backend->Checkout( m_output_number, output_length, CalculateAPA102LatchBytes(m_pixel_count)); // only update SPI data if possible if (!output) { return; } // only write to APA102_START_FRAME_BYTES on the first port!! if (m_output_number == 0) { // set APA102_START_FRAME_BYTES to zero memset(output, 0, APA102_START_FRAME_BYTES); } for (uint16_t i = 0; i < m_pixel_count; i++) { // Convert RGB to APA102 Pixel uint16_t offset = first_slot + (i * APA102_SLOTS_PER_PIXEL); uint16_t spi_offset = (i * APA102_SPI_BYTES_PER_PIXEL); // only skip APA102_START_FRAME_BYTES on the first port!! if (m_output_number == 0) { // We need to avoid the first 4 bytes of the buffer since that acts as a // start of frame delimiter spi_offset += APA102_START_FRAME_BYTES; } // set pixel data // first Byte contains: // 3 bits start mark (111) + 5 bits global brightness // set global brightness fixed to 31 --> that reduces flickering // that can be written as 0xE0 & 0x1F output[spi_offset] = 0xFF; // only write pixel data if buffer has complete data for this pixel: if ((buffer.Size() - offset) >= APA102_SLOTS_PER_PIXEL) { // Convert RGB to APA102 Pixel // skip spi_offset + 0 (is already set) output[spi_offset + 1] = buffer.Get(offset + 2); // blue output[spi_offset + 2] = buffer.Get(offset + 1); // green output[spi_offset + 3] = buffer.Get(offset); // red } } // write output back m_backend->Commit(m_output_number); } void SPIOutput::CombinedAPA102Control(const DmxBuffer &buffer) { // for Protocol details see IndividualAPA102Control // calculate DMX-start-address const uint16_t first_slot = m_start_address - 1; // 0 offset // check if enough data is there. if (buffer.Size() - first_slot < APA102_SLOTS_PER_PIXEL) { OLA_INFO << "Insufficient DMX data, required " << APA102_SLOTS_PER_PIXEL << ", got " << buffer.Size() - first_slot; return; } // We always check out the entire string length, even if we only have data // for part of it uint16_t output_length = (m_pixel_count * APA102_SPI_BYTES_PER_PIXEL); // only add the APA102_START_FRAME_BYTES on the first port!! if (m_output_number == 0) { output_length += APA102_START_FRAME_BYTES; } uint8_t *output = m_backend->Checkout( m_output_number, output_length, CalculateAPA102LatchBytes(m_pixel_count)); // only update SPI data if possible if (!output) { return; } // only write to APA102_START_FRAME_BYTES on the first port!! if (m_output_number == 0) { // set APA102_START_FRAME_BYTES to zero memset(output, 0, APA102_START_FRAME_BYTES); } // create Pixel Data uint8_t pixel_data[APA102_SPI_BYTES_PER_PIXEL]; pixel_data[0] = 0xFF; pixel_data[1] = buffer.Get(first_slot + 2); // Get Blue pixel_data[2] = buffer.Get(first_slot + 1); // Get Green pixel_data[3] = buffer.Get(first_slot); // Get Red // set all pixel to same value for (uint16_t i = 0; i < m_pixel_count; i++) { uint16_t spi_offset = (i * APA102_SPI_BYTES_PER_PIXEL); if (m_output_number == 0) { spi_offset += APA102_START_FRAME_BYTES; } memcpy(&output[spi_offset], pixel_data, APA102_SPI_BYTES_PER_PIXEL); } // write output back... m_backend->Commit(m_output_number); } /** * Calculate Latch Bytes for APA102: * Use at least half the pixel count bits * round up to next full byte count. * datasheet says endframe should consist of 4 bytes - * but thats only valid for up to 64 pixels/leds. (4Byte*8Bit*2=64) * * the function is valid up to 4080 pixels. (255*8*2) * ( otherwise the return type must be changed to uint16_t) */ uint8_t SPIOutput::CalculateAPA102LatchBytes(uint16_t pixel_count) { // round up so that we get definitely enough bits const uint8_t latch_bits = (pixel_count + 1) / 2; const uint8_t latch_bytes = (latch_bits + 7) / 8; return latch_bytes; } RDMResponse *SPIOutput::GetDeviceInfo(const RDMRequest *request) { return ResponderHelper::GetDeviceInfo( request, ola::rdm::OLA_SPI_DEVICE_MODEL, ola::rdm::PRODUCT_CATEGORY_FIXTURE, 4, m_personality_manager.get(), m_start_address, 0, m_sensors.size()); } RDMResponse *SPIOutput::GetProductDetailList(const RDMRequest *request) { // Shortcut for only one item in the vector return ResponderHelper::GetProductDetailList(request, vector (1, ola::rdm::PRODUCT_DETAIL_LED)); } RDMResponse *SPIOutput::GetDeviceModelDescription(const RDMRequest *request) { return ResponderHelper::GetString(request, "OLA SPI Device"); } RDMResponse *SPIOutput::GetManufacturerLabel(const RDMRequest *request) { return ResponderHelper::GetString( request, ola::rdm::OLA_MANUFACTURER_LABEL); } RDMResponse *SPIOutput::GetDeviceLabel(const RDMRequest *request) { return ResponderHelper::GetString(request, m_device_label); } RDMResponse *SPIOutput::SetDeviceLabel(const RDMRequest *request) { return ResponderHelper::SetString(request, &m_device_label); } RDMResponse *SPIOutput::GetSoftwareVersionLabel(const RDMRequest *request) { return ResponderHelper::GetString(request, string("OLA Version ") + VERSION); } RDMResponse *SPIOutput::GetDmxPersonality(const RDMRequest *request) { return ResponderHelper::GetPersonality(request, m_personality_manager.get()); } RDMResponse *SPIOutput::SetDmxPersonality(const RDMRequest *request) { return ResponderHelper::SetPersonality(request, m_personality_manager.get(), m_start_address); } RDMResponse *SPIOutput::GetPersonalityDescription(const RDMRequest *request) { return ResponderHelper::GetPersonalityDescription( request, m_personality_manager.get()); } RDMResponse *SPIOutput::GetDmxStartAddress(const RDMRequest *request) { return ResponderHelper::GetDmxAddress(request, m_personality_manager.get(), m_start_address); } RDMResponse *SPIOutput::SetDmxStartAddress(const RDMRequest *request) { return ResponderHelper::SetDmxAddress(request, m_personality_manager.get(), &m_start_address); } RDMResponse *SPIOutput::GetIdentify(const RDMRequest *request) { return ResponderHelper::GetBoolValue(request, m_identify_mode); } RDMResponse *SPIOutput::SetIdentify(const RDMRequest *request) { bool old_value = m_identify_mode; RDMResponse *response = ResponderHelper::SetBoolValue( request, &m_identify_mode); if (m_identify_mode != old_value) { OLA_INFO << "SPI " << m_spi_device_name << " identify mode " << ( m_identify_mode ? "on" : "off"); DmxBuffer identify_buffer; if (m_identify_mode) { identify_buffer.SetRangeToValue(0, DMX_MAX_SLOT_VALUE, DMX_UNIVERSE_SIZE); } else { identify_buffer.Blackout(); } InternalWriteDMX(identify_buffer); } return response; } /** * PID_SENSOR_DEFINITION */ RDMResponse *SPIOutput::GetSensorDefinition(const RDMRequest *request) { return ResponderHelper::GetSensorDefinition(request, m_sensors); } /** * PID_SENSOR_VALUE */ RDMResponse *SPIOutput::GetSensorValue(const RDMRequest *request) { return ResponderHelper::GetSensorValue(request, m_sensors); } RDMResponse *SPIOutput::SetSensorValue(const RDMRequest *request) { return ResponderHelper::SetSensorValue(request, m_sensors); } /** * PID_RECORD_SENSORS */ RDMResponse *SPIOutput::RecordSensor(const RDMRequest *request) { return ResponderHelper::RecordSensor(request, m_sensors); } /** * E1.37-2 PIDs */ RDMResponse *SPIOutput::GetListInterfaces(const RDMRequest *request) { return ResponderHelper::GetListInterfaces(request, m_network_manager.get()); } RDMResponse *SPIOutput::GetInterfaceLabel(const RDMRequest *request) { return ResponderHelper::GetInterfaceLabel(request, m_network_manager.get()); } RDMResponse *SPIOutput::GetInterfaceHardwareAddressType1( const RDMRequest *request) { return ResponderHelper::GetInterfaceHardwareAddressType1( request, m_network_manager.get()); } RDMResponse *SPIOutput::GetIPV4CurrentAddress(const RDMRequest *request) { return ResponderHelper::GetIPV4CurrentAddress(request, m_network_manager.get()); } RDMResponse *SPIOutput::GetIPV4DefaultRoute(const RDMRequest *request) { return ResponderHelper::GetIPV4DefaultRoute(request, m_network_manager.get()); } RDMResponse *SPIOutput::GetDNSHostname(const RDMRequest *request) { return ResponderHelper::GetDNSHostname(request, m_network_manager.get()); } RDMResponse *SPIOutput::GetDNSDomainName(const RDMRequest *request) { return ResponderHelper::GetDNSDomainName(request, m_network_manager.get()); } RDMResponse *SPIOutput::GetDNSNameServer(const RDMRequest *request) { return ResponderHelper::GetDNSNameServer(request, m_network_manager.get()); } } // namespace spi } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/spi/FakeSPIWriter.h0000644000175000017500000000455613023355232020534 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * FakeSPIWriter.h * The SPIWriter used for testing. * Copyright (C) 2013 Simon Newton */ #ifndef PLUGINS_SPI_FAKESPIWRITER_H_ #define PLUGINS_SPI_FAKESPIWRITER_H_ #include #include #include #include #include "plugins/spi/SPIWriter.h" namespace ola { namespace plugin { namespace spi { /** * A Fake SPI Writer used for testing */ class FakeSPIWriter : public SPIWriterInterface { public: explicit FakeSPIWriter(const std::string &device_path) : m_device_path(device_path), m_write_pending(0), m_writes(0), m_last_write_size(0), m_data(NULL) { } ~FakeSPIWriter() { delete[] m_data; } bool Init() { return true; } std::string DevicePath() const { return m_device_path; } bool WriteSPIData(const uint8_t *data, unsigned int length); // Methods used for testing void BlockWriter(); void UnblockWriter(); void ResetWrite(); void WaitForWrite(); unsigned int WriteCount() const; unsigned int LastWriteSize() const; void CheckDataMatches(const ola::testing::SourceLine &source_line, const uint8_t *data, unsigned int length); private: const std::string m_device_path; bool m_write_pending; // GUARDED_BY(m_mutex) unsigned int m_writes; // GUARDED_BY(m_mutex) unsigned int m_last_write_size; // GUARDED_BY(m_mutex) uint8_t *m_data; // GUARDED_BY(m_mutex) ola::thread::Mutex m_write_lock; mutable ola::thread::Mutex m_mutex; ola::thread::ConditionVariable m_cond_var; }; } // namespace spi } // namespace plugin } // namespace ola #endif // PLUGINS_SPI_FAKESPIWRITER_H_ ola-0.10.5.nojsmin/plugins/spi/SPIWriter.h0000644000175000017500000000453613023355232017743 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SPIWriter.h * This writes data to a SPI device. * Copyright (C) 2013 Simon Newton */ #ifndef PLUGINS_SPI_SPIWRITER_H_ #define PLUGINS_SPI_SPIWRITER_H_ #include #include #include #include namespace ola { namespace plugin { namespace spi { /** * The interface for the SPI Writer */ class SPIWriterInterface { public: virtual ~SPIWriterInterface() {} virtual std::string DevicePath() const = 0; virtual bool Init() = 0; virtual bool WriteSPIData(const uint8_t *data, unsigned int length) = 0; }; /** * The SPI Writer, this writes data to a SPI device */ class SPIWriter : public SPIWriterInterface { public: /** * SPIWriter Options */ struct Options { uint32_t spi_speed; bool cs_enable_high; Options() : spi_speed(1000000), cs_enable_high(false) {} }; SPIWriter(const std::string &spi_device, const Options &options, ExportMap *export_map); ~SPIWriter(); std::string DevicePath() const { return m_device_path; } /** * Init the SPIWriter * @returns false if initialization failed. */ bool Init(); bool WriteSPIData(const uint8_t *data, unsigned int length); private: const std::string m_device_path; const uint32_t m_spi_speed; const bool m_cs_enable_high; int m_fd; UIntMap *m_error_map_var; UIntMap *m_write_map_var; static const uint8_t SPI_MODE; static const uint8_t SPI_BITS_PER_WORD; static const char SPI_DEVICE_KEY[]; static const char SPI_ERROR_VAR[]; static const char SPI_WRITE_VAR[]; }; } // namespace spi } // namespace plugin } // namespace ola #endif // PLUGINS_SPI_SPIWRITER_H_ ola-0.10.5.nojsmin/plugins/spi/SPIWriter.cpp0000644000175000017500000000744013023355232020273 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SPIWriter.cpp * This writes data to a SPI device. * Copyright (C) 2013 Simon Newton */ #include #include #include #include #include #include #include #include #include #include #include "ola/io/IOUtils.h" #include "ola/Logging.h" #include "ola/network/SocketCloser.h" #include "plugins/spi/SPIWriter.h" namespace ola { namespace plugin { namespace spi { using ola::thread::MutexLocker; using std::string; const uint8_t SPIWriter::SPI_BITS_PER_WORD = 8; const uint8_t SPIWriter::SPI_MODE = 0; const char SPIWriter::SPI_DEVICE_KEY[] = "device"; const char SPIWriter::SPI_ERROR_VAR[] = "spi-write-errors"; const char SPIWriter::SPI_WRITE_VAR[] = "spi-writes"; SPIWriter::SPIWriter(const string &spi_device, const Options &options, ExportMap *export_map) : m_device_path(spi_device), m_spi_speed(options.spi_speed), m_cs_enable_high(options.cs_enable_high), m_fd(-1), m_error_map_var(NULL), m_write_map_var(NULL) { OLA_INFO << "Created SPI Writer " << spi_device << " with speed " << options.spi_speed << ", CE is " << m_cs_enable_high; if (export_map) { m_error_map_var = export_map->GetUIntMapVar(SPI_ERROR_VAR, SPI_DEVICE_KEY); (*m_error_map_var)[m_device_path] = 0; m_write_map_var = export_map->GetUIntMapVar(SPI_WRITE_VAR, SPI_DEVICE_KEY); (*m_write_map_var)[m_device_path] = 0; } } SPIWriter::~SPIWriter() { if (m_fd >= 0) close(m_fd); } bool SPIWriter::Init() { int fd; if (!ola::io::Open(m_device_path, O_RDWR, &fd)) { return false; } ola::network::SocketCloser closer(fd); uint8_t spi_mode = SPI_MODE; if (m_cs_enable_high) { spi_mode |= SPI_CS_HIGH; } if (ioctl(fd, SPI_IOC_WR_MODE, &spi_mode) < 0) { OLA_WARN << "Failed to set SPI_IOC_WR_MODE for " << m_device_path; return false; } uint8_t spi_bits_per_word = SPI_BITS_PER_WORD; if (ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &spi_bits_per_word) < 0) { OLA_WARN << "Failed to set SPI_IOC_WR_BITS_PER_WORD for " << m_device_path; return false; } if (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &m_spi_speed) < 0) { OLA_WARN << "Failed to set SPI_IOC_WR_MAX_SPEED_HZ for " << m_device_path; return false; } m_fd = closer.Release(); return true; } bool SPIWriter::WriteSPIData(const uint8_t *data, unsigned int length) { struct spi_ioc_transfer spi; memset(&spi, 0, sizeof(spi)); spi.tx_buf = reinterpret_cast<__u64>(data); spi.len = length; if (m_write_map_var) { (*m_write_map_var)[m_device_path]++; } int bytes_written = ioctl(m_fd, SPI_IOC_MESSAGE(1), &spi); if (bytes_written != static_cast(length)) { OLA_WARN << "Failed to write all the SPI data: " << strerror(errno); if (m_error_map_var) { (*m_error_map_var)[m_device_path]++; } return false; } return true; } } // namespace spi } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/spi/SPIOutput.h0000644000175000017500000001603313023355232017762 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SPIOutput.h * An RDM-controllable SPI device. Takes up to one universe of DMX. * Copyright (C) 2013 Simon Newton */ #ifndef PLUGINS_SPI_SPIOUTPUT_H_ #define PLUGINS_SPI_SPIOUTPUT_H_ #include #include #include "common/rdm/NetworkManager.h" #include "ola/DmxBuffer.h" #include "ola/rdm/RDMControllerInterface.h" #include "ola/rdm/UID.h" #include "ola/stl/STLUtils.h" #include "ola/rdm/ResponderOps.h" #include "ola/rdm/ResponderPersonality.h" #include "ola/rdm/ResponderSensor.h" namespace ola { namespace plugin { namespace spi { class SPIOutput: public ola::rdm::DiscoverableRDMControllerInterface { public: struct Options { std::string device_label; uint8_t pixel_count; uint8_t output_number; explicit Options(uint8_t output_number, const std::string &spi_device_name) : device_label("SPI Device - " + spi_device_name), pixel_count(25), // For the https://www.adafruit.com/products/738 output_number(output_number) { } }; SPIOutput(const ola::rdm::UID &uid, class SPIBackendInterface *backend, const Options &options); ~SPIOutput(); std::string GetDeviceLabel() const; bool SetDeviceLabel(const std::string &device_label); uint8_t GetPersonality() const; bool SetPersonality(uint16_t personality); uint16_t GetStartAddress() const; bool SetStartAddress(uint16_t start_address); unsigned int PixelCount() const { return m_pixel_count; } std::string Description() const; bool WriteDMX(const DmxBuffer &buffer); void RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback); void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback); void SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *callback); private: /** * The RDM Operations for the MovingLightResponder. */ class RDMOps : public ola::rdm::ResponderOps { public: static RDMOps *Instance() { if (!instance) instance = new RDMOps(); return instance; } private: RDMOps() : ola::rdm::ResponderOps(PARAM_HANDLERS) {} static RDMOps *instance; }; class SPIBackendInterface *m_backend; const uint8_t m_output_number; std::string m_spi_device_name; const ola::rdm::UID m_uid; const unsigned int m_pixel_count; std::string m_device_label; uint16_t m_start_address; // starts from 1 bool m_identify_mode; std::auto_ptr m_personality_collection; std::auto_ptr m_personality_manager; ola::rdm::Sensors m_sensors; std::auto_ptr m_network_manager; // DMX methods bool InternalWriteDMX(const DmxBuffer &buffer); void IndividualWS2801Control(const DmxBuffer &buffer); void CombinedWS2801Control(const DmxBuffer &buffer); void IndividualLPD8806Control(const DmxBuffer &buffer); void CombinedLPD8806Control(const DmxBuffer &buffer); void IndividualP9813Control(const DmxBuffer &buffer); void CombinedP9813Control(const DmxBuffer &buffer); void IndividualAPA102Control(const DmxBuffer &buffer); void CombinedAPA102Control(const DmxBuffer &buffer); unsigned int LPD8806BufferSize() const; void WriteSPIData(const uint8_t *data, unsigned int length); // RDM methods ola::rdm::RDMResponse *GetDeviceInfo( const ola::rdm::RDMRequest *request); ola::rdm::RDMResponse *GetProductDetailList( const ola::rdm::RDMRequest *request); ola::rdm::RDMResponse *GetDeviceModelDescription( const ola::rdm::RDMRequest *request); ola::rdm::RDMResponse *GetManufacturerLabel( const ola::rdm::RDMRequest *request); ola::rdm::RDMResponse *GetDeviceLabel( const ola::rdm::RDMRequest *request); ola::rdm::RDMResponse *SetDeviceLabel( const ola::rdm::RDMRequest *request); ola::rdm::RDMResponse *GetSoftwareVersionLabel( const ola::rdm::RDMRequest *request); ola::rdm::RDMResponse *GetDmxPersonality( const ola::rdm::RDMRequest *request); ola::rdm::RDMResponse *SetDmxPersonality( const ola::rdm::RDMRequest *request); ola::rdm::RDMResponse *GetPersonalityDescription( const ola::rdm::RDMRequest *request); ola::rdm::RDMResponse *GetDmxStartAddress( const ola::rdm::RDMRequest *request); ola::rdm::RDMResponse *SetDmxStartAddress( const ola::rdm::RDMRequest *request); ola::rdm::RDMResponse *GetIdentify( const ola::rdm::RDMRequest *request); ola::rdm::RDMResponse *SetIdentify( const ola::rdm::RDMRequest *request); ola::rdm::RDMResponse *GetSensorDefinition( const ola::rdm::RDMRequest *request); ola::rdm::RDMResponse *GetSensorValue( const ola::rdm::RDMRequest *request); ola::rdm::RDMResponse *SetSensorValue( const ola::rdm::RDMRequest *request); ola::rdm::RDMResponse *RecordSensor( const ola::rdm::RDMRequest *request); ola::rdm::RDMResponse *GetListInterfaces( const ola::rdm::RDMRequest *request); ola::rdm::RDMResponse *GetInterfaceLabel( const ola::rdm::RDMRequest *request); ola::rdm::RDMResponse *GetInterfaceHardwareAddressType1( const ola::rdm::RDMRequest *request); ola::rdm::RDMResponse *GetIPV4CurrentAddress( const ola::rdm::RDMRequest *request); ola::rdm::RDMResponse *GetIPV4DefaultRoute( const ola::rdm::RDMRequest *request); ola::rdm::RDMResponse *GetDNSHostname( const ola::rdm::RDMRequest *request); ola::rdm::RDMResponse *GetDNSDomainName( const ola::rdm::RDMRequest *request); ola::rdm::RDMResponse *GetDNSNameServer( const ola::rdm::RDMRequest *request); // Helpers uint8_t P9813CreateFlag(uint8_t red, uint8_t green, uint8_t blue); static uint8_t CalculateAPA102LatchBytes(uint16_t pixel_count); static const uint8_t SPI_MODE; static const uint8_t SPI_BITS_PER_WORD; static const uint16_t SPI_DELAY; static const uint32_t SPI_SPEED; static const uint16_t WS2801_SLOTS_PER_PIXEL; static const uint16_t LPD8806_SLOTS_PER_PIXEL; static const uint16_t P9813_SLOTS_PER_PIXEL; static const uint16_t P9813_SPI_BYTES_PER_PIXEL; static const uint16_t APA102_SLOTS_PER_PIXEL; static const uint16_t APA102_SPI_BYTES_PER_PIXEL; static const uint16_t APA102_START_FRAME_BYTES; static const ola::rdm::ResponderOps::ParamHandler PARAM_HANDLERS[]; }; } // namespace spi } // namespace plugin } // namespace ola #endif // PLUGINS_SPI_SPIOUTPUT_H_ ola-0.10.5.nojsmin/plugins/spi/SPIOutputTest.cpp0000644000175000017500000006574613023355232021174 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SPIOutputTest.cpp * Test fixture for SPIOutput. * Copyright (C) 2013 Simon Newton */ #include #include #include "ola/base/Array.h" #include "ola/DmxBuffer.h" #include "ola/Logging.h" #include "ola/rdm/UID.h" #include "ola/testing/TestUtils.h" #include "plugins/spi/SPIBackend.h" #include "plugins/spi/SPIOutput.h" using ola::DmxBuffer; using ola::plugin::spi::FakeSPIBackend; using ola::plugin::spi::SPIBackendInterface; using ola::plugin::spi::SPIOutput; using ola::rdm::UID; using std::string; class SPIOutputTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(SPIOutputTest); CPPUNIT_TEST(testDescription); CPPUNIT_TEST(testIndividualWS2801Control); CPPUNIT_TEST(testCombinedWS2801Control); CPPUNIT_TEST(testIndividualLPD8806Control); CPPUNIT_TEST(testCombinedLPD8806Control); CPPUNIT_TEST(testIndividualP9813Control); CPPUNIT_TEST(testCombinedP9813Control); CPPUNIT_TEST(testIndividualAPA102Control); CPPUNIT_TEST(testCombinedAPA102Control); CPPUNIT_TEST_SUITE_END(); public: SPIOutputTest() : CppUnit::TestFixture(), m_uid(0x707a, 0) { } void setUp(); void testDescription(); void testIndividualWS2801Control(); void testCombinedWS2801Control(); void testIndividualLPD8806Control(); void testCombinedLPD8806Control(); void testIndividualP9813Control(); void testCombinedP9813Control(); void testIndividualAPA102Control(); void testCombinedAPA102Control(); private: UID m_uid; }; CPPUNIT_TEST_SUITE_REGISTRATION(SPIOutputTest); void SPIOutputTest::setUp() { ola::InitLogging(ola::OLA_LOG_INFO, ola::OLA_LOG_STDERR); } /** * Check the descrption, start address & personality. */ void SPIOutputTest::testDescription() { FakeSPIBackend backend(2); SPIOutput output1(m_uid, &backend, SPIOutput::Options(0, "Test SPI Device")); SPIOutput::Options options(1, "Test SPI Device"); options.pixel_count = 32; SPIOutput output2(m_uid, &backend, options); OLA_ASSERT_EQ( string("test, output 0, WS2801 Individual Control, 75 slots @ 1." " (707a:00000000)"), output1.Description()); OLA_ASSERT_EQ(static_cast(1), output1.GetStartAddress()); OLA_ASSERT_EQ(static_cast(1), output1.GetPersonality()); OLA_ASSERT_EQ( string("test, output 1, WS2801 Individual Control, 96 slots @ 1." " (707a:00000000)"), output2.Description()); // change the start address & personality output1.SetStartAddress(10); output1.SetPersonality(3); OLA_ASSERT_EQ( string("test, output 0, LPD8806 Individual Control, 75 slots @ 10." " (707a:00000000)"), output1.Description()); OLA_ASSERT_EQ(static_cast(10), output1.GetStartAddress()); OLA_ASSERT_EQ(static_cast(3), output1.GetPersonality()); } /** * Test DMX writes in the individual WS2801 mode. */ void SPIOutputTest::testIndividualWS2801Control() { FakeSPIBackend backend(2); SPIOutput::Options options(0, "Test SPI Device"); options.pixel_count = 2; SPIOutput output(m_uid, &backend, options); DmxBuffer buffer; unsigned int length = 0; const uint8_t *data = NULL; buffer.SetFromString("1, 10, 100"); output.WriteDMX(buffer); data = backend.GetData(0, &length); const uint8_t EXPECTED0[] = { 1, 10, 100, 0, 0, 0}; OLA_ASSERT_DATA_EQUALS(EXPECTED0, arraysize(EXPECTED0), data, length); OLA_ASSERT_EQ(1u, backend.Writes(0)); buffer.SetFromString("255,128,0,10,20,30"); output.WriteDMX(buffer); data = backend.GetData(0, &length); const uint8_t EXPECTED1[] = { 255, 128, 0, 10, 20, 30 }; OLA_ASSERT_DATA_EQUALS(EXPECTED1, arraysize(EXPECTED1), data, length); OLA_ASSERT_EQ(2u, backend.Writes(0)); buffer.SetFromString("34,56,78"); output.WriteDMX(buffer); data = backend.GetData(0, &length); const uint8_t EXPECTED2[] = { 34, 56, 78, 10, 20, 30 }; OLA_ASSERT_DATA_EQUALS(EXPECTED2, arraysize(EXPECTED2), data, length); OLA_ASSERT_EQ(3u, backend.Writes(0)); buffer.SetFromString("7, 9"); output.WriteDMX(buffer); data = backend.GetData(0, &length); const uint8_t EXPECTED3[] = { 7, 9, 78, 10, 20, 30 }; OLA_ASSERT_DATA_EQUALS(EXPECTED3, arraysize(EXPECTED3), data, length); OLA_ASSERT_EQ(4u, backend.Writes(0)); output.SetStartAddress(3); buffer.SetFromString("1,2,3,4,5,6,7,8"); output.WriteDMX(buffer); data = backend.GetData(0, &length); const uint8_t EXPECTED4[] = { 3, 4, 5, 6, 7, 8 }; OLA_ASSERT_DATA_EQUALS(EXPECTED4, arraysize(EXPECTED4), data, length); OLA_ASSERT_EQ(5u, backend.Writes(0)); // Check nothing changed on the other output. OLA_ASSERT_EQ(reinterpret_cast(NULL), backend.GetData(1, &length)); OLA_ASSERT_EQ(0u, backend.Writes(1)); } /** * Test DMX writes in the combined WS2801 mode. */ void SPIOutputTest::testCombinedWS2801Control() { FakeSPIBackend backend(2); SPIOutput::Options options(0, "Test SPI Device"); options.pixel_count = 2; SPIOutput output(m_uid, &backend, options); output.SetPersonality(2); DmxBuffer buffer; buffer.SetFromString("255,128,0,10,20,30"); output.WriteDMX(buffer); unsigned int length = 0; const uint8_t *data = backend.GetData(0, &length); const uint8_t EXPECTED1[] = { 255, 128, 0, 255, 128, 0 }; OLA_ASSERT_DATA_EQUALS(EXPECTED1, arraysize(EXPECTED1), data, length); OLA_ASSERT_EQ(1u, backend.Writes(0)); buffer.SetFromString("34,56,78"); output.WriteDMX(buffer); data = backend.GetData(0, &length); const uint8_t EXPECTED2[] = { 34, 56, 78, 34, 56, 78 }; OLA_ASSERT_DATA_EQUALS(EXPECTED2, arraysize(EXPECTED2), data, length); OLA_ASSERT_EQ(2u, backend.Writes(0)); // Frames with insufficient data don't trigger writes. buffer.SetFromString("7, 9"); output.WriteDMX(buffer); data = backend.GetData(0, &length); OLA_ASSERT_DATA_EQUALS(EXPECTED2, arraysize(EXPECTED2), data, length); OLA_ASSERT_EQ(2u, backend.Writes(0)); output.SetStartAddress(3); buffer.SetFromString("1,2,3,4,5,6,7,8"); output.WriteDMX(buffer); data = backend.GetData(0, &length); const uint8_t EXPECTED4[] = { 3, 4, 5, 3, 4, 5}; OLA_ASSERT_DATA_EQUALS(EXPECTED4, arraysize(EXPECTED4), data, length); OLA_ASSERT_EQ(3u, backend.Writes(0)); // Check nothing changed on the other output. OLA_ASSERT_EQ(reinterpret_cast(NULL), backend.GetData(1, &length)); OLA_ASSERT_EQ(0u, backend.Writes(1)); } /** * Test DMX writes in the individual LPD8806 mode. */ void SPIOutputTest::testIndividualLPD8806Control() { FakeSPIBackend backend(2); SPIOutput::Options options(0, "Test SPI Device"); options.pixel_count = 2; SPIOutput output(m_uid, &backend, options); output.SetPersonality(3); DmxBuffer buffer; unsigned int length = 0; const uint8_t *data = NULL; buffer.SetFromString("1, 10, 100"); output.WriteDMX(buffer); data = backend.GetData(0, &length); const uint8_t EXPECTED0[] = { 0x85, 0x80, 0xB2, 0, 0, 0, 0}; OLA_ASSERT_DATA_EQUALS(EXPECTED0, arraysize(EXPECTED0), data, length); OLA_ASSERT_EQ(1u, backend.Writes(0)); buffer.SetFromString("255,128,0,10,20,30"); output.WriteDMX(buffer); data = backend.GetData(0, &length); const uint8_t EXPECTED1[] = { 0xC0, 0xFF, 0x80, 0x8A, 0x85, 0x8F, 0 }; OLA_ASSERT_DATA_EQUALS(EXPECTED1, arraysize(EXPECTED1), data, length); OLA_ASSERT_EQ(2u, backend.Writes(0)); buffer.SetFromString("34,56,78"); output.WriteDMX(buffer); data = backend.GetData(0, &length); const uint8_t EXPECTED2[] = { 0x9C, 0x91, 0xA7, 0x8A, 0x85, 0x8F, 0 }; OLA_ASSERT_DATA_EQUALS(EXPECTED2, arraysize(EXPECTED2), data, length); OLA_ASSERT_EQ(3u, backend.Writes(0)); buffer.SetFromString("7, 9"); output.WriteDMX(buffer); data = backend.GetData(0, &length); OLA_ASSERT_DATA_EQUALS(EXPECTED2, arraysize(EXPECTED2), data, length); OLA_ASSERT_EQ(3u, backend.Writes(0)); output.SetStartAddress(3); buffer.SetFromString("1,2,3,4,5,6,7,8"); output.WriteDMX(buffer); data = backend.GetData(0, &length); const uint8_t EXPECTED4[] = { 0x82, 0x81, 0x82, 0x83, 0x83, 0x84, 0 }; OLA_ASSERT_DATA_EQUALS(EXPECTED4, arraysize(EXPECTED4), data, length); OLA_ASSERT_EQ(4u, backend.Writes(0)); // Check nothing changed on the other output. OLA_ASSERT_EQ(reinterpret_cast(NULL), backend.GetData(1, &length)); OLA_ASSERT_EQ(0u, backend.Writes(1)); } /** * Test DMX writes in the combined LPD8806 mode. */ void SPIOutputTest::testCombinedLPD8806Control() { FakeSPIBackend backend(2); SPIOutput::Options options(0, "Test SPI Device"); options.pixel_count = 2; SPIOutput output(m_uid, &backend, options); output.SetPersonality(4); DmxBuffer buffer; buffer.SetFromString("255,128,0,10,20,30"); output.WriteDMX(buffer); unsigned int length = 0; const uint8_t *data = backend.GetData(0, &length); const uint8_t EXPECTED1[] = { 0xC0, 0xFF, 0x80, 0xC0, 0xFF, 0x80, 0}; OLA_ASSERT_DATA_EQUALS(EXPECTED1, arraysize(EXPECTED1), data, length); OLA_ASSERT_EQ(1u, backend.Writes(0)); buffer.SetFromString("34,56,78"); output.WriteDMX(buffer); data = backend.GetData(0, &length); const uint8_t EXPECTED2[] = { 0x9C, 0x91, 0xA7, 0x9C, 0x91, 0xA7, 0 }; OLA_ASSERT_DATA_EQUALS(EXPECTED2, arraysize(EXPECTED2), data, length); OLA_ASSERT_EQ(2u, backend.Writes(0)); buffer.SetFromString("7, 9"); output.WriteDMX(buffer); data = backend.GetData(0, &length); OLA_ASSERT_DATA_EQUALS(EXPECTED2, arraysize(EXPECTED2), data, length); OLA_ASSERT_EQ(2u, backend.Writes(0)); output.SetStartAddress(3); buffer.SetFromString("1,2,3,4,5,6,7,8"); output.WriteDMX(buffer); data = backend.GetData(0, &length); const uint8_t EXPECTED4[] = { 0x82, 0x81, 0x82, 0x82, 0x81, 0x82, 0 }; OLA_ASSERT_DATA_EQUALS(EXPECTED4, arraysize(EXPECTED4), data, length); // Check nothing changed on the other output. OLA_ASSERT_EQ(reinterpret_cast(NULL), backend.GetData(1, &length)); OLA_ASSERT_EQ(0u, backend.Writes(1)); } /** * Test DMX writes in the individual P9813 mode. */ void SPIOutputTest::testIndividualP9813Control() { FakeSPIBackend backend(2); SPIOutput::Options options(0, "Test SPI Device"); options.pixel_count = 2; SPIOutput output(m_uid, &backend, options); output.SetPersonality(5); DmxBuffer buffer; unsigned int length = 0; const uint8_t *data = NULL; buffer.SetFromString("1, 10, 100"); output.WriteDMX(buffer); data = backend.GetData(0, &length); const uint8_t EXPECTED0[] = { 0, 0, 0, 0, 0xEF, 0x64, 0x0A, 0x01, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; OLA_ASSERT_DATA_EQUALS(EXPECTED0, arraysize(EXPECTED0), data, length); OLA_ASSERT_EQ(1u, backend.Writes(0)); buffer.SetFromString("255,128,0,10,20,30"); output.WriteDMX(buffer); data = backend.GetData(0, &length); const uint8_t EXPECTED1[] = { 0, 0, 0, 0, 0xF4, 0, 0x80, 0xFF, 0xFF, 0x1E, 0x14, 0x0A, 0, 0, 0, 0, 0, 0, 0, 0}; OLA_ASSERT_DATA_EQUALS(EXPECTED1, arraysize(EXPECTED1), data, length); OLA_ASSERT_EQ(2u, backend.Writes(0)); buffer.SetFromString("34,56,78"); output.WriteDMX(buffer); data = backend.GetData(0, &length); const uint8_t EXPECTED2[] = { 0, 0, 0, 0, 0xEF, 0x4E, 0x38, 0x22, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; OLA_ASSERT_DATA_EQUALS(EXPECTED2, arraysize(EXPECTED2), data, length); OLA_ASSERT_EQ(3u, backend.Writes(0)); buffer.SetFromString("7, 9"); output.WriteDMX(buffer); data = backend.GetData(0, &length); OLA_ASSERT_DATA_EQUALS(EXPECTED2, arraysize(EXPECTED2), data, length); OLA_ASSERT_EQ(3u, backend.Writes(0)); output.SetStartAddress(3); buffer.SetFromString("1,2,3,4,5,6,7,8"); output.WriteDMX(buffer); data = backend.GetData(0, &length); const uint8_t EXPECTED4[] = { 0, 0, 0, 0, 0xFF, 0x05, 0x04, 0x03, 0xFF, 0x08, 0x07, 0x06, 0, 0, 0, 0, 0, 0, 0, 0}; OLA_ASSERT_DATA_EQUALS(EXPECTED4, arraysize(EXPECTED4), data, length); OLA_ASSERT_EQ(4u, backend.Writes(0)); // Check nothing changed on the other output. OLA_ASSERT_EQ(reinterpret_cast(NULL), backend.GetData(1, &length)); OLA_ASSERT_EQ(0u, backend.Writes(1)); } /** * Test DMX writes in the combined P9813 mode. */ void SPIOutputTest::testCombinedP9813Control() { FakeSPIBackend backend(2); SPIOutput::Options options(0, "Test SPI Device"); options.pixel_count = 2; SPIOutput output(m_uid, &backend, options); output.SetPersonality(6); DmxBuffer buffer; buffer.SetFromString("255,128,0,10,20,30"); output.WriteDMX(buffer); unsigned int length = 0; const uint8_t *data = backend.GetData(0, &length); const uint8_t EXPECTED1[] = { 0, 0, 0, 0, 0xF4, 0, 0x80, 0xFF, 0xF4, 0, 0x80, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0}; OLA_ASSERT_DATA_EQUALS(EXPECTED1, arraysize(EXPECTED1), data, length); OLA_ASSERT_EQ(1u, backend.Writes(0)); buffer.SetFromString("34,56,78"); output.WriteDMX(buffer); data = backend.GetData(0, &length); const uint8_t EXPECTED2[] = { 0, 0, 0, 0, 0xEF, 0x4E, 0x38, 0x22, 0xEF, 0x4E, 0x38, 0x22, 0, 0, 0, 0, 0, 0, 0, 0}; OLA_ASSERT_DATA_EQUALS(EXPECTED2, arraysize(EXPECTED2), data, length); OLA_ASSERT_EQ(2u, backend.Writes(0)); buffer.SetFromString("7, 9"); output.WriteDMX(buffer); data = backend.GetData(0, &length); OLA_ASSERT_DATA_EQUALS(EXPECTED2, arraysize(EXPECTED2), data, length); OLA_ASSERT_EQ(2u, backend.Writes(0)); output.SetStartAddress(3); buffer.SetFromString("1,2,3,4,5,6,7,8"); output.WriteDMX(buffer); data = backend.GetData(0, &length); const uint8_t EXPECTED4[] = { 0, 0, 0, 0, 0xFF, 0x05, 0x04, 0x03, 0xFF, 0x05, 0x04, 0x03, 0, 0, 0, 0, 0, 0, 0, 0}; OLA_ASSERT_DATA_EQUALS(EXPECTED4, arraysize(EXPECTED4), data, length); // Check nothing changed on the other output. OLA_ASSERT_EQ(reinterpret_cast(NULL), backend.GetData(1, &length)); OLA_ASSERT_EQ(0u, backend.Writes(1)); } /** * Test DMX writes in the individual APA102 mode. */ void SPIOutputTest::testIndividualAPA102Control() { // personality 7= Individual APA102 const uint16_t this_test_personality = 7; // setup Backend FakeSPIBackend backend(2); SPIOutput::Options options(0, "Test SPI Device"); // setup pixel_count to 2 (enough to test all cases) options.pixel_count = 2; // setup SPIOutput SPIOutput output(m_uid, &backend, options); // set personality output.SetPersonality(this_test_personality); // simulate incoming DMX data with this buffer DmxBuffer buffer; // setup a pointer to the returned data (the fake SPI data stream) unsigned int length = 0; const uint8_t *data = NULL; // test1 // setup some 'DMX' data buffer.SetFromString("1, 10, 100"); // simulate incoming data output.WriteDMX(buffer); // get fake SPI data stream data = backend.GetData(0, &length); // this is the expected spi data stream: const uint8_t EXPECTED1[] = { 0, 0, 0, 0, // StartFrame 0xFF, 0x64, 0x0A, 0x01, // first Pixel 0xFF, 0x00, 0x00, 0x00, // second Pixel 0}; // EndFrame // check for Equality OLA_ASSERT_DATA_EQUALS(EXPECTED1, arraysize(EXPECTED1), data, length); // check if the output writes are 1 OLA_ASSERT_EQ(1u, backend.Writes(0)); // test2 buffer.SetFromString("255,128,0,10,20,30"); output.WriteDMX(buffer); data = backend.GetData(0, &length); const uint8_t EXPECTED2[] = { 0, 0, 0, 0, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x1E, 0x14, 0x0A, 0}; OLA_ASSERT_DATA_EQUALS(EXPECTED2, arraysize(EXPECTED2), data, length); OLA_ASSERT_EQ(2u, backend.Writes(0)); // test3 // test what happens when only new data for the first leds is available. // later data should be not modified so for pixel2 data set in test2 is valid buffer.SetFromString("34,56,78"); output.WriteDMX(buffer); data = backend.GetData(0, &length); const uint8_t EXPECTED3[] = { 0, 0, 0, 0, 0xFF, 0x4E, 0x38, 0x22, 0xFF, 0x1E, 0x14, 0x0A, 0}; OLA_ASSERT_DATA_EQUALS(EXPECTED3, arraysize(EXPECTED3), data, length); OLA_ASSERT_EQ(3u, backend.Writes(0)); // test4 // tests what happens if fewer then needed color information are received buffer.SetFromString("7, 9"); output.WriteDMX(buffer); data = backend.GetData(0, &length); // check that the returns are the same as test3 (nothing changed) OLA_ASSERT_DATA_EQUALS(EXPECTED3, arraysize(EXPECTED3), data, length); OLA_ASSERT_EQ(3u, backend.Writes(0)); // test5 // test with changed StartAddress // set StartAddress output.SetStartAddress(3); // values 1 & 2 should not be visible in SPI data stream buffer.SetFromString("1,2,3,4,5,6,7,8"); output.WriteDMX(buffer); data = backend.GetData(0, &length); const uint8_t EXPECTED5[] = { 0, 0, 0, 0, 0xFF, 0x05, 0x04, 0x03, 0xFF, 0x08, 0x07, 0x06, 0}; OLA_ASSERT_DATA_EQUALS(EXPECTED5, arraysize(EXPECTED5), data, length); OLA_ASSERT_EQ(4u, backend.Writes(0)); // change StartAddress back to default output.SetStartAddress(1); // test6 // Check nothing changed on the other output. OLA_ASSERT_EQ(reinterpret_cast(NULL), backend.GetData(1, &length)); OLA_ASSERT_EQ(0u, backend.Writes(1)); // test7 // test for multiple ports // StartFrame is only allowed on first port. SPIOutput::Options options1(1, "second SPI Device"); // setup pixel_count to 2 (enough to test all cases) options1.pixel_count = 2; // setup SPIOutput SPIOutput output1(m_uid, &backend, options1); // set personality output1.SetPersonality(this_test_personality); // setup some 'DMX' data buffer.SetFromString("1, 10, 100, 100, 10, 1"); // simulate incoming data output1.WriteDMX(buffer); // get fake SPI data stream data = backend.GetData(1, &length); // this is the expected spi data stream: // StartFrame is missing --> port is >0 ! const uint8_t EXPECTED7[] = { // 0, 0, 0, 0, // StartFrame 0xFF, 0x64, 0x0A, 0x01, // first Pixel 0xFF, 0x01, 0x0A, 0x64, // second Pixel 0}; // EndFrame // check for Equality OLA_ASSERT_DATA_EQUALS(EXPECTED7, arraysize(EXPECTED7), data, length); // check if the output writes are 1 OLA_ASSERT_EQ(1u, backend.Writes(1)); // test8 // create new output with pixel_count=16 and check data length // setup pixel_count to 16 options.pixel_count = 16; // setup SPIOutput SPIOutput output2(m_uid, &backend, options); // set personality output2.SetPersonality(this_test_personality); buffer.SetFromString( std::string("0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0,") + "0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0,"); output2.WriteDMX(buffer); data = backend.GetData(0, &length); const uint8_t EXPECTED8[] = { 0, 0, 0, 0, 0xFF, 0, 0, 0, // Pixel 1 0xFF, 0, 0, 0, // Pixel 2 0xFF, 0, 0, 0, // Pixel 3 0xFF, 0, 0, 0, // Pixel 4 0xFF, 0, 0, 0, // Pixel 5 0xFF, 0, 0, 0, // Pixel 6 0xFF, 0, 0, 0, // Pixel 7 0xFF, 0, 0, 0, // Pixel 8 0xFF, 0, 0, 0, // Pixel 9 0xFF, 0, 0, 0, // Pixel 10 0xFF, 0, 0, 0, // Pixel 11 0xFF, 0, 0, 0, // Pixel 12 0xFF, 0, 0, 0, // Pixel 13 0xFF, 0, 0, 0, // Pixel 14 0xFF, 0, 0, 0, // Pixel 15 0xFF, 0, 0, 0, // Pixel 16 0}; OLA_ASSERT_DATA_EQUALS(EXPECTED8, arraysize(EXPECTED8), data, length); OLA_ASSERT_EQ(5u, backend.Writes(0)); // test9 // create new output with pixel_count=17 and check data length // setup pixel_count to 17 options.pixel_count = 17; // setup SPIOutput SPIOutput output3(m_uid, &backend, options); // set personality output3.SetPersonality(this_test_personality); // generate dmx data buffer.SetFromString( std::string("0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0,") + "0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0," + "0,0,0"); output3.WriteDMX(buffer); data = backend.GetData(0, &length); const uint8_t EXPECTED9[] = { 0, 0, 0, 0, 0xFF, 0, 0, 0, // Pixel 1 0xFF, 0, 0, 0, // Pixel 2 0xFF, 0, 0, 0, // Pixel 3 0xFF, 0, 0, 0, // Pixel 4 0xFF, 0, 0, 0, // Pixel 5 0xFF, 0, 0, 0, // Pixel 6 0xFF, 0, 0, 0, // Pixel 7 0xFF, 0, 0, 0, // Pixel 8 0xFF, 0, 0, 0, // Pixel 9 0xFF, 0, 0, 0, // Pixel 10 0xFF, 0, 0, 0, // Pixel 11 0xFF, 0, 0, 0, // Pixel 12 0xFF, 0, 0, 0, // Pixel 13 0xFF, 0, 0, 0, // Pixel 14 0xFF, 0, 0, 0, // Pixel 15 0xFF, 0, 0, 0, // Pixel 16 0xFF, 0, 0, 0, // Pixel 17 0, 0}; // now we have two latch bytes... OLA_ASSERT_DATA_EQUALS(EXPECTED9, arraysize(EXPECTED9), data, length); OLA_ASSERT_EQ(6u, backend.Writes(0)); } /** * Test DMX writes in the combined APA102 mode. */ void SPIOutputTest::testCombinedAPA102Control() { // personality 8= Combined APA102 const uint16_t this_test_personality = 8; // setup Backend FakeSPIBackend backend(2); SPIOutput::Options options(0, "Test SPI Device"); // setup pixel_count to 2 (enough to test all cases) options.pixel_count = 2; // setup SPIOutput SPIOutput output(m_uid, &backend, options); // set personality to 8= Combined APA102 output.SetPersonality(this_test_personality); // simulate incoming dmx data with this buffer DmxBuffer buffer; // setup an pointer to the returned data (the fake SPI data stream) unsigned int length = 0; const uint8_t *data = NULL; // test1 // setup some 'DMX' data buffer.SetFromString("1, 10, 100"); // simulate incoming data output.WriteDMX(buffer); // get fake SPI data stream data = backend.GetData(0, &length); // this is the expected spi data stream: const uint8_t EXPECTED1[] = { 0, 0, 0, 0, // StartFrame 0xFF, 0x64, 0x0A, 0x01, // first Pixel 0xFF, 0x64, 0x0A, 0x01, // second Pixel 0}; // EndFrame // check for Equality OLA_ASSERT_DATA_EQUALS(EXPECTED1, arraysize(EXPECTED1), data, length); // check if the output writes are 1 OLA_ASSERT_EQ(1u, backend.Writes(0)); // test2 buffer.SetFromString("255,128,0,10,20,30"); output.WriteDMX(buffer); data = backend.GetData(0, &length); const uint8_t EXPECTED2[] = { 0, 0, 0, 0, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0}; OLA_ASSERT_DATA_EQUALS(EXPECTED2, arraysize(EXPECTED2), data, length); OLA_ASSERT_EQ(2u, backend.Writes(0)); // test3 buffer.SetFromString("34,56,78"); output.WriteDMX(buffer); data = backend.GetData(0, &length); const uint8_t EXPECTED3[] = { 0, 0, 0, 0, 0xFF, 0x4E, 0x38, 0x22, 0xFF, 0x4E, 0x38, 0x22, 0}; OLA_ASSERT_DATA_EQUALS(EXPECTED3, arraysize(EXPECTED3), data, length); OLA_ASSERT_EQ(3u, backend.Writes(0)); // test4 // tests what happens if fewer then needed color information are received buffer.SetFromString("7, 9"); output.WriteDMX(buffer); data = backend.GetData(0, &length); // check that the returns are the same as test2 (nothing changed) OLA_ASSERT_DATA_EQUALS(EXPECTED3, arraysize(EXPECTED3), data, length); OLA_ASSERT_EQ(3u, backend.Writes(0)); // test5 // test with other StartAddress // set StartAddress output.SetStartAddress(3); // values 1 & 2 should not be visible in SPI data stream buffer.SetFromString("1,2,3,4,5,6,7,8"); output.WriteDMX(buffer); data = backend.GetData(0, &length); const uint8_t EXPECTED5[] = { 0, 0, 0, 0, 0xFF, 0x05, 0x04, 0x03, 0xFF, 0x05, 0x04, 0x03, 0}; OLA_ASSERT_DATA_EQUALS(EXPECTED5, arraysize(EXPECTED5), data, length); OLA_ASSERT_EQ(4u, backend.Writes(0)); // test6 // Check nothing changed on the other output. OLA_ASSERT_EQ(reinterpret_cast(NULL), backend.GetData(1, &length)); OLA_ASSERT_EQ(0u, backend.Writes(1)); // test7 // test for multiple ports // StartFrame is only allowed on first port. SPIOutput::Options option1(1, "second SPI Device"); // setup pixel_count to 2 (enough to test all cases) option1.pixel_count = 2; // setup SPIOutput SPIOutput output1(m_uid, &backend, option1); // set personality output1.SetPersonality(this_test_personality); // setup some 'DMX' data buffer.SetFromString("1, 10, 100"); // simulate incoming data output1.WriteDMX(buffer); // get fake SPI data stream data = backend.GetData(1, &length); // this is the expected spi data stream: // StartFrame is missing --> port is >0 ! const uint8_t EXPECTED7[] = { // 0, 0, 0, 0, // StartFrame 0xFF, 0x64, 0x0A, 0x01, // first Pixel 0xFF, 0x64, 0x0A, 0x01, // second Pixel 0}; // EndFrame // check for Equality OLA_ASSERT_DATA_EQUALS(EXPECTED7, arraysize(EXPECTED7), data, length); // check if the output writes are 1 OLA_ASSERT_EQ(1u, backend.Writes(1)); } ola-0.10.5.nojsmin/plugins/spi/SPIPlugin.h0000644000175000017500000000345113023355232017720 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SPIPlugin.h * An SPI plugin. * Copyright (C) 2013 Simon Newton */ #ifndef PLUGINS_SPI_SPIPLUGIN_H_ #define PLUGINS_SPI_SPIPLUGIN_H_ #include #include #include "olad/Plugin.h" #include "ola/plugin_id.h" namespace ola { namespace plugin { namespace spi { class SPIPlugin: public ola::Plugin { public: explicit SPIPlugin(class ola::PluginAdaptor *plugin_adaptor) : Plugin(plugin_adaptor) {} std::string Name() const { return PLUGIN_NAME; } std::string Description() const; ola_plugin_id Id() const { return OLA_PLUGIN_SPI; } std::string PluginPrefix() const { return PLUGIN_PREFIX; } private: std::vector m_devices; bool StartHook(); bool StopHook(); bool SetDefaultPreferences(); static const char DEFAULT_BASE_UID[]; static const char DEFAULT_SPI_DEVICE_PREFIX[]; static const char PLUGIN_NAME[]; static const char PLUGIN_PREFIX[]; static const char SPI_BASE_UID_KEY[]; static const char SPI_DEVICE_PREFIX_KEY[]; }; } // namespace spi } // namespace plugin } // namespace ola #endif // PLUGINS_SPI_SPIPLUGIN_H_ ola-0.10.5.nojsmin/plugins/spi/SPIDevice.h0000644000175000017500000000553613023355232017667 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SPIDevice.h * The SPI Device class * Copyright (C) 2013 Simon Newton */ #ifndef PLUGINS_SPI_SPIDEVICE_H_ #define PLUGINS_SPI_SPIDEVICE_H_ #include #include #include #include "olad/Device.h" #include "ola/io/SelectServer.h" #include "ola/rdm/UIDAllocator.h" #include "ola/rdm/UID.h" #include "plugins/spi/SPIBackend.h" #include "plugins/spi/SPIWriter.h" namespace ola { namespace plugin { namespace spi { class SPIDevice: public ola::Device { public: SPIDevice(class SPIPlugin *owner, class Preferences *preferences, class PluginAdaptor *plugin_adaptor, const std::string &spi_device, ola::rdm::UIDAllocator *uid_allocator); std::string DeviceId() const; bool AllowMultiPortPatching() const { return true; } protected: bool StartHook(); void PrePortStop(); private: typedef std::vector SPIPorts; std::auto_ptr m_writer; std::auto_ptr m_backend; class Preferences *m_preferences; class PluginAdaptor *m_plugin_adaptor; SPIPorts m_spi_ports; std::string m_spi_device_name; // Per device options std::string SPIBackendKey() const; std::string SPISpeedKey() const; std::string SPICEKey() const; std::string PortCountKey() const; std::string SyncPortKey() const; std::string GPIOPinKey() const; // Per port options std::string DeviceLabelKey(uint8_t port) const; std::string PersonalityKey(uint8_t port) const; std::string PixelCountKey(uint8_t port) const; std::string StartAddressKey(uint8_t port) const; std::string GetPortKey(const std::string &suffix, uint8_t port) const; void SetDefaults(); void PopulateHardwareBackendOptions(HardwareBackend::Options *options); void PopulateSoftwareBackendOptions(SoftwareBackend::Options *options); void PopulateWriterOptions(SPIWriter::Options *options); static const char SPI_DEVICE_NAME[]; static const char HARDWARE_BACKEND[]; static const char SOFTWARE_BACKEND[]; static const uint16_t MAX_GPIO_PIN = 1023; }; } // namespace spi } // namespace plugin } // namespace ola #endif // PLUGINS_SPI_SPIDEVICE_H_ ola-0.10.5.nojsmin/plugins/spi/SPIBackend.h0000644000175000017500000001463113023355232020013 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SPIBackend.h * The backend for SPI output. These are the classes which write the data to * the SPI bus. * Copyright (C) 2013 Simon Newton */ #ifndef PLUGINS_SPI_SPIBACKEND_H_ #define PLUGINS_SPI_SPIBACKEND_H_ #include #include #include #include #include #include "plugins/spi/SPIWriter.h" namespace ola { namespace plugin { namespace spi { /** * The interface for all SPI Backends. */ class SPIBackendInterface { public: virtual ~SPIBackendInterface() {} virtual uint8_t *Checkout(uint8_t output, unsigned int length) = 0; virtual uint8_t *Checkout(uint8_t output, unsigned int length, unsigned int latch_bytes) = 0; virtual void Commit(uint8_t output) = 0; virtual std::string DevicePath() const = 0; virtual bool Init() = 0; protected: static const char SPI_DROP_VAR[]; static const char SPI_DROP_VAR_KEY[]; }; /** * A HardwareBackend which uses GPIO pins and an external de-multiplexer */ class HardwareBackend : public ola::thread::Thread, public SPIBackendInterface { public: struct Options { // Which GPIO bits to use to select the output. The number of outputs // will be 2 ** gpio_pins.size(); std::vector gpio_pins; }; HardwareBackend(const Options &options, SPIWriterInterface *writer, ExportMap *export_map); ~HardwareBackend(); bool Init(); uint8_t *Checkout(uint8_t output, unsigned int length) { return Checkout(output, length, 0); } uint8_t *Checkout(uint8_t output, unsigned int length, unsigned int latch_bytes); void Commit(uint8_t output); std::string DevicePath() const { return m_spi_writer->DevicePath(); } protected: void* Run(); private: class OutputData { public: OutputData() : m_data(NULL), m_write_pending(false), m_size(0), m_actual_size(0), m_latch_bytes(0) { } ~OutputData() { delete[] m_data; } uint8_t *Resize(unsigned int length); void SetLatchBytes(unsigned int latch_bytes); void SetPending(); bool IsPending() const { return m_write_pending; } void ResetPending() { m_write_pending = false; } const uint8_t *GetData() const { return m_data; } unsigned int Size() const { return m_size; } OutputData& operator=(const OutputData &other); private: uint8_t *m_data; bool m_write_pending; unsigned int m_size; unsigned int m_actual_size; unsigned int m_latch_bytes; OutputData(const OutputData&); }; typedef std::vector GPIOFds; typedef std::vector Outputs; SPIWriterInterface *m_spi_writer; UIntMap *m_drop_map; const uint8_t m_output_count; ola::thread::Mutex m_mutex; ola::thread::ConditionVariable m_cond_var; bool m_exit; Outputs m_output_data; // GPIO members GPIOFds m_gpio_fds; const std::vector m_gpio_pins; std::vector m_gpio_pin_state; void SetupOutputs(Outputs *outputs); void WriteOutput(uint8_t output_id, OutputData *output); bool SetupGPIO(); void CloseGPIOFDs(); }; /** * An SPI Backend which uses a software multipliexer. This accumulates all data * into a single buffer and then writes it to the SPI bus. */ class SoftwareBackend : public SPIBackendInterface, public ola::thread::Thread { public: struct Options { /* * The number of outputs. */ uint8_t outputs; /* * Controls if we designate one of the outputs as the 'sync' output. * If set >= 0, it denotes the output which triggers the SPI write. * If set to -1, we perform an SPI write on each update. */ int16_t sync_output; Options() : outputs(1), sync_output(0) {} }; SoftwareBackend(const Options &options, SPIWriterInterface *writer, ExportMap *export_map); ~SoftwareBackend(); bool Init(); uint8_t *Checkout(uint8_t output, unsigned int length) { return Checkout(output, length, 0); } uint8_t *Checkout(uint8_t output, unsigned int length, unsigned int latch_bytes); void Commit(uint8_t output); std::string DevicePath() const { return m_spi_writer->DevicePath(); } protected: void* Run(); private: SPIWriterInterface *m_spi_writer; UIntMap *m_drop_map; ola::thread::Mutex m_mutex; ola::thread::ConditionVariable m_cond_var; bool m_write_pending; bool m_exit; const int16_t m_sync_output; std::vector m_output_sizes; std::vector m_latch_bytes; uint8_t *m_output; unsigned int m_length; }; /** * A fake backend used for testing. If we had gmock this would be much * easier... */ class FakeSPIBackend : public SPIBackendInterface { public: explicit FakeSPIBackend(unsigned int outputs); ~FakeSPIBackend(); uint8_t *Checkout(uint8_t output, unsigned int length) { return Checkout(output, length, 0); } uint8_t *Checkout(uint8_t output, unsigned int length, unsigned int latch_bytes); void Commit(uint8_t output); const uint8_t *GetData(uint8_t output, unsigned int *length); std::string DevicePath() const { return "/dev/test"; } bool Init() { return true; } unsigned int Writes(uint8_t output) const; private: class Output { public: Output() : data(NULL), length(0), writes(0) {} ~Output() { delete[] data; } uint8_t *data; unsigned int length; unsigned int writes; }; typedef std::vector Outputs; Outputs m_outputs; }; } // namespace spi } // namespace plugin } // namespace ola #endif // PLUGINS_SPI_SPIBACKEND_H_ ola-0.10.5.nojsmin/plugins/spi/SPIPort.h0000644000175000017500000000405613023355232017410 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SPIPort.h * An OLA SPI Port. This simply wraps the SPIOutput. * Copyright (C) 2013 Simon Newton */ #ifndef PLUGINS_SPI_SPIPORT_H_ #define PLUGINS_SPI_SPIPORT_H_ #include #include "ola/DmxBuffer.h" #include "olad/Port.h" #include "plugins/spi/SPIDevice.h" #include "plugins/spi/SPIOutput.h" namespace ola { namespace plugin { namespace spi { class SPIOutputPort: public BasicOutputPort { public: SPIOutputPort(SPIDevice *parent, class SPIBackendInterface *backend, const ola::rdm::UID &uid, const SPIOutput::Options &options); ~SPIOutputPort() {} std::string GetDeviceLabel() const; bool SetDeviceLabel(const std::string &device_label); uint8_t GetPersonality() const; bool SetPersonality(uint16_t personality); uint16_t GetStartAddress() const; bool SetStartAddress(uint16_t start_address); unsigned int PixelCount() const; std::string Description() const; bool WriteDMX(const DmxBuffer &buffer, uint8_t priority); void RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback); void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback); void SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *callback); private: SPIOutput m_spi_output; }; } // namespace spi } // namespace plugin } // namespace ola #endif // PLUGINS_SPI_SPIPORT_H_ ola-0.10.5.nojsmin/plugins/spi/SPIDevice.cpp0000644000175000017500000002117013023355232020212 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SPIDevice.cpp * SPI device * Copyright (C) 2013 Simon Newton */ #include #include #include #include #include "ola/Logging.h" #include "ola/StringUtils.h" #include "ola/file/Util.h" #include "ola/network/NetworkUtils.h" #include "olad/PluginAdaptor.h" #include "olad/Preferences.h" #include "olad/Universe.h" #include "plugins/spi/SPIDevice.h" #include "plugins/spi/SPIPort.h" #include "plugins/spi/SPIPlugin.h" namespace ola { namespace plugin { namespace spi { using ola::rdm::UID; using std::auto_ptr; using std::ostringstream; using std::set; using std::string; using std::vector; const char SPIDevice::SPI_DEVICE_NAME[] = "SPI Device"; const char SPIDevice::HARDWARE_BACKEND[] = "hardware"; const char SPIDevice::SOFTWARE_BACKEND[] = "software"; /* * Create a new device */ SPIDevice::SPIDevice(SPIPlugin *owner, Preferences *prefs, PluginAdaptor *plugin_adaptor, const string &spi_device, ola::rdm::UIDAllocator *uid_allocator) : Device(owner, SPI_DEVICE_NAME), m_preferences(prefs), m_plugin_adaptor(plugin_adaptor), m_spi_device_name(spi_device) { m_spi_device_name = ola::file::FilenameFromPathOrPath(m_spi_device_name); SetDefaults(); unsigned int port_count = 0; string backend_type = m_preferences->GetValue(SPIBackendKey()); SPIWriter::Options writer_options; PopulateWriterOptions(&writer_options); m_writer.reset(new SPIWriter(spi_device, writer_options, plugin_adaptor->GetExportMap())); if (backend_type == HARDWARE_BACKEND) { HardwareBackend::Options options; PopulateHardwareBackendOptions(&options); m_backend.reset( new HardwareBackend(options, m_writer.get(), plugin_adaptor->GetExportMap())); port_count = 1 << options.gpio_pins.size(); OLA_INFO << m_spi_device_name << ", Hardware backend, " << port_count << " ports"; } else { if (backend_type != SOFTWARE_BACKEND) { OLA_WARN << "Unknown backend_type '" << backend_type << "' for SPI device " << m_spi_device_name; } SoftwareBackend::Options options; PopulateSoftwareBackendOptions(&options); m_backend.reset( new SoftwareBackend(options, m_writer.get(), plugin_adaptor->GetExportMap())); port_count = options.outputs; OLA_INFO << m_spi_device_name << ", Software backend, " << port_count << " ports"; } for (uint8_t i = 0; i < port_count; i++) { SPIOutput::Options spi_output_options(i, m_spi_device_name); if (m_preferences->HasKey(DeviceLabelKey(i))) { spi_output_options.device_label = m_preferences->GetValue(DeviceLabelKey(i)); } uint8_t pixel_count; if (StringToInt(m_preferences->GetValue(PixelCountKey(i)), &pixel_count)) { spi_output_options.pixel_count = pixel_count; } auto_ptr uid(uid_allocator->AllocateNext()); if (!uid.get()) { OLA_WARN << "Insufficient UIDs remaining to allocate a UID for SPI port " << static_cast(i); continue; } m_spi_ports.push_back( new SPIOutputPort(this, m_backend.get(), *uid.get(), spi_output_options)); } } string SPIDevice::DeviceId() const { return m_spi_device_name; } /* * Start this device */ bool SPIDevice::StartHook() { if (!m_backend->Init()) { STLDeleteElements(&m_spi_ports); return false; } SPIPorts::iterator iter = m_spi_ports.begin(); for (uint8_t i = 0; iter != m_spi_ports.end(); iter++, i++) { uint8_t personality; if (StringToInt(m_preferences->GetValue(PersonalityKey(i)), &personality)) { (*iter)->SetPersonality(personality); } uint16_t dmx_address; if (StringToInt(m_preferences->GetValue(StartAddressKey(i)), &dmx_address)) { (*iter)->SetStartAddress(dmx_address); } AddPort(*iter); } return true; } void SPIDevice::PrePortStop() { SPIPorts::iterator iter = m_spi_ports.begin(); for (uint8_t i = 0; iter != m_spi_ports.end(); iter++, i++) { ostringstream str; m_preferences->SetValue(DeviceLabelKey(i), (*iter)->GetDeviceLabel()); str << static_cast((*iter)->GetPersonality()); m_preferences->SetValue(PersonalityKey(i), str.str()); str.str(""); str << (*iter)->GetStartAddress(); m_preferences->SetValue(StartAddressKey(i), str.str()); str.str(""); str << (*iter)->PixelCount(); m_preferences->SetValue(PixelCountKey(i), str.str()); } m_preferences->Save(); } string SPIDevice::SPIBackendKey() const { return m_spi_device_name + "-backend"; } string SPIDevice::SPISpeedKey() const { return m_spi_device_name + "-spi-speed"; } string SPIDevice::SPICEKey() const { return m_spi_device_name + "-spi-ce-high"; } string SPIDevice::PortCountKey() const { return m_spi_device_name + "-ports"; } string SPIDevice::SyncPortKey() const { return m_spi_device_name + "-sync-port"; } string SPIDevice::GPIOPinKey() const { return m_spi_device_name + "-gpio-pin"; } string SPIDevice::DeviceLabelKey(uint8_t port) const { return GetPortKey("device-label", port); } string SPIDevice::PersonalityKey(uint8_t port) const { return GetPortKey("personality", port); } string SPIDevice::StartAddressKey(uint8_t port) const { return GetPortKey("dmx-address", port); } string SPIDevice::PixelCountKey(uint8_t port) const { return GetPortKey("pixel-count", port); } string SPIDevice::GetPortKey(const string &suffix, uint8_t port) const { std::ostringstream str; str << m_spi_device_name << "-" << static_cast(port) << "-" << suffix; return str.str(); } void SPIDevice::SetDefaults() { // Set device options set valid_backends; valid_backends.insert(HARDWARE_BACKEND); valid_backends.insert(SOFTWARE_BACKEND); m_preferences->SetDefaultValue(SPIBackendKey(), SetValidator(valid_backends), SOFTWARE_BACKEND); m_preferences->SetDefaultValue(SPISpeedKey(), UIntValidator(0, 32000000), 1000000); m_preferences->SetDefaultValue(SPICEKey(), BoolValidator(), false); m_preferences->SetDefaultValue(PortCountKey(), UIntValidator(1, 8), 1); m_preferences->SetDefaultValue(SyncPortKey(), IntValidator(-2, 8), 0); m_preferences->Save(); } void SPIDevice::PopulateHardwareBackendOptions( HardwareBackend::Options *options) { vector pins = m_preferences->GetMultipleValue(GPIOPinKey()); vector::const_iterator iter = pins.begin(); for (; iter != pins.end(); iter++) { uint16_t pin; if (!StringToInt(*iter, &pin)) { OLA_WARN << "Invalid GPIO pin " << *iter; continue; } if (pin > MAX_GPIO_PIN) { OLA_WARN << "Invalid GPIO pin " << *iter << ", must be < " << static_cast(MAX_GPIO_PIN); continue; } options->gpio_pins.push_back(pin); } } void SPIDevice::PopulateSoftwareBackendOptions( SoftwareBackend::Options *options) { if (!StringToInt(m_preferences->GetValue(PortCountKey()), &options->outputs)) { OLA_WARN << "Invalid integer value for " << PortCountKey(); } if (!StringToInt(m_preferences->GetValue(SyncPortKey()), &options->sync_output)) { OLA_WARN << "Invalid integer value for " << SyncPortKey(); } if (options->sync_output == -2) { options->sync_output = options->outputs - 1; } } void SPIDevice::PopulateWriterOptions(SPIWriter::Options *options) { uint32_t spi_speed; if (StringToInt(m_preferences->GetValue(SPISpeedKey()), &spi_speed)) { options->spi_speed = spi_speed; } bool ce_high; if (StringToBool(m_preferences->GetValue(SPICEKey()), &ce_high)) { options->cs_enable_high = ce_high; } } } // namespace spi } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/renard/0000755000175000017500000000000013155164170016417 5ustar wouterwouterola-0.10.5.nojsmin/plugins/renard/Makefile.mk0000644000175000017500000000111413023355232020455 0ustar wouterwouter# LIBRARIES ################################################## if USE_RENARD lib_LTLIBRARIES += plugins/renard/libolarenard.la plugins_renard_libolarenard_la_SOURCES = \ plugins/renard/RenardDevice.cpp \ plugins/renard/RenardDevice.h \ plugins/renard/RenardPlugin.cpp \ plugins/renard/RenardPlugin.h \ plugins/renard/RenardPort.cpp \ plugins/renard/RenardPort.h \ plugins/renard/RenardWidget.cpp \ plugins/renard/RenardWidget.h plugins_renard_libolarenard_la_LIBADD = \ common/libolacommon.la \ olad/plugin_api/libolaserverplugininterface.la endif ola-0.10.5.nojsmin/plugins/renard/RenardPort.cpp0000644000175000017500000000216413023355232021201 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RenardPort.cpp * The Renard plugin for ola * Copyright (C) 2013 Hakan Lindestaf */ #include "plugins/renard/RenardPort.h" namespace ola { namespace plugin { namespace renard { bool RenardOutputPort::WriteDMX(const DmxBuffer &buffer, OLA_UNUSED uint8_t priority) { return m_widget->SendDmx(buffer); } } // namespace renard } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/renard/RenardPort.h0000644000175000017500000000305513023355232020646 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RenardPort.h * The Renard plugin for ola * Copyright (C) 2013 Hakan Lindestaf */ #ifndef PLUGINS_RENARD_RENARDPORT_H_ #define PLUGINS_RENARD_RENARDPORT_H_ #include #include "plugins/renard/RenardDevice.h" #include "plugins/renard/RenardWidget.h" namespace ola { namespace plugin { namespace renard { class RenardOutputPort: public BasicOutputPort { public: RenardOutputPort(RenardDevice *parent, unsigned int id, RenardWidget *widget) : BasicOutputPort(parent, id), m_widget(widget) {} bool WriteDMX(const DmxBuffer &buffer, uint8_t priority); std::string Description() const { return m_widget->GetPath(); } private: RenardWidget *m_widget; }; } // namespace renard } // namespace plugin } // namespace ola #endif // PLUGINS_RENARD_RENARDPORT_H_ ola-0.10.5.nojsmin/plugins/renard/RenardWidget.cpp0000644000175000017500000001305513023355232021501 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RenardWidget.cpp * This is the Renard widget class * Copyright (C) 2013 Hakan Lindestaf */ #include #include #include "ola/Logging.h" #include "ola/io/IOUtils.h" #include "ola/io/Serial.h" #include "plugins/renard/RenardWidget.h" namespace ola { namespace plugin { namespace renard { using std::string; // Based on standard Renard firmware const uint8_t RenardWidget::RENARD_COMMAND_PAD = 0x7D; const uint8_t RenardWidget::RENARD_COMMAND_START_PACKET = 0x7E; const uint8_t RenardWidget::RENARD_COMMAND_ESCAPE = 0x7F; const uint8_t RenardWidget::RENARD_ESCAPE_PAD = 0x2F; const uint8_t RenardWidget::RENARD_ESCAPE_START_PACKET = 0x30; const uint8_t RenardWidget::RENARD_ESCAPE_ESCAPE = 0x31; // The Renard protocol is built around 8 channels per packet const uint8_t RenardWidget::RENARD_CHANNELS_IN_BANK = 8; // Discussions on the Renard firmware recommended a padding each 100 bytes or so const uint32_t RenardWidget::RENARD_BYTES_BETWEEN_PADDING = 100; /* * New widget */ RenardWidget::~RenardWidget() { if (m_socket) { m_socket->Close(); delete m_socket; } } /* * Connect to the widget */ bool RenardWidget::Connect() { OLA_DEBUG << "Connecting to " << m_path; OLA_DEBUG << "Baudrate set to " << static_cast(m_baudrate); speed_t baudrate; if (!ola::io::UIntToSpeedT(m_baudrate, &baudrate)) { OLA_DEBUG << "Failed to convert baudrate, i.e. not supported baud rate"; return false; } int fd = ConnectToWidget(m_path, baudrate); if (fd < 0) return false; m_socket = new ola::io::DeviceDescriptor(fd); OLA_DEBUG << "Connected to " << m_path; return true; } /* * Connect to the widget */ int RenardWidget::ConnectToWidget(const string &path, speed_t speed) { struct termios newtio; if (path.empty()) { OLA_DEBUG << "No path configured for device, please set one in " "ola-renard.conf"; return -1; } int fd; if (!ola::io::Open(path, O_RDWR | O_NONBLOCK | O_NOCTTY, &fd)) { return -1; } memset(&newtio, 0, sizeof(newtio)); // Clear struct for new port settings tcgetattr(fd, &newtio); newtio.c_cflag |= (CLOCAL | CREAD); // Enable read newtio.c_cflag |= CS8; // 8n1 newtio.c_cflag &= ~CRTSCTS; // No flow control cfsetispeed(&newtio, speed); cfsetospeed(&newtio, speed); tcsetattr(fd, TCSANOW, &newtio); return fd; } /* * Disconnect from the widget */ int RenardWidget::Disconnect() { m_socket->Close(); return 0; } /* * Check if this is actually a Renard device * @return true if this is a renard, false otherwise */ bool RenardWidget::DetectDevice() { // This device doesn't do two way comms, so just return true return true; } /* * Send a DMX msg. */ bool RenardWidget::SendDmx(const DmxBuffer &buffer) { unsigned int channels = std::max((unsigned int)0, std::min((unsigned int) m_channels + m_dmxOffset, buffer.Size()) - m_dmxOffset); OLA_DEBUG << "Sending " << static_cast(channels) << " channels"; // Max buffer size for worst case scenario (escaping + padding) unsigned int bufferSize = channels * 2 + 10; uint8_t msg[bufferSize]; int dataToSend = 0; for (unsigned int i = 0; i < channels; i++) { if ((i % RENARD_CHANNELS_IN_BANK) == 0) { if (m_byteCounter >= RENARD_BYTES_BETWEEN_PADDING) { // Send PAD every 100 (or so) bytes. Note that the counter is per // device, so the counter should span multiple calls to SendDMX. msg[dataToSend++] = RENARD_COMMAND_PAD; m_byteCounter = 0; } // Send address msg[dataToSend++] = RENARD_COMMAND_START_PACKET; msg[dataToSend++] = m_startAddress + (i / RENARD_CHANNELS_IN_BANK); m_byteCounter += 2; } uint8_t b = buffer.Get(m_dmxOffset + i); // Escaping magic bytes switch (b) { case RENARD_COMMAND_PAD: msg[dataToSend++] = RENARD_COMMAND_ESCAPE; msg[dataToSend++] = RENARD_ESCAPE_PAD; m_byteCounter += 2; break; case RENARD_COMMAND_START_PACKET: msg[dataToSend++] = RENARD_COMMAND_ESCAPE; msg[dataToSend++] = RENARD_ESCAPE_START_PACKET; m_byteCounter += 2; break; case RENARD_COMMAND_ESCAPE: msg[dataToSend++] = RENARD_COMMAND_ESCAPE; msg[dataToSend++] = RENARD_ESCAPE_ESCAPE; m_byteCounter += 2; break; default: msg[dataToSend++] = b; m_byteCounter++; break; } OLA_DEBUG << "Setting Renard " << m_startAddress + (i / RENARD_CHANNELS_IN_BANK) << "/" << ((i % RENARD_CHANNELS_IN_BANK) + 1) << " to " << static_cast(b); } int bytes_sent = m_socket->Send(msg, dataToSend); OLA_DEBUG << "Sending DMX, sent " << bytes_sent << " bytes"; return true; } } // namespace renard } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/renard/RenardDevice.h0000644000175000017500000000412113023355232021114 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RenardDevice.h * Interface for the renard device * Copyright (C) 2013 Hakan Lindestaf */ #ifndef PLUGINS_RENARD_RENARDDEVICE_H_ #define PLUGINS_RENARD_RENARDDEVICE_H_ #include #include #include "olad/Device.h" namespace ola { class AbstractPlugin; namespace plugin { namespace renard { class RenardDevice: public ola::Device { public: RenardDevice(AbstractPlugin *owner, class Preferences *preferences, const std::string &dev_path); ~RenardDevice(); std::string DeviceId() const { return m_dev_path; } ola::io::ConnectedDescriptor *GetSocket() const; protected: bool StartHook(); void PrePortStop(); private: std::auto_ptr m_widget; const std::string m_dev_path; class Preferences *m_preferences; // Per device options std::string DeviceBaudrateKey() const; std::string DeviceChannelsKey() const; std::string DeviceDmxOffsetKey() const; void SetDefaults(); static const char RENARD_DEVICE_NAME[]; static const uint8_t RENARD_START_ADDRESS; static const uint8_t RENARD_AVAILABLE_ADDRESSES; static const uint8_t DEFAULT_DMX_OFFSET; static const uint8_t DEFAULT_NUM_CHANNELS; static const uint32_t DEFAULT_BAUDRATE; }; } // namespace renard } // namespace plugin } // namespace ola #endif // PLUGINS_RENARD_RENARDDEVICE_H_ ola-0.10.5.nojsmin/plugins/renard/RenardPlugin.h0000644000175000017500000000403613023355232021160 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RenardPlugin.h * Interface for the Renard plugin class * Copyright (C) 2013 Hakan Lindestaf */ #ifndef PLUGINS_RENARD_RENARDPLUGIN_H_ #define PLUGINS_RENARD_RENARDPLUGIN_H_ #include #include #include "ola/io/Descriptor.h" #include "olad/Plugin.h" namespace ola { namespace plugin { namespace renard { class RenardDevice; class RenardPlugin: public Plugin { public: explicit RenardPlugin(PluginAdaptor *plugin_adaptor) : Plugin(plugin_adaptor) {} ~RenardPlugin() {} std::string Name() const { return PLUGIN_NAME; } ola_plugin_id Id() const { return OLA_PLUGIN_RENARD; } std::string Description() const; int SocketClosed(ola::io::ConnectedDescriptor *socket); std::string PluginPrefix() const { return PLUGIN_PREFIX; } private: bool StartHook(); bool StopHook(); bool SetDefaultPreferences(); void DeleteDevice(RenardDevice *device); std::vector m_devices; // list of our devices static const char RENARD_DEVICE_PATH[]; static const char RENARD_BASE_DEVICE_NAME[]; static const char RENARD_SS_DEVICE_NAME[]; static const char PLUGIN_NAME[]; static const char PLUGIN_PREFIX[]; static const char DEVICE_KEY[]; }; } // namespace renard } // namespace plugin } // namespace ola #endif // PLUGINS_RENARD_RENARDPLUGIN_H_ ola-0.10.5.nojsmin/plugins/renard/RenardWidget.h0000644000175000017500000000720313023355232021144 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RenardWidget.h * Interface for the renard widget * Copyright (C) 2013 Hakan Lindestaf */ #ifndef PLUGINS_RENARD_RENARDWIDGET_H_ #define PLUGINS_RENARD_RENARDWIDGET_H_ #include #include #include #include "ola/io/SelectServer.h" #include "ola/io/Serial.h" #include "ola/DmxBuffer.h" namespace ola { namespace plugin { namespace renard { class RenardWidget { public: // The DMX offset is where in the DMX universe the Renard channels // will be mapped. Set to 0 means the first Renard channel will be // mapped to DMX channel 1, next to 2, etc. If you set the DMX offset // to 100 then the first Renard channel will respond to DMX channel // 101. I envisioned this would be applicable to multiple (serial) // devices sharing the same DMX universe. // Number of channels is how many channels we'll output on the device. // There are limits to how many channels we can address for any given // refresh rate, based on baud rate and escaping. Renard ignores // any extra channels that are sent on the wire, so setting this too // high is not a major concern. // The start address is the Renard-address of the first board. The // default in the standard firmware is 0x80, and it may be a reasonable // future feature request to have this configurable for more advanced // Renard configurations (using wireless transmitters, etc). explicit RenardWidget(const std::string &path, int dmxOffset, int channels, uint32_t baudrate, uint8_t startAddress) : m_path(path), m_socket(NULL), m_byteCounter(0), m_dmxOffset(dmxOffset), m_channels(channels), m_baudrate(baudrate), m_startAddress(startAddress) {} virtual ~RenardWidget(); // these methods are for communicating with the device bool Connect(); int Disconnect(); ola::io::ConnectedDescriptor *GetSocket() { return m_socket; } std::string GetPath() { return m_path; } bool SendDmx(const DmxBuffer &buffer); bool DetectDevice(); static const uint8_t RENARD_CHANNELS_IN_BANK; private: int ConnectToWidget(const std::string &path, speed_t speed); // instance variables const std::string m_path; ola::io::ConnectedDescriptor *m_socket; uint32_t m_byteCounter; uint32_t m_dmxOffset; uint32_t m_channels; uint32_t m_baudrate; uint8_t m_startAddress; static const uint8_t RENARD_COMMAND_PAD; static const uint8_t RENARD_COMMAND_START_PACKET; static const uint8_t RENARD_COMMAND_ESCAPE; static const uint8_t RENARD_ESCAPE_PAD; static const uint8_t RENARD_ESCAPE_START_PACKET; static const uint8_t RENARD_ESCAPE_ESCAPE; static const uint32_t RENARD_BYTES_BETWEEN_PADDING; }; } // namespace renard } // namespace plugin } // namespace ola #endif // PLUGINS_RENARD_RENARDWIDGET_H_ ola-0.10.5.nojsmin/plugins/renard/RenardDevice.cpp0000644000175000017500000001215513023355232021455 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RenardDevice.cpp * Renard device * Copyright (C) 2013 Hakan Lindestaf */ #include #include #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/StringUtils.h" #include "olad/Preferences.h" #include "plugins/renard/RenardPort.h" #include "plugins/renard/RenardWidget.h" #include "plugins/renard/RenardDevice.h" namespace ola { namespace plugin { namespace renard { using ola::AbstractPlugin; using ola::io::ConnectedDescriptor; using std::set; using std::string; const char RenardDevice::RENARD_DEVICE_NAME[] = "Renard Device"; // The default Renard firmware has 0x80 as start address. It would be // possible to make this configurable in a future release if needed. const uint8_t RenardDevice::RENARD_START_ADDRESS = 0x80; // Between 0x80 and 0xFF const uint8_t RenardDevice::RENARD_AVAILABLE_ADDRESSES = 127; const uint8_t RenardDevice::DEFAULT_DMX_OFFSET = 0; const uint8_t RenardDevice::DEFAULT_NUM_CHANNELS = 64; const uint32_t RenardDevice::DEFAULT_BAUDRATE = ola::io::BAUD_RATE_57600; /* * Create a new device * * @param owner the plugin that owns this device * @param preferences config settings * @param dev_path path to the pro widget */ RenardDevice::RenardDevice(AbstractPlugin *owner, class Preferences *preferences, const string &dev_path) : Device(owner, RENARD_DEVICE_NAME), m_dev_path(dev_path), m_preferences(preferences) { OLA_INFO << "Create device " << m_dev_path; SetDefaults(); uint32_t dmxOffset; if (!StringToInt(m_preferences->GetValue(DeviceDmxOffsetKey()), &dmxOffset)) { dmxOffset = DEFAULT_DMX_OFFSET; } uint32_t channels; if (!StringToInt(m_preferences->GetValue(DeviceChannelsKey()), &channels)) { channels = DEFAULT_NUM_CHANNELS; } uint32_t baudrate; if (!StringToInt(m_preferences->GetValue(DeviceBaudrateKey()), &baudrate)) { baudrate = DEFAULT_BAUDRATE; } m_widget.reset(new RenardWidget(m_dev_path, dmxOffset, channels, baudrate, RENARD_START_ADDRESS)); OLA_DEBUG << "DMX offset set to " << static_cast(dmxOffset); OLA_DEBUG << "Channels set to " << static_cast(channels); OLA_DEBUG << "Baudrate set to " << static_cast(baudrate); } /* * Destroy this device */ RenardDevice::~RenardDevice() { // Stub destructor for compatibility with RenardWidget subclasses } /* * Start this device */ bool RenardDevice::StartHook() { if (!m_widget.get()) { return false; } if (!m_widget->Connect()) { OLA_WARN << "Failed to connect to " << m_dev_path; return false; } if (!m_widget->DetectDevice()) { OLA_WARN << "No device found at " << m_dev_path; return false; } RenardOutputPort *port = new RenardOutputPort(this, 0, m_widget.get()); AddPort(port); return true; } /* * Stop this device */ void RenardDevice::PrePortStop() { // disconnect from widget m_widget->Disconnect(); m_preferences->Save(); } string RenardDevice::DeviceBaudrateKey() const { return m_dev_path + "-baudrate"; } string RenardDevice::DeviceChannelsKey() const { return m_dev_path + "-channels"; } string RenardDevice::DeviceDmxOffsetKey() const { return m_dev_path + "-dmx-offset"; } void RenardDevice::SetDefaults() { set valid_baudrates; valid_baudrates.insert(ola::io::BAUD_RATE_19200); valid_baudrates.insert(ola::io::BAUD_RATE_38400); valid_baudrates.insert(ola::io::BAUD_RATE_57600); valid_baudrates.insert(ola::io::BAUD_RATE_115200); // Set device options m_preferences->SetDefaultValue(DeviceBaudrateKey(), SetValidator(valid_baudrates), DEFAULT_BAUDRATE); // Renard supports more than 512 channels, but in our application // we're tied to a single DMX universe so we'll limit it to 512 channels. m_preferences->SetDefaultValue( DeviceChannelsKey(), UIntValidator(RenardWidget::RENARD_CHANNELS_IN_BANK, DMX_UNIVERSE_SIZE), DEFAULT_NUM_CHANNELS); m_preferences->SetDefaultValue( DeviceDmxOffsetKey(), UIntValidator( 0, DMX_UNIVERSE_SIZE - RenardWidget::RENARD_CHANNELS_IN_BANK), DEFAULT_DMX_OFFSET); } /* * return the sd for this device */ ConnectedDescriptor *RenardDevice::GetSocket() const { return m_widget->GetSocket(); } } // namespace renard } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/renard/RenardPlugin.cpp0000644000175000017500000001176413023355232021521 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RenardPlugin.cpp * The Renard plugin for ola * Copyright (C) 2013 Hakan Lindestaf */ #include #include #include "ola/Logging.h" #include "olad/PluginAdaptor.h" #include "olad/Preferences.h" #include "plugins/renard/RenardDevice.h" #include "plugins/renard/RenardPlugin.h" namespace ola { namespace plugin { namespace renard { using ola::io::ConnectedDescriptor; using std::string; using std::vector; // Blank default path, so we don't start using a serial port without being asked const char RenardPlugin::RENARD_DEVICE_PATH[] = ""; const char RenardPlugin::PLUGIN_NAME[] = "Renard"; const char RenardPlugin::PLUGIN_PREFIX[] = "renard"; const char RenardPlugin::DEVICE_KEY[] = "device"; /* * Start the plugin */ bool RenardPlugin::StartHook() { vector device_names; vector::iterator it; RenardDevice *device; // fetch device listing device_names = m_preferences->GetMultipleValue(DEVICE_KEY); for (it = device_names.begin(); it != device_names.end(); ++it) { if (it->empty()) { OLA_DEBUG << "No path configured for device, please set one in " "ola-renard.conf"; continue; } device = new RenardDevice(this, m_preferences, *it); OLA_DEBUG << "Adding device " << *it; if (!device->Start()) { delete device; continue; } OLA_DEBUG << "Started device " << *it; m_plugin_adaptor->AddReadDescriptor(device->GetSocket()); m_plugin_adaptor->RegisterDevice(device); m_devices.push_back(device); } return true; } /* * Stop the plugin * @return true on success, false on failure */ bool RenardPlugin::StopHook() { vector::iterator iter; for (iter = m_devices.begin(); iter != m_devices.end(); ++iter) { m_plugin_adaptor->RemoveReadDescriptor((*iter)->GetSocket()); DeleteDevice(*iter); } m_devices.clear(); return true; } /* * Return the description for this plugin */ string RenardPlugin::Description() const { return "Renard Plugin\n" "----------------------------\n" "\n" "This plugin creates devices with one output port. It supports multiple " "Renard SS boards directly connected, or daisy-chained. See this link " "for more information: " "http://www.doityourselfchristmas.com/wiki/index.php?title=Renard\n" "\n" "--- Config file : ola-renard.conf ---\n" "\n" "device = /dev/ttyUSB0\n" "The device to use as a path for the serial port or USB-Serial adapter. " "Renard boards don't have a built-in USB port, you will need an adapter (" "USB->RS232 or USB->RS485). Multiple devices are supported.\n" "\n" "--- Per Device Settings (using above device name without /dev/) ---\n" "-baudrate = \n" "The speed of the serial port, options are 9600, 19200, 38400, 57600, " "115200. Default is 57600.\n" "\n" "-channels = \n" "The number of channels connected to this device. Default 64.\n" "Note that the max number of channels vary by baud rate and " "the encoding.\n" "\n" "-dmx-offset = \n" "Which starting point in the DMX universe this device is mapped to. " "The default is 0, which means the first channel on Renard address " "128 (0x80) will be mapped to DMX channel 1.\n" "\n"; } /* * Called when the file descriptor is closed. */ int RenardPlugin::SocketClosed(ConnectedDescriptor *socket) { vector::iterator iter; for (iter = m_devices.begin(); iter != m_devices.end(); ++iter) { if ((*iter)->GetSocket() == socket) { break; } } if (iter == m_devices.end()) { OLA_WARN << "unknown fd"; return -1; } DeleteDevice(*iter); m_devices.erase(iter); return 0; } /* * load the plugin prefs and default to sensible values * */ bool RenardPlugin::SetDefaultPreferences() { if (!m_preferences) { return false; } bool save = false; save |= m_preferences->SetDefaultValue(DEVICE_KEY, StringValidator(), RENARD_DEVICE_PATH); if (save) { m_preferences->Save(); } // Just check key exists, as we've set it to "" if (!m_preferences->HasKey(DEVICE_KEY)) { return false; } return true; } /* * Cleanup a single device */ void RenardPlugin::DeleteDevice(RenardDevice *device) { m_plugin_adaptor->UnregisterDevice(device); device->Stop(); delete device; } } // namespace renard } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/osc/0000755000175000017500000000000013155164170015730 5ustar wouterwouterola-0.10.5.nojsmin/plugins/osc/Makefile.mk0000644000175000017500000000260713023355232017776 0ustar wouterwouter# LIBRARIES ################################################## if USE_OSC # This is a library which isn't coupled to olad noinst_LTLIBRARIES += plugins/osc/libolaoscnode.la plugins_osc_libolaoscnode_la_SOURCES = \ plugins/osc/OSCAddressTemplate.cpp \ plugins/osc/OSCAddressTemplate.h \ plugins/osc/OSCNode.cpp \ plugins/osc/OSCNode.h \ plugins/osc/OSCTarget.h plugins_osc_libolaoscnode_la_CXXFLAGS = $(COMMON_CXXFLAGS) $(liblo_CFLAGS) plugins_osc_libolaoscnode_la_LIBADD = $(liblo_LIBS) lib_LTLIBRARIES += plugins/osc/libolaosc.la plugins_osc_libolaosc_la_SOURCES = \ plugins/osc/OSCDevice.cpp \ plugins/osc/OSCDevice.h \ plugins/osc/OSCPlugin.cpp \ plugins/osc/OSCPlugin.h \ plugins/osc/OSCPort.cpp \ plugins/osc/OSCPort.h plugins_osc_libolaosc_la_CXXFLAGS = $(COMMON_CXXFLAGS) $(liblo_CFLAGS) plugins_osc_libolaosc_la_LIBADD = \ olad/plugin_api/libolaserverplugininterface.la \ plugins/osc/libolaoscnode.la # TESTS ################################################## test_programs += plugins/osc/OSCTester plugins_osc_OSCTester_SOURCES = \ plugins/osc/OSCAddressTemplateTest.cpp \ plugins/osc/OSCNodeTest.cpp plugins_osc_OSCTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) plugins_osc_OSCTester_LDADD = $(COMMON_TESTING_LIBS) \ plugins/osc/libolaoscnode.la \ common/libolacommon.la endif EXTRA_DIST += plugins/osc/README ola-0.10.5.nojsmin/plugins/osc/OSCDevice.h0000644000175000017500000000416013023355232017641 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OSCDevice.h * The OSC Device. * Copyright (C) 2012 Simon Newton */ #ifndef PLUGINS_OSC_OSCDEVICE_H_ #define PLUGINS_OSC_OSCDEVICE_H_ #include #include #include #include "ola/io/SelectServerInterface.h" #include "ola/network/SocketAddress.h" #include "olad/Device.h" #include "plugins/osc/OSCTarget.h" #include "plugins/osc/OSCNode.h" namespace ola { class AbstractPlugin; namespace plugin { namespace osc { class OSCDevice: public Device { public: struct PortConfig { PortConfig() : data_format(OSCNode::FORMAT_BLOB) {} std::vector targets; OSCNode::DataFormat data_format; }; typedef std::vector PortConfigs; OSCDevice(AbstractPlugin *owner, PluginAdaptor *plugin_adaptor, uint16_t udp_port, const std::vector &addresses, const PortConfigs &port_configs); std::string DeviceId() const { return "1"; } bool AllowLooping() const { return true; } bool AllowMultiPortPatching() const { return true; } protected: PluginAdaptor *m_plugin_adaptor; const std::vector m_port_addresses; const PortConfigs m_port_configs; std::auto_ptr m_osc_node; bool StartHook(); static const char DEVICE_NAME[]; }; } // namespace osc } // namespace plugin } // namespace ola #endif // PLUGINS_OSC_OSCDEVICE_H_ ola-0.10.5.nojsmin/plugins/osc/OSCAddressTemplateTest.cpp0000644000175000017500000000351713023355232022723 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OSCAddressTemplateTest.cpp * Test fixture for the OSCAddressTemplate function. * Copyright (C) 2012 Simon Newton */ #include #include #include "ola/testing/TestUtils.h" #include "plugins/osc/OSCAddressTemplate.h" using ola::plugin::osc::ExpandTemplate; using std::string; class OSCAddressTemplateTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(OSCAddressTemplateTest); // The tests to run. CPPUNIT_TEST(testExpand); CPPUNIT_TEST_SUITE_END(); public: // The test method void testExpand(); }; // Register this test class CPPUNIT_TEST_SUITE_REGISTRATION(OSCAddressTemplateTest); /** * Check that ExpandTemplate() works. */ void OSCAddressTemplateTest::testExpand() { OLA_ASSERT_EQ(string(""), ExpandTemplate("", 0)); OLA_ASSERT_EQ(string("foo"), ExpandTemplate("foo", 0)); OLA_ASSERT_EQ(string("/dmx/universe/0"), ExpandTemplate("/dmx/universe/%d", 0)); OLA_ASSERT_EQ(string("0"), ExpandTemplate("%d", 0)); OLA_ASSERT_EQ(string("port_1"), ExpandTemplate("port_%d", 1)); OLA_ASSERT_EQ(string("1_%d"), ExpandTemplate("%d_%d", 1)); } ola-0.10.5.nojsmin/plugins/osc/OSCNodeTest.cpp0000644000175000017500000002424713023355232020532 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OSCNodeTest.cpp * Test fixture for the OSCNode class * Copyright (C) 2012 Simon Newton */ #include #include #include "ola/Callback.h" #include "ola/DmxBuffer.h" #include "ola/Logging.h" #include "ola/base/Init.h" #include "ola/io/SelectServer.h" #include "ola/network/IPV4Address.h" #include "ola/network/Socket.h" #include "ola/network/SocketAddress.h" #include "ola/testing/TestUtils.h" #include "plugins/osc/OSCNode.h" #include "plugins/osc/OSCTarget.h" using ola::DmxBuffer; using ola::NewCallback; using ola::io::SelectServer; using ola::network::IPV4Address; using ola::network::IPV4SocketAddress; using ola::network::UDPSocket; using ola::plugin::osc::OSCNode; using ola::plugin::osc::OSCTarget; using std::auto_ptr; /** * The test fixture for the OSCNode. */ class OSCNodeTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(OSCNodeTest); CPPUNIT_TEST(testSendBlob); CPPUNIT_TEST(testReceive); CPPUNIT_TEST_SUITE_END(); public: /** * Initilize the OSCNode and the timeout_id */ OSCNodeTest() : CppUnit::TestFixture(), m_timeout_id(ola::thread::INVALID_TIMEOUT) { OSCNode::OSCNodeOptions options; options.listen_port = 0; m_osc_node.reset(new OSCNode(&m_ss, NULL, options)); } // The setUp and tearDown methods. These are run before and after each test // case. void setUp(); void tearDown() { m_osc_node->Stop(); } // our two tests void testSendBlob(); void testReceive(); // Called if we don't receive data in ABORT_TIMEOUT_IN_MS void Timeout() { OLA_FAIL("timeout"); } private: ola::io::SelectServer m_ss; auto_ptr m_osc_node; UDPSocket m_udp_socket; ola::thread::timeout_id m_timeout_id; DmxBuffer m_dmx_data; DmxBuffer m_received_data; void UDPSocketReady(); void DMXHandler(const DmxBuffer &dmx); static const unsigned int TEST_GROUP = 10; // the group to use for testing // The number of mseconds to wait before failing the test. static const int ABORT_TIMEOUT_IN_MS = 2000; static const uint8_t OSC_BLOB_DATA[]; static const uint8_t OSC_SINGLE_FLOAT_DATA[]; static const uint8_t OSC_SINGLE_INT_DATA[]; static const uint8_t OSC_INT_TUPLE_DATA[]; static const uint8_t OSC_FLOAT_TUPLE_DATA[]; // The OSC address to use for testing static const char TEST_OSC_ADDRESS[]; }; CPPUNIT_TEST_SUITE_REGISTRATION(OSCNodeTest); // A OSC blob packet. See http://opensoundcontrol.org/ for what each // byte means. const uint8_t OSCNodeTest::OSC_BLOB_DATA[] = { // osc address '/', 'd', 'm', 'x', '/', 'u', 'n', 'i', 'v', 'e', 'r', 's', 'e', '/', '1', '0', 0, 0, 0, 0, // tag type ',', 'b', 0, 0, 0, 0, 0, 0x0b, // data 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0 }; // An OSC single float packet for slot 1 const uint8_t OSCNodeTest::OSC_SINGLE_FLOAT_DATA[] = { // osc address '/', 'd', 'm', 'x', '/', 'u', 'n', 'i', 'v', 'e', 'r', 's', 'e', '/', '1', '0', '/', '1', 0, 0, // tag type ',', 'f', 0, 0, // data (0.5 which translates to 127) 0x3f, 0, 0, 0 }; // An OSC single int packet for slot 5 const uint8_t OSCNodeTest::OSC_SINGLE_INT_DATA[] = { // osc address '/', 'd', 'm', 'x', '/', 'u', 'n', 'i', 'v', 'e', 'r', 's', 'e', '/', '1', '0', '/', '6', 0, 0, // tag type ',', 'i', 0, 0, // data 0, 0, 0, 140 }; // An OSC 'ii' packet for slot 7 const uint8_t OSCNodeTest::OSC_INT_TUPLE_DATA[] = { // osc address '/', 'd', 'm', 'x', '/', 'u', 'n', 'i', 'v', 'e', 'r', 's', 'e', '/', '1', '0', 0, 0, 0, 0, // tag type ',', 'i', 'i', 0, // data 0, 0, 0, 8, 0, 0, 0, 90 }; // An OSC 'if' packet for slot 8 const uint8_t OSCNodeTest::OSC_FLOAT_TUPLE_DATA[] = { // osc address '/', 'd', 'm', 'x', '/', 'u', 'n', 'i', 'v', 'e', 'r', 's', 'e', '/', '1', '0', 0, 0, 0, 0, // tag type ',', 'i', 'f', 0, // data 0, 0, 0, 9, 0x3f, 0, 0, 0 }; // An OSC Address used for testing. const char OSCNodeTest::TEST_OSC_ADDRESS[] = "/dmx/universe/10"; void OSCNodeTest::setUp() { // Init logging ola::InitLogging(ola::OLA_LOG_INFO, ola::OLA_LOG_STDERR); ola::NetworkInit(); // Setup and register the Timeout. m_timeout_id = m_ss.RegisterSingleTimeout( ABORT_TIMEOUT_IN_MS, ola::NewSingleCallback(this, &OSCNodeTest::Timeout)); OLA_ASSERT_TRUE(m_timeout_id); // Init our UDP socket. OLA_ASSERT_TRUE(m_udp_socket.Init()); // Put some data into the DMXBuffer m_dmx_data.SetFromString("0,1,2,3,4,5,6,7,8,9,10"); // Initialize the OSCNode OLA_ASSERT_TRUE(m_osc_node->Init()); } /** * Called when data arrives on our UDP socket. We check that this data matches * the expected OSC packet */ void OSCNodeTest::UDPSocketReady() { uint8_t data[500]; // 500 bytes is more than enough ssize_t data_read = sizeof(data); // Read the received packet into 'data'. OLA_ASSERT_TRUE(m_udp_socket.RecvFrom(data, &data_read)); // Verify it matches the expected packet OLA_ASSERT_DATA_EQUALS(OSC_BLOB_DATA, sizeof(OSC_BLOB_DATA), data, data_read); // Stop the SelectServer m_ss.Terminate(); } /** * Called when we receive DMX data via OSC. We check this matches what we * expect, and then stop the SelectServer. */ void OSCNodeTest::DMXHandler(const DmxBuffer &dmx) { m_received_data = dmx; m_ss.Terminate(); } /** * Check that we send OSC messages correctly. */ void OSCNodeTest::testSendBlob() { // First up create a UDP socket to receive the messages on. // Port 0 means 'ANY' IPV4SocketAddress socket_address(IPV4Address::Loopback(), 0); // Bind the socket, set the callback, and register with the select server. OLA_ASSERT_TRUE(m_udp_socket.Bind(socket_address)); m_udp_socket.SetOnData(NewCallback(this, &OSCNodeTest::UDPSocketReady)); OLA_ASSERT_TRUE(m_ss.AddReadDescriptor(&m_udp_socket)); // Store the local address of the UDP socket so we know where to tell the // OSCNode to send to. OLA_ASSERT_TRUE(m_udp_socket.GetSocketAddress(&socket_address)); // Setup the OSCTarget pointing to the local socket address OSCTarget target(socket_address, TEST_OSC_ADDRESS); // Add the target to the node. m_osc_node->AddTarget(TEST_GROUP, target); // Send the data OLA_ASSERT_TRUE(m_osc_node->SendData(TEST_GROUP, OSCNode::FORMAT_BLOB, m_dmx_data)); // Run the SelectServer this will return either when UDPSocketReady // completes, or the abort timeout triggers. m_ss.Run(); // Remove target OLA_ASSERT_TRUE(m_osc_node->RemoveTarget(TEST_GROUP, target)); // Try to remove it a second time OLA_ASSERT_FALSE(m_osc_node->RemoveTarget(TEST_GROUP, target)); // Try to remove the target from a group that doesn't exist OLA_ASSERT_FALSE(m_osc_node->RemoveTarget(TEST_GROUP + 1, target)); } /** * Check that we receive OSC messages correctly. */ void OSCNodeTest::testReceive() { DmxBuffer expected_data; // Register the test OSC Address with the OSCNode using the DMXHandler as the // callback. OLA_ASSERT_TRUE(m_osc_node->RegisterAddress( TEST_OSC_ADDRESS, NewCallback(this, &OSCNodeTest::DMXHandler))); // Attempt to register the same address with a different path, this should // return false OLA_ASSERT_FALSE(m_osc_node->RegisterAddress( TEST_OSC_ADDRESS, NewCallback(this, &OSCNodeTest::DMXHandler))); // Using our test UDP socket, send the OSC_BLOB_DATA to the default OSC // port. The OSCNode should receive the packet and call DMXHandler. IPV4SocketAddress dest_address(IPV4Address::Loopback(), m_osc_node->ListeningPort()); // send a single float update m_udp_socket.SendTo(OSC_SINGLE_FLOAT_DATA, sizeof(OSC_SINGLE_FLOAT_DATA), dest_address); m_ss.Run(); OLA_ASSERT_EQ(512u, m_received_data.Size()); expected_data.SetChannel(0, 127); OLA_ASSERT_EQ(expected_data, m_received_data); // now send a blob update m_udp_socket.SendTo(OSC_BLOB_DATA, sizeof(OSC_BLOB_DATA), dest_address); // Run the SelectServer, this will return either when DMXHandler // completes, or the abort timeout triggers. m_ss.Run(); OLA_ASSERT_EQ(11u, m_received_data.Size()); expected_data.SetFromString("0,1,2,3,4,5,6,7,8,9,10"); OLA_ASSERT_EQ(expected_data, m_received_data); // Now try sending a float update. m_udp_socket.SendTo(OSC_SINGLE_FLOAT_DATA, sizeof(OSC_SINGLE_FLOAT_DATA), dest_address); m_ss.Run(); OLA_ASSERT_EQ(11u, m_received_data.Size()); expected_data.SetChannel(0, 127); OLA_ASSERT_EQ(expected_data, m_received_data); // Now try sending an int update. m_udp_socket.SendTo(OSC_SINGLE_INT_DATA, sizeof(OSC_SINGLE_INT_DATA), dest_address); m_ss.Run(); OLA_ASSERT_EQ(11u, m_received_data.Size()); expected_data.SetChannel(5, 140); OLA_ASSERT_EQ(expected_data, m_received_data); // An 'ii' update m_udp_socket.SendTo(OSC_INT_TUPLE_DATA, sizeof(OSC_INT_TUPLE_DATA), dest_address); m_ss.Run(); OLA_ASSERT_EQ(11u, m_received_data.Size()); expected_data.SetChannel(7, 90); OLA_ASSERT_EQ(expected_data, m_received_data); // An 'if' update m_udp_socket.SendTo(OSC_FLOAT_TUPLE_DATA, sizeof(OSC_FLOAT_TUPLE_DATA), dest_address); m_ss.Run(); OLA_ASSERT_EQ(11u, m_received_data.Size()); expected_data.SetChannel(8, 127); OLA_ASSERT_EQ(expected_data, m_received_data); // De-regsiter OLA_ASSERT_TRUE(m_osc_node->RegisterAddress(TEST_OSC_ADDRESS, NULL)); // De-register a second time OLA_ASSERT_TRUE(m_osc_node->RegisterAddress(TEST_OSC_ADDRESS, NULL)); } ola-0.10.5.nojsmin/plugins/osc/OSCPort.cpp0000644000175000017500000001027113023355232017721 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OSCPort.cpp * The OSCInputPort and OSCOutputPort classes. * Copyright (C) 2012 Simon Newton */ #include #include #include #include "ola/Logging.h" #include "olad/Port.h" #include "plugins/osc/OSCAddressTemplate.h" #include "plugins/osc/OSCDevice.h" #include "plugins/osc/OSCNode.h" #include "plugins/osc/OSCPort.h" namespace ola { namespace plugin { namespace osc { using std::ostringstream; using std::string; using std::vector; OSCInputPort::OSCInputPort( OSCDevice *parent, unsigned int port_id, PluginAdaptor *plugin_adaptor, OSCNode *node, const string &address) : BasicInputPort(parent, port_id, plugin_adaptor), m_node(node), m_address(address), m_actual_address(address) { } bool OSCInputPort::PreSetUniverse(Universe *old_universe, Universe *new_universe) { // if the old_universe is not NULL, we need to de-register if (old_universe) { m_node->RegisterAddress(m_actual_address, NULL); // reset the actual address m_actual_address = m_address; } // if we've been supplied with a new universe, attempt to register if (new_universe) { string osc_address = ExpandTemplate(m_address, new_universe->UniverseId()); bool ok = m_node->RegisterAddress( osc_address, NewCallback(this, &OSCInputPort::NewDMXData)); if (!ok) // means that another port is registered with the same address return false; // update the address since the registration was successful. m_actual_address = osc_address; } return true; } void OSCInputPort::NewDMXData(const DmxBuffer &data) { m_buffer = data; // store the data DmxChanged(); // signal that our data has changed } OSCOutputPort::OSCOutputPort( OSCDevice *device, unsigned int port_id, OSCNode *node, const vector &targets, OSCNode::DataFormat data_format) : BasicOutputPort(device, port_id), m_node(node), m_template_targets(targets), m_data_format(data_format) { SetUnpatchedDescription(); } OSCOutputPort::~OSCOutputPort() { RemoveTargets(); } bool OSCOutputPort::PreSetUniverse(Universe *, Universe *new_universe) { RemoveTargets(); vector::const_iterator iter = m_template_targets.begin(); if (new_universe) { ostringstream str; for (; iter != m_template_targets.end(); ++iter) { string osc_address = ExpandTemplate(iter->osc_address, new_universe->UniverseId()); OSCTarget new_target(iter->socket_address, osc_address); m_node->AddTarget(PortId(), new_target); m_registered_targets.push_back(new_target); if (iter != m_template_targets.begin()) str << ", "; str << new_target; } m_description = str.str(); } else { SetUnpatchedDescription(); } return true; } void OSCOutputPort::RemoveTargets() { vector::const_iterator iter = m_registered_targets.begin(); for (; iter != m_registered_targets.end(); ++iter) { m_node->RemoveTarget(PortId(), *iter); } m_registered_targets.clear(); } void OSCOutputPort::SetUnpatchedDescription() { ostringstream str; vector::const_iterator iter = m_template_targets.begin(); for (; iter != m_template_targets.end(); ++iter) { if (iter != m_template_targets.begin()) str << ", "; str << *iter; } m_description = str.str(); } } // namespace osc } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/osc/README0000644000175000017500000006261213023355232016612 0ustar wouterwouterWelcome to the OSC Plugin walkthrough. This is a step by step guide on how to write a plugin for OLA, using the OSC (Open Sound Control) plugin as an example. The OSC plugin uses liblo (http://liblo.sourceforge.net/) to handle the OSC messages. This assumes you have a working knowledge of C++ including references and pointers as well as a basic understanding of the string, map and vector classes. Most of the documentation is inline with the code so please keep it up to date if you change anything. Before we begin you should do the following: * Read https://wiki.openlighting.org/index.php/OLA_developer_info which provides an overview of some of the classes we'll use. * Have an understanding of the map & vector classes from the STL - http://www.sgi.com/tech/stl/ or http://www.cplusplus.com/reference/stl/ . * Know something about the OSC specification: http://opensoundcontrol.org/spec-1_0 . You don't need to know the wire format for the OSC messages. but you should at least recognize OSC addresses and know the different data types in a message. * Look at the liblo site (http://liblo.sourceforge.net/ ) and read the examples. * Get familiar with the string class http://www.cplusplus.com/reference/string/string/, since we use that a bit. * Basic knowledge of shell scripting, which is used in the ./configure script. * Make sure you can complete a full OLA build & test cycle (make, make check). The initial commit of this plugin was Rev b9d6a47e9a2586d51dac521d7532fb11d76e0ae5. It's worth having that diff open as you step through the explanations. Let's get to it. If you make it all the way through this doc and I ever meet you in person I'll buy you a beer! Chapter 1, Build Configuration ============================== Before we start writing code, we need to configure the build system. Start off by creating the plugins/osc directory. 1.1 Configure script -------------------- Next we need to modify the ./configure script so that we only build the OSC plugin if liblo is installed. So that we don't break existing users of OLA, a system without liblo will just skip building the plugin, rather than causing a failure in the configure script. To be polite, we should also provide a ./configure flag to disable the osc plugin, even if liblo is installed. The ./configure is generated from configure.ac so that's where we'll do our changes. configure.ac is essentially shell script AC_ARG_ENABLE( [osc], AS_HELP_STRING([--disable-osc], [Disable the OSC plugin even if liblo exists])) These lines add a ./configure argument "--disable-osc". If this argument is provided, the variable $enable_liblo will be set to "no". have_liblo="no" This defaults the $have_liblo variable to "no". if test "${enable_osc}" != "no"; then PKG_CHECK_MODULES(liblo, [liblo >= 0.26], [have_liblo="yes"], [true]) fi If the enable_liblo variable does not equal "no" (i.e. --disable-osc) wasn't provided, we go ahead and run pkg-config to check that liblo is installed. The PKG_CHECK_MODULES() macro does the equivalent of: $ pkg-config --modversion liblo To ensure the version of liblo is >= 0.26, and if it's installed, it sets the have_liblo to "yes" and the automake variables liblo_CFLAGS and liblo_LIBS from the output of: $ pkg-config --cflags --libs liblo We'll use liblo_CFLAGS and liblo_LIBS in the Makefile. AM_CONDITIONAL(HAVE_LIBLO, test "${have_liblo}" = "yes") This sets the automake variable HAVE_LIBLO according to the value of have_liblo. This is what controls if we build the osc plugin. if test "${have_liblo}" = "yes"; then PLUGINS="${PLUGINS} osc" AC_DEFINE(HAVE_LIBLO, 1, [define if liblo is installed]) fi Finally if have_liblo is "yes", we append osc to the PLUGINS variable and set a #define HAVE_LIBLO 1. Variables specified in AC_DEFINE are written to the config.h file which can be included as a normal header file. This allows the plugin loader code to know whether to attempt to load the osc plugin. Finally don't forget to add plugins/osc/Makefile to the AC_OUTPUT section at the end. The tells autoconf to write a Makefile for the plugins/osc directory. To summarize, we know have the following: * The automake variable HAVE_LIBLO, which is true if we should build the OSC plugin. * The automake variables liblo_CFLAGS & liblo_LIBS, which contains the compiler and linker options required to use liblo. * A #define'd value HAVE_LIBLO which lets us know within the code if the OSC plugin was built. 1.2 Makefiles ------------- On to the Makefiles. Because we use autoconf / automake the Makefile is generated from Makefile.am. First we edit plugins/Makefile.am and add the osc directory to the SUBDIRS line. Now we can create a plugins/osc/Makefile.am. We'll cover this file line by line. include $(top_srcdir)/common.mk This does what you'd expect, it includes the top level common.mk file, which defines $(COMMON_CXXFLAGS) to include things like -Wall and -Werror. libdir = $(plugindir) This sets the destination install directory for the shared object (the OSC plugin in this case) to the plugin directory. By default that's /usr/local/lib/olad but the user may have changed it. EXTRA_DIST = OSCAddressTemplate.h OSCDevice.h OSCNode.h OSCPlugin.h OSCPort.h \ OSCTarget.h This specifies the header files that need to be included in the tarball. if HAVE_LIBLO Everything from this point onwards is only run if HAVE_LIBLO was true. noinst_LTLIBRARIES = libolaoscnode.la libolaoscnode_la_SOURCES = OSCAddressTemplate.cpp OSCNode.cpp libolaoscnode_la_CXXFLAGS = $(COMMON_CXXFLAGS) $(liblo_CFLAGS) libolaoscnode_la_LIBADD = $(liblo_LIBS) This sets up our first build target, a shared library called libolaoscnode.la. This library contains the OSCNode class, along with the functions in OSCAddressTemplate.cpp. The libolaoscnode.la is a helper library, it's not installed when the user runs `make install` (the noinst_ prefix does this) but it simplifies the build rules since both the OSC plugin and the tests depend on it. Because we depend on liblo we need to add liblo_CFLAGS and liblo_LIBS to the appropriate lines. lib_LTLIBRARIES = libolaosc.la libolaosc_la_SOURCES = OSCDevice.cpp OSCPlugin.cpp libolaosc_la_CXXFLAGS = $(COMMON_CXXFLAGS) $(liblo_CFLAGS) libolaosc_la_LIBADD = libolaoscnode.la Here is our llibolaosc.la plugin. This contains code from OSCDevice.cpp and OSCPlugin.cpp. Note that because the code in OSCPort is simple, all the code lives in OSCPort.h and there is no corresponding .cpp file. If there was we'd need to list it here as well. This depends on the libolaoscnode.la helper library. if BUILD_TESTS TESTS = OSCTester endif On to the tests, These three lines add the OSCTester program to the list of tests to execute when `make check` is run. If the user ran ./configure with --disable-unittests we don't build or run any of the unittesting code. check_PROGRAMS = $(TESTS) This sets check_PROGRAMS to what's contained in the $TESTS variable. OSCTester_SOURCES = OSCAddressTemplateTest.cpp \ OSCNodeTest.cpp \ OSCTester.cpp OSCTester_CXXFLAGS = $(COMMON_CXXFLAGS) $(CPPUNIT_CFLAGS) OSCTester_LDADD = $(CPPUNIT_LIBS) \ libolaoscnode.la \ ../../common/libolacommon.la \ ../../common/testing/libolatesting.la Here are the rules OSCTester. This specifies the 3 source files as well as the libraries the code depends on. endif This completes the "if HAVE_LIBLO" from above. 1.3 Putting it together ----------------------- At this point you can move back to the top level directory and run the following: autoreconf This creates the ./configure script, which we'll now run: ./configure If you watch the output you should see the line "checking for liblo... yes". You should also see that HAVE_LIBLO is #defined to 1 in the config.h file and that the plugins/osc/Makefile has been created. That's it for the build configuration. Time to write some code! Chapter 2, Plugin Boilerplate ============================= 2.1 Plugin ID ------------- We need to reserve a plugin ID in common/protocol/Ola.proto . Before you pick a plugin id please send a message to the open-lighting@googlegroups.com list so we can co-ordinate plugin IDs. Once we've assigned a plugin id, we can run `make` in the top directory. This will update include/ola/plugin_id.h. You'll notice plugin_id.h isn't included in the git repo since it's a generated file. 2.2 Plugin Loader ----------------- We need to tell the Plugin Loader to load our new OSC plugin. Remember the HAVE_LIBLO variable in config.h? We'll make use of that now. In olad/DynamicPluginLoader.cpp we add: #ifdef HAVE_LIBLO #include "plugins/osc/OSCPlugin.h" #endif // HAVE_LIBLO DynamicPluginLoader.cpp includes config.h at the top of the file, which is how HAVE_LIBLO is defined. #ifdef HAVE_LIBLO m_plugins.push_back( new ola::plugin::osc::OSCPlugin(m_plugin_adaptor)); #endif // HAVE_LIBLO If HAVE_LIBLO is defined, we go ahead and add the OSCPlugin to the vector of plugins to load. That's it for the boilerplate Chapter 3, Helper Code ====================== The OSC code is divided into two parts: - OSCNode is a C++ & DMX orientated wrapper around liblo. - OSCPlugin, OSCDevice & OSCPort are the glue between OLA and the OSCNode. There is a little bit of support code that is used in both parts, so we factor that out here. 3.1 OSCTarget ------------- OSCTarget.h contains a struct used to represent OSC targets. Each target has an IP & UDP Port, along with a string that holds the OSC address for the target. We also provide three constructors to help us create OSCTarget structs. The first is the default constructor, the second is the copy constructor and the third takes an IPV4SocketAddress and string and initializes the member variables. Notice in the second constructor we pass both the IPV4SocketAddress and string by (const) reference. If we passed by value (the default) we'd incur a copy of the IPV4SocketAddress / string class. A good string implementation this would avoid copying the actual string data and rather just copy the internal members of the string class. However even that is likely to be more expensive than taking a reference, so we pass strings by const reference wherever possible. You'll notice that all the OSC code is contained within the ola::plugin::osc namespace. This is to avoid conflicts with the core OLA classes and code in other plugins. 3.2 ExpandTemplate() -------------------- OSCAddressTemplate.h provides a single method, ExpandTemplate() which behaves a bit like printf. Why don't we just use printf you ask? Because the strings to expand are provided in the config file by the user and using printf for user specified strings is dangerous (see http://www.cis.syr.edu/~wedu/Teaching/cis643/LectureNotes_New/Format_String.pdf). At this point it's worth mentioning testing. Have a look at the OSCAddressTemplateTest.cpp file. We define a single test method testExpand that confirms ExpandTemplate() behaves as we expect. If you're in the mood for experimentation, change output.find("%d"); to output.find_first_of("%d"); Watch the tests fail and make sure you understand why. Chapter 4, OSCNode ================== As mentioned, OSCNode is the C++ wrapper around liblo. It uses the OLA network & IO classes so that it integrates nicely with OLA. As one would expect, the code is split across OSCNode.h and OSCNode.cpp 4.1 OSCNode.h -------------- Lets step through the interface to the OSCNode class. First we include all the headers we're going to depend on. Since all our code exists in the ola::plugin::osc namespace, we need to either add "using ..." directives or fully qualify the data types in the rest of the file. Generally if I'm going to use a data type more than once in a file I'll typically add a using directive. Options Structure ----------------- The OSCNode constructor takes a const reference to a OSCNodeOptions structure. Often the number of options passed to a constructor grows over the lifetime of the code. Consider a class Foo, which starts off with: Foo(const string &option1, int option2); Then at some later date, someone added another int and a bool option: Foo(const string &option1, int option2, int option3, bool option4); At this point you need to update all the caller of Foo(...). It gets even worse we people start adding default values: Foo(const string &option1, int option2, int option3, bool option4, bool option5 = false, bool option6 = true); Now if the caller wants to set option6 to false, they need to set option5 as well. This leads to buggy code. Passing in an options struct avoids this. The constructor can set the default values for all options and then the callers can override the options they are interested in. More options can then be added at a later stage without having to update all the callers. The downside to using an option struct is that mandatory options can be omitted, We could add a IsValid() method on the options struct to check for this, but it's not worth it in this case. Ok, back to the code, the next line typedefs a Callback1 to DMXCallback. This shortens the code a bit, shorter code is usually easier to understand. The OSCNode constructor takes a SelectServer, ExportMap as well as the previously described options struct. Methods ------- The Init() and Stop() methods are self explanatory. Sending Data ------------ The next three methods (AddTarget, RemoveTarget & SendData) are used for sending DMX data using OSC. To ease the burden on the caller, we group OSCTargets into groups (one target may exist in more than one group but that's rare). In OLA, each group can be thought of as a universe. Groups are identified by their group_id, which is just an integer. AddTarget(id, target) associates a target with a group. RemoveTarget does the opposite. SendData(id, dmx_data) sends the DMX data to all members of the group. Receiving Data -------------- The RegisterAddress() method is used for receiving DMX data over OSC. It takes an osc_address (e.g. /dmx/universe/1), and a callback. Whenever OSC data is received for the given address, the callback is invoked and passed the DMX data. When the callback argument to RegisterAddress() is NULL the osc_address is un-registered. Finally HandleDMXData() is a method called by liblo. Private Types, Variables & Methods ---------------------------------- Let's go over the internal data members of the OSCNode class. NodeOSCTarget is derived from OSCTarget. It includes a lo_address member. We do this because liblo doesn't provide a way to create lo_addresses from a socket address, rather lo_address_new() takes strings, and then calls inet_aton to convert to the network data types. We don't want to incur this overhead ever time we send a packet, so we create the lo_address object once for each target in AddTarget(). Next we have three typedefs, which are used with our internal data structures. On the sending side, we need to track a collection of OSCTargets for each group. We do this with a map of vectors, so you can think of it like this: Group 1 -> [ target1, target2, target3 ], Group 2 -> [ target4 ] We could have used a set rather than a vector to hold the NodeOSCTarget objects, but then we'd need to define a < operator since the set container stores it's elements in sorted order. Using a set would also require us to store the objects directly rather than pointers to the objects, This would incur additional copying when elements are inserted into the set but since we only do this once when the plugin starts and the number of elements (OSC Targets) is small it wouldn't matter. We typedef a vector of pointers to NodeOSCTargets to OSCTargetVector, and then typedef a map of unsigned ints to pointers to OSCTargetVectors as a OSCTargetMap. On the receiving side, we have a map of OSC addresses to callbacks: "/dmx/universe/8" -> "/dmx/universe/9 -> We typedef a map of strings to callback objects to AddressCallbackMap. That's it for the types, the members are documented in the OSCNode.h file itself. We store pointers to the SelectServer and ExportMap objects passed in to the constructor as well as the UDP port to listen on. We also hold a pointer to a UnmanagedFileDescriptor which is how we add the socket description used by liblo to the SelectServer. There is also the lo_server data, as well as the OSCTargetMap and AddressCallbackMap discussed above. On Windows, we need to create an UnmanagedSocketDescriptor instead. The DescriptorReady method is called when the liblo socket description has data pending. Finally there are two static variables, DEFAULT_OSC_PORT which is the default UDP port to listen on and OSC_PORT_VARIABLE, which is what we use with the ExportMap. 4.2 OSCNode.cpp --------------- Onwards to the implementation! Most of this is documented in the file itself so I'll just point out the interesting bits. void OSCErrorHandler(int error_code, const char *msg, const char *stack) The call to lo_server_new_with_proto() takes a pointer to a function which is called when liblo wants to log an error message. We pass a pointer to OSCErrorHandler which uses the OLA logging mechanism. OSCDataHandler is what liblo calls when there is new OSC data. The last argument is a pointer back to the OSCNode object, so after we perform some checks we call HandleDMXData(). We return 0 so that liblo doesn't try to find other OSC handlers to process the same data (see the liblo API for more info on this). In the OSCNode constructor, if an ExportMap was provided, we export the UDP port that liblo is listening on. If olad is built with the web server then users can navigate to http://:9090/debug and see the internal state of the server. The ExportMap provides an easy method to export this internal state, and we should really make more use of it since it's incredibly valuable for debugging. The destructor just calls Stop(). Note that Stop() may have been called previously, so we need to account for that. The Init method sets up the node. It creates a new lo_server and associates the socket description with the SelectServer. Stop deletes any of the entries in the OSCTargetMap and AddressCallbackMap, cleans up the socket description and frees the lo_server. It's important to clear both maps once the entries have been deleted since Stop() may be called more than once. Similarly, once the UnmanagedFileDescriptor and lo_server have been freed we set both of them to NULL. SendData() packs the DmxBuffer into a lo_blob variable. We use OSC blobs for transporting DMX over OSC. It then calls lo_send_from for each target in the group. Chapter 5, Testing ================== Congratulations, at this point we're more than half way through. Let's take a detour and discuss about testing. All good code comes with tests and OLA is no exception. Well written tests increases the chance of having your plugin accepted into OLA. The OSCNodeTest.cpp contains the unittests for the OSCNode class. To test the node, we create a second UDP socket (liblo creates the first one) which we then use to send and receive OSC messages. For each test we register a timeout which aborts the test after ABORT_TIMEOUT_IN_MS. This prevents the test from hanging if the packets are dropped (which they shouldn't be since it's all localhost communication). In this test code we just use OLA_ASSERT_TRUE. ola/testing/TestUtils.h provides many more testing macros so take a look. Finally we need the OSCTester.cpp to pull it all together. This is just boiler plate code that sets up the unittests. Chapter 6, Plugins, Devices & Ports =================================== Now it's just a matter of building the OLA classes around the OSCNode. In OLA a Plugin creates objects of the Device type (if you use Java or other Object Orientated languages think of the Plugin class as a factory). Each device then has one of more input and output ports. For the OSC plugin, we allow the user to specify the number of input and output ports to create in the config file. Each input port is assigned an OSC address (e.g. /dmx/universe or /foo/bar). If '%d' occurs in the OSC address it's replaced by the current universe number. The default OSC address for each port is "/dmx/universe/%d" so the default behavior is sane. Each output port is configured with a list of OSC Targets in the form ip:port/address. 6.1 Plugin ---------- The OSCPlugin is pretty simple. like all OLA plugins, it inherits from the base ola::Plugin class. It's passed a pointer to a PluginAdaptor object, which is how the plugins interface with the rest of OLA. We'll cover the methods in a different order from which they appear in the file, since I think it makes more sense. Description() just returns a string which contains a description for the Plugin. This is what appears in the output of ola_plugin_info or on the web page under the 'Plugins' menu. It should explain what the plugin does, as well as the configuration options available. SetDefaultPreferences() is used to initialize the config file. It should check if configuration options exist, and if they don't reset them to default values. We use a bool to keep track if any of the options have changed, since if they do we need to write out the changes. Once SetDefaultPreferences() is called, the next method to run is StartHook(). This reads the configuration options, extracts the OSCTargets from the string (by calling ExtractOSCTarget()) and adds them to a vector. Once the configuration options have been processed we create a new OSCDevice, call Start() and register it with OLA. The StopHook() method unregisters the device and deletes it. GetPortCount() is a helper method to save duplicating similar code more than once. ExtractOSCTarget unpacks a string in the form "ip:port/address" into a OSCTarget structure. 6.2 Device ---------- Like the Plugin, the device is also pretty simple. Each OSCDevice owns a OSCNode object. In the constructor, the OSCDevice takes a pointer to the plugin which created the device, as well as the UDP port to listen on, and a list of addresses (for the input ports) and targets (for the output ports). These data structures are saved as member variables since they are required in StartHook(). The OSCDevice uses the static ID of 1, which means we can only ever have one OSCDevice. This is probably fine unless people are doing fancy things with multiple network interfaces. AllowMultiPortPatching() returns true, which means that multiple ports of the same type can be patched to the same universe. This is fine because the RegisterAddress method in OSCNode detects if we try to register the same address more than once. The only interesting method is StartHook(). This calls Init on the OSCNode and then sets up the ports. We call Init() from within StartHook() rather than in the constructor so that we can propagate a failure up the call change (constructors don't have return values so there is no way to notify the caller of an error). In general it's best to avoid any code that may fail in a constructor. StartHook iterates over the vector of addresses and creates an OSCInputPort for each. Similarly it iterates over the vector of vectors contains OSCTargets and sets up an OSCOutputPort for each. For both the input and output ports we create a description string which shows up in ola_dev_info and on the web UI. For the input port this is the OSC address they are listening on, for the output ports it's the list of OSC targets it's sending to. 6.3 Ports --------- Since there isn't much code for the Port classes I put it all in OSCPort.h rather than splitting over two files. The OSCInputPort is the more complex of the two. Firstly the PreSetUniverse() method is called, which is where we Register a callback with the OSCNode (if needed). If the registration fails (say another port has the same address) we return false, and OLA informs the user that patching failed. We also need to handle the unpatch case, where the new_universe argument will be NULL. In this case we call RegisterAddress and pass a NULL as the callback argument which unregisters the address. The callback passed to RegisterAddress() runs the NewDMXData() method, which copies the DmxBuffer values into the port's internal buffer and calls DmxChanged(). This notifies the universe that the port is bound to that new data has arrived. The universe then calls ReadDMX() to collect the new data. OSCOutput port is much more simple, when the WriteDMX() method is called we call SendData() on the OSCNode object. Note that our simple DMX over OSC format has no notion of priority, so we ignore the priority argument. Chapter 7, Wrapping Up ====================== That's it for the code. At this point you can change back to the top level directory and run `make` to build the new plugin. Running `make check` will run all the unittests. While you're developing, you'll find it quicker to run `make` and `make check` within the directory you're changing. Just remember to run it at the top level every so often or before trying to run olad. Chapter 8, Final Words ====================== 8.1 Code Style -------------- Just a couple more points to wrap things up. As mentioned into README.developer, OLA uses the Google C++ style guide (http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml) There is a tool, cpplint.py which will check the code for style violations. See README.developer for more information. 8.2 Memory Leaks ---------------- Valgrind is an excellent tool for discovering and debugging memory leaks. You can find out more at http://valgrind.org/. ola-0.10.5.nojsmin/plugins/osc/OSCNode.cpp0000644000175000017500000004603313023355232017667 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OSCNode.cpp * A self contained object for sending and receiving OSC messages. * Copyright (C) 2012 Simon Newton */ #ifdef _WIN32 #include #endif // _WIN32 #include #include #include #include #include #include #include #include #include #include #include "plugins/osc/OSCNode.h" namespace ola { namespace plugin { namespace osc { #ifdef _WIN32 class UnmanagedSocketDescriptor : public ola::io::UnmanagedFileDescriptor { public: explicit UnmanagedSocketDescriptor(int fd) : ola::io::UnmanagedFileDescriptor(fd) { m_handle.m_type = ola::io::SOCKET_DESCRIPTOR; // Set socket to nonblocking to enable WSAEventSelect u_long mode = 1; ioctlsocket(fd, FIONBIO, &mode); } private: DISALLOW_COPY_AND_ASSIGN(UnmanagedSocketDescriptor); }; #endif // _WIN32 using ola::IntToString; using ola::io::SelectServerInterface; using std::make_pair; using std::max; using std::min; using std::string; using std::vector; const char OSCNode::OSC_PORT_VARIABLE[] = "osc-listen-port"; /* * The Error handler for the OSC server. */ void OSCErrorHandler(int error_code, const char *msg, const char *stack) { string msg_str, stack_str; if (msg) { msg_str.assign(msg); } if (stack) { stack_str.assign(stack); } OLA_WARN << "OSC Error. Code " << error_code << ", " << msg_str << ", " << stack_str; } /** * Extract the slot number and group address from an OSC address */ bool ExtractSlotFromPath(const string &osc_address, string *group_address, uint16_t *slot) { size_t pos = osc_address.find_last_of("/"); if (pos == string::npos) { OLA_WARN << "Got invalid OSC message to " << osc_address; return false; } if (!StringToInt(osc_address.substr(pos + 1), slot, true)) { OLA_WARN << "Unable to extract slot from " << osc_address.substr(pos + 1); return false; } if (*slot == 0 || *slot > DMX_UNIVERSE_SIZE) { OLA_WARN << "Ignoring slot " << *slot; return 0; } (*slot)--; *group_address = osc_address.substr(0, pos); return true; } /** * Extract the slot and value from a tuple (either ii or if) */ bool ExtractSlotValueFromPair(const string &type, lo_arg **argv, int argc, uint16_t *slot, uint8_t *value) { if (argc != 2 || !(type == "ii" || type == "if")) { OLA_WARN << "Unknown OSC message type " << type; return false; } int raw_slot = argv[0]->i; if (raw_slot <= 0 || raw_slot > DMX_UNIVERSE_SIZE) { OLA_WARN << "Invalid slot # " << raw_slot; return false; } *slot = static_cast(raw_slot - 1); if (type == "ii") { *value = min(static_cast(DMX_MAX_SLOT_VALUE), max(0, argv[1]->i)); } else if (type == "if") { float val = max(0.0f, min(1.0f, argv[1]->f)); *value = val * DMX_MAX_SLOT_VALUE; } return true; } /** * Called when liblo receives data. * @param osc_address the OSC Address this data was sent to * @param types the OSC data type for the data * @param argv the data itself * @param argc the number of data blocks * @param user_data a pointer to the OSCNode object. */ int OSCDataHandler(const char *osc_address, const char *types, lo_arg **argv, int argc, void *, void *user_data) { OLA_DEBUG << "Got OSC message for " << osc_address << ", types are " << types; OSCNode *node = reinterpret_cast(user_data); const string type(types); uint16_t slot; if (argc == 1) { if (type == "b") { lo_blob blob = argv[0]; unsigned int size = min(static_cast(DMX_UNIVERSE_SIZE), lo_blob_datasize(blob)); node->SetUniverse( osc_address, static_cast(lo_blob_dataptr(blob)), size); return 0; } else if (type == "f") { float val = max(0.0f, min(1.0f, argv[0]->f)); string group_address; if (!ExtractSlotFromPath(osc_address, &group_address, &slot)) return 0; node->SetSlot(group_address, slot, val * DMX_MAX_SLOT_VALUE); return 0; } else if (type == "i") { int val = min(static_cast(DMX_MAX_SLOT_VALUE), max(0, argv[0]->i)); string group_address; if (!ExtractSlotFromPath(osc_address, &group_address, &slot)) return 0; node->SetSlot(group_address, slot, val); return 0; } } else if (argc == 2) { uint8_t value; if (!ExtractSlotValueFromPair(type, argv, argc, &slot, &value)) { return 0; } node->SetSlot(osc_address, slot, value); return 0; } OLA_WARN << "Unknown OSC message type " << type; return 0; } OSCNode::NodeOSCTarget::NodeOSCTarget(const OSCTarget &target) : socket_address(target.socket_address), osc_address(target.osc_address), liblo_address(lo_address_new( socket_address.Host().ToString().c_str(), IntToString(socket_address.Port()).c_str())) { } OSCNode::NodeOSCTarget::~NodeOSCTarget() { lo_address_free(liblo_address); } /** * Create a new OSCNode. * @param ss the SelectServer to use * @param export_map a pointer to an ExportMap (may be NULL) * @param options the OSCNodeOptions */ OSCNode::OSCNode(SelectServerInterface *ss, ExportMap *export_map, const OSCNodeOptions &options) : m_ss(ss), m_listen_port(options.listen_port), m_osc_server(NULL) { if (export_map) { // export the OSC listening port if we have an export map ola::IntegerVariable *osc_port_var = export_map->GetIntegerVar(OSC_PORT_VARIABLE); osc_port_var->Set(options.listen_port); } } /** * Cleanup */ OSCNode::~OSCNode() { Stop(); } /* * Setup the Node */ bool OSCNode::Init() { // create a new lo_server // lo_server_new_with_proto doesn't understand that "0" means "any port". // Instead you have to pass in NULL. Weird. if (m_listen_port) { m_osc_server = lo_server_new_with_proto(IntToString(m_listen_port).c_str(), LO_UDP, OSCErrorHandler); } else { m_osc_server = lo_server_new_with_proto(NULL, LO_UDP, OSCErrorHandler); } if (!m_osc_server) return false; // Get the socket descriptor that liblo is using, create a // UnmanagedFileDescriptor, assign a callback and register with the // SelectServer. int fd = lo_server_get_socket_fd(m_osc_server); #ifdef _WIN32 m_descriptor.reset(new UnmanagedSocketDescriptor(fd)); #else m_descriptor.reset(new ola::io::UnmanagedFileDescriptor(fd)); #endif // _WIN32 m_descriptor->SetOnData(NewCallback(this, &OSCNode::DescriptorReady)); m_ss->AddReadDescriptor(m_descriptor.get()); // liblo doesn't support address pattern matching. So rather than registering // a bunch of handlers, we just register for any address matching the types // we want, and handle the dispatching ourselves. NULL means 'any address' // Similarly liblo tries to coerce types so rather than letting it do // anything we just register for all types and sort it out ourselves. lo_server_add_method(m_osc_server, NULL, NULL, OSCDataHandler, this); return true; } /** * Stop this node. This removes all registrations and targets. */ void OSCNode::Stop() { if (m_osc_server) { lo_server_del_method(m_osc_server, NULL, NULL); } // Clean up the m_output_map map OutputGroupMap::iterator group_iter = m_output_map.begin(); for (; group_iter != m_output_map.end(); ++group_iter) { STLDeleteElements(&group_iter->second->targets); delete group_iter->second; } m_output_map.clear(); // Delete all the RX callbacks. STLDeleteValues(&m_input_map); if (m_descriptor.get()) { // if there was an UnmanagedFileDescriptor, de-register from the // SelectServer and delete it. m_ss->RemoveReadDescriptor(m_descriptor.get()); m_descriptor.reset(); } if (m_osc_server) { // If there was an lo_server then free it. lo_server_free(m_osc_server); m_osc_server = NULL; } } /** * Add a target for a particular group. * @param group the group to add this target to * @param target the OSC address for the target */ void OSCNode::AddTarget(unsigned int group, const OSCTarget &target) { OSCOutputGroup *output_group = STLFindOrNull(m_output_map, group); if (!output_group) { // not found, create a new one output_group = new OSCOutputGroup(); STLReplaceAndDelete(&m_output_map, group, output_group); } OSCTargetVector &targets = output_group->targets; // Check if this target already exists in the group. If it does log a warning // and return OSCTargetVector::iterator target_iter = targets.begin(); for (; target_iter != targets.end(); ++target_iter) { if (**target_iter == target) { OLA_WARN << "Attempted to add " << target.socket_address << target.osc_address << " twice"; return; } } // Add to the list of targets output_group->targets.push_back(new NodeOSCTarget(target)); } /** * De-Register a target from this group. * @param group the group to remove the target from * @param target the OSCTarget to remove * @returns true if the target was removed, false if it wasn't in the group */ bool OSCNode::RemoveTarget(unsigned int group, const OSCTarget &target) { OSCOutputGroup *output_group = STLFindOrNull(m_output_map, group); if (!output_group) { return false; } OSCTargetVector &targets = output_group->targets; OSCTargetVector::iterator target_iter = targets.begin(); for (; target_iter != targets.end(); ++target_iter) { if (**target_iter == target) { // the target was found, delete the NodeOSCTarget and remove the entry // from the vector. delete *target_iter; targets.erase(target_iter); return true; } } return false; } /** * Send the DMX data to all targets registered for this group. * @param group the group to send the data to * @param data_format the format of data to send * @param dmx_data the DmxBuffer to send * @returns true if sucesfully sent, false if any error occured. */ bool OSCNode::SendData(unsigned int group, DataFormat data_format, const ola::DmxBuffer &dmx_data) { OSCOutputGroup *output_group = STLFindOrNull(m_output_map, group); if (!output_group) { OLA_WARN << "failed to find " << group; // group doesn't exist, just return return false; } switch (data_format) { case FORMAT_BLOB: return SendBlob(dmx_data, output_group->targets); case FORMAT_INT_INDIVIDUAL: return SendIndividualInts(dmx_data, output_group); case FORMAT_INT_ARRAY: return SendIntArray(dmx_data, output_group->targets); case FORMAT_FLOAT_INDIVIDUAL: return SendIndividualFloats(dmx_data, output_group); case FORMAT_FLOAT_ARRAY: return SendFloatArray(dmx_data, output_group->targets); default: OLA_WARN << "Unimplemented data format"; return false; } } /** * Register a callback to be run when we receive data for an address. * De-registration can be performed by passing NULL as a callback. Attempting * to register more than once on the same address will return false. * @param osc_address the OSC address to register. * @param callback the callback to run, ownership is transferred. The callback * can be set to NULL to de-register. * @returns false if callback was non-NULL, but the address was already * registered. true otherwise. */ bool OSCNode::RegisterAddress(const string &osc_address, DMXCallback *callback) { if (callback) { // register OSCInputGroup *universe_data = STLFindOrNull(m_input_map, osc_address); if (universe_data) { OLA_WARN << "Attempt to register a second callback for " << osc_address; // delete the callback, since we have ownership of it delete callback; return false; } else { // This is a new registration, insert into the AddressCallbackMap and // register with liblo. m_input_map.insert( make_pair(osc_address, new OSCInputGroup(callback))); } } else { // deregister STLRemoveAndDelete(&m_input_map, osc_address); } return true; } /** * Called by OSCDataHandler when there is new data. * @param osc_address the OSC address this data arrived on * @param data the DmxBuffer containing the data. * @param size the number of slots. */ void OSCNode::SetUniverse(const string &osc_address, const uint8_t *data, unsigned int size) { OSCInputGroup *universe_data = STLFindOrNull(m_input_map, osc_address); if (!universe_data) return; universe_data->dmx.Set(data, size); if (universe_data->callback.get()) { universe_data->callback->Run(universe_data->dmx); } } /** * Called by OSCDataHandler when there is new data. * @param osc_address the OSC address this data arrived on * @param slot the slot offset to set. * @param value the DMX value for the slot */ void OSCNode::SetSlot(const string &osc_address, uint16_t slot, uint8_t value) { OSCInputGroup *universe_data = STLFindOrNull(m_input_map, osc_address); if (!universe_data) return; universe_data->dmx.SetChannel(slot, value); if (universe_data->callback.get()) { universe_data->callback->Run(universe_data->dmx); } } /** * Return the listening port. Will be 0 if the node isn't setup. */ uint16_t OSCNode::ListeningPort() const { if (m_osc_server) { return lo_server_get_port(m_osc_server); } return 0; } /** * Called when the OSC FD is readable. */ void OSCNode::DescriptorReady() { // Call into liblo with a timeout of 0 so we don't block. lo_server_recv_noblock(m_osc_server, 0); } /** * Send a DMXBuffer as a blob to a set of targets */ bool OSCNode::SendBlob(const DmxBuffer &dmx_data, const OSCTargetVector &targets) { // create the new OSC blob lo_blob osc_data = lo_blob_new(dmx_data.Size(), dmx_data.GetRaw()); bool ok = true; // iterate over all the targets, and send to each one. OSCTargetVector::const_iterator target_iter = targets.begin(); for (; target_iter != targets.end(); ++target_iter) { OLA_DEBUG << "Sending to " << (*target_iter)->socket_address; int ret = lo_send_from((*target_iter)->liblo_address, m_osc_server, LO_TT_IMMEDIATE, (*target_iter)->osc_address.c_str(), "b", osc_data, LO_ARGS_END); ok &= (ret > 0); } // free the blob lo_blob_free(osc_data); return ok; } /** * Send a DMXBuffer as individual float messages to a set of targets. */ bool OSCNode::SendIndividualFloats(const DmxBuffer &dmx_data, OSCOutputGroup *group) { return SendIndividualMessages(dmx_data, group, "f"); } /** * Send a DMXBuffer as individual int messages to a set of targets. */ bool OSCNode::SendIndividualInts(const DmxBuffer &dmx_data, OSCOutputGroup *group) { return SendIndividualMessages(dmx_data, group, "i"); } /** * Send the DmxBuffer as an array of ints. */ bool OSCNode::SendIntArray(const DmxBuffer &dmx_data, const OSCTargetVector &targets) { lo_message message = lo_message_new(); for (size_t i = 0; i < dmx_data.Size(); ++i) { lo_message_add_int32(message, dmx_data.Get(i)); } bool ok = SendMessageToTargets(message, targets); lo_message_free(message); return ok; } /** * Send the DmxBuffer as an array of normalized floats. */ bool OSCNode::SendFloatArray(const DmxBuffer &dmx_data, const OSCTargetVector &targets) { lo_message message = lo_message_new(); for (size_t i = 0; i < dmx_data.Size(); ++i) { lo_message_add_float(message, dmx_data.Get(i) / 255.0f); } bool ok = SendMessageToTargets(message, targets); lo_message_free(message); return ok; } /** * Send an lo_message to each target in a set. * @param message the lo_message to send. * @param targets the list of targets to send the message to. */ bool OSCNode::SendMessageToTargets(lo_message message, const OSCTargetVector &targets) { bool ok = true; OSCTargetVector::const_iterator target_iter = targets.begin(); for (; target_iter != targets.end(); ++target_iter) { int ret = lo_send_message_from( (*target_iter)->liblo_address, m_osc_server, (*target_iter)->osc_address.c_str(), message); ok &= (ret > 0); } return ok; } /** * Send individual messages (one slot per message) to a set of targets. * @param dmx_data the DmxBuffer to send * @param group the OSCOutputGroup with the targets. * @param osc_type the type of OSC message, either "i" or "f" */ bool OSCNode::SendIndividualMessages(const DmxBuffer &dmx_data, OSCOutputGroup *group, const string &osc_type) { bool ok = true; const OSCTargetVector &targets = group->targets; vector messages; // We only send the slots that have changed. for (unsigned int i = 0; i < dmx_data.Size(); ++i) { if (i > group->dmx.Size() || dmx_data.Get(i) != group->dmx.Get(i)) { SlotMessage message = {i, lo_message_new()}; if (osc_type == "i") { lo_message_add_int32(message.message, dmx_data.Get(i)); } else { lo_message_add_float(message.message, dmx_data.Get(i) / 255.0f); } messages.push_back(message); } } group->dmx.Set(dmx_data); // Send all messages to each target. OSCTargetVector::const_iterator target_iter = targets.begin(); for (; target_iter != targets.end(); ++target_iter) { OLA_DEBUG << "Sending to " << (*target_iter)->socket_address; vector::const_iterator message_iter = messages.begin(); for (; message_iter != messages.end(); ++message_iter) { std::ostringstream path; path << (*target_iter)->osc_address << "/" << message_iter->slot + 1; int ret = lo_send_message_from((*target_iter)->liblo_address, m_osc_server, path.str().c_str(), message_iter->message); ok &= (ret > 0); } } // Clean up the messages. vector::iterator message_iter = messages.begin(); for (; message_iter != messages.end(); ++message_iter) { lo_message_free(message_iter->message); } return ok; } } // namespace osc } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/osc/OSCPlugin.h0000644000175000017500000000522213023355232017700 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OSCPlugin.h * Interface for the OSC plugin. * Copyright (C) 2012 Simon Newton */ #ifndef PLUGINS_OSC_OSCPLUGIN_H_ #define PLUGINS_OSC_OSCPLUGIN_H_ #include #include "olad/Plugin.h" #include "ola/plugin_id.h" #include "plugins/osc/OSCDevice.h" #include "plugins/osc/OSCTarget.h" namespace ola { namespace plugin { namespace osc { class OSCDevice; class OSCPlugin: public ola::Plugin { public: explicit OSCPlugin(ola::PluginAdaptor *plugin_adaptor): ola::Plugin(plugin_adaptor), m_device(NULL) {} std::string Name() const { return PLUGIN_NAME; } std::string Description() const; ola_plugin_id Id() const { return OLA_PLUGIN_OSC; } std::string PluginPrefix() const { return PLUGIN_PREFIX; } private: bool StartHook(); bool StopHook(); bool SetDefaultPreferences(); unsigned int GetPortCount(const std::string &key) const; bool ExtractOSCTarget(const std::string &str, OSCTarget *target); void SetDataFormat(const std::string &format_option, OSCDevice::PortConfig *port_config); OSCDevice *m_device; static const uint8_t DEFAULT_PORT_COUNT = 5; static const uint16_t DEFAULT_UDP_PORT = 7770; static const char DEFAULT_ADDRESS_TEMPLATE[]; static const char DEFAULT_TARGETS_TEMPLATE[]; static const char INPUT_PORT_COUNT_KEY[]; static const char OUTPUT_PORT_COUNT_KEY[]; static const char PLUGIN_NAME[]; static const char PLUGIN_PREFIX[]; static const char PORT_ADDRESS_TEMPLATE[]; static const char PORT_TARGETS_TEMPLATE[]; static const char PORT_FORMAT_TEMPLATE[]; static const char UDP_PORT_KEY[]; static const char BLOB_FORMAT[]; static const char FLOAT_ARRAY_FORMAT[]; static const char FLOAT_INDIVIDUAL_FORMAT[]; static const char INT_ARRAY_FORMAT[]; static const char INT_INDIVIDUAL_FORMAT[]; }; } // namespace osc } // namespace plugin } // namespace ola #endif // PLUGINS_OSC_OSCPLUGIN_H_ ola-0.10.5.nojsmin/plugins/osc/OSCAddressTemplate.cpp0000644000175000017500000000315113023355232022055 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OSCAddressTemplate.cpp * Expand a template, substituting values. * Copyright (C) 2012 Simon Newton */ #include #include "ola/StringUtils.h" #include "plugins/osc/OSCAddressTemplate.h" namespace ola { namespace plugin { namespace osc { using std::string; /** * If the string contains %d, replace it with the given value. This only * replaces the first instance of %d. * @param str the template string to use * @param value the value to use as the replacement. * @returns str with %d replaced by value. */ string ExpandTemplate(const string &str, unsigned int value) { string output = str; // find the first instance of "%d" in the string. size_t pos = output.find("%d"); if (pos != string::npos) { // %d was found, perform the replacement. output.replace(pos, 2, IntToString(value)); } return output; } } // namespace osc } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/osc/OSCTarget.h0000644000175000017500000000400713023355232017670 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OSCTarget.h * Represents a IP:Port & OSC Address pair used to direct OSC messages. * Copyright (C) 2012 Simon Newton */ #ifndef PLUGINS_OSC_OSCTARGET_H_ #define PLUGINS_OSC_OSCTARGET_H_ #include #include "ola/network/SocketAddress.h" namespace ola { namespace plugin { namespace osc { struct OSCTarget { ola::network::IPV4SocketAddress socket_address; std::string osc_address; // The default constructor. OSCTarget() {} // The copy constructor OSCTarget(const OSCTarget &target) : socket_address(target.socket_address), osc_address(target.osc_address) { } // A constuctor that initializes the member variables as well. OSCTarget(const ola::network::IPV4SocketAddress &socket_address, const std::string &osc_address) : socket_address(socket_address), osc_address(osc_address) { } std::string ToString() const { return socket_address.ToString() + osc_address; } /** * @brief A helper function to write a OSCTarget to an ostream. * @param out the ostream * @param target the OSCTarget to write. */ friend std::ostream& operator<<(std::ostream &out, const OSCTarget &target) { return out << target.ToString(); } }; } // namespace osc } // namespace plugin } // namespace ola #endif // PLUGINS_OSC_OSCTARGET_H_ ola-0.10.5.nojsmin/plugins/osc/OSCAddressTemplate.h0000644000175000017500000000222613023355232021524 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OSCAddressTemplate.h * Expand a template, substituting values. * Copyright (C) 2012 Simon Newton */ #ifndef PLUGINS_OSC_OSCADDRESSTEMPLATE_H_ #define PLUGINS_OSC_OSCADDRESSTEMPLATE_H_ #include namespace ola { namespace plugin { namespace osc { std::string ExpandTemplate(const std::string &str, unsigned int value); } // namespace osc } // namespace plugin } // namespace ola #endif // PLUGINS_OSC_OSCADDRESSTEMPLATE_H_ ola-0.10.5.nojsmin/plugins/osc/OSCDevice.cpp0000644000175000017500000000653113023355232020200 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OSCDevice.cpp * The OSC Device. * Copyright (C) 2012 Simon Newton */ #include #include #include "ola/Logging.h" #include "ola/io/SelectServerInterface.h" #include "plugins/osc/OSCDevice.h" #include "plugins/osc/OSCPort.h" namespace ola { namespace plugin { namespace osc { using std::string; using std::vector; const char OSCDevice::DEVICE_NAME[] = "OSC Device"; /** * Constructor for the OSCDevice * @param owner the plugin which created this device * @param plugin_adaptor a pointer to a PluginAdaptor object * @param udp_port the UDP port to listen on * @param addresses a list of strings to use as OSC addresses for the input * ports. * @param port_configs config to use for the ports */ OSCDevice::OSCDevice(AbstractPlugin *owner, PluginAdaptor *plugin_adaptor, uint16_t udp_port, const vector &addresses, const PortConfigs &port_configs) : Device(owner, DEVICE_NAME), m_plugin_adaptor(plugin_adaptor), m_port_addresses(addresses), m_port_configs(port_configs) { OSCNode::OSCNodeOptions options; options.listen_port = udp_port; // allocate a new OSCNode but delay the call to Init() until later m_osc_node.reset(new OSCNode(plugin_adaptor, plugin_adaptor->GetExportMap(), options)); } /* * Start this device. * @returns true if the device started successfully, false otherwise. */ bool OSCDevice::StartHook() { bool ok = true; if (!m_osc_node->Init()) return false; // Create an input port for each OSC Address. for (unsigned int i = 0; i < m_port_addresses.size(); ++i) { OSCInputPort *port = new OSCInputPort(this, i, m_plugin_adaptor, m_osc_node.get(), m_port_addresses[i]); if (!AddPort(port)) { delete port; ok = false; } } // Create an output port for each list of OSC Targets. PortConfigs::const_iterator port_iter = m_port_configs.begin(); for (int i = 0; port_iter != m_port_configs.end(); ++port_iter, ++i) { const PortConfig &port_config = *port_iter; if (port_config.targets.empty()) { OLA_INFO << "No targets specified for OSC Output port " << i; continue; } OSCOutputPort *port = new OSCOutputPort(this, i, m_osc_node.get(), port_config.targets, port_config.data_format); if (!AddPort(port)) { delete port; ok = false; } } return ok; } } // namespace osc } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/osc/OSCPort.h0000644000175000017500000000776513023355232017404 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OSCPort.h * The OSCInputPort and OSCOutputPort classes. * Copyright (C) 2012 Simon Newton */ #ifndef PLUGINS_OSC_OSCPORT_H_ #define PLUGINS_OSC_OSCPORT_H_ #include #include #include "olad/Port.h" #include "plugins/osc/OSCAddressTemplate.h" #include "plugins/osc/OSCDevice.h" #include "plugins/osc/OSCNode.h" namespace ola { namespace plugin { namespace osc { /** * @brief The Input Port class, for receiving DMX via OSC. * * Note that the description of the port may change as it's patched and * unpatched from a universe (since the description can contain %d). Therefore * we store the description as a template, as well as the current value. */ class OSCInputPort: public BasicInputPort { public: /** * Create an OSCInputPort. * @param parent the parent device * @param port_id the id for this port * @param plugin_adaptor a PluginAdaptor object, used by the base class. * @param node the OSCNode object to use * @param address the OSC address string for this port */ OSCInputPort(OSCDevice *parent, unsigned int port_id, PluginAdaptor *plugin_adaptor, OSCNode *node, const std::string &address); /** * Just return our DmxBuffer. */ const DmxBuffer &ReadDMX() const { return m_buffer; } /** * Called during the patch process, just before the Universe of this port * changes. */ bool PreSetUniverse(Universe *old_universe, Universe *new_universe); /** * Return the actual description */ std::string Description() const { return m_actual_address; } private: OSCNode *m_node; DmxBuffer m_buffer; const std::string m_address; std::string m_actual_address; /** * This is called when we receive new DMX values via OSC. */ void NewDMXData(const DmxBuffer &data); }; /** * The Output Port class, for sending DMX via OSC. */ class OSCOutputPort: public BasicOutputPort { public: /** * @brief Create an OSCOutputPort. * @param device the parent device * @param port_id the id for this port * @param node the OSCNode object to use * @param targets the OSC targets to send to * @param data_format the format of OSC to send */ OSCOutputPort(OSCDevice *device, unsigned int port_id, OSCNode *node, const std::vector &targets, OSCNode::DataFormat data_format); ~OSCOutputPort(); /** * Called during the patch process, just before the Universe of this port * changes. */ bool PreSetUniverse(Universe *old_universe, Universe *new_universe); /** * @brief Send this DMX buffer using OSC. The second argument (priority) is not * used. * @param buffer the DMX data */ bool WriteDMX(const DmxBuffer &buffer, uint8_t) { return m_node->SendData(this->PortId(), m_data_format, buffer); } /** * Return the description for this port */ std::string Description() const { return m_description; } private: OSCNode *m_node; const std::vector m_template_targets; std::vector m_registered_targets; std::string m_description; OSCNode::DataFormat m_data_format; void RemoveTargets(); void SetUnpatchedDescription(); }; } // namespace osc } // namespace plugin } // namespace ola #endif // PLUGINS_OSC_OSCPORT_H_ ola-0.10.5.nojsmin/plugins/osc/OSCPlugin.cpp0000644000175000017500000002171413023355232020237 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OSCPlugin.cpp * The OSC plugin for ola. This creates a single OSC device. * Copyright (C) 2012 Simon Newton */ #define __STDC_LIMIT_MACROS // for UINT8_MAX & friends #include #include #include #include #include #include #include #include "ola/StringUtils.h" #include "olad/PluginAdaptor.h" #include "olad/Preferences.h" #include "plugins/osc/OSCAddressTemplate.h" #include "plugins/osc/OSCDevice.h" #include "plugins/osc/OSCPlugin.h" namespace ola { namespace plugin { namespace osc { using ola::network::IPV4SocketAddress; using std::set; using std::string; using std::vector; const char OSCPlugin::DEFAULT_ADDRESS_TEMPLATE[] = "/dmx/universe/%d"; const char OSCPlugin::DEFAULT_TARGETS_TEMPLATE[] = ""; const char OSCPlugin::INPUT_PORT_COUNT_KEY[] = "input_ports"; const char OSCPlugin::OUTPUT_PORT_COUNT_KEY[] = "output_ports"; const char OSCPlugin::PLUGIN_NAME[] = "OSC"; const char OSCPlugin::PLUGIN_PREFIX[] = "osc"; const char OSCPlugin::PORT_ADDRESS_TEMPLATE[] = "port_%d_address"; const char OSCPlugin::PORT_TARGETS_TEMPLATE[] = "port_%d_targets"; const char OSCPlugin::PORT_FORMAT_TEMPLATE[] = "port_%d_output_format"; const char OSCPlugin::UDP_PORT_KEY[] = "udp_listen_port"; const char OSCPlugin::BLOB_FORMAT[] = "blob"; const char OSCPlugin::FLOAT_ARRAY_FORMAT[] = "float_array"; const char OSCPlugin::FLOAT_INDIVIDUAL_FORMAT[] = "individual_float"; const char OSCPlugin::INT_ARRAY_FORMAT[] = "int_array"; const char OSCPlugin::INT_INDIVIDUAL_FORMAT[] = "individual_int"; /* * Start the plugin. */ bool OSCPlugin::StartHook() { // Get the value of UDP_PORT_KEY or use the default value if it isn't valid. uint16_t udp_port = StringToIntOrDefault( m_preferences->GetValue(UDP_PORT_KEY), DEFAULT_UDP_PORT); // For each input port, add the address to the vector vector port_addresses; for (unsigned int i = 0; i < GetPortCount(INPUT_PORT_COUNT_KEY); i++) { const string key = ExpandTemplate(PORT_ADDRESS_TEMPLATE, i); port_addresses.push_back(m_preferences->GetValue(key)); } // For each ouput port, extract the list of OSCTargets and store them in // port_targets. OSCDevice::PortConfigs port_configs; for (unsigned int i = 0; i < GetPortCount(OUTPUT_PORT_COUNT_KEY); i++) { OSCDevice::PortConfig port_config; const string format_key = ExpandTemplate(PORT_FORMAT_TEMPLATE, i); SetDataFormat(m_preferences->GetValue(format_key), &port_config); const string key = ExpandTemplate(PORT_TARGETS_TEMPLATE, i); vector tokens; StringSplit(m_preferences->GetValue(key), &tokens, ","); vector::const_iterator iter = tokens.begin(); for (; iter != tokens.end(); ++iter) { OSCTarget target; if (ExtractOSCTarget(*iter, &target)) { port_config.targets.push_back(target); } } port_configs.push_back(port_config); } // Finally create the new OSCDevice, start it and register the device. std::auto_ptr device( new OSCDevice(this, m_plugin_adaptor, udp_port, port_addresses, port_configs)); if (!device->Start()) { return false; } m_device = device.release(); m_plugin_adaptor->RegisterDevice(m_device); return true; } /* * Stop the plugin * @return true on success, false on failure */ bool OSCPlugin::StopHook() { if (m_device) { m_plugin_adaptor->UnregisterDevice(m_device); bool ret = m_device->Stop(); delete m_device; return ret; } return true; } string OSCPlugin::Description() const { return "OSC (Open Sound Control) Plugin\n" "--------------------------------\n" "\n" "This plugin allows OLA to send and receive OSC\n" "( http://www.opensoundcontrol.org/ ) messages.\n" "\n" "OLA uses the blob type for transporting DMX data.\n" "\n" "--- Config file : ola-osc.conf ---\n" "\n" "input_ports = \n" "The number of input ports to create.\n" "\n" "output_ports = \n" "The number of output ports to create.\n" "\n" "port_N_targets = ip:port/address,ip:port/address,...\n" "For output port N, the list of targets to send OSC messages to. If the\n" "targets contain %d it's replaced by the universe number for port N\n" "\n" "port_N_address = /address\n" "The OSC address to listen on for port N. If the address contains %d\n" "it's replaced by the universe number for port N.\n" "\n" "port_N_format = [blob|float_array,individual_float,individual_int,int_array]\n" "The format (OSC Type) to send the DMX data in:\n" " - blob: a OSC-blob\n" " - float_array: an array of float values. 0.0 - 1.0\n" " - individual_float: one float message for each slot (channel). 0.0 - 1.0 \n" " - individual_int: one int message for each slot (channel). 0 - 255.\n" " - int_array: an array of int values. 0 - 255.\n" "\n" "udp_listen_port = \n" "The UDP Port to listen on for OSC messages.\n" "\n"; } /** * Set the default preferences for the OSC plugin. */ bool OSCPlugin::SetDefaultPreferences() { if (!m_preferences) { return false; } bool save = false; save |= m_preferences->SetDefaultValue(INPUT_PORT_COUNT_KEY, UIntValidator(0, 32), DEFAULT_PORT_COUNT); save |= m_preferences->SetDefaultValue(OUTPUT_PORT_COUNT_KEY, UIntValidator(0, 32), DEFAULT_PORT_COUNT); save |= m_preferences->SetDefaultValue(UDP_PORT_KEY, UIntValidator(1, UINT16_MAX), DEFAULT_UDP_PORT); for (unsigned int i = 0; i < GetPortCount(INPUT_PORT_COUNT_KEY); i++) { const string key = ExpandTemplate(PORT_ADDRESS_TEMPLATE, i); save |= m_preferences->SetDefaultValue(key, StringValidator(), DEFAULT_ADDRESS_TEMPLATE); } set valid_formats; valid_formats.insert(BLOB_FORMAT); valid_formats.insert(FLOAT_ARRAY_FORMAT); valid_formats.insert(FLOAT_INDIVIDUAL_FORMAT); valid_formats.insert(INT_ARRAY_FORMAT); valid_formats.insert(INT_INDIVIDUAL_FORMAT); SetValidator format_validator = SetValidator(valid_formats); for (unsigned int i = 0; i < GetPortCount(OUTPUT_PORT_COUNT_KEY); i++) { save |= m_preferences->SetDefaultValue( ExpandTemplate(PORT_TARGETS_TEMPLATE, i), StringValidator(true), DEFAULT_TARGETS_TEMPLATE); save |= m_preferences->SetDefaultValue( ExpandTemplate(PORT_FORMAT_TEMPLATE, i), format_validator, BLOB_FORMAT); } if (save) { m_preferences->Save(); } return true; } /** * @brief Given a key, return the port count from the preferences. * * Defaults to DEFAULT_PORT_COUNT if the value was invalid. */ unsigned int OSCPlugin::GetPortCount(const string& key) const { unsigned int port_count; if (!StringToInt(m_preferences->GetValue(key), &port_count)) { return DEFAULT_PORT_COUNT; } return port_count; } /** * Try to parse the string as an OSC Target. */ bool OSCPlugin::ExtractOSCTarget(const string &str, OSCTarget *target) { size_t pos = str.find_first_of("/"); if (pos == string::npos) { return false; } if (!IPV4SocketAddress::FromString(str.substr(0, pos), &target->socket_address)) { return false; } target->osc_address = str.substr(pos); return true; } /** * Set the PortConfig data format based on the option the user provides */ void OSCPlugin::SetDataFormat(const string &format_option, OSCDevice::PortConfig *port_config) { if (format_option == BLOB_FORMAT) { port_config->data_format = OSCNode::FORMAT_BLOB; } else if (format_option == FLOAT_ARRAY_FORMAT) { port_config->data_format = OSCNode::FORMAT_FLOAT_ARRAY; } else if (format_option == FLOAT_INDIVIDUAL_FORMAT) { port_config->data_format = OSCNode::FORMAT_FLOAT_INDIVIDUAL; } else if (format_option == INT_ARRAY_FORMAT) { port_config->data_format = OSCNode::FORMAT_INT_ARRAY; } else if (format_option == INT_INDIVIDUAL_FORMAT) { port_config->data_format = OSCNode::FORMAT_INT_INDIVIDUAL; } else { OLA_WARN << "Unknown OSC format " << format_option << ", defaulting to blob"; } } } // namespace osc } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/osc/OSCNode.h0000644000175000017500000001331213023355232017326 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OSCNode.h * A DMX orientated, C++ wrapper around liblo. * Copyright (C) 2012 Simon Newton */ #ifndef PLUGINS_OSC_OSCNODE_H_ #define PLUGINS_OSC_OSCNODE_H_ #include #include #include #include #include #include #include #include #include #include #include #include "plugins/osc/OSCTarget.h" namespace ola { namespace plugin { namespace osc { /** * The OSCNode object handles sending and receiving DMX data using OSC. * * Sending: * For sending, OSC Targets are assigned to groups. A group ID is just an * arbitary integer used to identify the group. It's not sent in the OSC * packets. For example: * * OSCNode node(OSCNode::OSCNodeOptions(), ...); * node.Init(); * * node.AddTarget(1, OSCTarget(...)); * node.AddTarget(1, OSCTarget(...)); * node.SendData(1, FORMAT_BLOB, dmx); * * Receiving: * To receive DMX data, register a Callback for a specific OSC Address. For * example: * * OSCNode node(OSCNode::OSCNodeOptions(), ...); * node.Init(); * * node.RegisterAddress("/dmx/1", NewCallback(...)); * // run the SelectServer * * // once it's time to stop, de-register this address * node.RegisterAddress("/dmx/1", NULL); */ class OSCNode { public: // The different data formats we can send in. enum DataFormat { FORMAT_BLOB, FORMAT_INT_ARRAY, FORMAT_INT_INDIVIDUAL, FORMAT_FLOAT_ARRAY, FORMAT_FLOAT_INDIVIDUAL, }; // The options for the OSCNode object. struct OSCNodeOptions { uint16_t listen_port; // UDP port to listen on OSCNodeOptions() : listen_port(DEFAULT_OSC_PORT) {} }; // The callback run when we receive new DMX data. typedef Callback1 DMXCallback; OSCNode(ola::io::SelectServerInterface *ss, ola::ExportMap *export_map, const OSCNodeOptions &options); ~OSCNode(); bool Init(); void Stop(); // Sending methods void AddTarget(unsigned int group, const OSCTarget &target); bool RemoveTarget(unsigned int group, const OSCTarget &target); bool SendData(unsigned int group, DataFormat data_format, const ola::DmxBuffer &data); // Receiving methods bool RegisterAddress(const std::string &osc_address, DMXCallback *callback); // Called by the liblo handlers. void SetUniverse(const std::string &osc_address, const uint8_t *data, unsigned int size); void SetSlot(const std::string &osc_address, uint16_t slot, uint8_t value); // The port OSC is listening on. uint16_t ListeningPort() const; private: class NodeOSCTarget { public: explicit NodeOSCTarget(const OSCTarget &target); ~NodeOSCTarget(); bool operator==(const NodeOSCTarget &other) const { return (socket_address == other.socket_address && osc_address == other.osc_address); } bool operator==(const OSCTarget &other) const { return (socket_address == other.socket_address && osc_address == other.osc_address); } ola::network::IPV4SocketAddress socket_address; std::string osc_address; lo_address liblo_address; private: NodeOSCTarget(const NodeOSCTarget&); NodeOSCTarget& operator=(const NodeOSCTarget&); }; typedef std::vector OSCTargetVector; struct OSCOutputGroup { OSCTargetVector targets; DmxBuffer dmx; // holds the last values. }; struct OSCInputGroup { explicit OSCInputGroup(DMXCallback *callback) : callback(callback) {} DmxBuffer dmx; std::auto_ptr callback; }; typedef std::map OutputGroupMap; typedef std::map InputUniverseMap; struct SlotMessage { unsigned int slot; lo_message message; }; ola::io::SelectServerInterface *m_ss; const uint16_t m_listen_port; std::auto_ptr m_descriptor; lo_server m_osc_server; OutputGroupMap m_output_map; InputUniverseMap m_input_map; void DescriptorReady(); bool SendBlob(const DmxBuffer &data, const OSCTargetVector &targets); bool SendIndividualFloats(const DmxBuffer &data, OSCOutputGroup *group); bool SendIndividualInts(const DmxBuffer &data, OSCOutputGroup *group); bool SendIntArray(const DmxBuffer &data, const OSCTargetVector &targets); bool SendFloatArray(const DmxBuffer &data, const OSCTargetVector &targets); bool SendMessageToTargets(lo_message message, const OSCTargetVector &targets); bool SendIndividualMessages(const DmxBuffer &data, OSCOutputGroup *group, const std::string &osc_type); static const uint16_t DEFAULT_OSC_PORT = 7770; static const char OSC_PORT_VARIABLE[]; }; } // namespace osc } // namespace plugin } // namespace ola #endif // PLUGINS_OSC_OSCNODE_H_ ola-0.10.5.nojsmin/plugins/gpio/0000755000175000017500000000000013155164170016102 5ustar wouterwouterola-0.10.5.nojsmin/plugins/gpio/GPIOPort.h0000644000175000017500000000351113023355232017651 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * GPIOPort.h * An OLA GPIO Port. * Copyright (C) 2014 Simon Newton */ #ifndef PLUGINS_GPIO_GPIOPORT_H_ #define PLUGINS_GPIO_GPIOPORT_H_ #include #include "ola/DmxBuffer.h" #include "olad/Port.h" #include "plugins/gpio/GPIODevice.h" #include "plugins/gpio/GPIODriver.h" namespace ola { namespace plugin { namespace gpio { /** * @brief The GPIO Output port. */ class GPIOOutputPort: public BasicOutputPort { public: /** * @brief Create a new GPIOOutputPort. * @param parent The parent device. * @param options the Options for the GPIODriver. */ GPIOOutputPort(GPIODevice *parent, const GPIODriver::Options &options); /** * @brief Destructor. */ ~GPIOOutputPort() {} /** * @brief Initialize the port. * @returns true if successful, false otherwise. */ bool Init(); std::string Description() const; bool WriteDMX(const DmxBuffer &buffer, uint8_t priority); private: std::auto_ptr m_driver; DISALLOW_COPY_AND_ASSIGN(GPIOOutputPort); }; } // namespace gpio } // namespace plugin } // namespace ola #endif // PLUGINS_GPIO_GPIOPORT_H_ ola-0.10.5.nojsmin/plugins/gpio/Makefile.mk0000644000175000017500000000142113023355232020141 0ustar wouterwouter# LIBRARIES ################################################## if USE_GPIO lib_LTLIBRARIES += plugins/gpio/libolagpiocore.la \ plugins/gpio/libolagpio.la # This is a library which isn't coupled to olad plugins_gpio_libolagpiocore_la_SOURCES = \ plugins/gpio/GPIODriver.cpp \ plugins/gpio/GPIODriver.h plugins_gpio_libolagpiocore_la_LIBADD = common/libolacommon.la plugins_gpio_libolagpio_la_SOURCES = \ plugins/gpio/GPIODevice.cpp \ plugins/gpio/GPIODevice.h \ plugins/gpio/GPIOPlugin.cpp \ plugins/gpio/GPIOPlugin.h \ plugins/gpio/GPIOPort.cpp \ plugins/gpio/GPIOPort.h plugins_gpio_libolagpio_la_LIBADD = \ common/libolacommon.la \ olad/plugin_api/libolaserverplugininterface.la \ plugins/gpio/libolagpiocore.la endif ola-0.10.5.nojsmin/plugins/gpio/GPIODriver.cpp0000644000175000017500000001214013023355232020511 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * GPIODriver.cpp * Uses data in a DMXBuffer to drive GPIO pins. * Copyright (C) 2014 Simon Newton */ #include "plugins/gpio/GPIODriver.h" #include #include #include #include #include #include #include #include #include #include #include "ola/io/IOUtils.h" #include "ola/Logging.h" #include "ola/thread/Mutex.h" namespace ola { namespace plugin { namespace gpio { const char GPIODriver::GPIO_BASE_DIR[] = "/sys/class/gpio/gpio"; using ola::thread::MutexLocker; using std::string; using std::vector; GPIODriver::GPIODriver(const Options &options) : m_options(options), m_term(false), m_dmx_changed(false) { } GPIODriver::~GPIODriver() { { MutexLocker locker(&m_mutex); m_term = true; } m_cond.Signal(); Join(); CloseGPIOFDs(); } bool GPIODriver::Init() { if (!SetupGPIO()) { return false; } return Start(); } bool GPIODriver::SendDmx(const DmxBuffer &dmx) { { MutexLocker locker(&m_mutex); // avoid the reference counting m_buffer.Set(dmx); m_dmx_changed = true; } m_cond.Signal(); return true; } void *GPIODriver::Run() { Clock clock; DmxBuffer output; while (true) { bool update_pins = false; TimeStamp wake_up; clock.CurrentTime(&wake_up); wake_up += TimeInterval(1, 0); // Wait for one of: i) termination ii) DMX changed iii) timeout m_mutex.Lock(); if (!m_term && !m_dmx_changed) { m_cond.TimedWait(&m_mutex, wake_up); } if (m_term) { m_mutex.Unlock(); break; } else if (m_dmx_changed) { output.Set(m_buffer); m_dmx_changed = false; update_pins = true; } m_mutex.Unlock(); if (update_pins) { UpdateGPIOPins(output); } } return NULL; } bool GPIODriver::SetupGPIO() { /** * This relies on the pins being exported: * echo N > /sys/class/gpio/export * That requires root access. */ const string direction("out"); bool failed = false; vector::const_iterator iter = m_options.gpio_pins.begin(); for (; iter != m_options.gpio_pins.end(); ++iter) { std::ostringstream str; str << GPIO_BASE_DIR << static_cast(*iter) << "/value"; int pin_fd; if (!ola::io::Open(str.str(), O_RDWR, &pin_fd)) { failed = true; break; } GPIOPin pin = {pin_fd, UNDEFINED, false}; // Set dir str.str(""); str << GPIO_BASE_DIR << static_cast(*iter) << "/direction"; int fd; if (!ola::io::Open(str.str(), O_RDWR, &fd)) { failed = true; break; } if (write(fd, direction.c_str(), direction.size()) < 0) { OLA_WARN << "Failed to enable output on " << str.str() << " : " << strerror(errno); failed = true; } close(fd); m_gpio_pins.push_back(pin); } if (failed) { CloseGPIOFDs(); return false; } return true; } bool GPIODriver::UpdateGPIOPins(const DmxBuffer &dmx) { enum Action { TURN_ON, TURN_OFF, NO_CHANGE, }; for (uint16_t i = 0; i < m_gpio_pins.size() && (i + m_options.start_address < dmx.Size()); i++) { Action action = NO_CHANGE; uint8_t slot_value = dmx.Get(i + m_options.start_address - 1); switch (m_gpio_pins[i].state) { case ON: action = (slot_value <= m_options.turn_off ? TURN_OFF : NO_CHANGE); break; case OFF: action = (slot_value >= m_options.turn_on ? TURN_ON : NO_CHANGE); break; case UNDEFINED: default: // If the state if undefined and the value is in the mid-range, then // default to turning off. action = (slot_value >= m_options.turn_on ? TURN_ON : TURN_OFF); } // Change the pin state if required. if (action != NO_CHANGE) { char data = (action == TURN_ON ? '1' : '0'); if (write(m_gpio_pins[i].fd, &data, sizeof(data)) < 0) { OLA_WARN << "Failed to toggle GPIO pin " << i << ", fd " << static_cast(m_gpio_pins[i].fd) << ": " << strerror(errno); return false; } m_gpio_pins[i].state = (action == TURN_ON ? ON : OFF); } } return true; } void GPIODriver::CloseGPIOFDs() { GPIOPins::iterator iter = m_gpio_pins.begin(); for (; iter != m_gpio_pins.end(); ++iter) { close(iter->fd); } m_gpio_pins.clear(); } } // namespace gpio } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/gpio/GPIODevice.cpp0000644000175000017500000000270213023355232020460 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * GPIODevice.cpp * The GPIO Device. * Copyright (C) 2014 Simon Newton */ #include "plugins/gpio/GPIODevice.h" #include "plugins/gpio/GPIOPort.h" #include "plugins/gpio/GPIOPlugin.h" #include "plugins/gpio/GPIODriver.h" namespace ola { namespace plugin { namespace gpio { /* * Create a new device */ GPIODevice::GPIODevice(GPIOPlugin *owner, const GPIODriver::Options &options) : Device(owner, "General Purpose I/O Device"), m_options(options) { } bool GPIODevice::StartHook() { GPIOOutputPort *port = new GPIOOutputPort(this, m_options); if (!port->Init()) { delete port; return false; } AddPort(port); return true; } } // namespace gpio } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/gpio/GPIODevice.h0000644000175000017500000000317013023355232020125 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * GPIODevice.h * The GPIO Device. * Copyright (C) 2014 Simon Newton */ #ifndef PLUGINS_GPIO_GPIODEVICE_H_ #define PLUGINS_GPIO_GPIODEVICE_H_ #include #include #include #include "olad/Device.h" #include "plugins/gpio/GPIODriver.h" namespace ola { namespace plugin { namespace gpio { /** * @brief The GPIO Device */ class GPIODevice: public ola::Device { public: /** * @brief Create a new GPIODevice. * @param owner The Plugin that owns this device. * @param options the options to use for the new device. */ GPIODevice(class GPIOPlugin *owner, const GPIODriver::Options &options); std::string DeviceId() const { return "1"; } protected: bool StartHook(); private: const GPIODriver::Options m_options; DISALLOW_COPY_AND_ASSIGN(GPIODevice); }; } // namespace gpio } // namespace plugin } // namespace ola #endif // PLUGINS_GPIO_GPIODEVICE_H_ ola-0.10.5.nojsmin/plugins/gpio/GPIOPort.cpp0000644000175000017500000000321513023355232020205 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * GPIOPort.cpp * An OLA GPIO Port. * Copyright (C) 2014 Simon Newton */ #include "plugins/gpio/GPIOPort.h" #include #include #include #include "ola/StringUtils.h" #include "plugins/gpio/GPIODriver.h" namespace ola { namespace plugin { namespace gpio { using std::string; using std::vector; GPIOOutputPort::GPIOOutputPort(GPIODevice *parent, const GPIODriver::Options &options) : BasicOutputPort(parent, 1), m_driver(new GPIODriver(options)) { } bool GPIOOutputPort::Init() { return m_driver->Init(); } string GPIOOutputPort::Description() const { vector pins = m_driver->PinList(); return "Pins " + ola::StringJoin(", ", pins); } bool GPIOOutputPort::WriteDMX(const DmxBuffer &buffer, OLA_UNUSED uint8_t priority) { return m_driver->SendDmx(buffer); } } // namespace gpio } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/gpio/GPIODriver.h0000644000175000017500000000616713023355232020172 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * GPIODriver.h * Uses data in a DMXBuffer to drive GPIO pins. * Copyright (C) 2014 Simon Newton */ #ifndef PLUGINS_GPIO_GPIODRIVER_H_ #define PLUGINS_GPIO_GPIODRIVER_H_ #include #include #include #include #include namespace ola { namespace plugin { namespace gpio { /** * @brief Uses data in a DMXBuffer to drive GPIO pins. */ class GPIODriver : private ola::thread::Thread { public: /** * @brief The Options. */ struct Options { public: Options(): start_address(1), turn_on(128), turn_off(127) {} /** * @brief A list of I/O pins to map to slots. */ std::vector gpio_pins; /** * @brief The DMX512 start address of the first pin */ uint16_t start_address; /** * @brief The value above which a pin will be turned on. */ uint8_t turn_on; /** * @brief The value below which a pin will be turned off. */ uint8_t turn_off; }; /** * @brief Create a new GPIODriver. * @param options the Options struct. */ explicit GPIODriver(const Options &options); /** * @brief Destructor. */ ~GPIODriver(); /** * @brief Initialize the GPIODriver. * @returns true is successful, false otherwise. */ bool Init(); /** * @brief Get a list of the GPIO pins controlled by this driver. * @returns A list of GPIO pin numbers. */ std::vector PinList() const { return m_options.gpio_pins; } /** * @brief Set the values of the GPIO pins from the data in the DMXBuffer. * @param dmx the DmxBuffer with the values to use. * @returns true is the GPIO pins were updated. */ bool SendDmx(const DmxBuffer &dmx); void *Run(); private: enum GPIOState { ON, OFF, UNDEFINED, }; struct GPIOPin { int fd; GPIOState state; bool last_value; }; typedef std::vector GPIOPins; const Options m_options; GPIOPins m_gpio_pins; DmxBuffer m_buffer; bool m_term; // GUARDED_BY(m_mutex); bool m_dmx_changed; // GUARDED_BY(m_mutex); ola::thread::Mutex m_mutex; ola::thread::ConditionVariable m_cond; bool SetupGPIO(); bool UpdateGPIOPins(const DmxBuffer &dmx); void CloseGPIOFDs(); static const char GPIO_BASE_DIR[]; DISALLOW_COPY_AND_ASSIGN(GPIODriver); }; } // namespace gpio } // namespace plugin } // namespace ola #endif // PLUGINS_GPIO_GPIODRIVER_H_ ola-0.10.5.nojsmin/plugins/gpio/GPIOPlugin.cpp0000644000175000017500000001155113023355232020521 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * GPIOPlugin.cpp * The General Purpose digital I/O plugin. * Copyright (C) 2014 Simon Newton */ #include "plugins/gpio/GPIOPlugin.h" #include #include #include #include "olad/Preferences.h" #include "ola/Logging.h" #include "ola/StringUtils.h" #include "plugins/gpio/GPIODevice.h" #include "plugins/gpio/GPIODriver.h" namespace ola { namespace plugin { namespace gpio { using std::auto_ptr; using std::string; using std::vector; const char GPIOPlugin::GPIO_PINS_KEY[] = "gpio_pins"; const char GPIOPlugin::GPIO_SLOT_OFFSET_KEY[] = "gpio_slot_offset"; const char GPIOPlugin::GPIO_TURN_OFF_KEY[] = "gpio_turn_off"; const char GPIOPlugin::GPIO_TURN_ON_KEY[] = "gpio_turn_on"; const char GPIOPlugin::PLUGIN_NAME[] = "GPIO"; const char GPIOPlugin::PLUGIN_PREFIX[] = "gpio"; bool GPIOPlugin::StartHook() { GPIODriver::Options options; if (!StringToInt(m_preferences->GetValue(GPIO_TURN_ON_KEY), &options.turn_on)) { OLA_WARN << "Invalid value for " << GPIO_TURN_ON_KEY; return false; } if (!StringToInt(m_preferences->GetValue(GPIO_TURN_OFF_KEY), &options.turn_off)) { OLA_WARN << "Invalid value for " << GPIO_TURN_OFF_KEY; return false; } if (!StringToInt(m_preferences->GetValue(GPIO_SLOT_OFFSET_KEY), &options.start_address)) { OLA_WARN << "Invalid value for " << GPIO_SLOT_OFFSET_KEY; return false; } if (options.turn_off >= options.turn_on) { OLA_WARN << GPIO_TURN_OFF_KEY << " must be strictly less than " << GPIO_TURN_ON_KEY; return false; } vector pin_list; StringSplit(m_preferences->GetValue(GPIO_PINS_KEY), &pin_list, ","); vector::const_iterator iter = pin_list.begin(); for (; iter != pin_list.end(); ++iter) { if (iter->empty()) { continue; } uint16_t pin; if (!StringToInt(*iter, &pin)) { OLA_WARN << "Invalid value for GPIO pin: " << *iter; return false; } options.gpio_pins.push_back(pin); } if (options.gpio_pins.empty()) { return true; } std::auto_ptr device(new GPIODevice(this, options)); if (!device->Start()) { return false; } m_plugin_adaptor->RegisterDevice(device.get()); m_device = device.release(); return true; } bool GPIOPlugin::StopHook() { if (m_device) { m_plugin_adaptor->UnregisterDevice(m_device); m_device->Stop(); delete m_device; m_device = NULL; } return true; } string GPIOPlugin::Description() const { return "General Purpose I/O Plugin\n" "----------------------------\n" "\n" "This plugin controls the General Purpose Digital I/O (GPIO) pins on devices\n" "like a Raspberry Pi. It creates a single device, with a single output port.\n" "The offset (start address) of the GPIO pins is configurable.\n" "\n" "--- Config file : ola-gpio.conf ---\n" "\n" "gpio_pins = [int]\n" "The list of GPIO pins to control, each pin is mapped to a DMX512 slot.\n" "\n" "gpio_slot_offset = \n" "The DMX512 slot for the first pin. Slots are indexed from 1\n." "\n" "gpio_turn_on = \n" "The DMX512 value above which a GPIO pin will be turned on.\n" "\n" "gpio_turn_off = \n" "The DMX512 value below which a GPIO pin will be turned off.\n" "\n"; } bool GPIOPlugin::SetDefaultPreferences() { bool save = false; if (!m_preferences) return false; save |= m_preferences->SetDefaultValue(GPIO_PINS_KEY, StringValidator(), ""); save |= m_preferences->SetDefaultValue(GPIO_SLOT_OFFSET_KEY, UIntValidator(1, DMX_UNIVERSE_SIZE), "1"); save |= m_preferences->SetDefaultValue( GPIO_TURN_ON_KEY, UIntValidator(DMX_MIN_SLOT_VALUE + 1, DMX_MAX_SLOT_VALUE), "128"); save |= m_preferences->SetDefaultValue( GPIO_TURN_OFF_KEY, UIntValidator(DMX_MIN_SLOT_VALUE, DMX_MAX_SLOT_VALUE - 1), "127"); if (save) { m_preferences->Save(); } if (m_preferences->GetValue(GPIO_SLOT_OFFSET_KEY).empty()) { return false; } return true; } } // namespace gpio } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/gpio/GPIOPlugin.h0000644000175000017500000000402313023355232020162 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * GPIOPlugin.h * The General Purpose digital I/O plugin. * Copyright (C) 2014 Simon Newton */ #ifndef PLUGINS_GPIO_GPIOPLUGIN_H_ #define PLUGINS_GPIO_GPIOPLUGIN_H_ #include #include "olad/Plugin.h" #include "ola/plugin_id.h" namespace ola { namespace plugin { namespace gpio { /** * @brief A plugin that drives general purpose digital I/O lines. */ class GPIOPlugin: public ola::Plugin { public: /** * @brief Create a new GPIOPlugin. * @param plugin_adaptor the PluginAdaptor to use */ explicit GPIOPlugin(class ola::PluginAdaptor *plugin_adaptor) : Plugin(plugin_adaptor), m_device(NULL) {} std::string Name() const { return PLUGIN_NAME; } std::string Description() const; ola_plugin_id Id() const { return OLA_PLUGIN_GPIO; } std::string PluginPrefix() const { return PLUGIN_PREFIX; } private: class GPIODevice *m_device; bool StartHook(); bool StopHook(); bool SetDefaultPreferences(); static const char GPIO_PINS_KEY[]; static const char GPIO_SLOT_OFFSET_KEY[]; static const char GPIO_TURN_OFF_KEY[]; static const char GPIO_TURN_ON_KEY[]; static const char PLUGIN_NAME[]; static const char PLUGIN_PREFIX[]; DISALLOW_COPY_AND_ASSIGN(GPIOPlugin); }; } // namespace gpio } // namespace plugin } // namespace ola #endif // PLUGINS_GPIO_GPIOPLUGIN_H_ ola-0.10.5.nojsmin/plugins/kinet/0000755000175000017500000000000013155164170016256 5ustar wouterwouterola-0.10.5.nojsmin/plugins/kinet/Makefile.mk0000644000175000017500000000216513023355232020323 0ustar wouterwouter# LIBRARIES ################################################## if USE_KINET # This is a library which isn't coupled to olad noinst_LTLIBRARIES += plugins/kinet/libolakinetnode.la plugins_kinet_libolakinetnode_la_SOURCES = plugins/kinet/KiNetNode.cpp \ plugins/kinet/KiNetNode.h plugins_kinet_libolakinetnode_la_LIBADD = common/libolacommon.la lib_LTLIBRARIES += plugins/kinet/libolakinet.la plugins_kinet_libolakinet_la_SOURCES = \ plugins/kinet/KiNetPlugin.cpp \ plugins/kinet/KiNetPlugin.h \ plugins/kinet/KiNetDevice.cpp \ plugins/kinet/KiNetDevice.h \ plugins/kinet/KiNetPort.h plugins_kinet_libolakinet_la_LIBADD = \ olad/plugin_api/libolaserverplugininterface.la \ plugins/kinet/libolakinetnode.la # TESTS ################################################## test_programs += plugins/kinet/KiNetTester plugins_kinet_KiNetTester_SOURCES = plugins/kinet/KiNetNodeTest.cpp plugins_kinet_KiNetTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) plugins_kinet_KiNetTester_LDADD = $(COMMON_TESTING_LIBS) \ plugins/kinet/libolakinetnode.la endif ola-0.10.5.nojsmin/plugins/kinet/KiNetDevice.h0000644000175000017500000000323413023355232020556 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * KiNetDevice.h * Interface for the KiNet device * Copyright (C) 2013 Simon Newton */ #ifndef PLUGINS_KINET_KINETDEVICE_H_ #define PLUGINS_KINET_KINETDEVICE_H_ #include #include #include "ola/network/IPV4Address.h" #include "olad/Device.h" namespace ola { namespace plugin { namespace kinet { class KiNetDevice: public ola::Device { public: KiNetDevice(AbstractPlugin *owner, const std::vector &power_supplies, class PluginAdaptor *plugin_adaptor); // Only one KiNet device std::string DeviceId() const { return "1"; } protected: bool StartHook(); void PrePortStop(); void PostPortStop(); private: const std::vector m_power_supplies; class KiNetNode *m_node; class PluginAdaptor *m_plugin_adaptor; }; } // namespace kinet } // namespace plugin } // namespace ola #endif // PLUGINS_KINET_KINETDEVICE_H_ ola-0.10.5.nojsmin/plugins/kinet/KiNetPlugin.cpp0000644000175000017500000000676413023355232021163 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * KiNetPlugin.cpp * The KiNet plugin for ola * Copyright (C) 2013 Simon Newton */ #include #include #include "ola/Logging.h" #include "ola/network/IPV4Address.h" #include "olad/PluginAdaptor.h" #include "olad/Preferences.h" #include "plugins/kinet/KiNetDevice.h" #include "plugins/kinet/KiNetPlugin.h" namespace ola { namespace plugin { namespace kinet { using ola::network::IPV4Address; using std::string; using std::vector; const char KiNetPlugin::POWER_SUPPLY_KEY[] = "power_supply"; const char KiNetPlugin::PLUGIN_NAME[] = "KiNET"; const char KiNetPlugin::PLUGIN_PREFIX[] = "kinet"; KiNetPlugin::KiNetPlugin(PluginAdaptor *plugin_adaptor) : Plugin(plugin_adaptor) { } KiNetPlugin::~KiNetPlugin() {} /* * Start the plugin. */ bool KiNetPlugin::StartHook() { vector power_supplies_strings = m_preferences->GetMultipleValue( POWER_SUPPLY_KEY); vector::const_iterator iter = power_supplies_strings.begin(); vector power_supplies; for (; iter != power_supplies_strings.end(); ++iter) { if (iter->empty()) { continue; } IPV4Address target; if (IPV4Address::FromString(*iter, &target)) { power_supplies.push_back(target); } else { OLA_WARN << "Invalid power supply IP address : " << *iter; } } m_device.reset(new KiNetDevice(this, power_supplies, m_plugin_adaptor)); if (!m_device->Start()) { m_device.reset(); return false; } m_plugin_adaptor->RegisterDevice(m_device.get()); return true; } /* * Stop the plugin * @return true on success, false on failure */ bool KiNetPlugin::StopHook() { if (m_device.get()) { // stop the device m_plugin_adaptor->UnregisterDevice(m_device.get()); bool ret = m_device->Stop(); m_device.reset(); return ret; } return true; } /* * Return the description for this plugin. * @return a string description of the plugin */ string KiNetPlugin::Description() const { return "KiNET Plugin\n" "----------------------------\n" "\n" "This plugin creates a single device with multiple output ports. Each port\n" "represents a power supply. This plugin uses the V1 DMX-Out version of the\n" "KiNET protocol\n" "\n" "--- Config file : ola-kinet.conf ---\n" "\n" "power_supply = \n" "The IP of the power supply to send to. You can communicate with more than\n" "one power supply by adding multiple power_supply = lines\n" "\n"; } /* * Set default preferences. */ bool KiNetPlugin::SetDefaultPreferences() { bool save = false; if (!m_preferences) { return false; } save |= m_preferences->SetDefaultValue(POWER_SUPPLY_KEY, StringValidator(true), ""); if (save) { m_preferences->Save(); } return true; } } // namespace kinet } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/kinet/KiNetNode.h0000644000175000017500000000440213023355232020242 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * KiNetNode.h * Header file for the KiNetNode class. * Copyright (C) 2013 Simon Newton */ #ifndef PLUGINS_KINET_KINETNODE_H_ #define PLUGINS_KINET_KINETNODE_H_ #include #include "ola/DmxBuffer.h" #include "ola/io/BigEndianStream.h" #include "ola/io/IOQueue.h" #include "ola/io/SelectServerInterface.h" #include "ola/network/IPV4Address.h" #include "ola/network/Socket.h" namespace ola { namespace plugin { namespace kinet { class KiNetNode { public: KiNetNode(ola::io::SelectServerInterface *ss, ola::network::UDPSocketInterface *socket = NULL); virtual ~KiNetNode(); bool Start(); bool Stop(); // The following apply to Input Ports (those which send data) bool SendDMX(const ola::network::IPV4Address &target, const ola::DmxBuffer &buffer); private: bool m_running; ola::io::SelectServerInterface *m_ss; ola::io::IOQueue m_output_queue; ola::io::BigEndianOutputStream m_output_stream; ola::network::Interface m_interface; std::auto_ptr m_socket; KiNetNode(const KiNetNode&); KiNetNode& operator=(const KiNetNode&); void SocketReady(); void PopulatePacketHeader(uint16_t msg_type); bool InitNetwork(); static const uint16_t KINET_PORT = 6038; static const uint32_t KINET_MAGIC_NUMBER = 0x0401dc4a; static const uint16_t KINET_VERSION_ONE = 0x0100; static const uint16_t KINET_DMX_MSG = 0x0101; }; } // namespace kinet } // namespace plugin } // namespace ola #endif // PLUGINS_KINET_KINETNODE_H_ ola-0.10.5.nojsmin/plugins/kinet/KiNetDevice.cpp0000644000175000017500000000455713023355232021122 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * KiNetDevice.cpp * A KiNet Device. * Copyright (C) 2013 Simon Newton */ #include #include #include #include "ola/Callback.h" #include "ola/Logging.h" #include "ola/StringUtils.h" #include "ola/network/IPV4Address.h" #include "ola/network/InterfacePicker.h" #include "ola/network/NetworkUtils.h" #include "olad/PluginAdaptor.h" #include "olad/Port.h" #include "plugins/kinet/KiNetDevice.h" #include "plugins/kinet/KiNetPort.h" namespace ola { namespace plugin { namespace kinet { using ola::network::IPV4Address; using std::auto_ptr; using std::vector; /* * Create a new KiNet Device */ KiNetDevice::KiNetDevice( AbstractPlugin *owner, const vector &power_supplies, PluginAdaptor *plugin_adaptor) : Device(owner, "KiNet Device"), m_power_supplies(power_supplies), m_node(NULL), m_plugin_adaptor(plugin_adaptor) { } /* * Start this device * @return true on success, false on failure */ bool KiNetDevice::StartHook() { m_node = new KiNetNode(m_plugin_adaptor); if (!m_node->Start()) { delete m_node; m_node = NULL; return false; } vector::const_iterator iter = m_power_supplies.begin(); unsigned int port_id = 0; for (; iter != m_power_supplies.end(); ++iter) { AddPort(new KiNetOutputPort(this, *iter, m_node, port_id++)); } return true; } /** * Stop this device. This is called before the ports are deleted */ void KiNetDevice::PrePortStop() { m_node->Stop(); } /* * Stop this device */ void KiNetDevice::PostPortStop() { delete m_node; m_node = NULL; } } // namespace kinet } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/kinet/KiNetPlugin.h0000644000175000017500000000333413023355232020616 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * KiNetPlugin.h * The KiNET plugin for ola * Copyright (C) 2013 Simon Newton */ #ifndef PLUGINS_KINET_KINETPLUGIN_H_ #define PLUGINS_KINET_KINETPLUGIN_H_ #include #include #include "olad/Plugin.h" #include "ola/plugin_id.h" namespace ola { namespace plugin { namespace kinet { class KiNetPlugin : public Plugin { public: explicit KiNetPlugin(PluginAdaptor *plugin_adaptor); ~KiNetPlugin(); std::string Name() const { return PLUGIN_NAME; } ola_plugin_id Id() const { return OLA_PLUGIN_KINET; } std::string Description() const; std::string PluginPrefix() const { return PLUGIN_PREFIX; } private: std::auto_ptr m_device; // only have one device bool StartHook(); bool StopHook(); bool SetDefaultPreferences(); static const char PLUGIN_NAME[]; static const char PLUGIN_PREFIX[]; static const char POWER_SUPPLY_KEY[]; }; } // namespace kinet } // namespace plugin } // namespace ola #endif // PLUGINS_KINET_KINETPLUGIN_H_ ola-0.10.5.nojsmin/plugins/kinet/KiNetNodeTest.cpp0000644000175000017500000000474713023355232021451 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * KiNetNodeTest.cpp * Test fixture for the KiNetNode class * Copyright (C) 2013 Simon Newton */ #include #include "ola/DmxBuffer.h" #include "ola/Logging.h" #include "ola/io/SelectServer.h" #include "ola/network/IPV4Address.h" #include "ola/testing/MockUDPSocket.h" #include "plugins/kinet/KiNetNode.h" #include "ola/testing/TestUtils.h" using ola::DmxBuffer; using ola::network::IPV4Address; using ola::plugin::kinet::KiNetNode; using ola::testing::MockUDPSocket; class KiNetNodeTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(KiNetNodeTest); CPPUNIT_TEST(testSendDMX); CPPUNIT_TEST_SUITE_END(); public: KiNetNodeTest() : CppUnit::TestFixture(), ss(NULL), m_socket(new MockUDPSocket()) { } void setUp(); void testSendDMX(); private: ola::io::SelectServer ss; IPV4Address target_ip; MockUDPSocket *m_socket; static const uint16_t KINET_PORT = 6038; }; CPPUNIT_TEST_SUITE_REGISTRATION(KiNetNodeTest); void KiNetNodeTest::setUp() { ola::InitLogging(ola::OLA_LOG_INFO, ola::OLA_LOG_STDERR); ola::network::IPV4Address::FromString("10.0.0.10", &target_ip); } /** * Check sending DMX works. */ void KiNetNodeTest::testSendDMX() { KiNetNode node(&ss, m_socket); OLA_ASSERT_TRUE(node.Start()); const uint8_t expected_data[] = { 0x04, 0x01, 0xdc, 0x4a, 0x01, 0x00, 0x01, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0, 1, 5, 8, 10, 14, 45, 100, 255 }; m_socket->AddExpectedData(expected_data, sizeof(expected_data), target_ip, KINET_PORT); DmxBuffer buffer; buffer.SetFromString("1,5,8,10,14,45,100,255"); OLA_ASSERT_TRUE(node.SendDMX(target_ip, buffer)); m_socket->Verify(); OLA_ASSERT(node.Stop()); } ola-0.10.5.nojsmin/plugins/kinet/KiNetPort.h0000644000175000017500000000343013023355232020301 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * KiNetPort.h * The KiNet plugin for ola * Copyright (C) 2013 Simon Newton */ #ifndef PLUGINS_KINET_KINETPORT_H_ #define PLUGINS_KINET_KINETPORT_H_ #include #include "ola/network/IPV4Address.h" #include "olad/Port.h" #include "plugins/kinet/KiNetDevice.h" #include "plugins/kinet/KiNetNode.h" namespace ola { namespace plugin { namespace kinet { class KiNetOutputPort: public BasicOutputPort { public: KiNetOutputPort(KiNetDevice *device, const ola::network::IPV4Address &target, KiNetNode *node, unsigned int port_id) : BasicOutputPort(device, port_id), m_node(node), m_target(target) { } bool WriteDMX(const DmxBuffer &buffer, OLA_UNUSED uint8_t priority) { return m_node->SendDMX(m_target, buffer); } std::string Description() const { return "Power Supply: " + m_target.ToString(); } private: KiNetNode *m_node; const ola::network::IPV4Address m_target; }; } // namespace kinet } // namespace plugin } // namespace ola #endif // PLUGINS_KINET_KINETPORT_H_ ola-0.10.5.nojsmin/plugins/kinet/KiNetNode.cpp0000644000175000017500000001016713023355232020602 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * KiNetNode.cpp * An KiNet node * Copyright (C) 2013 Simon Newton */ #include #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/network/IPV4Address.h" #include "ola/network/SocketAddress.h" #include "plugins/kinet/KiNetNode.h" namespace ola { namespace plugin { namespace kinet { using ola::network::IPV4Address; using ola::network::IPV4SocketAddress; using ola::network::UDPSocket; using std::auto_ptr; /* * Create a new KiNet node. * @param ss a SelectServerInterface to use * @param socket a UDPSocket or Null. Ownership is transferred. */ KiNetNode::KiNetNode(ola::io::SelectServerInterface *ss, ola::network::UDPSocketInterface *socket) : m_running(false), m_ss(ss), m_output_stream(&m_output_queue), m_socket(socket) { } /* * Cleanup. */ KiNetNode::~KiNetNode() { Stop(); } /* * Start this node. */ bool KiNetNode::Start() { if (m_running) return false; if (!InitNetwork()) return false; m_running = true; return true; } /* * Stop this node. */ bool KiNetNode::Stop() { if (!m_running) return false; m_ss->RemoveReadDescriptor(m_socket.get()); m_socket.reset(); m_running = false; return true; } /* * Send some DMX data */ bool KiNetNode::SendDMX(const IPV4Address &target_ip, const DmxBuffer &buffer) { static const uint8_t port = 0; static const uint8_t flags = 0; static const uint16_t timer_val = 0; static const uint32_t universe = 0xffffffff; if (!buffer.Size()) { OLA_DEBUG << "Not sending 0 length packet"; return true; } m_output_queue.Clear(); PopulatePacketHeader(KINET_DMX_MSG); m_output_stream << port << flags << timer_val << universe; m_output_stream << DMX512_START_CODE; m_output_stream.Write(buffer.GetRaw(), buffer.Size()); IPV4SocketAddress target(target_ip, KINET_PORT); bool ok = m_socket->SendTo(&m_output_queue, target); if (!ok) OLA_WARN << "Failed to send KiNet DMX packet"; if (!m_output_queue.Empty()) { OLA_WARN << "Failed to send complete KiNet packet"; m_output_queue.Clear(); } return ok; } /* * Called when there is data on this socket. Right now we discard all packets. */ void KiNetNode::SocketReady() { uint8_t packet[1500]; ssize_t packet_size = sizeof(packet); ola::network::IPV4SocketAddress source; if (!m_socket->RecvFrom(reinterpret_cast(&packet), &packet_size, &source)) return; OLA_INFO << "Received Kinet packet from " << source << ", discarding"; } /* * Fill in the header for a packet */ void KiNetNode::PopulatePacketHeader(uint16_t msg_type) { uint32_t sequence_number = 0; // everything seems to set this to 0. m_output_stream << KINET_MAGIC_NUMBER << KINET_VERSION_ONE; m_output_stream << msg_type << sequence_number; } /* * Setup the networking components. */ bool KiNetNode::InitNetwork() { std::auto_ptr socket(m_socket.release()); if (!socket.get()) socket.reset(new UDPSocket()); if (!socket->Init()) { OLA_WARN << "Socket init failed"; return false; } if (!socket->Bind(IPV4SocketAddress(IPV4Address::WildCard(), KINET_PORT))) { return false; } socket->SetOnData(NewCallback(this, &KiNetNode::SocketReady)); m_ss->AddReadDescriptor(socket.get()); m_socket.reset(socket.release()); return true; } } // namespace kinet } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/openpixelcontrol/0000755000175000017500000000000013155164170020550 5ustar wouterwouterola-0.10.5.nojsmin/plugins/openpixelcontrol/OPCPort.h0000644000175000017500000000551313023355232022206 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OPCPort.h * Ports for the Open Pixel Control plugin. * Copyright (C) 2014 Simon Newton */ #ifndef PLUGINS_OPENPIXELCONTROL_OPCPORT_H_ #define PLUGINS_OPENPIXELCONTROL_OPCPORT_H_ #include #include "ola/DmxBuffer.h" #include "olad/Port.h" #include "plugins/openpixelcontrol/OPCDevice.h" namespace ola { namespace plugin { namespace openpixelcontrol { /** * @brief An InputPort for the OPC plugin. * * OPCInputPorts correspond to a listening TCP socket. */ class OPCInputPort: public BasicInputPort { public: /** * @brief Create a new OPC Input Port. * @param parent the OPCDevice this port belongs to * @param channel the OPC channel for the port. * @param plugin_adaptor the PluginAdaptor to use * @param server the OPCServer to use, ownership is not transferred. */ OPCInputPort(OPCServerDevice *parent, uint8_t channel, class PluginAdaptor *plugin_adaptor, class OPCServer *server); const DmxBuffer &ReadDMX() const { return m_buffer; } bool WriteDMX(const DmxBuffer &buffer, uint8_t priority); std::string Description() const; private: const uint8_t m_channel; class OPCServer* const m_server; DmxBuffer m_buffer; void NewData(uint8_t command, const uint8_t *data, unsigned int length); DISALLOW_COPY_AND_ASSIGN(OPCInputPort); }; /** * @brief An OutputPort for the OPC plugin. */ class OPCOutputPort: public BasicOutputPort { public: /** * @brief Create a new OPC Output Port. * @param parent the OPCDevice this port belongs to * @param channel the OPC channel for the port. * @param client the OPCClient to use for this port, ownership is not * transferred. */ OPCOutputPort(OPCClientDevice *parent, uint8_t channel, class OPCClient *client); bool WriteDMX(const DmxBuffer &buffer, uint8_t priority); std::string Description() const; private: class OPCClient* const m_client; const uint8_t m_channel; DISALLOW_COPY_AND_ASSIGN(OPCOutputPort); }; } // namespace openpixelcontrol } // namespace plugin } // namespace ola #endif // PLUGINS_OPENPIXELCONTROL_OPCPORT_H_ ola-0.10.5.nojsmin/plugins/openpixelcontrol/Makefile.mk0000644000175000017500000000355113023355232022615 0ustar wouterwouter# LIBRARIES ################################################## if USE_OPENPIXELCONTROL # This is a library which isn't coupled to olad noinst_LTLIBRARIES += plugins/openpixelcontrol/libolaopc.la plugins_openpixelcontrol_libolaopc_la_SOURCES = \ plugins/openpixelcontrol/OPCClient.cpp \ plugins/openpixelcontrol/OPCClient.h \ plugins/openpixelcontrol/OPCConstants.h \ plugins/openpixelcontrol/OPCServer.cpp \ plugins/openpixelcontrol/OPCServer.h plugins_openpixelcontrol_libolaopc_la_LIBADD = \ common/libolacommon.la lib_LTLIBRARIES += plugins/openpixelcontrol/libolaopenpixelcontrol.la plugins_openpixelcontrol_libolaopenpixelcontrol_la_SOURCES = \ plugins/openpixelcontrol/OPCDevice.cpp \ plugins/openpixelcontrol/OPCDevice.h \ plugins/openpixelcontrol/OPCPlugin.cpp \ plugins/openpixelcontrol/OPCPlugin.h \ plugins/openpixelcontrol/OPCPort.cpp \ plugins/openpixelcontrol/OPCPort.h plugins_openpixelcontrol_libolaopenpixelcontrol_la_LIBADD = \ common/libolacommon.la \ olad/plugin_api/libolaserverplugininterface.la \ plugins/openpixelcontrol/libolaopc.la # TESTS ################################################## test_programs += \ plugins/openpixelcontrol/OPCClientTester \ plugins/openpixelcontrol/OPCServerTester plugins_openpixelcontrol_OPCClientTester_SOURCES = \ plugins/openpixelcontrol/OPCClientTest.cpp plugins_openpixelcontrol_OPCClientTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) plugins_openpixelcontrol_OPCClientTester_LDADD = \ $(COMMON_TESTING_LIBS) \ plugins/openpixelcontrol/libolaopc.la plugins_openpixelcontrol_OPCServerTester_SOURCES = \ plugins/openpixelcontrol/OPCServerTest.cpp plugins_openpixelcontrol_OPCServerTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) plugins_openpixelcontrol_OPCServerTester_LDADD = \ $(COMMON_TESTING_LIBS) \ plugins/openpixelcontrol/libolaopc.la endif ola-0.10.5.nojsmin/plugins/openpixelcontrol/OPCClient.h0000644000175000017500000000622713023355232022503 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OPCClient.h * The Open Pixel Control Client. * Copyright (C) 2014 Simon Newton */ #ifndef PLUGINS_OPENPIXELCONTROL_OPCCLIENT_H_ #define PLUGINS_OPENPIXELCONTROL_OPCCLIENT_H_ #include #include #include "ola/DmxBuffer.h" #include "ola/io/MemoryBlockPool.h" #include "ola/io/SelectServerInterface.h" #include "ola/network/AdvancedTCPConnector.h" #include "ola/network/SocketAddress.h" #include "ola/network/TCPSocket.h" #include "ola/util/Backoff.h" namespace ola { namespace io { class NonBlockingSender; } // namespace io namespace plugin { namespace openpixelcontrol { /** * @brief An Open Pixel Control client. * * The OPC client connects to a remote IP:port and sends OPC messages. */ class OPCClient { public: /** * @brief Called when the socket changes state. */ typedef ola::Callback1 SocketEventCallback; /** * @brief Create a new OPCClient. * @param ss The SelectServer to use * @param target the remote IP:port to connect to. */ OPCClient(ola::io::SelectServerInterface *ss, const ola::network::IPV4SocketAddress &target); /** * @brief Destructor. */ ~OPCClient(); /** * @brief Return the remote address for this Client. * @returns An IP:port as a string. */ std::string GetRemoteAddress() const { return m_target.ToString(); } /** * @brief Send a DMX frame. * @param channel the OPC channel to use. * @param buffer the DMX data. */ bool SendDmx(uint8_t channel, const DmxBuffer &buffer); /** * @brief Set the callback to be run when the socket state changes. * @param callback the callback to run when the socket state changes. * Ownership is transferred. */ void SetSocketCallback(SocketEventCallback *callback); private: ola::io::SelectServerInterface *m_ss; const ola::network::IPV4SocketAddress m_target; ola::ExponentialBackoffPolicy m_backoff; ola::io::MemoryBlockPool m_pool; ola::network::TCPSocketFactory m_socket_factory; ola::network::AdvancedTCPConnector m_tcp_connector; std::auto_ptr m_client_socket; std::auto_ptr m_sender; std::auto_ptr m_socket_callback; void SocketConnected(ola::network::TCPSocket *socket); void NewData(); void SocketClosed(); DISALLOW_COPY_AND_ASSIGN(OPCClient); }; } // namespace openpixelcontrol } // namespace plugin } // namespace ola #endif // PLUGINS_OPENPIXELCONTROL_OPCCLIENT_H_ ola-0.10.5.nojsmin/plugins/openpixelcontrol/OPCConstants.h0000644000175000017500000000271113023355232023233 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OPCConstants.h * Constants for the Open Pixel Control Protocol. * Copyright (C) 2014 Simon Newton */ #ifndef PLUGINS_OPENPIXELCONTROL_OPCCONSTANTS_H_ #define PLUGINS_OPENPIXELCONTROL_OPCCONSTANTS_H_ #include #include "ola/Constants.h" namespace ola { namespace plugin { namespace openpixelcontrol { enum { /** * @brief The size of the OPC frame header. */ OPC_HEADER_SIZE = 4, /** * @brief The size of an OPC frame with DMX512 data. */ OPC_FRAME_SIZE = DMX_UNIVERSE_SIZE + OPC_HEADER_SIZE, }; /** * @brief The set-pixel command */ static const uint8_t SET_PIXEL_COMMAND = 0; } // namespace openpixelcontrol } // namespace plugin } // namespace ola #endif // PLUGINS_OPENPIXELCONTROL_OPCCONSTANTS_H_ ola-0.10.5.nojsmin/plugins/openpixelcontrol/OPCPlugin.cpp0000644000175000017500000000762013023355232023054 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OPCPlugin.cpp * The Open Pixel Control Plugin. * Copyright (C) 2014 Simon Newton */ #include "plugins/openpixelcontrol/OPCPlugin.h" #include #include #include #include "ola/Logging.h" #include "ola/network/SocketAddress.h" #include "olad/Device.h" #include "olad/PluginAdaptor.h" #include "olad/Preferences.h" #include "plugins/openpixelcontrol/OPCDevice.h" namespace ola { namespace plugin { namespace openpixelcontrol { using ola::network::IPV4SocketAddress; using std::string; using std::vector; const char OPCPlugin::LISTEN_KEY[] = "listen"; const char OPCPlugin::PLUGIN_NAME[] = "Open Pixel Control"; const char OPCPlugin::PLUGIN_PREFIX[] = "openpixelcontrol"; const char OPCPlugin::TARGET_KEY[] = "target"; OPCPlugin::~OPCPlugin() {} bool OPCPlugin::StartHook() { // Start Target (output) devices. AddDevices(TARGET_KEY); // Start listen (input) devices. AddDevices(LISTEN_KEY); return true; } bool OPCPlugin::StopHook() { OPCDevices::iterator iter = m_devices.begin(); for (; iter != m_devices.end(); ++iter) { m_plugin_adaptor->UnregisterDevice(*iter); (*iter)->Stop(); delete *iter; } m_devices.clear(); return true; } string OPCPlugin::Description() const { return "OPC Plugin\n" "----------------------------\n" "\n" "This plugin creates OPC Client and/or OPC Server Devices.\n" "\n" "--- Config file : ola-opc.conf ---\n" "\n" "target = :\n" "Create a Open Pixel Control client, connected to the IP:port.\n" "Multiple targets can be specified and a device will be created\n" "for each.\n" "\n" "listen = :\n" "Create an Open Pixel Control server, listening on IP:port.\n" "To listen on any address use listen = 0.0.0.0.\n" "Multiple listen keys can be specified and a device will be created\n" "for each.\n" "\n" "target_:_channel = \n" "The Open Pixel Control channels to use for the specified device.\n" "Multiple channels can be specified and an output port will be created\n" "for each.\n" "\n" "listen_:_channel = \n" "The Open Pixel Control channels to use for the specified device.\n" "Multiple channels can be specified and an input port will be created\n" "for each.\n" "\n"; } bool OPCPlugin::SetDefaultPreferences() { if (!m_preferences) { return false; } // No defaults. return true; } template void OPCPlugin::AddDevices(const std::string &key) { vector addresses = m_preferences->GetMultipleValue(key); vector::const_iterator iter = addresses.begin(); for (; iter != addresses.end(); ++iter) { IPV4SocketAddress target; if (!IPV4SocketAddress::FromString(*iter, &target)) { OLA_WARN << "Invalid Open Pixel Control address: " << *iter; continue; } std::auto_ptr device(new DeviceClass( this, m_plugin_adaptor, m_preferences, target)); if (!device->Start()) { OLA_INFO << "Failed to start OPCDevice"; continue; } m_plugin_adaptor->RegisterDevice(device.get()); OLA_INFO << "Added OPC device"; m_devices.push_back(device.release()); } } } // namespace openpixelcontrol } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/openpixelcontrol/OPCDevice.h0000644000175000017500000000575513023355232022471 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OPCDevice.h * The Open Pixel Control Device. * Copyright (C) 2014 Simon Newton */ #ifndef PLUGINS_OPENPIXELCONTROL_OPCDEVICE_H_ #define PLUGINS_OPENPIXELCONTROL_OPCDEVICE_H_ #include #include #include "ola/network/Socket.h" #include "olad/Device.h" #include "plugins/openpixelcontrol/OPCClient.h" #include "plugins/openpixelcontrol/OPCServer.h" namespace ola { class AbstractPlugin; namespace plugin { namespace openpixelcontrol { class OPCServerDevice: public ola::Device { public: /** * @brief Create a new OPC server device. * @param owner the Plugin that owns this device * @param plugin_adaptor the PluginAdaptor to use * @param preferences the Preferences container. * @param listen_addr the IP:port to listen on. */ OPCServerDevice(AbstractPlugin *owner, PluginAdaptor *plugin_adaptor, Preferences *preferences, const ola::network::IPV4SocketAddress listen_addr); std::string DeviceId() const; bool AllowMultiPortPatching() const { return true; } protected: bool StartHook(); private: PluginAdaptor* const m_plugin_adaptor; Preferences* const m_preferences; const ola::network::IPV4SocketAddress m_listen_addr; std::auto_ptr m_server; DISALLOW_COPY_AND_ASSIGN(OPCServerDevice); }; class OPCClientDevice: public ola::Device { public: /** * @brief Create a new OPC client device. * @param owner the Plugin that owns this device * @param plugin_adaptor the PluginAdaptor to use * @param preferences the Preferences container. * @param target the IP:port to connect to. */ OPCClientDevice(AbstractPlugin *owner, PluginAdaptor *plugin_adaptor, Preferences *preferences, const ola::network::IPV4SocketAddress target); std::string DeviceId() const; bool AllowMultiPortPatching() const { return true; } protected: bool StartHook(); private: PluginAdaptor* const m_plugin_adaptor; Preferences* const m_preferences; const ola::network::IPV4SocketAddress m_target; std::auto_ptr m_client; DISALLOW_COPY_AND_ASSIGN(OPCClientDevice); }; } // namespace openpixelcontrol } // namespace plugin } // namespace ola #endif // PLUGINS_OPENPIXELCONTROL_OPCDEVICE_H_ ola-0.10.5.nojsmin/plugins/openpixelcontrol/OPCDevice.cpp0000644000175000017500000000714313023355232023015 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OPCDevice.cpp * The Open Pixel Control Device. * Copyright (C) 2014 Simon Newton */ #include "plugins/openpixelcontrol/OPCDevice.h" #include #include #include #include #include "ola/Logging.h" #include "olad/Preferences.h" #include "plugins/openpixelcontrol/OPCPort.h" namespace ola { namespace plugin { namespace openpixelcontrol { using ola::AbstractPlugin; using std::ostringstream; using std::set; using std::string; using std::vector; namespace { set DeDupChannels(const vector &channels) { set output; vector::const_iterator iter = channels.begin(); for (; iter != channels.end(); ++iter) { uint8_t channel; if (!StringToInt(*iter, &channel)) { OLA_WARN << "Invalid Open Pixel Control channel " << *iter; continue; } output.insert(channel); } return output; } } // namespace OPCServerDevice::OPCServerDevice( AbstractPlugin *owner, PluginAdaptor *plugin_adaptor, Preferences *preferences, const ola::network::IPV4SocketAddress listen_addr) : Device(owner, "OPC Server: " + listen_addr.ToString()), m_plugin_adaptor(plugin_adaptor), m_preferences(preferences), m_listen_addr(listen_addr), m_server(new OPCServer(plugin_adaptor, listen_addr)) { } string OPCServerDevice::DeviceId() const { return m_listen_addr.ToString(); } bool OPCServerDevice::StartHook() { if (!m_server->Init()) { return false; } ostringstream str; str << "listen_" << m_listen_addr << "_channel"; set channels = DeDupChannels( m_preferences->GetMultipleValue(str.str())); set::const_iterator iter = channels.begin(); for (; iter != channels.end(); ++iter) { OPCInputPort *port = new OPCInputPort(this, *iter, m_plugin_adaptor, m_server.get()); AddPort(port); } return true; } OPCClientDevice::OPCClientDevice(AbstractPlugin *owner, PluginAdaptor *plugin_adaptor, Preferences *preferences, const ola::network::IPV4SocketAddress target) : Device(owner, "OPC Client " + target.ToString()), m_plugin_adaptor(plugin_adaptor), m_preferences(preferences), m_target(target), m_client(new OPCClient(plugin_adaptor, target)) { } string OPCClientDevice::DeviceId() const { return m_target.ToString(); } bool OPCClientDevice::StartHook() { ostringstream str; str << "target_" << m_target << "_channel"; set channels = DeDupChannels( m_preferences->GetMultipleValue(str.str())); set::const_iterator iter = channels.begin(); for (; iter != channels.end(); ++iter) { OPCOutputPort *port = new OPCOutputPort(this, *iter, m_client.get()); AddPort(port); } return true; } } // namespace openpixelcontrol } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/openpixelcontrol/OPCPlugin.h0000644000175000017500000000364113023355232022520 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OPCPlugin.h * The Open Pixel Control Plugin. * Copyright (C) 2014 Simon Newton */ #ifndef PLUGINS_OPENPIXELCONTROL_OPCPLUGIN_H_ #define PLUGINS_OPENPIXELCONTROL_OPCPLUGIN_H_ #include #include #include "ola/plugin_id.h" #include "olad/Device.h" #include "olad/Plugin.h" namespace ola { namespace plugin { namespace openpixelcontrol { class OPCPlugin: public Plugin { public: explicit OPCPlugin(PluginAdaptor *plugin_adaptor) : Plugin(plugin_adaptor) {} ~OPCPlugin(); std::string Name() const { return PLUGIN_NAME; } ola_plugin_id Id() const { return OLA_PLUGIN_OPENPIXELCONTROL; } std::string Description() const; std::string PluginPrefix() const { return PLUGIN_PREFIX; } private: typedef std::vector OPCDevices; OPCDevices m_devices; bool StartHook(); bool StopHook(); bool SetDefaultPreferences(); template void AddDevices(const std::string &key); static const char LISTEN_KEY[]; static const char PLUGIN_NAME[]; static const char PLUGIN_PREFIX[]; static const char TARGET_KEY[]; }; } // namespace openpixelcontrol } // namespace plugin } // namespace ola #endif // PLUGINS_OPENPIXELCONTROL_OPCPLUGIN_H_ ola-0.10.5.nojsmin/plugins/openpixelcontrol/OPCClientTest.cpp0000644000175000017500000000620513023355232023672 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OPCClientTest.cpp * Test fixture for the OPCClient class * Copyright (C) 2014 Simon Newton */ #include #include #include "ola/base/Array.h" #include "ola/Callback.h" #include "ola/DmxBuffer.h" #include "ola/Logging.h" #include "ola/io/SelectServer.h" #include "ola/network/IPV4Address.h" #include "ola/network/SocketAddress.h" #include "ola/testing/TestUtils.h" #include "ola/util/Utils.h" #include "plugins/openpixelcontrol/OPCClient.h" #include "plugins/openpixelcontrol/OPCServer.h" using ola::DmxBuffer; using ola::network::IPV4Address; using ola::network::IPV4SocketAddress; using ola::plugin::openpixelcontrol::OPCClient; using ola::plugin::openpixelcontrol::OPCServer; using std::auto_ptr; class OPCClientTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(OPCClientTest); CPPUNIT_TEST(testTransmit); CPPUNIT_TEST_SUITE_END(); public: OPCClientTest() : CppUnit::TestFixture(), m_ss(NULL) { } void setUp(); void testTransmit(); private: ola::io::SelectServer m_ss; auto_ptr m_server; DmxBuffer m_received_data; uint8_t m_command; void CaptureData(uint8_t command, const uint8_t *data, unsigned int length) { m_received_data.Set(data, length); m_command = command; m_ss.Terminate(); } void SendDMX(OPCClient *client, DmxBuffer *buffer, bool connected) { if (connected) { OLA_ASSERT_TRUE(client->SendDmx(CHANNEL, *buffer)); } else { m_ss.Terminate(); } } static const uint8_t CHANNEL = 1; }; CPPUNIT_TEST_SUITE_REGISTRATION(OPCClientTest); void OPCClientTest::setUp() { IPV4SocketAddress listen_addr(IPV4Address::Loopback(), 0); m_server.reset(new OPCServer(&m_ss, listen_addr)); m_server->SetCallback( CHANNEL, ola::NewCallback(this, &OPCClientTest::CaptureData)); OLA_ASSERT_TRUE(m_server->Init()); } void OPCClientTest::testTransmit() { OPCClient client(&m_ss, m_server->ListenAddress()); OLA_ASSERT_EQ(m_server->ListenAddress().ToString(), client.GetRemoteAddress()); DmxBuffer buffer; buffer.SetFromString("1,2,3,4"); client.SetSocketCallback( ola::NewCallback(this, &OPCClientTest::SendDMX, &client, &buffer)); m_ss.Run(); OLA_ASSERT_EQ(m_received_data, buffer); // Now shut down the server. m_server.reset(); m_ss.Run(); // Now sends should fail since there is no connection OLA_ASSERT_FALSE(client.SendDmx(CHANNEL, buffer)); } ola-0.10.5.nojsmin/plugins/openpixelcontrol/OPCClient.cpp0000644000175000017500000000671213023355232023035 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OPCClient.cpp * The Open Pixel Control Client. * Copyright (C) 2014 Simon Newton */ #include "plugins/openpixelcontrol/OPCClient.h" #include "ola/Callback.h" #include "ola/Logging.h" #include "ola/base/Array.h" #include "ola/io/BigEndianStream.h" #include "ola/io/IOQueue.h" #include "ola/io/NonBlockingSender.h" #include "ola/network/SocketAddress.h" #include "ola/util/Utils.h" #include "plugins/openpixelcontrol/OPCConstants.h" namespace ola { namespace plugin { namespace openpixelcontrol { using ola::TimeInterval; using ola::network::TCPSocket; OPCClient::OPCClient(ola::io::SelectServerInterface *ss, const ola::network::IPV4SocketAddress &target) : m_ss(ss), m_target(target), m_backoff(TimeInterval(1, 0), TimeInterval(300, 0)), m_pool(OPC_FRAME_SIZE), m_socket_factory(NewCallback(this, &OPCClient::SocketConnected)), m_tcp_connector(ss, &m_socket_factory, TimeInterval(3, 0)) { m_tcp_connector.AddEndpoint(target, &m_backoff); } OPCClient::~OPCClient() { if (m_client_socket.get()) { m_ss->RemoveReadDescriptor(m_client_socket.get()); m_tcp_connector.Disconnect(m_target, true); } } bool OPCClient::SendDmx(uint8_t channel, const DmxBuffer &buffer) { if (!m_sender.get()) { return false; // not connected } ola::io::IOQueue queue(&m_pool); ola::io::BigEndianOutputStream stream(&queue); stream << channel; stream << SET_PIXEL_COMMAND; stream << static_cast(buffer.Size()); stream.Write(buffer.GetRaw(), buffer.Size()); return m_sender->SendMessage(&queue); } void OPCClient::SetSocketCallback(SocketEventCallback *callback) { m_socket_callback.reset(callback); } void OPCClient::SocketConnected(TCPSocket *socket) { m_client_socket.reset(socket); m_client_socket->SetOnData(NewCallback(this, &OPCClient::NewData)); m_client_socket->SetOnClose( NewSingleCallback(this, &OPCClient::SocketClosed)); m_ss->AddReadDescriptor(socket); m_sender.reset( new ola::io::NonBlockingSender(socket, m_ss, &m_pool, OPC_FRAME_SIZE)); if (m_socket_callback.get()) { m_socket_callback->Run(true); } } void OPCClient::NewData() { // The OPC protocol seems to be unidirectional. The other clients don't even // bother reading from the socket. // Rather than letting the data buffer we read and discard any incoming data // here. OLA_WARN << "Received unexpected data from " << m_target; uint8_t discard[512]; unsigned int data_received; m_client_socket->Receive(discard, arraysize(discard), data_received); } void OPCClient::SocketClosed() { m_sender.reset(); m_client_socket.reset(); if (m_socket_callback.get()) { m_socket_callback->Run(false); } } } // namespace openpixelcontrol } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/openpixelcontrol/OPCServer.h0000644000175000017500000000715713023355232022536 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OPCServer.h * The Open Pixel Server. * Copyright (C) 2014 Simon Newton */ #ifndef PLUGINS_OPENPIXELCONTROL_OPCSERVER_H_ #define PLUGINS_OPENPIXELCONTROL_OPCSERVER_H_ #include #include #include #include "ola/Constants.h" #include "ola/DmxBuffer.h" #include "ola/io/SelectServerInterface.h" #include "ola/network/SocketAddress.h" #include "ola/network/TCPSocket.h" #include "ola/network/TCPSocketFactory.h" #include "plugins/openpixelcontrol/OPCConstants.h" namespace ola { namespace plugin { namespace openpixelcontrol { /** * @brief An Open Pixel Control server. * * The server listens on a TCP port and receives OPC data. */ class OPCServer { public: /** * @brief The callback executed when new OPC data arrives. */ typedef Callback3 ChannelCallback; /** * @brief Create a new OPCServer. * @param ss The SelectServer to use * @param listen_addr the IP:port to listen on. */ OPCServer(ola::io::SelectServerInterface *ss, const ola::network::IPV4SocketAddress &listen_addr); /** * @brief Destructor. */ ~OPCServer(); /** * @brief Initialize the OPCServer. * @returns true if the server is now listening for new connections, false * otherwise. */ bool Init(); /** * @brief Set the callback to be run when channel data arrives. * @param channel the OPC channel this callback is for. * @param callback The callback to run, ownership is transferred and any * previous callbacks for this channel are removed. */ void SetCallback(uint8_t channel, ChannelCallback *callback); /** * @brief The listen address of this server * @returns The listen address of the server. If the server isn't listening * the empty string is returned. */ ola::network::IPV4SocketAddress ListenAddress() const; private: struct RxState { public: unsigned int offset; uint16_t expected_size; uint8_t *data; unsigned int buffer_size; RxState() : offset(0), expected_size(0) { buffer_size = OPC_FRAME_SIZE, data = new uint8_t[buffer_size]; } ~RxState() { delete[] data; } void CheckSize(); }; typedef std::map ClientMap; ola::io::SelectServerInterface* const m_ss; const ola::network::IPV4SocketAddress m_listen_addr; ola::network::TCPSocketFactory m_tcp_socket_factory; std::auto_ptr m_listening_socket; ClientMap m_clients; std::map m_callbacks; void NewTCPConnection(ola::network::TCPSocket *socket); void SocketReady(ola::network::TCPSocket *socket, RxState *rx_state); void SocketClosed(ola::network::TCPSocket *socket); DISALLOW_COPY_AND_ASSIGN(OPCServer); }; } // namespace openpixelcontrol } // namespace plugin } // namespace ola #endif // PLUGINS_OPENPIXELCONTROL_OPCSERVER_H_ ola-0.10.5.nojsmin/plugins/openpixelcontrol/OPCServerTest.cpp0000644000175000017500000001037213023355232023722 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OPCServerTest.cpp * Test fixture for the OPCServer class * Copyright (C) 2014 Simon Newton */ #include #include #include "ola/base/Array.h" #include "ola/Callback.h" #include "ola/DmxBuffer.h" #include "ola/Logging.h" #include "ola/io/SelectServer.h" #include "ola/network/IPV4Address.h" #include "ola/network/SocketAddress.h" #include "ola/network/TCPSocket.h" #include "ola/testing/TestUtils.h" #include "ola/util/Utils.h" #include "plugins/openpixelcontrol/OPCServer.h" using ola::DmxBuffer; using ola::network::IPV4Address; using ola::network::IPV4SocketAddress; using ola::network::TCPSocket; using ola::plugin::openpixelcontrol::OPCServer; using std::auto_ptr; class OPCServerTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(OPCServerTest); CPPUNIT_TEST(testReceiveDmx); CPPUNIT_TEST(testUnknownCommand); CPPUNIT_TEST(testLargeFrame); CPPUNIT_TEST(testHangingFrame); CPPUNIT_TEST_SUITE_END(); public: OPCServerTest() : CppUnit::TestFixture(), m_ss(NULL) { } void setUp(); void testReceiveDmx(); void testUnknownCommand(); void testLargeFrame(); void testHangingFrame(); private: ola::io::SelectServer m_ss; auto_ptr m_server; auto_ptr m_client_socket; DmxBuffer m_received_data; uint8_t m_command; void SendDataAndCheck(uint8_t channel, const DmxBuffer &data); void CaptureData(uint8_t command, const uint8_t *data, unsigned int length) { m_received_data.Set(data, length); m_command = command; m_ss.Terminate(); } static const uint8_t CHANNEL = 1; static const uint8_t SET_PIXELS_COMMAND = 0; }; CPPUNIT_TEST_SUITE_REGISTRATION(OPCServerTest); void OPCServerTest::setUp() { IPV4SocketAddress listen_addr(IPV4Address::Loopback(), 0); m_server.reset(new OPCServer(&m_ss, listen_addr)); m_server->SetCallback( CHANNEL, ola::NewCallback(this, &OPCServerTest::CaptureData)); OLA_ASSERT_TRUE(m_server->Init()); m_client_socket.reset(TCPSocket::Connect(m_server->ListenAddress())); } void OPCServerTest::SendDataAndCheck(uint8_t channel, const DmxBuffer &buffer) { unsigned int dmx_size = buffer.Size(); uint8_t data[dmx_size + 4]; data[0] = channel; data[1] = SET_PIXELS_COMMAND; ola::utils::SplitUInt16(static_cast(dmx_size), &data[2], &data[3]); buffer.Get(data + 4, &dmx_size); m_client_socket->Send(data, dmx_size + 4); m_ss.Run(); OLA_ASSERT_EQ(m_received_data, buffer); } void OPCServerTest::testReceiveDmx() { DmxBuffer buffer; buffer.SetFromString("1,2,3,4"); SendDataAndCheck(CHANNEL, buffer); buffer.SetFromString("5,6"); SendDataAndCheck(CHANNEL, buffer); buffer.SetFromString("5,6,7,8,89,9,5,6,7,8,3"); SendDataAndCheck(CHANNEL, buffer); } void OPCServerTest::testUnknownCommand() { uint8_t data[] = {1, 1, 0, 2, 3, 4}; m_client_socket->Send(data, arraysize(data)); m_ss.Run(); DmxBuffer buffer; buffer.SetFromString("3,4"); OLA_ASSERT_EQ(static_cast(1), m_command); OLA_ASSERT_EQ(m_received_data, buffer); } void OPCServerTest::testLargeFrame() { uint8_t data[1028]; data[0] = 1; data[1] = 0; data[2] = 4; data[3] = 0; for (unsigned int i = 0; i < 1024; i++) { data[i + 4] = i; } m_client_socket->Send(data, arraysize(data)); m_ss.Run(); DmxBuffer buffer(data + 4, ola::DMX_UNIVERSE_SIZE); OLA_ASSERT_EQ(m_received_data, buffer); } void OPCServerTest::testHangingFrame() { uint8_t data[] = {1, 0}; m_client_socket->Send(data, arraysize(data)); } ola-0.10.5.nojsmin/plugins/openpixelcontrol/OPCServer.cpp0000644000175000017500000001155513023355232023066 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OPCServer.cpp * The Open Pixel Server. * Copyright (C) 2014 Simon Newton */ #include "plugins/openpixelcontrol/OPCServer.h" #include #include "ola/Callback.h" #include "ola/Logging.h" #include "ola/base/Array.h" #include "ola/network/SocketAddress.h" #include "ola/stl/STLUtils.h" #include "ola/util/Utils.h" namespace ola { namespace plugin { namespace openpixelcontrol { using ola::network::GenericSocketAddress; using ola::network::IPV4SocketAddress; using ola::network::TCPAcceptingSocket; using ola::network::TCPSocket; using std::string; namespace { void CleanupSocket(TCPSocket *socket) { delete socket; } } // namespace void OPCServer::RxState::CheckSize() { expected_size = utils::JoinUInt8(data[2], data[3]); if (static_cast(expected_size) + OPC_HEADER_SIZE > buffer_size) { uint8_t *new_buffer = new uint8_t[expected_size + OPC_HEADER_SIZE]; memcpy(new_buffer, data, offset); delete[] data; data = new_buffer; buffer_size = expected_size + OPC_HEADER_SIZE; } } OPCServer::OPCServer(ola::io::SelectServerInterface *ss, const ola::network::IPV4SocketAddress &listen_addr) : m_ss(ss), m_listen_addr(listen_addr), m_tcp_socket_factory( ola::NewCallback(this, &OPCServer::NewTCPConnection)) { } OPCServer::~OPCServer() { if (m_listening_socket.get()) { m_ss->RemoveReadDescriptor(m_listening_socket.get()); m_listening_socket.reset(); } ClientMap::iterator iter = m_clients.begin(); for (; iter != m_clients.end(); ++iter) { m_ss->RemoveReadDescriptor(iter->first); delete iter->first; delete iter->second; } STLDeleteValues(&m_callbacks); } bool OPCServer::Init() { std::auto_ptr listening_socket( new TCPAcceptingSocket(&m_tcp_socket_factory)); if (!listening_socket->Listen(m_listen_addr)) { return false; } m_ss->AddReadDescriptor(listening_socket.get()); m_listening_socket.reset(listening_socket.release()); return true; } IPV4SocketAddress OPCServer::ListenAddress() const { if (m_listening_socket.get()) { GenericSocketAddress addr = m_listening_socket->GetLocalAddress(); if (addr.Family() == AF_INET) { return addr.V4Addr(); } } return IPV4SocketAddress(); } void OPCServer::SetCallback(uint8_t channel, ChannelCallback *callback) { STLReplaceAndDelete(&m_callbacks, channel, callback); } void OPCServer::NewTCPConnection(TCPSocket *socket) { if (!socket) return; RxState *rx_state = new RxState(); socket->SetNoDelay(); socket->SetOnData( NewCallback(this, &OPCServer::SocketReady, socket, rx_state)); socket->SetOnClose( NewSingleCallback(this, &OPCServer::SocketClosed, socket)); m_ss->AddReadDescriptor(socket); STLReplaceAndDelete(&m_clients, socket, rx_state); } void OPCServer::SocketReady(TCPSocket *socket, RxState *rx_state) { unsigned int data_received = 0; if (socket->Receive(rx_state->data + rx_state->offset, rx_state->buffer_size - rx_state->offset, data_received) < 0) { OLA_WARN << "Bad read from " << socket->GetPeerAddress(); SocketClosed(socket); return; } rx_state->offset += data_received; if (rx_state->offset < OPC_HEADER_SIZE) { return; } rx_state->CheckSize(); if (rx_state->offset < static_cast(rx_state->expected_size) + OPC_HEADER_SIZE) { return; } ChannelCallback *cb = STLFindOrNull(m_callbacks, rx_state->data[0]); if (cb) { DmxBuffer buffer(rx_state->data + OPC_HEADER_SIZE, rx_state->offset - OPC_HEADER_SIZE); cb->Run(rx_state->data[1], rx_state->data + OPC_HEADER_SIZE, rx_state->expected_size); } rx_state->offset = 0; rx_state->expected_size = 0; } void OPCServer::SocketClosed(TCPSocket *socket) { m_ss->RemoveReadDescriptor(socket); STLRemoveAndDelete(&m_clients, socket); // Since we're in the call stack of the socket, we schedule deletion during // the next run of the event loop to break out of the stack. m_ss->Execute(NewSingleCallback(&CleanupSocket, socket)); } } // namespace openpixelcontrol } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/openpixelcontrol/OPCPort.cpp0000644000175000017500000000532313023355232022540 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OPCPort.cpp * The OPC Port for ola * Copyright (C) 2014 Simon Newton */ #include "plugins/openpixelcontrol/OPCPort.h" #include #include "ola/base/Macro.h" #include "plugins/openpixelcontrol/OPCClient.h" #include "plugins/openpixelcontrol/OPCConstants.h" #include "plugins/openpixelcontrol/OPCDevice.h" #include "plugins/openpixelcontrol/OPCServer.h" namespace ola { namespace plugin { namespace openpixelcontrol { using std::string; OPCInputPort::OPCInputPort(OPCServerDevice *parent, uint8_t channel, class PluginAdaptor *plugin_adaptor, class OPCServer *server) : BasicInputPort(parent, channel, plugin_adaptor), m_channel(channel), m_server(server) { m_server->SetCallback(channel, NewCallback(this, &OPCInputPort::NewData)); } void OPCInputPort::NewData(uint8_t command, const uint8_t *data, unsigned int length) { if (command != SET_PIXEL_COMMAND) { OLA_DEBUG << "Received an unknown OPC command: " << static_cast(command); return; } m_buffer.Set(data, length); DmxChanged(); } string OPCInputPort::Description() const { std::ostringstream str; str << m_server->ListenAddress() << ", Channel " << static_cast(m_channel); return str.str(); } OPCOutputPort::OPCOutputPort(OPCClientDevice *parent, uint8_t channel, OPCClient *client) : BasicOutputPort(parent, channel), m_client(client), m_channel(channel) { } bool OPCOutputPort::WriteDMX(const DmxBuffer &buffer, OLA_UNUSED uint8_t priority) { return m_client->SendDmx(m_channel, buffer); } string OPCOutputPort::Description() const { std::ostringstream str; str << m_client->GetRemoteAddress() << ", Channel " << static_cast(m_channel); return str.str(); } } // namespace openpixelcontrol } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbpro/0000755000175000017500000000000013134123610016445 5ustar wouterwouterola-0.10.5.nojsmin/plugins/usbpro/BaseUsbProWidget.h0000644000175000017500000000760413023355232022002 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * BaseUsbProWidget.h * Read and Write to a USB Serial Widget that uses the Enttec Usb Pro frame * layout. * Copyright (C) 2010 Simon Newton */ #ifndef PLUGINS_USBPRO_BASEUSBPROWIDGET_H_ #define PLUGINS_USBPRO_BASEUSBPROWIDGET_H_ #include #include #include "ola/Callback.h" #include "ola/DmxBuffer.h" #include "ola/io/Descriptor.h" #include "plugins/usbpro/SerialWidgetInterface.h" namespace ola { namespace plugin { namespace usbpro { /* * A widget that implements the Usb Pro frame format. */ class BaseUsbProWidget: public SerialWidgetInterface { public: explicit BaseUsbProWidget(ola::io::ConnectedDescriptor *descriptor); virtual ~BaseUsbProWidget(); ola::io::ConnectedDescriptor *GetDescriptor() const { return m_descriptor; } void DescriptorReady(); // we locate the SendDMX in the base class since so many widgets share it. virtual bool SendDMX(const DmxBuffer &buffer); bool SendMessage(uint8_t label, const uint8_t *data, unsigned int length) const; static ola::io::ConnectedDescriptor *OpenDevice(const std::string &path); static const uint8_t DEVICE_LABEL = 78; static const uint8_t DMX_LABEL = 6; static const uint8_t GET_PARAMS = 3; static const uint8_t HARDWARE_VERSION_LABEL = 14; static const uint8_t MANUFACTURER_LABEL = 77; static const uint8_t SERIAL_LABEL = 10; private: typedef enum { PRE_SOM, RECV_LABEL, RECV_SIZE_LO, RECV_SIZE_HI, RECV_BODY, RECV_EOM, } receive_state; enum {MAX_DATA_SIZE = 600}; typedef struct { uint8_t som; uint8_t label; uint8_t len; uint8_t len_hi; } message_header; ola::io::ConnectedDescriptor *m_descriptor; receive_state m_state; unsigned int m_bytes_received; message_header m_header; uint8_t m_recv_buffer[MAX_DATA_SIZE]; void ReceiveMessage(); virtual void HandleMessage(uint8_t label, const uint8_t *data, unsigned int length) = 0; static const uint8_t EOM = 0xe7; static const uint8_t SOM = 0x7e; static const unsigned int HEADER_SIZE; }; /** * A Usb Pro Widget that can execute a callback when it receives messages. * This is used for discovery. */ class DispatchingUsbProWidget: public BaseUsbProWidget { public: typedef ola::Callback3 MessageCallback; DispatchingUsbProWidget(ola::io::ConnectedDescriptor *descriptor, MessageCallback *callback) : BaseUsbProWidget(descriptor), m_callback(callback) { } ~DispatchingUsbProWidget() { Stop(); } void Stop() { if (m_callback) delete m_callback; } void SetHandler(MessageCallback *callback) { if (m_callback) delete m_callback; m_callback = callback; } private: MessageCallback *m_callback; void HandleMessage(uint8_t label, const uint8_t *data, unsigned int length) { m_callback->Run(label, data, length); } }; } // namespace usbpro } // namespace plugin } // namespace ola #endif // PLUGINS_USBPRO_BASEUSBPROWIDGET_H_ ola-0.10.5.nojsmin/plugins/usbpro/UltraDMXProDevice.h0000644000175000017500000001213713023355232022067 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * UltraDMXProDevice.h * A DMX King Ultra DMX Pro Device * Copyright (C) 2011 Simon Newton */ #ifndef PLUGINS_USBPRO_ULTRADMXPRODEVICE_H_ #define PLUGINS_USBPRO_ULTRADMXPRODEVICE_H_ #include #include #include "ola/DmxBuffer.h" #include "olad/TokenBucket.h" #include "olad/PluginAdaptor.h" #include "olad/Port.h" #include "plugins/usbpro/UltraDMXProWidget.h" #include "plugins/usbpro/UsbSerialDevice.h" #include "plugins/usbpro/messages/UsbProConfigMessages.pb.h" namespace ola { namespace plugin { namespace usbpro { /* * An Ultra DMX Pro device */ class UltraDMXProDevice: public UsbSerialDevice { public: UltraDMXProDevice(ola::PluginAdaptor *plugin_adaptor, ola::AbstractPlugin *owner, const std::string &name, UltraDMXProWidget *widget, uint16_t esta_id, uint16_t device_id, uint32_t serial, uint16_t firmware_version, unsigned int fps_limit); std::string DeviceId() const { return m_serial; } // both output ports can be bound to the same universe bool AllowMultiPortPatching() const { return true; } void Configure(ola::rpc::RpcController *controller, const std::string &request, std::string *response, ConfigureCallback *done); protected: void PrePortStop(); private: void UpdateParams(bool status, const usb_pro_parameters ¶ms); void HandleParametersRequest(ola::rpc::RpcController *controller, const ola::plugin::usbpro::Request *request, std::string *response, ConfigureCallback *done); void HandleParametersResponse(ola::rpc::RpcController *controller, std::string *response, ConfigureCallback *done, bool status, const usb_pro_parameters ¶ms); void HandleSerialRequest(ola::rpc::RpcController *controller, const ola::plugin::usbpro::Request *request, std::string *response, ConfigureCallback *done); UltraDMXProWidget *m_ultra_widget; std::string m_serial; bool m_got_parameters; uint8_t m_break_time; uint8_t m_mab_time; uint8_t m_rate; }; /* * The Input port */ class UltraDMXProInputPort: public BasicInputPort { public: UltraDMXProInputPort(UltraDMXProDevice *parent, UltraDMXProWidget *widget, unsigned int id, ola::PluginAdaptor *plugin_adaptor, const std::string &description) : BasicInputPort(parent, id, plugin_adaptor), m_description(description), m_widget(widget) {} const DmxBuffer &ReadDMX() const { return m_widget->FetchDMX(); } std::string Description() const { return m_description; } private: const std::string m_description; UltraDMXProWidget *m_widget; }; /* * The output port, we have two of these per device. */ class UltraDMXProOutputPort: public BasicOutputPort { public: UltraDMXProOutputPort(UltraDMXProDevice *parent, UltraDMXProWidget *widget, unsigned int id, const std::string &description, const TimeStamp *wake_time, unsigned int max_burst, unsigned int rate, bool primary) : BasicOutputPort(parent, id), m_description(description), m_widget(widget), m_bucket(max_burst, rate, max_burst, *wake_time), m_wake_time(wake_time), m_primary(primary) {} bool WriteDMX(const DmxBuffer &buffer, OLA_UNUSED uint8_t priority) { if (m_bucket.GetToken(*m_wake_time)) { return m_primary ? m_widget->SendDMX(buffer) : m_widget->SendSecondaryDMX(buffer); } else { OLA_INFO << "Port rated limited, dropping frame"; } return true; } std::string Description() const { return m_description; } private: const std::string m_description; UltraDMXProWidget *m_widget; TokenBucket m_bucket; const TimeStamp *m_wake_time; bool m_primary; }; } // namespace usbpro } // namespace plugin } // namespace ola #endif // PLUGINS_USBPRO_ULTRADMXPRODEVICE_H_ ola-0.10.5.nojsmin/plugins/usbpro/Makefile.mk0000644000175000017500000001416713134123277020535 0ustar wouterwouterinclude plugins/usbpro/messages/Makefile.mk # LIBRARIES ################################################## # This is a library which isn't coupled to olad noinst_LTLIBRARIES += plugins/usbpro/libolausbprowidget.la plugins_usbpro_libolausbprowidget_la_SOURCES = \ plugins/usbpro/ArduinoWidget.cpp \ plugins/usbpro/ArduinoWidget.h \ plugins/usbpro/BaseRobeWidget.cpp \ plugins/usbpro/BaseRobeWidget.h \ plugins/usbpro/BaseUsbProWidget.cpp \ plugins/usbpro/BaseUsbProWidget.h \ plugins/usbpro/DmxTriWidget.cpp \ plugins/usbpro/DmxTriWidget.h \ plugins/usbpro/DmxterWidget.cpp \ plugins/usbpro/DmxterWidget.h \ plugins/usbpro/EnttecUsbProWidget.cpp \ plugins/usbpro/EnttecUsbProWidget.h \ plugins/usbpro/EnttecUsbProWidgetImpl.h \ plugins/usbpro/GenericUsbProWidget.cpp \ plugins/usbpro/GenericUsbProWidget.h \ plugins/usbpro/RobeWidget.cpp \ plugins/usbpro/RobeWidget.h \ plugins/usbpro/RobeWidgetDetector.cpp \ plugins/usbpro/RobeWidgetDetector.h \ plugins/usbpro/SerialWidgetInterface.h \ plugins/usbpro/SerialWidgetInterface.h \ plugins/usbpro/UltraDMXProWidget.cpp \ plugins/usbpro/UltraDMXProWidget.h \ plugins/usbpro/UsbProWidgetDetector.cpp \ plugins/usbpro/UsbProWidgetDetector.h \ plugins/usbpro/WidgetDetectorInterface.h \ plugins/usbpro/WidgetDetectorThread.cpp \ plugins/usbpro/WidgetDetectorThread.h plugins_usbpro_libolausbprowidget_la_LIBADD = common/libolacommon.la if USE_USBPRO # The OLA USB Pro Plugin lib_LTLIBRARIES += plugins/usbpro/libolausbpro.la plugins_usbpro_libolausbpro_la_SOURCES = \ plugins/usbpro/ArduinoRGBDevice.cpp \ plugins/usbpro/ArduinoRGBDevice.h \ plugins/usbpro/DmxTriDevice.cpp \ plugins/usbpro/DmxTriDevice.h \ plugins/usbpro/DmxterDevice.cpp \ plugins/usbpro/DmxterDevice.h \ plugins/usbpro/RobeDevice.cpp \ plugins/usbpro/RobeDevice.h \ plugins/usbpro/UltraDMXProDevice.cpp \ plugins/usbpro/UltraDMXProDevice.h \ plugins/usbpro/UsbProDevice.cpp \ plugins/usbpro/UsbProDevice.h \ plugins/usbpro/UsbSerialDevice.h \ plugins/usbpro/UsbSerialPlugin.cpp \ plugins/usbpro/UsbSerialPlugin.h plugins_usbpro_libolausbpro_la_CXXFLAGS = $(COMMON_PROTOBUF_CXXFLAGS) plugins_usbpro_libolausbpro_la_LIBADD = \ olad/plugin_api/libolaserverplugininterface.la \ plugins/usbpro/libolausbprowidget.la \ plugins/usbpro/messages/libolausbproconf.la # TESTS ################################################## test_programs += \ plugins/usbpro/ArduinoWidgetTester \ plugins/usbpro/BaseRobeWidgetTester \ plugins/usbpro/BaseUsbProWidgetTester \ plugins/usbpro/DmxTriWidgetTester \ plugins/usbpro/DmxterWidgetTester \ plugins/usbpro/EnttecUsbProWidgetTester \ plugins/usbpro/RobeWidgetDetectorTester \ plugins/usbpro/RobeWidgetTester \ plugins/usbpro/UltraDMXProWidgetTester \ plugins/usbpro/UsbProWidgetDetectorTester \ plugins/usbpro/WidgetDetectorThreadTester COMMON_USBPRO_TEST_LDADD = $(COMMON_TESTING_LIBS) \ plugins/usbpro/libolausbprowidget.la common_test_sources = \ plugins/usbpro/CommonWidgetTest.cpp \ plugins/usbpro/CommonWidgetTest.h \ plugins/usbpro/MockEndpoint.cpp \ plugins/usbpro/MockEndpoint.h plugins_usbpro_ArduinoWidgetTester_SOURCES = \ plugins/usbpro/ArduinoWidgetTest.cpp \ $(common_test_sources) plugins_usbpro_ArduinoWidgetTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) plugins_usbpro_ArduinoWidgetTester_LDADD = $(COMMON_USBPRO_TEST_LDADD) plugins_usbpro_BaseRobeWidgetTester_SOURCES = \ plugins/usbpro/BaseRobeWidgetTest.cpp \ $(common_test_sources) plugins_usbpro_BaseRobeWidgetTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) plugins_usbpro_BaseRobeWidgetTester_LDADD = $(COMMON_USBPRO_TEST_LDADD) plugins_usbpro_BaseUsbProWidgetTester_SOURCES = \ plugins/usbpro/BaseUsbProWidgetTest.cpp \ $(common_test_sources) plugins_usbpro_BaseUsbProWidgetTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) plugins_usbpro_BaseUsbProWidgetTester_LDADD = $(COMMON_USBPRO_TEST_LDADD) plugins_usbpro_DmxTriWidgetTester_SOURCES = \ plugins/usbpro/DmxTriWidgetTest.cpp \ $(common_test_sources) plugins_usbpro_DmxTriWidgetTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) plugins_usbpro_DmxTriWidgetTester_LDADD = $(COMMON_USBPRO_TEST_LDADD) plugins_usbpro_DmxterWidgetTester_SOURCES = \ plugins/usbpro/DmxterWidgetTest.cpp \ $(common_test_sources) plugins_usbpro_DmxterWidgetTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) plugins_usbpro_DmxterWidgetTester_LDADD = $(COMMON_USBPRO_TEST_LDADD) plugins_usbpro_EnttecUsbProWidgetTester_SOURCES = \ plugins/usbpro/EnttecUsbProWidgetTest.cpp \ $(common_test_sources) plugins_usbpro_EnttecUsbProWidgetTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) plugins_usbpro_EnttecUsbProWidgetTester_LDADD = $(COMMON_USBPRO_TEST_LDADD) plugins_usbpro_RobeWidgetDetectorTester_SOURCES = \ plugins/usbpro/RobeWidgetDetectorTest.cpp \ $(common_test_sources) plugins_usbpro_RobeWidgetDetectorTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) plugins_usbpro_RobeWidgetDetectorTester_LDADD = $(COMMON_USBPRO_TEST_LDADD) plugins_usbpro_RobeWidgetTester_SOURCES = \ plugins/usbpro/RobeWidgetTest.cpp \ $(common_test_sources) plugins_usbpro_RobeWidgetTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) plugins_usbpro_RobeWidgetTester_LDADD = $(COMMON_USBPRO_TEST_LDADD) plugins_usbpro_UltraDMXProWidgetTester_SOURCES = \ plugins/usbpro/UltraDMXProWidgetTest.cpp \ $(common_test_sources) plugins_usbpro_UltraDMXProWidgetTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) plugins_usbpro_UltraDMXProWidgetTester_LDADD = $(COMMON_USBPRO_TEST_LDADD) plugins_usbpro_UsbProWidgetDetectorTester_SOURCES = \ plugins/usbpro/UsbProWidgetDetectorTest.cpp \ $(common_test_sources) plugins_usbpro_UsbProWidgetDetectorTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) plugins_usbpro_UsbProWidgetDetectorTester_LDADD = $(COMMON_USBPRO_TEST_LDADD) plugins_usbpro_WidgetDetectorThreadTester_SOURCES = \ plugins/usbpro/WidgetDetectorThreadTest.cpp \ $(common_test_sources) plugins_usbpro_WidgetDetectorThreadTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) plugins_usbpro_WidgetDetectorThreadTester_LDADD = $(COMMON_USBPRO_TEST_LDADD) endif ola-0.10.5.nojsmin/plugins/usbpro/messages/0000755000175000017500000000000013155164170020265 5ustar wouterwouterola-0.10.5.nojsmin/plugins/usbpro/messages/Makefile.mk0000644000175000017500000000241613023355232022331 0ustar wouterwouter# The UsbPro plugin config messages. This needs to be available to client # programs. EXTRA_DIST += plugins/usbpro/messages/UsbProConfigMessages.proto # pkg-config ################################################## pkgconfig_DATA += plugins/usbpro/messages/libolausbproconf.pc # LIBRARIES ################################################## lib_LTLIBRARIES += plugins/usbpro/messages/libolausbproconf.la usbproincludedir = $(includedir)/ola/usbpro nodist_usbproinclude_HEADERS = \ plugins/usbpro/messages/UsbProConfigMessages.pb.h built_sources += plugins/usbpro/messages/UsbProConfigMessages.pb.cc \ plugins/usbpro/messages/UsbProConfigMessages.pb.h nodist_plugins_usbpro_messages_libolausbproconf_la_SOURCES = \ plugins/usbpro/messages/UsbProConfigMessages.pb.cc plugins_usbpro_messages_libolausbproconf_la_CXXFLAGS = $(COMMON_PROTOBUF_CXXFLAGS) plugins_usbpro_messages_libolausbproconf_la_LIBADD = $(libprotobuf_LIBS) plugins/usbpro/messages/UsbProConfigMessages.pb.cc plugins/usbpro/messages/UsbProConfigMessages.pb.h: plugins/usbpro/messages/Makefile.mk plugins/usbpro/messages/UsbProConfigMessages.proto $(PROTOC) --cpp_out plugins/usbpro/messages/ --proto_path $(srcdir)/plugins/usbpro/messages/ $(srcdir)/plugins/usbpro/messages/UsbProConfigMessages.proto ola-0.10.5.nojsmin/plugins/usbpro/messages/libolausbproconf.pc.in0000644000175000017500000000031713023355232024555 0ustar wouterwouterprefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libolausbproconf Version: @VERSION@ Description: Open Lighting Architecture - UsbPro Config Messages Libs: -lprotobuf ola-0.10.5.nojsmin/plugins/usbpro/messages/UsbProConfigMessages.proto0000644000175000017500000000400313023355232025372 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * UsbProConfigMessages.proto * Defines the protocol buffers used to configure the Usb Pro device * Copyright (C) 2005 Simon Newton */ package ola.plugin.usbpro; message ParameterReply { required uint32 firmware_high = 1; required uint32 firmware = 2; required uint32 break_time = 3; required uint32 mab_time = 4; required uint32 rate = 5; } /* * Setting any one of these will update the widget, otherwise we just do a * read. */ message ParameterRequest { required uint32 port_id = 4; optional uint32 break_time = 1; optional uint32 mab_time = 2; optional uint32 rate = 3; } message SerialNumberReply { required string serial = 1; } message PortAssignmentReply { required uint32 port_assignment1 = 1; required uint32 port_assignment2 = 2; } message Request { enum RequestType { USBPRO_PARAMETER_REQUEST = 1; USBPRO_SERIAL_REQUEST = 2; USBPRO_PORT_ASSIGNMENT_REQUEST = 3; } required RequestType type = 1; optional ParameterRequest parameters = 2; } message Reply { enum ReplyType { USBPRO_PARAMETER_REPLY = 1; USBPRO_SERIAL_REPLY = 2; USBPRO_PORT_ASSIGNMENT_REPLY = 3; } required ReplyType type = 1; optional ParameterReply parameters = 2; optional SerialNumberReply serial_number = 3; optional PortAssignmentReply port_assignment = 4; } ola-0.10.5.nojsmin/plugins/usbpro/SerialWidgetInterface.h0000644000175000017500000000310013023355232023020 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SerialWidgetInterface.h * The base class for USB Serial widgets. These are devices that appear as a * serial (COM) port, most of them use the FTDI chip. * Copyright (C) 2011 Simon Newton */ #ifndef PLUGINS_USBPRO_SERIALWIDGETINTERFACE_H_ #define PLUGINS_USBPRO_SERIALWIDGETINTERFACE_H_ #include #include #include #include "ola/io/Descriptor.h" namespace ola { namespace plugin { namespace usbpro { /* * The SerialWidgetInterface. */ class SerialWidgetInterface { public: SerialWidgetInterface() {} virtual ~SerialWidgetInterface() {} // The Stop() method should clear out any callbacks virtual void Stop() = 0; virtual ola::io::ConnectedDescriptor *GetDescriptor() const = 0; }; } // namespace usbpro } // namespace plugin } // namespace ola #endif // PLUGINS_USBPRO_SERIALWIDGETINTERFACE_H_ ola-0.10.5.nojsmin/plugins/usbpro/BaseUsbProWidget.cpp0000644000175000017500000001362013134123277022335 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * BaseUsbProWidget.cpp * Read and Write to a USB Widget. * Copyright (C) 2010 Simon Newton */ #include #include #include #include #include #include #include #include #include #include #include #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/io/IOUtils.h" #include "ola/io/Serial.h" #include "ola/base/Macro.h" #include "plugins/usbpro/BaseUsbProWidget.h" namespace ola { namespace plugin { namespace usbpro { using std::string; const unsigned int BaseUsbProWidget::HEADER_SIZE = sizeof(BaseUsbProWidget::message_header); BaseUsbProWidget::BaseUsbProWidget( ola::io::ConnectedDescriptor *descriptor) : m_descriptor(descriptor), m_state(PRE_SOM), m_bytes_received(0) { memset(&m_header, 0, sizeof(m_header)); m_descriptor->SetOnData( NewCallback(this, &BaseUsbProWidget::DescriptorReady)); } BaseUsbProWidget::~BaseUsbProWidget() { m_descriptor->SetOnData(NULL); } /* * Read data from the widget */ void BaseUsbProWidget::DescriptorReady() { while (m_descriptor->DataRemaining() > 0) { ReceiveMessage(); } } /* * Send a DMX frame. * @returns true if we sent ok, false otherwise */ bool BaseUsbProWidget::SendDMX(const DmxBuffer &buffer) { struct { uint8_t start_code; uint8_t dmx[DMX_UNIVERSE_SIZE]; } widget_dmx; widget_dmx.start_code = DMX512_START_CODE; unsigned int length = DMX_UNIVERSE_SIZE; buffer.Get(widget_dmx.dmx, &length); return SendMessage(DMX_LABEL, reinterpret_cast(&widget_dmx), length + 1); } /* * Send the msg * @return true if successful, false otherwise */ bool BaseUsbProWidget::SendMessage(uint8_t label, const uint8_t *data, unsigned int length) const { if (length && !data) return false; ssize_t frame_size = HEADER_SIZE + length + 1; uint8_t frame[frame_size]; message_header *header = reinterpret_cast(frame); header->som = SOM; header->label = label; header->len = length & 0xFF; header->len_hi = (length & 0xFF00) >> 8; memcpy(frame + sizeof(message_header), data, length); frame[frame_size - 1] = EOM; ssize_t bytes_sent = m_descriptor->Send(frame, frame_size); if (bytes_sent != frame_size) // we've probably screwed framing at this point return false; return true; } /** * Open a path and apply the settings required for talking to widgets. */ ola::io::ConnectedDescriptor *BaseUsbProWidget::OpenDevice( const string &path) { struct termios newtio; int fd; if (!ola::io::AcquireUUCPLockAndOpen(path, O_RDWR | O_NONBLOCK | O_NOCTTY, &fd)) { return NULL; } bzero(&newtio, sizeof(newtio)); // clear struct for new port settings newtio.c_cflag |= CREAD; newtio.c_cflag |= CS8; cfsetispeed(&newtio, B115200); cfsetospeed(&newtio, B115200); tcsetattr(fd, TCSANOW, &newtio); return new ola::io::DeviceDescriptor(fd); } /* * Read the data and handle the messages. */ void BaseUsbProWidget::ReceiveMessage() { unsigned int count, packet_length; switch (m_state) { case PRE_SOM: do { m_descriptor->Receive(&m_header.som, 1, count); if (count != 1) return; } while (m_header.som != SOM); m_state = RECV_LABEL; // fall through OLA_FALLTHROUGH case RECV_LABEL: m_descriptor->Receive(&m_header.label, 1, count); if (count != 1) return; m_state = RECV_SIZE_LO; // fall through OLA_FALLTHROUGH case RECV_SIZE_LO: m_descriptor->Receive(&m_header.len, 1, count); if (count != 1) return; m_state = RECV_SIZE_HI; // fall through OLA_FALLTHROUGH case RECV_SIZE_HI: m_descriptor->Receive(&m_header.len_hi, 1, count); if (count != 1) return; packet_length = (m_header.len_hi << 8) + m_header.len; if (packet_length == 0) { m_state = RECV_EOM; return; } else if (packet_length > MAX_DATA_SIZE) { m_state = PRE_SOM; return; } m_bytes_received = 0; m_state = RECV_BODY; // fall through OLA_FALLTHROUGH case RECV_BODY: packet_length = (m_header.len_hi << 8) + m_header.len; m_descriptor->Receive( reinterpret_cast(&m_recv_buffer) + m_bytes_received, packet_length - m_bytes_received, count); if (!count) return; m_bytes_received += count; if (m_bytes_received != packet_length) return; m_state = RECV_EOM; // fall through OLA_FALLTHROUGH case RECV_EOM: // check this is a valid frame with an end byte uint8_t eom; m_descriptor->Receive(&eom, 1, count); if (count != 1) return; packet_length = (m_header.len_hi << 8) + m_header.len; if (eom == EOM) HandleMessage(m_header.label, packet_length ? m_recv_buffer : NULL, packet_length); m_state = PRE_SOM; } return; } } // namespace usbpro } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbpro/ArduinoWidget.h0000644000175000017500000001014613023355232021371 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ArduinoWidget.h * The Arduino RGB Mixer widget. * Copyright (C) 2011 Simon Newton */ #ifndef PLUGINS_USBPRO_ARDUINOWIDGET_H_ #define PLUGINS_USBPRO_ARDUINOWIDGET_H_ #include #include "ola/DmxBuffer.h" #include "ola/rdm/UID.h" #include "ola/rdm/UIDSet.h" #include "ola/rdm/RDMControllerInterface.h" #include "ola/rdm/QueueingRDMController.h" #include "plugins/usbpro/BaseUsbProWidget.h" namespace ola { namespace plugin { namespace usbpro { /* * A Arduino Widget implementation. We separate the Widget from the * implementation so we can leverage the QueueingRDMController. */ class ArduinoWidgetImpl: public BaseUsbProWidget, public ola::rdm::DiscoverableRDMControllerInterface { public: ArduinoWidgetImpl(ola::io::ConnectedDescriptor *descriptor, uint16_t esta_id, uint32_t serial); ~ArduinoWidgetImpl(); void Stop(); void SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *on_complete); void RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { GetUidSet(callback); } void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { GetUidSet(callback); } private: uint8_t m_transaction_id; ola::rdm::UID m_uid; std::auto_ptr m_pending_request; ola::rdm::RDMCallback *m_rdm_request_callback; void HandleMessage(uint8_t label, const uint8_t *data, unsigned int length); void HandleRDMResponse(const uint8_t *data, unsigned int length); void GetUidSet(ola::rdm::RDMDiscoveryCallback *callback); static const uint8_t RDM_REQUEST_LABEL; // the first byte is the response code static const uint8_t RESPONSE_OK; static const uint8_t RESPONSE_WAS_BROADCAST; static const uint8_t RESPONSE_FAILED; static const uint8_t RESPONSE_FAILED_CHECKSUM; static const uint8_t RESONSE_INVALID_DESTINATION; static const uint8_t RESPONSE_INVALID_COMMAND; }; /* * A Arduino Widget. This mostly just wraps the implementation. */ class ArduinoWidget: public SerialWidgetInterface, public ola::rdm::DiscoverableRDMControllerInterface { public: ArduinoWidget(ola::io::ConnectedDescriptor *descriptor, uint16_t esta_id, uint32_t serial, unsigned int queue_size = 20); ~ArduinoWidget(); void Stop() { m_impl->Stop(); } bool SendDMX(const DmxBuffer &buffer) { return m_impl->SendDMX(buffer); } void SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *on_complete) { m_controller->SendRDMRequest(request, on_complete); } void RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { m_impl->RunFullDiscovery(callback); } void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { m_impl->RunIncrementalDiscovery(callback); } ola::io::ConnectedDescriptor *GetDescriptor() const { return m_impl->GetDescriptor(); } private: // we need to control the order of construction & destruction here so these // are pointers. ArduinoWidgetImpl *m_impl; ola::rdm::DiscoverableQueueingRDMController *m_controller; }; } // namespace usbpro } // namespace plugin } // namespace ola #endif // PLUGINS_USBPRO_ARDUINOWIDGET_H_ ola-0.10.5.nojsmin/plugins/usbpro/RobeWidget.h0000644000175000017500000001275613023355232020670 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RobeWidget.h * Read and Write to a USB Widget. * Copyright (C) 2011 Simon Newton */ #ifndef PLUGINS_USBPRO_ROBEWIDGET_H_ #define PLUGINS_USBPRO_ROBEWIDGET_H_ #include #include #include "ola/Callback.h" #include "ola/DmxBuffer.h" #include "ola/io/Descriptor.h" #include "ola/rdm/DiscoveryAgent.h" #include "ola/rdm/QueueingRDMController.h" #include "ola/rdm/RDMCommand.h" #include "ola/rdm/RDMControllerInterface.h" #include "ola/rdm/UID.h" #include "ola/rdm/UIDSet.h" #include "ola/thread/SchedulingExecutorInterface.h" #include "plugins/usbpro/BaseRobeWidget.h" class RobeWidgetTest; namespace ola { namespace plugin { namespace usbpro { /* * A Robe USB Widget implementation. */ class RobeWidgetImpl: public BaseRobeWidget, public ola::rdm::DiscoverableRDMControllerInterface, public ola::rdm::DiscoveryTargetInterface { public: explicit RobeWidgetImpl(ola::io::ConnectedDescriptor *descriptor, const ola::rdm::UID &uid); ~RobeWidgetImpl() {} void Stop(); bool SendDMX(const DmxBuffer &buffer); void SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *on_complete); void RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback); void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback); // incoming DMX methods bool ChangeToReceiveMode(); // ownership of the callback is transferred void SetDmxCallback(Callback0 *callback); const DmxBuffer &FetchDMX() { return m_buffer; } // The following are the implementation of DiscoveryTargetInterface void MuteDevice(const ola::rdm::UID &target, MuteDeviceCallback *mute_complete); void UnMuteAll(UnMuteDeviceCallback *unmute_complete); void Branch(const ola::rdm::UID &lower, const ola::rdm::UID &upper, BranchCallback *callback); static const int DMX_FRAME_DATA_SIZE; private: ola::rdm::RDMCallback *m_rdm_request_callback; MuteDeviceCallback *m_mute_callback; UnMuteDeviceCallback *m_unmute_callback; BranchCallback *m_branch_callback; ola::rdm::DiscoveryAgent m_discovery_agent; std::auto_ptr > m_dmx_callback; DmxBuffer m_buffer; std::auto_ptr m_pending_request; const ola::rdm::UID m_uid; uint8_t m_transaction_number; void HandleMessage(uint8_t label, const uint8_t *data, unsigned int length); void HandleRDMResponse(const uint8_t *data, unsigned int length); void HandleDiscoveryResponse(const uint8_t *data, unsigned int length); void DiscoveryComplete(ola::rdm::RDMDiscoveryCallback *callback, bool status, const ola::rdm::UIDSet &uids); void HandleDmxFrame(const uint8_t *data, unsigned int length); bool PackAndSendRDMRequest(uint8_t label, const ola::rdm::RDMRequest *request); static const unsigned int RDM_PADDING_BYTES = 4; }; /* * A Robe Widget. This mostly just wraps the implementation. */ class RobeWidget: public SerialWidgetInterface, public ola::rdm::DiscoverableRDMControllerInterface { public: RobeWidget(ola::io::ConnectedDescriptor *descriptor, const ola::rdm::UID &uid, unsigned int queue_size = 20); ~RobeWidget(); void Stop() { m_impl->Stop(); } ola::io::ConnectedDescriptor *GetDescriptor() const { return m_impl->GetDescriptor(); } bool SendDMX(const DmxBuffer &buffer) { return m_impl->SendDMX(buffer); } void SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *on_complete) { m_controller->SendRDMRequest(request, on_complete); } void RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { m_impl->RunFullDiscovery(callback); } void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { m_impl->RunIncrementalDiscovery(callback); } bool ChangeToReceiveMode() { return m_impl->ChangeToReceiveMode(); } void SetDmxCallback(Callback0 *callback) { m_impl->SetDmxCallback(callback); } const DmxBuffer& FetchDMX() { return m_impl->FetchDMX(); } // the tests access the implementation directly. friend class ::RobeWidgetTest; private: // we need to control the order of construction & destruction here so these // are pointers. RobeWidgetImpl *m_impl; ola::rdm::DiscoverableQueueingRDMController *m_controller; }; } // namespace usbpro } // namespace plugin } // namespace ola #endif // PLUGINS_USBPRO_ROBEWIDGET_H_ ola-0.10.5.nojsmin/plugins/usbpro/UsbProWidgetDetectorTest.cpp0000644000175000017500000001746613023355232024103 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * UsbProWidgetDetectorTest.cpp * Test fixture for the UsbProWidgetDetector class * Copyright (C) 2010 Simon Newton */ #include #include #include #include "ola/Callback.h" #include "ola/Logging.h" #include "ola/network/NetworkUtils.h" #include "plugins/usbpro/CommonWidgetTest.h" #include "plugins/usbpro/UsbProWidgetDetector.h" #include "ola/testing/TestUtils.h" using ola::io::ConnectedDescriptor; using ola::plugin::usbpro::UsbProWidgetInformation; using ola::plugin::usbpro::UsbProWidgetDetector; using std::auto_ptr; using std::string; class UsbProWidgetDetectorTest: public CommonWidgetTest { CPPUNIT_TEST_SUITE(UsbProWidgetDetectorTest); CPPUNIT_TEST(testExtendedDiscovery); CPPUNIT_TEST(testDiscovery); CPPUNIT_TEST(testTimeout); CPPUNIT_TEST(testSniffer); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void testExtendedDiscovery(); void testDiscovery(); void testTimeout(); void testSniffer(); private: auto_ptr m_detector; UsbProWidgetInformation m_device_info; bool m_found_widget; bool m_failed_widget; void NewWidget(ConnectedDescriptor *descriptor, const UsbProWidgetInformation *info); void FailedWidget(ConnectedDescriptor *descriptor); void Timeout() { m_ss.Terminate(); } static const uint8_t DEVICE_LABEL = 78; static const uint8_t MANUFACTURER_LABEL = 77; static const uint8_t SERIAL_LABEL = 10; static const uint8_t GET_PARAMS = 3; static const uint8_t HARDWARE_VERSION_LABEL = 14; static const uint8_t SNIFFER_LABEL = 0x81; }; CPPUNIT_TEST_SUITE_REGISTRATION(UsbProWidgetDetectorTest); void UsbProWidgetDetectorTest::setUp() { CommonWidgetTest::setUp(); m_found_widget = false; m_failed_widget = false; m_detector.reset(new UsbProWidgetDetector( &m_ss, ola::NewCallback(this, &UsbProWidgetDetectorTest::NewWidget), ola::NewCallback(this, &UsbProWidgetDetectorTest::FailedWidget), 10)); m_ss.RegisterSingleTimeout( 4000, // This should only take 40ms, but on slow platforms takes longer ola::NewSingleCallback(this, &UsbProWidgetDetectorTest::Timeout)); } void UsbProWidgetDetectorTest::NewWidget(ConnectedDescriptor *descriptor, const UsbProWidgetInformation *info) { OLA_ASSERT_EQ( static_cast(&m_descriptor), descriptor); m_found_widget = true; m_device_info = *info; m_ss.Terminate(); delete info; } void UsbProWidgetDetectorTest::FailedWidget(ConnectedDescriptor *descriptor) { OLA_ASSERT_EQ( static_cast(&m_descriptor), descriptor); m_failed_widget = true; m_ss.Terminate(); } /** * Test that discovery works for a device that implements the extended set of * messages. */ void UsbProWidgetDetectorTest::testExtendedDiscovery() { uint32_t expected_serial = 0x12345678; uint8_t serial_data[] = {0x78, 0x56, 0x34, 0x12}; uint16_t expected_manufacturer = 0x7a70; uint8_t manufacturer_data[] = "pzOpen Lighting"; uint16_t expected_device = 0x534e; uint8_t device_data[] = "NSUnittest Device"; uint8_t get_params_request[] = {0, 0}; uint8_t get_params_response[] = {4, 1, 9, 1, 1}; uint16_t expected_firmware_version = 0x0104; m_endpoint->AddExpectedUsbProDataAndReturn( MANUFACTURER_LABEL, NULL, 0, MANUFACTURER_LABEL, manufacturer_data, sizeof(manufacturer_data)); m_endpoint->AddExpectedUsbProDataAndReturn( DEVICE_LABEL, NULL, 0, DEVICE_LABEL, device_data, sizeof(device_data)); m_endpoint->AddExpectedUsbProDataAndReturn( SERIAL_LABEL, NULL, 0, SERIAL_LABEL, serial_data, sizeof(serial_data)); m_endpoint->AddExpectedUsbProDataAndReturn( GET_PARAMS, &get_params_request[0], sizeof(get_params_request), GET_PARAMS, get_params_response, sizeof(get_params_response)); m_detector->Discover(&m_descriptor); m_ss.Run(); OLA_ASSERT(m_found_widget); OLA_ASSERT_FALSE(m_failed_widget); OLA_ASSERT_EQ(expected_manufacturer, m_device_info.esta_id); OLA_ASSERT_EQ(expected_device, m_device_info.device_id); OLA_ASSERT_EQ(string("Open Lighting"), m_device_info.manufacturer); OLA_ASSERT_EQ(string("Unittest Device"), m_device_info.device); OLA_ASSERT_EQ(expected_serial, m_device_info.serial); OLA_ASSERT_EQ(expected_serial, m_device_info.serial); OLA_ASSERT_EQ(expected_firmware_version, m_device_info.firmware_version); } /* * Check that discovery works for a device that just implements the serial # */ void UsbProWidgetDetectorTest::testDiscovery() { uint32_t expected_serial = 0x12345678; uint8_t serial_data[] = {0x78, 0x56, 0x34, 0x12}; uint8_t get_params_request[] = {0, 0}; m_endpoint->AddExpectedUsbProMessage(MANUFACTURER_LABEL, NULL, 0); m_endpoint->AddExpectedUsbProMessage(DEVICE_LABEL, NULL, 0); m_endpoint->AddExpectedUsbProDataAndReturn( SERIAL_LABEL, NULL, 0, SERIAL_LABEL, serial_data, sizeof(serial_data)); m_endpoint->AddExpectedUsbProMessage(GET_PARAMS, &get_params_request[0], sizeof(get_params_request)); // Because the widget doesn't respond to Manufacturer or Device labels, we'll // send a HARDWARE_VERSION_LABEL message. m_endpoint->AddExpectedUsbProMessage(HARDWARE_VERSION_LABEL, NULL, 0); m_detector->Discover(&m_descriptor); m_ss.Run(); OLA_ASSERT(m_found_widget); OLA_ASSERT_FALSE(m_failed_widget); OLA_ASSERT_EQ(static_cast(0), m_device_info.esta_id); OLA_ASSERT_EQ(static_cast(0), m_device_info.device_id); OLA_ASSERT_EQ(string(), m_device_info.manufacturer); OLA_ASSERT_EQ(string(), m_device_info.device); OLA_ASSERT_EQ(expected_serial, m_device_info.serial); } /** * Check a widget that fails to respond */ void UsbProWidgetDetectorTest::testTimeout() { m_endpoint->AddExpectedUsbProMessage(MANUFACTURER_LABEL, NULL, 0); m_endpoint->AddExpectedUsbProMessage(DEVICE_LABEL, NULL, 0); m_endpoint->AddExpectedUsbProMessage(SERIAL_LABEL, NULL, 0); m_detector->Discover(&m_descriptor); m_ss.Run(); OLA_ASSERT_FALSE(m_found_widget); OLA_ASSERT(m_failed_widget); } /* * Check that we recognize Enttec sniffers. */ void UsbProWidgetDetectorTest::testSniffer() { uint8_t serial_data[] = {0x78, 0x56, 0x34, 0x12}; uint8_t get_params_request[] = {0, 0}; m_endpoint->AddExpectedUsbProMessage(MANUFACTURER_LABEL, NULL, 0); m_endpoint->AddExpectedUsbProMessage(DEVICE_LABEL, NULL, 0); m_endpoint->AddExpectedUsbProDataAndReturn( SERIAL_LABEL, NULL, 0, SERIAL_LABEL, serial_data, sizeof(serial_data)); m_endpoint->AddExpectedUsbProMessage(GET_PARAMS, &get_params_request[0], sizeof(get_params_request)); m_endpoint->AddExpectedUsbProMessage(HARDWARE_VERSION_LABEL, NULL, 0); m_endpoint->SendUnsolicitedUsbProData(SNIFFER_LABEL, NULL, 0); m_endpoint->SendUnsolicitedUsbProData(SNIFFER_LABEL, NULL, 0); m_detector->Discover(&m_descriptor); m_ss.Run(); OLA_ASSERT_FALSE(m_found_widget); OLA_ASSERT(m_failed_widget); } ola-0.10.5.nojsmin/plugins/usbpro/UsbProWidgetDetector.h0000644000175000017500000001411013023355232022667 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * UsbProWidgetDetector.h * Handles the discovery process for widgets that implement the Usb Pro frame * format. * Copyright (C) 2010 Simon Newton */ #ifndef PLUGINS_USBPRO_USBPROWIDGETDETECTOR_H_ #define PLUGINS_USBPRO_USBPROWIDGETDETECTOR_H_ #include #include #include #include #include "ola/Callback.h" #include "plugins/usbpro/WidgetDetectorInterface.h" namespace ola { namespace plugin { namespace usbpro { class DispatchingUsbProWidget; /* * Contains information about a USB Pro like device. */ class UsbProWidgetInformation { public: typedef uint32_t DeviceSerialNumber; typedef uint16_t DeviceFirmwareVersion; UsbProWidgetInformation(): esta_id(0), device_id(0), serial(0), firmware_version(0), has_firmware_version(false), dual_port(false) { } UsbProWidgetInformation(const UsbProWidgetInformation &other): esta_id(other.esta_id), device_id(other.device_id), serial(other.serial), firmware_version(other.firmware_version), has_firmware_version(other.has_firmware_version), manufacturer(other.manufacturer), device(other.device), dual_port(other.dual_port) { } UsbProWidgetInformation& operator=(const UsbProWidgetInformation &other); void SetFirmware(DeviceFirmwareVersion new_firmware_version) { has_firmware_version = true; firmware_version = new_firmware_version; } enum {SERIAL_LENGTH = 4}; uint16_t esta_id; uint16_t device_id; DeviceSerialNumber serial; DeviceFirmwareVersion firmware_version; bool has_firmware_version; std::string manufacturer; std::string device; bool dual_port; }; /* * Handles the discovery routine for devices that behave like a Enttec Usb Pro. */ class UsbProWidgetDetector: public WidgetDetectorInterface { public: typedef ola::Callback2 SuccessHandler; typedef ola::Callback1 FailureHandler; UsbProWidgetDetector(ola::thread::SchedulingExecutorInterface *scheduler, SuccessHandler *on_success, FailureHandler *on_failure, unsigned int message_interval = 200); ~UsbProWidgetDetector(); bool Discover(ola::io::ConnectedDescriptor *descriptor); private: // Hold the discovery state for a widget class DiscoveryState { public: DiscoveryState(): discovery_state(MANUFACTURER_SENT), timeout_id(ola::thread::INVALID_TIMEOUT), sniffer_packets(0), hardware_version(0) { } ~DiscoveryState() {} typedef enum { MANUFACTURER_SENT, DEVICE_SENT, SERIAL_SENT, GET_PARAM_SENT, HARDWARE_VERSION_SENT, } widget_state; UsbProWidgetInformation information; widget_state discovery_state; ola::thread::timeout_id timeout_id; unsigned int sniffer_packets; uint8_t hardware_version; }; ola::thread::SchedulingExecutorInterface *m_scheduler; const std::auto_ptr m_callback; const std::auto_ptr m_failure_callback; typedef std::map WidgetStateMap; WidgetStateMap m_widgets; unsigned int m_timeout_ms; void HandleMessage(DispatchingUsbProWidget *widget, uint8_t label, const uint8_t *data, unsigned int length); void WidgetRemoved(DispatchingUsbProWidget *widget); void SetupTimeout(DispatchingUsbProWidget *widget, DiscoveryState *discovery_state); void RemoveTimeout(DiscoveryState *discovery_state); void SendNameRequest(DispatchingUsbProWidget *widget); void SendSerialRequest(DispatchingUsbProWidget *widget); void SendGetParams(DispatchingUsbProWidget *widget); void MaybeSendHardwareVersionRequest(DispatchingUsbProWidget *widget); void SendAPIRequest(DispatchingUsbProWidget *widget); void DiscoveryTimeout(DispatchingUsbProWidget *widget); void HandleIdResponse(DispatchingUsbProWidget *widget, unsigned int length, const uint8_t *data, bool is_device); void HandleSerialResponse(DispatchingUsbProWidget *widget, unsigned int length, const uint8_t *data); void HandleGetParams(DispatchingUsbProWidget *widget, unsigned int length, const uint8_t *data); void HandleHardwareVersionResponse(DispatchingUsbProWidget *widget, unsigned int length, const uint8_t *data); void HandleSnifferPacket(DispatchingUsbProWidget *widget); void CompleteWidgetDiscovery(DispatchingUsbProWidget *widget); void DispatchWidget(DispatchingUsbProWidget *widget, const UsbProWidgetInformation *info); void HandleSniffer(DispatchingUsbProWidget *widget); static const uint8_t ENTTEC_SNIFFER_LABEL = 0x81; static const uint8_t USB_PRO_MKII_API_LABEL = 13; static const uint8_t DMX_PRO_MKII_VERSION = 2; static const uint8_t DMX_PRO_MKII_B_VERSION = 3; // The API key associated with OLA static const uint32_t USB_PRO_MKII_API_KEY = 0x0d11b2d7; }; } // namespace usbpro } // namespace plugin } // namespace ola #endif // PLUGINS_USBPRO_USBPROWIDGETDETECTOR_H_ ola-0.10.5.nojsmin/plugins/usbpro/WidgetDetectorThreadTest.cpp0000644000175000017500000004344013134123277024074 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * WidgetDetectorThreadTest.cpp * Test fixture for the RobeWidgetDetector class * Copyright (C) 2011 Simon Newton */ #include #include #include #include "ola/Callback.h" #include "ola/Logging.h" #include "ola/io/Descriptor.h" #include "ola/io/SelectServer.h" #include "ola/rdm/UID.h" #include "plugins/usbpro/ArduinoWidget.h" #include "plugins/usbpro/DmxTriWidget.h" #include "plugins/usbpro/DmxterWidget.h" #include "plugins/usbpro/EnttecUsbProWidget.h" #include "plugins/usbpro/MockEndpoint.h" #include "plugins/usbpro/BaseRobeWidget.h" #include "plugins/usbpro/RobeWidget.h" #include "plugins/usbpro/UltraDMXProWidget.h" #include "plugins/usbpro/WidgetDetectorThread.h" #include "ola/testing/TestUtils.h" using ola::io::ConnectedDescriptor; using ola::io::UnixSocket; using ola::plugin::usbpro::ArduinoWidget; using ola::plugin::usbpro::BaseRobeWidget; using ola::plugin::usbpro::BaseUsbProWidget; using ola::plugin::usbpro::DmxTriWidget; using ola::plugin::usbpro::DmxterWidget; using ola::plugin::usbpro::EnttecUsbProWidget; using ola::plugin::usbpro::NewWidgetHandler; using ola::plugin::usbpro::RobeWidget; using ola::plugin::usbpro::RobeWidgetInformation; using ola::plugin::usbpro::UltraDMXProWidget; using ola::plugin::usbpro::UsbProWidgetInformation; using ola::plugin::usbpro::WidgetDetectorThread; using ola::rdm::UID; using std::auto_ptr; using std::string; /** * This overrides RunScan so we don't attempt to open devices on the local * machine. */ class MockWidgetDetectorThread: public WidgetDetectorThread { public: MockWidgetDetectorThread(NewWidgetHandler *widget_handler, ola::io::SelectServerInterface *ss) // set very short timeouts since this is a unittest : WidgetDetectorThread(widget_handler, ss, 10, 10), m_descriptor(new ola::io::UnixSocket()) { m_descriptor->Init(); } UnixSocket* GetOtherEnd() { return m_descriptor->OppositeEnd(); } protected: bool RunScan() { PerformDiscovery("/mock_device", m_descriptor); return true; } private: UnixSocket *m_descriptor; }; class WidgetDetectorThreadTest: public CppUnit::TestFixture, public NewWidgetHandler { CPPUNIT_TEST_SUITE(WidgetDetectorThreadTest); CPPUNIT_TEST(testArduinoWidget); CPPUNIT_TEST(testDmxTriWidget); CPPUNIT_TEST(testDmxterWidget); CPPUNIT_TEST(testUsbProWidget); CPPUNIT_TEST(testUsbProMkIIWidget); CPPUNIT_TEST(testRobeWidget); CPPUNIT_TEST(testUltraDmxWidget); CPPUNIT_TEST(testTimeout); CPPUNIT_TEST(testClose); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void tearDown(); void testArduinoWidget(); void testDmxTriWidget(); void testDmxterWidget(); void testUsbProWidget(); void testUsbProMkIIWidget(); void testRobeWidget(); void testUltraDmxWidget(); void testTimeout(); void testClose(); private: typedef enum { NONE, ARDUINO, ENTTEC, DMX_TRI, DMXTER, ROBE, ULTRA_DMX, } WidgetType; ola::io::SelectServer m_ss; auto_ptr m_endpoint; auto_ptr m_thread; auto_ptr m_other_end; WidgetType m_received_widget_type; bool m_expect_dual_port_enttec_widget; void Timeout() { OLA_INFO << "Timeout triggered"; m_ss.Terminate(); } // widget handlers follow void NewWidget(ArduinoWidget *widget, const UsbProWidgetInformation &information) { OLA_ASSERT_EQ(static_cast(0x7a70), information.esta_id); OLA_ASSERT_EQ(string("Open Lighting"), information.manufacturer); OLA_ASSERT_EQ(static_cast(1), information.device_id); OLA_ASSERT_EQ(string("Unittest Device"), information.device); OLA_ASSERT_EQ(static_cast(0x12345678), information.serial); m_thread->FreeWidget(widget); m_received_widget_type = ARDUINO; m_ss.Terminate(); } void NewWidget(EnttecUsbProWidget *widget, const UsbProWidgetInformation &information) { OLA_ASSERT_EQ(static_cast(0), information.esta_id); OLA_ASSERT_EQ(string(""), information.manufacturer); OLA_ASSERT_EQ(static_cast(0), information.device_id); OLA_ASSERT_EQ(string(""), information.device); OLA_ASSERT_EQ(static_cast(0x12345678), information.serial); if (m_expect_dual_port_enttec_widget) { OLA_ASSERT(information.dual_port); } m_thread->FreeWidget(widget); m_received_widget_type = ENTTEC; m_ss.Terminate(); } void NewWidget(DmxTriWidget *widget, const UsbProWidgetInformation &information) { OLA_ASSERT_EQ(static_cast(0x6864), information.esta_id); OLA_ASSERT_EQ(string("JESE"), information.manufacturer); OLA_ASSERT_EQ(static_cast(2), information.device_id); OLA_ASSERT_EQ(string("RDM-TRI"), information.device); OLA_ASSERT_EQ(static_cast(0x12345678), information.serial); m_thread->FreeWidget(widget); m_received_widget_type = DMX_TRI; m_ss.Terminate(); } void NewWidget(DmxterWidget *widget, const UsbProWidgetInformation &information) { OLA_ASSERT_EQ(static_cast(0x4744), information.esta_id); OLA_ASSERT_EQ(string("Goddard Design"), information.manufacturer); OLA_ASSERT_EQ(static_cast(0x444d), information.device_id); OLA_ASSERT_EQ(string("DMXter4"), information.device); OLA_ASSERT_EQ(static_cast(0x12345678), information.serial); m_thread->FreeWidget(widget); m_received_widget_type = DMXTER; m_ss.Terminate(); } void NewWidget(RobeWidget *widget, const RobeWidgetInformation &information) { m_thread->FreeWidget(widget); OLA_ASSERT_EQ(static_cast(1), information.hardware_version); OLA_ASSERT_EQ(static_cast(11), information.software_version); OLA_ASSERT_EQ(static_cast(3), information.eeprom_version); OLA_ASSERT_EQ(UID(0x5253, 0x200000a), information.uid); m_received_widget_type = ROBE; m_ss.Terminate(); } void NewWidget(UltraDMXProWidget *widget, const UsbProWidgetInformation &information) { OLA_ASSERT_EQ(static_cast(0x6a6b), information.esta_id); OLA_ASSERT_EQ(string("DMXking.com"), information.manufacturer); OLA_ASSERT_EQ(static_cast(0x2), information.device_id); OLA_ASSERT_EQ(string("ultraDMX Pro"), information.device); OLA_ASSERT_EQ(static_cast(0x12345678), information.serial); m_thread->FreeWidget(widget); m_received_widget_type = ULTRA_DMX; m_ss.Terminate(); } static const uint8_t USB_PRO_MKII_API_LABEL = 13; static const uint8_t SET_PORT_ASSIGNMENTS = 145; }; CPPUNIT_TEST_SUITE_REGISTRATION(WidgetDetectorThreadTest); void WidgetDetectorThreadTest::setUp() { ola::InitLogging(ola::OLA_LOG_INFO, ola::OLA_LOG_STDERR); m_received_widget_type = NONE; m_expect_dual_port_enttec_widget = false; m_thread.reset(new MockWidgetDetectorThread(this, &m_ss)); m_ss.RegisterSingleTimeout( 100, // this should take at most 40ms ola::NewSingleCallback(this, &WidgetDetectorThreadTest::Timeout)); m_other_end.reset(m_thread->GetOtherEnd()); m_ss.AddReadDescriptor(m_other_end.get()); m_endpoint.reset(new MockEndpoint(m_other_end.get())); } void WidgetDetectorThreadTest::tearDown() { m_thread->Join(NULL); m_endpoint->Verify(); m_ss.RemoveReadDescriptor(m_other_end.get()); m_endpoint.reset(); } /** * Check that we can locate a Arduino widget */ void WidgetDetectorThreadTest::testArduinoWidget() { uint8_t serial_data[] = {0x78, 0x56, 0x34, 0x12}; uint8_t manufacturer_data[] = "pzOpen Lighting"; uint8_t device_data[] = "\001\000Unittest Device"; uint8_t get_params_request[] = {0, 0}; m_endpoint->AddExpectedUsbProDataAndReturn( BaseUsbProWidget::MANUFACTURER_LABEL, NULL, 0, BaseUsbProWidget::MANUFACTURER_LABEL, manufacturer_data, sizeof(manufacturer_data)); m_endpoint->AddExpectedUsbProDataAndReturn( BaseUsbProWidget::DEVICE_LABEL, NULL, 0, BaseUsbProWidget::DEVICE_LABEL, device_data, sizeof(device_data)); m_endpoint->AddExpectedUsbProDataAndReturn( BaseUsbProWidget::SERIAL_LABEL, NULL, 0, BaseUsbProWidget::SERIAL_LABEL, serial_data, sizeof(serial_data)); m_endpoint->AddExpectedUsbProMessage(BaseUsbProWidget::GET_PARAMS, &get_params_request[0], sizeof(get_params_request)); m_thread->Start(); m_thread->WaitUntilRunning(); m_ss.Run(); OLA_ASSERT_EQ(ARDUINO, m_received_widget_type); } /** * Check that we can locate a DMX-TRI widget */ void WidgetDetectorThreadTest::testDmxTriWidget() { uint8_t serial_data[] = {0x78, 0x56, 0x34, 0x12}; uint8_t manufacturer_data[] = "\144\150JESE"; uint8_t device_data[] = "\002\000RDM-TRI"; uint8_t get_params_request[] = {0, 0}; m_endpoint->AddExpectedUsbProDataAndReturn( BaseUsbProWidget::MANUFACTURER_LABEL, NULL, 0, BaseUsbProWidget::MANUFACTURER_LABEL, manufacturer_data, sizeof(manufacturer_data)); m_endpoint->AddExpectedUsbProDataAndReturn( BaseUsbProWidget::DEVICE_LABEL, NULL, 0, BaseUsbProWidget::DEVICE_LABEL, device_data, sizeof(device_data)); m_endpoint->AddExpectedUsbProDataAndReturn( BaseUsbProWidget::SERIAL_LABEL, NULL, 0, BaseUsbProWidget::SERIAL_LABEL, serial_data, sizeof(serial_data)); m_endpoint->AddExpectedUsbProMessage(BaseUsbProWidget::GET_PARAMS, &get_params_request[0], sizeof(get_params_request)); m_thread->Start(); m_thread->WaitUntilRunning(); m_ss.Run(); OLA_ASSERT_EQ(DMX_TRI, m_received_widget_type); } /** * Check that we can locate a Arduino widget */ void WidgetDetectorThreadTest::testDmxterWidget() { uint8_t serial_data[] = {0x78, 0x56, 0x34, 0x12}; uint8_t manufacturer_data[] = "\104\107Goddard Design"; uint8_t device_data[] = "\115\104DMXter4"; uint8_t get_params_request[] = {0, 0}; m_endpoint->AddExpectedUsbProDataAndReturn( BaseUsbProWidget::MANUFACTURER_LABEL, NULL, 0, BaseUsbProWidget::MANUFACTURER_LABEL, manufacturer_data, sizeof(manufacturer_data)); m_endpoint->AddExpectedUsbProDataAndReturn( BaseUsbProWidget::DEVICE_LABEL, NULL, 0, BaseUsbProWidget::DEVICE_LABEL, device_data, sizeof(device_data)); m_endpoint->AddExpectedUsbProDataAndReturn( BaseUsbProWidget::SERIAL_LABEL, NULL, 0, BaseUsbProWidget::SERIAL_LABEL, serial_data, sizeof(serial_data)); m_endpoint->AddExpectedUsbProMessage(BaseUsbProWidget::GET_PARAMS, &get_params_request[0], sizeof(get_params_request)); m_thread->Start(); m_thread->WaitUntilRunning(); m_ss.Run(); OLA_ASSERT_EQ(DMXTER, m_received_widget_type); } /** * Check that we can locate a Usb Pro widget */ void WidgetDetectorThreadTest::testUsbProWidget() { const uint8_t serial_data[] = {0x78, 0x56, 0x34, 0x12}; uint8_t get_params_request[] = {0, 0}; uint8_t get_params_response[] = {4, 1, 9, 1, 1}; m_endpoint->AddExpectedUsbProMessage(BaseUsbProWidget::MANUFACTURER_LABEL, NULL, 0); m_endpoint->AddExpectedUsbProMessage(BaseUsbProWidget::DEVICE_LABEL, NULL, 0); m_endpoint->AddExpectedUsbProDataAndReturn( BaseUsbProWidget::SERIAL_LABEL, NULL, 0, BaseUsbProWidget::SERIAL_LABEL, serial_data, sizeof(serial_data)); m_endpoint->AddExpectedUsbProDataAndReturn( BaseUsbProWidget::GET_PARAMS, &get_params_request[0], sizeof(get_params_request), BaseUsbProWidget::GET_PARAMS, get_params_response, sizeof(get_params_response)); m_endpoint->AddExpectedUsbProMessage(BaseUsbProWidget::HARDWARE_VERSION_LABEL, NULL, 0); m_thread->Start(); m_thread->WaitUntilRunning(); m_ss.Run(); OLA_ASSERT_EQ(ENTTEC, m_received_widget_type); } /** * Check that we can locate a Usb Pro MK II widget */ void WidgetDetectorThreadTest::testUsbProMkIIWidget() { const uint8_t serial_data[] = {0x78, 0x56, 0x34, 0x12}; uint8_t get_params_request[] = {0, 0}; uint8_t get_params_response[] = {4, 1, 9, 1, 1}; m_endpoint->AddExpectedUsbProMessage(BaseUsbProWidget::MANUFACTURER_LABEL, NULL, 0); m_endpoint->AddExpectedUsbProMessage(BaseUsbProWidget::DEVICE_LABEL, NULL, 0); m_endpoint->AddExpectedUsbProDataAndReturn( BaseUsbProWidget::SERIAL_LABEL, NULL, 0, BaseUsbProWidget::SERIAL_LABEL, serial_data, sizeof(serial_data)); m_endpoint->AddExpectedUsbProDataAndReturn( BaseUsbProWidget::GET_PARAMS, &get_params_request[0], sizeof(get_params_request), BaseUsbProWidget::GET_PARAMS, get_params_response, sizeof(get_params_response)); const uint8_t hardware_version = 2; m_endpoint->AddExpectedUsbProDataAndReturn( BaseUsbProWidget::HARDWARE_VERSION_LABEL, NULL, 0, BaseUsbProWidget::HARDWARE_VERSION_LABEL, &hardware_version, sizeof(hardware_version)); // expect the unlock message and then the port enable const uint8_t unlock_key[] = {0xd7, 0xb2, 0x11, 0x0d}; m_endpoint->AddExpectedUsbProMessage(USB_PRO_MKII_API_LABEL, unlock_key, sizeof(unlock_key)); const uint8_t port_enable[] = {1, 1}; m_endpoint->AddExpectedUsbProMessage(SET_PORT_ASSIGNMENTS, port_enable, sizeof(port_enable)); m_expect_dual_port_enttec_widget = true; m_thread->Start(); m_thread->WaitUntilRunning(); m_ss.Run(); OLA_ASSERT_EQ(ENTTEC, m_received_widget_type); } /** * Check that we can locate a Robe widget. */ void WidgetDetectorThreadTest::testRobeWidget() { // usb pro messages first m_endpoint->AddExpectedUsbProMessage(BaseUsbProWidget::MANUFACTURER_LABEL, NULL, 0); m_endpoint->AddExpectedUsbProMessage(BaseUsbProWidget::DEVICE_LABEL, NULL, 0); m_endpoint->AddExpectedUsbProMessage(BaseUsbProWidget::SERIAL_LABEL, NULL, 0); // robe messages uint8_t info_data[] = {1, 11, 3, 0, 0}; uint8_t uid_data[] = {0x52, 0x53, 2, 0, 0, 10}; m_endpoint->AddExpectedRobeDataAndReturn( BaseRobeWidget::INFO_REQUEST, NULL, 0, BaseRobeWidget::INFO_RESPONSE, info_data, sizeof(info_data)); m_endpoint->AddExpectedRobeDataAndReturn( BaseRobeWidget::UID_REQUEST, NULL, 0, BaseRobeWidget::UID_RESPONSE, uid_data, sizeof(uid_data)); m_thread->Start(); m_thread->WaitUntilRunning(); m_ss.Run(); OLA_ASSERT_EQ(ROBE, m_received_widget_type); } /** * Check that we can locate an Ultra DMX widget. */ void WidgetDetectorThreadTest::testUltraDmxWidget() { uint8_t serial_data[] = {0x78, 0x56, 0x34, 0x12}; uint8_t manufacturer_data[] = "\153\152DMXking.com"; uint8_t device_data[] = "\002\000ultraDMX Pro"; uint8_t get_params_request[] = {0, 0}; m_endpoint->AddExpectedUsbProDataAndReturn( BaseUsbProWidget::MANUFACTURER_LABEL, NULL, 0, BaseUsbProWidget::MANUFACTURER_LABEL, manufacturer_data, sizeof(manufacturer_data)); m_endpoint->AddExpectedUsbProDataAndReturn( BaseUsbProWidget::DEVICE_LABEL, NULL, 0, BaseUsbProWidget::DEVICE_LABEL, device_data, sizeof(device_data)); m_endpoint->AddExpectedUsbProDataAndReturn( BaseUsbProWidget::SERIAL_LABEL, NULL, 0, BaseUsbProWidget::SERIAL_LABEL, serial_data, sizeof(serial_data)); m_endpoint->AddExpectedUsbProMessage(BaseUsbProWidget::GET_PARAMS, &get_params_request[0], sizeof(get_params_request)); m_thread->Start(); m_thread->WaitUntilRunning(); m_ss.Run(); OLA_ASSERT_EQ(ULTRA_DMX, m_received_widget_type); } /** * Check a widget that fails to respond */ void WidgetDetectorThreadTest::testTimeout() { m_endpoint->AddExpectedUsbProMessage(BaseUsbProWidget::MANUFACTURER_LABEL, NULL, 0); m_endpoint->AddExpectedUsbProMessage(BaseUsbProWidget::DEVICE_LABEL, NULL, 0); m_endpoint->AddExpectedUsbProMessage(BaseUsbProWidget::SERIAL_LABEL, NULL, 0); m_endpoint->AddExpectedRobeMessage(BaseRobeWidget::INFO_REQUEST, NULL, 0); m_thread->Start(); m_thread->WaitUntilRunning(); m_ss.Run(); OLA_ASSERT_EQ(NONE, m_received_widget_type); } /** * Check we handle the case when a widget disappears. */ void WidgetDetectorThreadTest::testClose() { m_ss.RemoveReadDescriptor(m_other_end.get()); m_thread->Start(); m_thread->WaitUntilRunning(); // possible race condition here m_other_end->Close(); m_ss.Run(); OLA_ASSERT_EQ(NONE, m_received_widget_type); } ola-0.10.5.nojsmin/plugins/usbpro/DmxTriDevice.cpp0000644000175000017500000000514413023355232021510 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DmxTriDevice.cpp * The Jese DMX TRI device. This just wraps the DmxTriWidget. * Copyright (C) 2010 Simon Newton */ #include #include "ola/Callback.h" #include "ola/Logging.h" #include "plugins/usbpro/DmxTriDevice.h" #include "plugins/usbpro/DmxTriWidget.h" namespace ola { namespace plugin { namespace usbpro { using std::string; /* * New DMX TRI device */ DmxTriDevice::DmxTriDevice(ola::AbstractPlugin *owner, const string &name, DmxTriWidget *widget, uint16_t esta_id, uint16_t device_id, uint32_t serial, uint16_t firmware_version) : UsbSerialDevice(owner, name, widget), m_tri_widget(widget) { std::ostringstream str; str << std::hex << esta_id << "-" << device_id << "-" << serial; m_device_id = str.str(); str.str(""); str << "Serial #: " << serial << ", firmware " << (firmware_version >> 8) << "." << (firmware_version & 0xff); ola::OutputPort *output_port = new DmxTriOutputPort( this, widget, str.str()); AddPort(output_port); } /* * Remove the rdm timeout if it's still running */ void DmxTriDevice::PrePortStop() { m_tri_widget->Stop(); } /** * New DmxTriOutputPort */ DmxTriOutputPort::DmxTriOutputPort(DmxTriDevice *parent, DmxTriWidget *widget, const string &description) : BasicOutputPort(parent, 0, true, true), m_tri_widget(widget), m_description(description) { } /* * Shutdown */ DmxTriOutputPort::~DmxTriOutputPort() {} /* * Send a dmx frame * @returns true if we sent ok, false otherwise */ bool DmxTriOutputPort::WriteDMX(const DmxBuffer &buffer, uint8_t) { return m_tri_widget->SendDMX(buffer); } } // namespace usbpro } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbpro/EnttecUsbProWidgetTest.cpp0000644000175000017500000006270513023355232023550 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * EnttecUsbProWidgetTest.cpp * Test fixture for the EnttecUsbProWidget class * Copyright (C) 2010 Simon Newton */ #include #include #include #include #include "common/rdm/TestHelper.h" #include "ola/Callback.h" #include "ola/DmxBuffer.h" #include "ola/Logging.h" #include "ola/base/Array.h" #include "ola/rdm/RDMCommandSerializer.h" #include "ola/rdm/UID.h" #include "ola/testing/TestUtils.h" #include "plugins/usbpro/CommonWidgetTest.h" #include "plugins/usbpro/EnttecUsbProWidget.h" #include "plugins/usbpro/EnttecUsbProWidgetImpl.h" using ola::plugin::usbpro::EnttecPort; using ola::plugin::usbpro::EnttecUsbProWidget; using ola::rdm::GetResponseFromData; using ola::rdm::RDMCommandSerializer; using ola::rdm::RDMDiscoveryRequest; using ola::rdm::RDMFrame; using ola::rdm::RDMFrames; using ola::rdm::RDMReply; using ola::rdm::RDMRequest; using ola::rdm::RDMResponse; using ola::rdm::UID; using std::auto_ptr; using std::string; using std::vector; using ola::plugin::usbpro::usb_pro_parameters; class EnttecUsbProWidgetTest: public CommonWidgetTest { CPPUNIT_TEST_SUITE(EnttecUsbProWidgetTest); CPPUNIT_TEST(testParams); CPPUNIT_TEST(testReceiveDMX); CPPUNIT_TEST(testChangeMode); CPPUNIT_TEST(testSendRDMRequest); CPPUNIT_TEST(testSendRDMMute); CPPUNIT_TEST(testSendRDMDUB); CPPUNIT_TEST(testMuteDevice); CPPUNIT_TEST(testUnMuteAll); CPPUNIT_TEST(testBranch); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void testParams(); void testReceiveDMX(); void testChangeMode(); void testSendRDMRequest(); void testSendRDMMute(); void testSendRDMDUB(); void testMuteDevice(); void testUnMuteAll(); void testBranch(); private: auto_ptr m_widget; uint8_t m_transaction_number; ola::rdm::RDMStatusCode m_received_code; RDMRequest *NewRequest(const UID &destination, const uint8_t *data = NULL, unsigned int length = 0); uint8_t *PackRDMRequest(const RDMRequest *request, unsigned int *size); uint8_t *PackRDMResponse(const RDMResponse *response, unsigned int *size); void ValidateResponse(RDMReply *reply); void ValidateStatus(ola::rdm::RDMStatusCode expected_code, RDMFrames expected_frames, RDMReply *reply); void ValidateMuteStatus(bool expected, bool actual); void ValidateBranchStatus(const uint8_t *expected_data, unsigned int length, const uint8_t *actual_data, unsigned int actual_length); void SendResponseAndTimeout(const uint8_t *response_data, unsigned int length); void Terminate() { m_ss.Terminate(); } void ValidateParams(bool status, const usb_pro_parameters ¶ms); void ValidateDMX(EnttecPort *port, const ola::DmxBuffer *expected_buffer); bool m_got_dmx; static const UID BCAST_DESTINATION; static const UID DESTINATION; static const UID SOURCE; static const uint16_t ESTA_ID = 0x00a1; static const uint32_t SERIAL_NUMBER = 0x01020304; static const uint8_t CHANGE_MODE_LABEL = 8; static const uint8_t CHANGE_OF_STATE_LABEL = 9; static const uint8_t GET_PARAM_LABEL = 3; static const uint8_t RDM_DISCOVERY_PACKET = 11; static const uint8_t RDM_PACKET = 7; static const uint8_t RDM_TIMEOUT_PACKET = 12; static const uint8_t RECEIVE_DMX_LABEL = 5; static const uint8_t SET_PARAM_LABEL = 4; static const uint8_t TEST_RDM_DATA[]; static const unsigned int FOOTER_SIZE = 1; static const unsigned int HEADER_SIZE = 4; }; const UID EnttecUsbProWidgetTest::DESTINATION(ESTA_ID, SERIAL_NUMBER); const UID EnttecUsbProWidgetTest::BCAST_DESTINATION(ESTA_ID, 0xffffffff); const UID EnttecUsbProWidgetTest::SOURCE(EnttecUsbProWidget::ENTTEC_ESTA_ID, 1); const uint8_t EnttecUsbProWidgetTest::TEST_RDM_DATA[] = { 0x5a, 0x5a, 0x5a, 0x5a}; CPPUNIT_TEST_SUITE_REGISTRATION(EnttecUsbProWidgetTest); void EnttecUsbProWidgetTest::setUp() { CommonWidgetTest::setUp(); EnttecUsbProWidget::EnttecUsbProWidgetOptions options( EnttecUsbProWidget::ENTTEC_ESTA_ID, 1); options.enable_rdm = true; m_widget.reset(new EnttecUsbProWidget(&m_ss, &m_descriptor, options)); m_transaction_number = 0; m_got_dmx = false; } /* * Helper method to create new GetRDMRequest objects. * @param destination the destination UID * @param data the RDM Request data * @param length the size of the RDM data. */ RDMRequest *EnttecUsbProWidgetTest::NewRequest(const UID &destination, const uint8_t *data, unsigned int length) { return new ola::rdm::RDMGetRequest( SOURCE, destination, m_transaction_number++, // transaction # 1, // port id 10, // sub device 296, // param id data, length); } /** * Pack a RDM request into a buffer */ uint8_t *EnttecUsbProWidgetTest::PackRDMRequest(const RDMRequest *request, unsigned int *size) { unsigned int request_size = RDMCommandSerializer::RequiredSize(*request); uint8_t *rdm_data = new uint8_t[request_size + 1]; rdm_data[0] = ola::rdm::RDMCommand::START_CODE; memset(&rdm_data[1], 0, request_size); OLA_ASSERT(RDMCommandSerializer::Pack(*request, &rdm_data[1], &request_size)); *size = request_size + 1; return rdm_data; } /** * Pack a RDM Response into a buffer */ uint8_t *EnttecUsbProWidgetTest::PackRDMResponse(const RDMResponse *response, unsigned int *size) { unsigned int response_size = RDMCommandSerializer::RequiredSize(*response); uint8_t *rdm_data = new uint8_t[response_size + 2]; rdm_data[0] = 0; // status ok rdm_data[1] = ola::rdm::RDMCommand::START_CODE; memset(&rdm_data[2], 0, response_size); OLA_ASSERT(RDMCommandSerializer::Pack(*response, &rdm_data[2], &response_size)); *size = response_size + 2; return rdm_data; } /* * Check the response matches what we expected. */ void EnttecUsbProWidgetTest::ValidateResponse(RDMReply *reply) { OLA_ASSERT_EQ(ola::rdm::RDM_COMPLETED_OK, reply->StatusCode()); OLA_ASSERT(reply->Response()); OLA_ASSERT_DATA_EQUALS(TEST_RDM_DATA, arraysize(TEST_RDM_DATA), reply->Response()->ParamData(), reply->Response()->ParamDataSize()); const RDMFrames &frames = reply->Frames(); OLA_ASSERT_EQ((size_t) 1, frames.size()); ola::rdm::RDMStatusCode raw_code; auto_ptr raw_response( ola::rdm::RDMResponse::InflateFromData(frames[0].data.data() + 1, frames[0].data.size() - 1, &raw_code)); OLA_ASSERT_TRUE(*raw_response.get() == *reply->Response()); m_ss.Terminate(); } /* * Check that this request returned the expected status code */ void EnttecUsbProWidgetTest::ValidateStatus( ola::rdm::RDMStatusCode expected_code, RDMFrames expected_frames, RDMReply *reply) { OLA_ASSERT_EQ(expected_code, reply->StatusCode()); OLA_ASSERT_FALSE(reply->Response()); const RDMFrames &frames = reply->Frames(); OLA_ASSERT_EQ(expected_frames.size(), frames.size()); for (unsigned int i = 0; i < frames.size(); i++) { OLA_ASSERT_DATA_EQUALS(expected_frames[i].data.data(), expected_frames[i].data.size(), frames[i].data.data(), frames[i].data.size()); OLA_ASSERT_TRUE(expected_frames[i] == frames[i]); } m_received_code = expected_code; m_ss.Terminate(); } /** * Validate that a mute response matches what we expect */ void EnttecUsbProWidgetTest::ValidateMuteStatus(bool expected, bool actual) { OLA_ASSERT_EQ(expected, actual); m_ss.Terminate(); } /** * Validate that a branch request returns what we expect. */ void EnttecUsbProWidgetTest::ValidateBranchStatus(const uint8_t *expected_data, unsigned int length, const uint8_t *actual_data, unsigned int actual_length) { OLA_ASSERT_EQ(length, actual_length); OLA_ASSERT_FALSE(memcmp(expected_data, actual_data, length)); m_ss.Terminate(); } /** * Send a RDM response message, followed by a RDM timeout message */ void EnttecUsbProWidgetTest::SendResponseAndTimeout( const uint8_t *response_data, unsigned int length) { m_endpoint->SendUnsolicitedUsbProData( RECEIVE_DMX_LABEL, response_data, length); m_endpoint->SendUnsolicitedUsbProData( RDM_TIMEOUT_PACKET, NULL, 0); } /** * Check the params are ok */ void EnttecUsbProWidgetTest::ValidateParams( bool status, const usb_pro_parameters ¶ms) { OLA_ASSERT(status); OLA_ASSERT_EQ((uint8_t) 0, params.firmware); OLA_ASSERT_EQ((uint8_t) 1, params.firmware_high); OLA_ASSERT_EQ((uint8_t) 10, params.break_time); OLA_ASSERT_EQ((uint8_t) 14, params.mab_time); OLA_ASSERT_EQ((uint8_t) 40, params.rate); m_ss.Terminate(); } /** * Check the DMX data is what we expected */ void EnttecUsbProWidgetTest::ValidateDMX( EnttecPort *port, const ola::DmxBuffer *expected_buffer) { const ola::DmxBuffer &buffer = port->FetchDMX(); OLA_ASSERT(*expected_buffer == buffer); m_got_dmx = true; m_ss.Terminate(); } /** * Check that discovery works for a device that just implements the serial # */ void EnttecUsbProWidgetTest::testParams() { EnttecPort *port = m_widget->GetPort(0); OLA_ASSERT_NOT_NULL(port); OLA_ASSERT_NULL(m_widget->GetPort(1)); uint8_t get_param_request_data[] = {0, 0}; uint8_t get_param_response_data[] = {0, 1, 10, 14, 40}; m_endpoint->AddExpectedUsbProDataAndReturn( GET_PARAM_LABEL, get_param_request_data, sizeof(get_param_request_data), GET_PARAM_LABEL, get_param_response_data, sizeof(get_param_response_data)); port->GetParameters( ola::NewSingleCallback(this, &EnttecUsbProWidgetTest::ValidateParams)); m_ss.Run(); m_endpoint->Verify(); // now try a set params request uint8_t set_param_request_data[] = {0, 0, 9, 63, 20}; m_endpoint->AddExpectedUsbProMessage( SET_PARAM_LABEL, set_param_request_data, sizeof(set_param_request_data), ola::NewSingleCallback(this, &EnttecUsbProWidgetTest::Terminate)); OLA_ASSERT(port->SetParameters(9, 63, 20)); m_ss.Run(); m_endpoint->Verify(); } /** * Check that receiving DMX works. */ void EnttecUsbProWidgetTest::testReceiveDMX() { EnttecPort *port = m_widget->GetPort(0); OLA_ASSERT_NOT_NULL(port); ola::DmxBuffer buffer; buffer.SetFromString("1,10,14,40"); port->SetDMXCallback(ola::NewCallback( this, &EnttecUsbProWidgetTest::ValidateDMX, port, const_cast(&buffer))); uint8_t dmx_data[] = { 0, 0, // no error 1, 10, 14, 40 }; m_endpoint->SendUnsolicitedUsbProData( RECEIVE_DMX_LABEL, dmx_data, sizeof(dmx_data)); m_ss.Run(); m_endpoint->Verify(); OLA_ASSERT(m_got_dmx); // now try one with the error bit set dmx_data[0] = 1; m_got_dmx = false; m_endpoint->SendUnsolicitedUsbProData( RECEIVE_DMX_LABEL, dmx_data, sizeof(dmx_data)); // because this doesn't trigger the callback we have no way to terminate the // select server, so we use a timeout, which is nasty, but fails closed m_ss.RegisterSingleTimeout( 100, // shold be more than enough time ola::NewSingleCallback(this, &EnttecUsbProWidgetTest::Terminate)); m_ss.Run(); m_endpoint->Verify(); OLA_ASSERT_FALSE(m_got_dmx); // now try a non-0 start code dmx_data[0] = 0; dmx_data[1] = 0x0a; m_got_dmx = false; m_endpoint->SendUnsolicitedUsbProData( RECEIVE_DMX_LABEL, dmx_data, sizeof(dmx_data)); // use the timeout trick again m_ss.RegisterSingleTimeout( 100, ola::NewSingleCallback(this, &EnttecUsbProWidgetTest::Terminate)); m_ss.Run(); m_endpoint->Verify(); OLA_ASSERT_FALSE(m_got_dmx); // now do a change of state packet buffer.SetFromString("1,10,22,93,144"); uint8_t change_of_state_data[] = { 0, 0x38, 0, 0, 0, 0, 22, 93, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; m_endpoint->SendUnsolicitedUsbProData( CHANGE_OF_STATE_LABEL, change_of_state_data, sizeof(change_of_state_data)); m_ss.Run(); m_endpoint->Verify(); OLA_ASSERT(m_got_dmx); } /* * Check that changing mode works. */ void EnttecUsbProWidgetTest::testChangeMode() { EnttecPort *port = m_widget->GetPort(0); OLA_ASSERT_NOT_NULL(port); // first we test 'send always' mode uint8_t change_mode_data[] = {0}; m_endpoint->AddExpectedUsbProMessage( CHANGE_MODE_LABEL, change_mode_data, sizeof(change_mode_data), ola::NewSingleCallback(this, &EnttecUsbProWidgetTest::Terminate)); port->ChangeToReceiveMode(false); m_ss.Run(); m_endpoint->Verify(); // now try 'send data on change' mode change_mode_data[0] = 1; m_endpoint->AddExpectedUsbProMessage( CHANGE_MODE_LABEL, change_mode_data, sizeof(change_mode_data), ola::NewSingleCallback(this, &EnttecUsbProWidgetTest::Terminate)); port->ChangeToReceiveMode(true); m_ss.Run(); m_endpoint->Verify(); } /** * Check that we send RDM messages correctly. */ void EnttecUsbProWidgetTest::testSendRDMRequest() { EnttecPort *port = m_widget->GetPort(0); OLA_ASSERT_NOT_NULL(port); // request RDMRequest *rdm_request = NewRequest(DESTINATION); unsigned int expected_request_frame_size; uint8_t *expected_request_frame = PackRDMRequest( rdm_request, &expected_request_frame_size); // response auto_ptr response( GetResponseFromData(rdm_request, TEST_RDM_DATA, sizeof(TEST_RDM_DATA))); unsigned int response_size; uint8_t *response_frame = PackRDMResponse(response.get(), &response_size); // add the expected response, send and verify m_endpoint->AddExpectedUsbProDataAndReturn( RDM_PACKET, expected_request_frame, expected_request_frame_size, RECEIVE_DMX_LABEL, response_frame, response_size); port->SendRDMRequest( rdm_request, ola::NewSingleCallback(this, &EnttecUsbProWidgetTest::ValidateResponse)); m_ss.Run(); m_endpoint->Verify(); delete[] expected_request_frame; delete[] response_frame; // now check broadcast messages // request rdm_request = NewRequest(BCAST_DESTINATION); uint8_t *expected_bcast_request_frame = PackRDMRequest( rdm_request, &expected_request_frame_size); // add the expected response, send and verify m_endpoint->AddExpectedUsbProDataAndReturn( RDM_PACKET, expected_bcast_request_frame, expected_request_frame_size, RDM_TIMEOUT_PACKET, NULL, 0); RDMFrames frames; m_received_code = ola::rdm::RDM_COMPLETED_OK; port->SendRDMRequest( rdm_request, ola::NewSingleCallback(this, &EnttecUsbProWidgetTest::ValidateStatus, ola::rdm::RDM_WAS_BROADCAST, frames)); m_ss.Run(); OLA_ASSERT_EQ(ola::rdm::RDM_WAS_BROADCAST, m_received_code); m_endpoint->Verify(); // cleanup time delete[] expected_bcast_request_frame; } /** * Check that RDM Mute requests work */ void EnttecUsbProWidgetTest::testSendRDMMute() { EnttecPort *port = m_widget->GetPort(0); OLA_ASSERT_NOT_NULL(port); // request RDMRequest *rdm_request = new ola::rdm::RDMDiscoveryRequest( SOURCE, DESTINATION, m_transaction_number++, // transaction # 1, // port id 0, // sub device ola::rdm::PID_DISC_MUTE, // param id NULL, 0); unsigned int expected_request_frame_size; uint8_t *expected_request_frame = PackRDMRequest( rdm_request, &expected_request_frame_size); // response // to keep things simple here we return the TEST_RDM_DATA. auto_ptr response( GetResponseFromData(rdm_request, TEST_RDM_DATA, sizeof(TEST_RDM_DATA))); unsigned int response_size; uint8_t *response_frame = PackRDMResponse(response.get(), &response_size); // add the expected response, send and verify m_endpoint->AddExpectedUsbProDataAndReturn( RDM_PACKET, expected_request_frame, expected_request_frame_size, RECEIVE_DMX_LABEL, response_frame, response_size); port->SendRDMRequest( rdm_request, ola::NewSingleCallback(this, &EnttecUsbProWidgetTest::ValidateResponse)); m_ss.Run(); m_endpoint->Verify(); delete[] expected_request_frame; delete[] response_frame; } /** * Check that we send RDM discovery messages correctly. */ void EnttecUsbProWidgetTest::testSendRDMDUB() { EnttecPort *port = m_widget->GetPort(0); OLA_ASSERT_NOT_NULL(port); static const uint8_t REQUEST_DATA[] = { 0x7a, 0x70, 0, 0, 0, 0, 0x7a, 0x70, 0xff, 0xff, 0xff, 0xff }; // request RDMRequest *rdm_request = new ola::rdm::RDMDiscoveryRequest( SOURCE, DESTINATION, m_transaction_number++, // transaction # 1, // port id 0, // sub device ola::rdm::PID_DISC_UNIQUE_BRANCH, // param id REQUEST_DATA, sizeof(REQUEST_DATA)); unsigned int expected_request_frame_size; uint8_t *expected_request_frame = PackRDMRequest( rdm_request, &expected_request_frame_size); // a 4 byte response means a timeout static const uint8_t EMPTY_RESPONSE[] = {0, 0, 0, 0}; // add the expected response, send and verify m_endpoint->AddExpectedUsbProDataAndReturn( RDM_DISCOVERY_PACKET, expected_request_frame, expected_request_frame_size, RDM_TIMEOUT_PACKET, EMPTY_RESPONSE, sizeof(EMPTY_RESPONSE)); RDMFrames frames; port->SendRDMRequest( rdm_request, ola::NewSingleCallback(this, &EnttecUsbProWidgetTest::ValidateStatus, ola::rdm::RDM_TIMEOUT, frames)); m_ss.Run(); m_endpoint->Verify(); delete[] expected_request_frame; // now try a dub response that returns something rdm_request = new ola::rdm::RDMDiscoveryRequest( SOURCE, DESTINATION, m_transaction_number++, // transaction # 1, // port id 0, // sub device ola::rdm::PID_DISC_UNIQUE_BRANCH, // param id REQUEST_DATA, sizeof(REQUEST_DATA)); expected_request_frame = PackRDMRequest( rdm_request, &expected_request_frame_size); // something that looks like a DUB response static const uint8_t FAKE_RESPONSE[] = {0x00, 0xfe, 0xfe, 0xaa, 0xaa}; // add the expected response, send and verify m_endpoint->AddExpectedUsbProDataAndReturn( RDM_DISCOVERY_PACKET, expected_request_frame, expected_request_frame_size, RECEIVE_DMX_LABEL, FAKE_RESPONSE, sizeof(FAKE_RESPONSE)); frames.push_back(RDMFrame(FAKE_RESPONSE + 1, arraysize(FAKE_RESPONSE) - 1)); port->SendRDMRequest( rdm_request, ola::NewSingleCallback(this, &EnttecUsbProWidgetTest::ValidateStatus, ola::rdm::RDM_DUB_RESPONSE, frames)); m_ss.Run(); m_endpoint->Verify(); delete[] expected_request_frame; } /** * Test mute device */ void EnttecUsbProWidgetTest::testMuteDevice() { EnttecPort *port = m_widget->GetPort(0); OLA_ASSERT_NOT_NULL(port); // first test when a device doesn't respond auto_ptr mute_request( ola::rdm::NewMuteRequest(SOURCE, DESTINATION, m_transaction_number++)); unsigned int expected_request_frame_size; uint8_t *expected_request_frame = PackRDMRequest( mute_request.get(), &expected_request_frame_size); // add the expected response, send and verify m_endpoint->AddExpectedUsbProDataAndReturn( RDM_PACKET, expected_request_frame, expected_request_frame_size, RDM_TIMEOUT_PACKET, NULL, 0); port->m_impl->MuteDevice( DESTINATION, ola::NewSingleCallback(this, &EnttecUsbProWidgetTest::ValidateMuteStatus, false)); m_ss.Run(); m_endpoint->Verify(); delete[] expected_request_frame; // now try an actual mute response auto_ptr mute_request2( ola::rdm::NewMuteRequest(SOURCE, DESTINATION, m_transaction_number++)); expected_request_frame = PackRDMRequest( mute_request2.get(), &expected_request_frame_size); // We can really return anything // TODO(simon): make this better uint8_t mute_response_frame[] = { 0, ola::rdm::RDMCommand::START_CODE, 0}; // add the expected response, send and verify m_endpoint->AddExpectedUsbProDataAndReturn( RDM_PACKET, expected_request_frame, expected_request_frame_size, RECEIVE_DMX_LABEL, mute_response_frame, sizeof(mute_response_frame)); port->m_impl->MuteDevice( DESTINATION, ola::NewSingleCallback(this, &EnttecUsbProWidgetTest::ValidateMuteStatus, true)); m_ss.Run(); m_endpoint->Verify(); delete[] expected_request_frame; } /** * Test the unmute all request works */ void EnttecUsbProWidgetTest::testUnMuteAll() { EnttecPort *port = m_widget->GetPort(0); OLA_ASSERT_NOT_NULL(port); auto_ptr unmute_request( ola::rdm::NewUnMuteRequest(SOURCE, UID::AllDevices(), m_transaction_number++)); unsigned int expected_request_frame_size; uint8_t *expected_request_frame = PackRDMRequest( unmute_request.get(), &expected_request_frame_size); // add the expected response, send and verify m_endpoint->AddExpectedUsbProDataAndReturn( RDM_PACKET, expected_request_frame, expected_request_frame_size, RDM_TIMEOUT_PACKET, NULL, 0); port->m_impl->UnMuteAll( ola::NewSingleCallback(this, &EnttecUsbProWidgetTest::Terminate)); m_ss.Run(); m_endpoint->Verify(); delete[] expected_request_frame; } /** * Test the DUB request works */ void EnttecUsbProWidgetTest::testBranch() { EnttecPort *port = m_widget->GetPort(0); OLA_ASSERT_NOT_NULL(port); // first test when no devices respond auto_ptr discovery_request( ola::rdm::NewDiscoveryUniqueBranchRequest( SOURCE, UID(0, 0), UID::AllDevices(), m_transaction_number++)); unsigned int expected_request_frame_size; uint8_t *expected_request_frame = PackRDMRequest( discovery_request.get(), &expected_request_frame_size); // add the expected response, send and verify m_endpoint->AddExpectedUsbProDataAndReturn( RDM_DISCOVERY_PACKET, expected_request_frame, expected_request_frame_size, RDM_TIMEOUT_PACKET, NULL, 0); port->m_impl->Branch( UID(0, 0), UID::AllDevices(), ola::NewSingleCallback(this, &EnttecUsbProWidgetTest::ValidateBranchStatus, static_cast(NULL), static_cast(0))); m_ss.Run(); m_endpoint->Verify(); delete[] expected_request_frame; // now try an actual response, the data doesn't actually have to be valid // because it's just passed straight to the callback. auto_ptr discovery_request2( ola::rdm::NewDiscoveryUniqueBranchRequest( SOURCE, UID(0, 0), UID::AllDevices(), m_transaction_number++)); expected_request_frame = PackRDMRequest( discovery_request2.get(), &expected_request_frame_size); // the response, can be anything really, only the first byte counts uint8_t response_frame2[] = {0, 1, 2, 3, 4}; m_endpoint->AddExpectedUsbProMessage( RDM_DISCOVERY_PACKET, expected_request_frame, expected_request_frame_size, ola::NewSingleCallback( this, &EnttecUsbProWidgetTest::SendResponseAndTimeout, static_cast(response_frame2), static_cast(sizeof(response_frame2)))); port->m_impl->Branch( UID(0, 0), UID::AllDevices(), ola::NewSingleCallback( this, &EnttecUsbProWidgetTest::ValidateBranchStatus, static_cast(&response_frame2[1]), static_cast(sizeof(response_frame2) - 1))); m_ss.Run(); m_endpoint->Verify(); delete[] expected_request_frame; } ola-0.10.5.nojsmin/plugins/usbpro/RobeWidgetTest.cpp0000644000175000017500000005270213023355232022056 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RobeWidgetTest.cpp * Test fixture for the DmxterWidget class * Copyright (C) 2010 Simon Newton */ #include #include #include #include #include #include "common/rdm/TestHelper.h" #include "ola/Callback.h" #include "ola/Constants.h" #include "ola/DmxBuffer.h" #include "ola/base/Array.h" #include "ola/Logging.h" #include "ola/rdm/RDMCommandSerializer.h" #include "ola/rdm/RDMEnums.h" #include "ola/rdm/UID.h" #include "plugins/usbpro/BaseRobeWidget.h" #include "plugins/usbpro/RobeWidget.h" #include "plugins/usbpro/CommonWidgetTest.h" #include "ola/testing/TestUtils.h" using ola::DmxBuffer; using ola::plugin::usbpro::BaseRobeWidget; using ola::plugin::usbpro::RobeWidget; using ola::rdm::GetResponseFromData; using ola::rdm::RDMCommandSerializer; using ola::rdm::RDMFrame; using ola::rdm::RDMFrames; using ola::rdm::RDMReply; using ola::rdm::RDMRequest; using ola::rdm::RDMResponse; using ola::rdm::UID; using std::auto_ptr; using std::string; using std::vector; class RobeWidgetTest: public CommonWidgetTest { CPPUNIT_TEST_SUITE(RobeWidgetTest); CPPUNIT_TEST(testSendDMX); CPPUNIT_TEST(testSendRDMRequest); CPPUNIT_TEST(testSendRDMMute); CPPUNIT_TEST(testSendRDMDUB); CPPUNIT_TEST(testMuteDevice); CPPUNIT_TEST(testUnMuteAll); CPPUNIT_TEST(testReceive); CPPUNIT_TEST(testBranch); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void testSendDMX(); void testSendRDMRequest(); void testSendRDMMute(); void testSendRDMDUB(); void testMuteDevice(); void testUnMuteAll(); void testBranch(); void testReceive(); private: auto_ptr m_widget; uint8_t m_transaction_number; ola::rdm::RDMStatusCode m_received_code; bool m_new_dmx_data; void Terminate() { m_ss.Terminate(); } void NewDMXData() { m_new_dmx_data = true; m_ss.Terminate(); } RDMRequest *NewRequest(const UID &destination, const uint8_t *data = NULL, unsigned int length = 0); uint8_t *PackRDMRequest(const RDMRequest *request, unsigned int *size); uint8_t *PackRDMResponse(const RDMResponse *response, unsigned int *size); void ValidateResponse(RDMReply *reply); void ValidateStatus(ola::rdm::RDMStatusCode expected_code, RDMFrames expected_frames, RDMReply *reply); void ValidateMuteStatus(bool expected, bool actual); void ValidateBranchStatus(const uint8_t *expected_data, unsigned int length, const uint8_t *actual_data, unsigned int actual_length); void CallbackComplete() { m_ss.Terminate(); } static const UID BCAST_DESTINATION; static const UID DESTINATION; static const UID SOURCE; static const uint16_t ESTA_ID = 0x7890; static const uint32_t SERIAL_NUMBER = 0x01020304; static const uint8_t DMX_IN_REQUEST_LABEL = 0x04; static const uint8_t DMX_IN_RESPONSE_LABEL = 0x05; static const uint8_t DMX_FRAME_LABEL = 0x06; static const uint8_t TEST_RDM_DATA[]; static const uint8_t TEST_MUTE_RESPONSE_DATA[]; static const unsigned int FOOTER_SIZE = 1; static const unsigned int HEADER_SIZE = 5; static const unsigned int PADDING_SIZE = 4; }; const UID RobeWidgetTest::SOURCE(1, 2); const UID RobeWidgetTest::DESTINATION(ESTA_ID, SERIAL_NUMBER); const UID RobeWidgetTest::BCAST_DESTINATION(ESTA_ID, 0xffffffff); const uint8_t RobeWidgetTest::TEST_RDM_DATA[] = {0x5a, 0x5a, 0x5a, 0x5a}; const uint8_t RobeWidgetTest::TEST_MUTE_RESPONSE_DATA[] = {0, 0}; CPPUNIT_TEST_SUITE_REGISTRATION(RobeWidgetTest); void RobeWidgetTest::setUp() { CommonWidgetTest::setUp(); m_widget.reset(new ola::plugin::usbpro::RobeWidget(&m_descriptor, SOURCE)); m_transaction_number = 0; m_new_dmx_data = false; } /* * Helper method to create new GetRDMRequest objects. * @param destination the destination UID * @param data the RDM Request data * @param length the size of the RDM data. */ RDMRequest *RobeWidgetTest::NewRequest(const UID &destination, const uint8_t *data, unsigned int length) { return new ola::rdm::RDMGetRequest( SOURCE, destination, m_transaction_number++, // transaction # 1, // port id 10, // sub device 296, // param id data, length); } /** * Pack a RDM request into a buffer */ uint8_t *RobeWidgetTest::PackRDMRequest(const RDMRequest *request, unsigned int *size) { unsigned int request_size = RDMCommandSerializer::RequiredSize(*request) + PADDING_SIZE; uint8_t *rdm_data = new uint8_t[request_size]; memset(rdm_data, 0, request_size); OLA_ASSERT(RDMCommandSerializer::Pack(*request, rdm_data, &request_size)); *size = request_size + PADDING_SIZE; return rdm_data; } /** * Pack a RDM Response into a buffer */ uint8_t *RobeWidgetTest::PackRDMResponse(const RDMResponse *response, unsigned int *size) { unsigned int response_size = RDMCommandSerializer::RequiredSize(*response) + PADDING_SIZE; uint8_t *rdm_data = new uint8_t[response_size]; memset(rdm_data, 0, response_size); OLA_ASSERT(RDMCommandSerializer::Pack(*response, rdm_data, &response_size)); *size = response_size + PADDING_SIZE; return rdm_data; } /* * Check the response matches what we expected. */ void RobeWidgetTest::ValidateResponse(RDMReply *reply) { OLA_ASSERT_EQ(ola::rdm::RDM_COMPLETED_OK, reply->StatusCode()); OLA_ASSERT(reply->Response()); OLA_ASSERT_DATA_EQUALS(TEST_RDM_DATA, arraysize(TEST_RDM_DATA), reply->Response()->ParamData(), reply->Response()->ParamDataSize()); const RDMFrames &frames = reply->Frames(); OLA_ASSERT_EQ((size_t) 1, frames.size()); ola::rdm::RDMStatusCode raw_code; auto_ptr raw_response( ola::rdm::RDMResponse::InflateFromData(frames[0].data.data() + 1, frames[0].data.size() - 1, &raw_code)); OLA_ASSERT_TRUE(*raw_response.get() == *reply->Response()); m_ss.Terminate(); } /* * Check that this request returned the expected status code */ void RobeWidgetTest::ValidateStatus( ola::rdm::RDMStatusCode expected_code, RDMFrames expected_frames, RDMReply *reply) { OLA_ASSERT_EQ(expected_code, reply->StatusCode()); OLA_ASSERT_FALSE(reply->Response()); const RDMFrames &frames = reply->Frames(); OLA_ASSERT_EQ(expected_frames.size(), frames.size()); for (unsigned int i = 0; i < frames.size(); i++) { OLA_ASSERT_DATA_EQUALS(expected_frames[i].data.data(), expected_frames[i].data.size(), frames[i].data.data(), frames[i].data.size()); OLA_ASSERT_TRUE(expected_frames[i] == frames[i]); } m_received_code = expected_code; m_ss.Terminate(); } /** * Validate that a mute response matches what we expect */ void RobeWidgetTest::ValidateMuteStatus(bool expected, bool actual) { OLA_ASSERT_EQ(expected, actual); m_ss.Terminate(); } void RobeWidgetTest::ValidateBranchStatus(const uint8_t *expected_data, unsigned int length, const uint8_t *actual_data, unsigned int actual_length) { OLA_ASSERT_EQ(length, actual_length); OLA_ASSERT_FALSE(memcmp(expected_data, actual_data, length)); m_ss.Terminate(); } /* * Check that we can send DMX */ void RobeWidgetTest::testSendDMX() { // dmx data DmxBuffer buffer; buffer.SetFromString("0,1,2,3,4"); // expected message uint8_t dmx_frame_data[] = {0, 1, 2, 3, 4, 0, 0, 0, 0}; // add the expected data, run and verify. m_endpoint->AddExpectedRobeMessage( DMX_FRAME_LABEL, dmx_frame_data, sizeof(dmx_frame_data), ola::NewSingleCallback(this, &RobeWidgetTest::Terminate)); m_widget->SendDMX(buffer); m_ss.Run(); m_endpoint->Verify(); // now test an empty frame DmxBuffer buffer2; uint8_t empty_frame_data[] = {0, 0, 0, 0}; // null frames still have 4 bytes // add the expected data, run and verify. m_endpoint->AddExpectedRobeMessage( DMX_FRAME_LABEL, empty_frame_data, sizeof(empty_frame_data), ola::NewSingleCallback(this, &RobeWidgetTest::Terminate)); m_widget->SendDMX(buffer2); m_ss.Run(); m_endpoint->Verify(); } /** * Check that we send RDM messages correctly. */ void RobeWidgetTest::testSendRDMRequest() { // request RDMRequest *rdm_request = NewRequest(DESTINATION); unsigned int expected_request_frame_size; uint8_t *expected_request_frame = PackRDMRequest( rdm_request, &expected_request_frame_size); // response auto_ptr response( GetResponseFromData(rdm_request, TEST_RDM_DATA, sizeof(TEST_RDM_DATA))); unsigned int response_size; uint8_t *response_frame = PackRDMResponse(response.get(), &response_size); // add the expected response, send and verify m_endpoint->AddExpectedRobeDataAndReturn( BaseRobeWidget::RDM_REQUEST, expected_request_frame, expected_request_frame_size, BaseRobeWidget::RDM_RESPONSE, response_frame, response_size); m_widget->SendRDMRequest( rdm_request, ola::NewSingleCallback(this, &RobeWidgetTest::ValidateResponse)); m_ss.Run(); m_endpoint->Verify(); delete[] expected_request_frame; delete[] response_frame; // now check broadcast messages // request rdm_request = NewRequest(BCAST_DESTINATION); uint8_t *expected_bcast_request_frame = PackRDMRequest( rdm_request, &expected_request_frame_size); // add the expected response, send and verify m_endpoint->AddExpectedRobeDataAndReturn( BaseRobeWidget::RDM_REQUEST, expected_bcast_request_frame, expected_request_frame_size, BaseRobeWidget::RDM_RESPONSE, NULL, 0); RDMFrames frames; m_widget->SendRDMRequest( rdm_request, ola::NewSingleCallback(this, &RobeWidgetTest::ValidateStatus, ola::rdm::RDM_WAS_BROADCAST, frames)); m_ss.Run(); OLA_ASSERT_EQ(ola::rdm::RDM_WAS_BROADCAST, m_received_code); m_endpoint->Verify(); // cleanup time delete[] expected_bcast_request_frame; } /** * Check that we send RDM mute messages correctly. */ void RobeWidgetTest::testSendRDMMute() { // request RDMRequest *rdm_request = new ola::rdm::RDMDiscoveryRequest( SOURCE, DESTINATION, m_transaction_number++, // transaction # 1, // port id 0, // sub device ola::rdm::PID_DISC_MUTE, // param id NULL, 0); unsigned int expected_request_frame_size; uint8_t *expected_request_frame = PackRDMRequest( rdm_request, &expected_request_frame_size); // response // to keep things simple here we return the TEST_RDM_DATA. auto_ptr response( GetResponseFromData(rdm_request, TEST_RDM_DATA, sizeof(TEST_RDM_DATA))); unsigned int response_size; uint8_t *response_frame = PackRDMResponse(response.get(), &response_size); // add the expected response, send and verify m_endpoint->AddExpectedRobeDataAndReturn( BaseRobeWidget::RDM_REQUEST, expected_request_frame, expected_request_frame_size, BaseRobeWidget::RDM_RESPONSE, response_frame, response_size); m_widget->SendRDMRequest( rdm_request, ola::NewSingleCallback(this, &RobeWidgetTest::ValidateResponse)); m_ss.Run(); m_endpoint->Verify(); delete[] expected_request_frame; delete[] response_frame; } /** * Check that we send RDM discovery messages correctly. */ void RobeWidgetTest::testSendRDMDUB() { static const uint8_t REQUEST_DATA[] = { 0x7a, 0x70, 0, 0, 0, 0, 0x7a, 0x70, 0xff, 0xff, 0xff, 0xff }; // request RDMRequest *rdm_request = new ola::rdm::RDMDiscoveryRequest( SOURCE, DESTINATION, m_transaction_number++, // transaction # 1, // port id 0, // sub device ola::rdm::PID_DISC_UNIQUE_BRANCH, // param id REQUEST_DATA, sizeof(REQUEST_DATA)); unsigned int expected_request_frame_size; uint8_t *expected_request_frame = PackRDMRequest( rdm_request, &expected_request_frame_size); // a 4 byte response means a timeout static const uint8_t EMPTY_RESPONSE[] = {0, 0, 0, 0}; // add the expected response, send and verify m_endpoint->AddExpectedRobeDataAndReturn( BaseRobeWidget::RDM_DISCOVERY, expected_request_frame, expected_request_frame_size, BaseRobeWidget::RDM_DISCOVERY_RESPONSE, EMPTY_RESPONSE, sizeof(EMPTY_RESPONSE)); RDMFrames frames; m_widget->SendRDMRequest( rdm_request, ola::NewSingleCallback(this, &RobeWidgetTest::ValidateStatus, ola::rdm::RDM_TIMEOUT, frames)); m_ss.Run(); m_endpoint->Verify(); delete[] expected_request_frame; // now try a dub response that returns something rdm_request = new ola::rdm::RDMDiscoveryRequest( SOURCE, DESTINATION, m_transaction_number++, // transaction # 1, // port id 0, // sub device ola::rdm::PID_DISC_UNIQUE_BRANCH, // param id REQUEST_DATA, sizeof(REQUEST_DATA)); expected_request_frame = PackRDMRequest( rdm_request, &expected_request_frame_size); // something that looks like a DUB response static const uint8_t FAKE_RESPONSE[] = {0xfe, 0xfe, 0xaa, 0xaa, 0, 0, 0, 0}; // add the expected response, send and verify m_endpoint->AddExpectedRobeDataAndReturn( BaseRobeWidget::RDM_DISCOVERY, expected_request_frame, expected_request_frame_size, BaseRobeWidget::RDM_DISCOVERY_RESPONSE, FAKE_RESPONSE, sizeof(FAKE_RESPONSE)); frames.push_back(RDMFrame(FAKE_RESPONSE, arraysize(FAKE_RESPONSE) - 4)); m_widget->SendRDMRequest( rdm_request, ola::NewSingleCallback(this, &RobeWidgetTest::ValidateStatus, ola::rdm::RDM_DUB_RESPONSE, frames)); m_ss.Run(); m_endpoint->Verify(); delete[] expected_request_frame; } /** * Test mute device */ void RobeWidgetTest::testMuteDevice() { // first test when a device doesn't respond auto_ptr mute_request( ola::rdm::NewMuteRequest(SOURCE, DESTINATION, m_transaction_number++)); unsigned int expected_request_frame_size; uint8_t *expected_request_frame = PackRDMRequest( mute_request.get(), &expected_request_frame_size); // response, we get PADDING_SIZE bytes when nothing else is returned uint8_t response_frame[PADDING_SIZE]; memset(response_frame, 0, PADDING_SIZE); // add the expected response, send and verify m_endpoint->AddExpectedRobeDataAndReturn( BaseRobeWidget::RDM_REQUEST, expected_request_frame, expected_request_frame_size, BaseRobeWidget::RDM_RESPONSE, response_frame, PADDING_SIZE); m_widget.get()->m_impl->MuteDevice( DESTINATION, ola::NewSingleCallback(this, &RobeWidgetTest::ValidateMuteStatus, false)); m_ss.Run(); m_endpoint->Verify(); delete[] expected_request_frame; // now try an actual mute response auto_ptr mute_request2( ola::rdm::NewMuteRequest(SOURCE, DESTINATION, m_transaction_number++)); expected_request_frame = PackRDMRequest( mute_request2.get(), &expected_request_frame_size); // We can really return anything as long as it's > 4 bytes // TODO(simon): make this better uint8_t mute_response_frame[] = {0, 0, 0, 0, 0, 0}; // add the expected response, send and verify m_endpoint->AddExpectedRobeDataAndReturn( BaseRobeWidget::RDM_REQUEST, expected_request_frame, expected_request_frame_size, BaseRobeWidget::RDM_RESPONSE, mute_response_frame, sizeof(mute_response_frame)); m_widget.get()->m_impl->MuteDevice( DESTINATION, ola::NewSingleCallback(this, &RobeWidgetTest::ValidateMuteStatus, true)); m_ss.Run(); m_endpoint->Verify(); delete[] expected_request_frame; } /** * Test the unmute all request works */ void RobeWidgetTest::testUnMuteAll() { auto_ptr unmute_request( ola::rdm::NewUnMuteRequest(SOURCE, UID::AllDevices(), m_transaction_number++)); unsigned int expected_request_frame_size; uint8_t *expected_request_frame = PackRDMRequest( unmute_request.get(), &expected_request_frame_size); // response, we get PADDING_SIZE bytes when nothing else is returned uint8_t response_frame[PADDING_SIZE]; memset(response_frame, 0, PADDING_SIZE); // add the expected response, send and verify m_endpoint->AddExpectedRobeDataAndReturn( BaseRobeWidget::RDM_REQUEST, expected_request_frame, expected_request_frame_size, BaseRobeWidget::RDM_RESPONSE, response_frame, PADDING_SIZE); m_widget.get()->m_impl->UnMuteAll( ola::NewSingleCallback(this, &RobeWidgetTest::CallbackComplete)); m_ss.Run(); m_endpoint->Verify(); delete[] expected_request_frame; } /** * Test the DUB request works */ void RobeWidgetTest::testBranch() { // first test when no devices respond auto_ptr discovery_request( ola::rdm::NewDiscoveryUniqueBranchRequest( SOURCE, UID(0, 0), UID::AllDevices(), m_transaction_number++)); unsigned int expected_request_frame_size; uint8_t *expected_request_frame = PackRDMRequest( discovery_request.get(), &expected_request_frame_size); // response, we get PADDING_SIZE bytes when nothing else is returned uint8_t response_frame[PADDING_SIZE]; memset(response_frame, 0, PADDING_SIZE); // add the expected response, send and verify m_endpoint->AddExpectedRobeDataAndReturn( BaseRobeWidget::RDM_DISCOVERY, expected_request_frame, expected_request_frame_size, BaseRobeWidget::RDM_DISCOVERY_RESPONSE, NULL, 0); m_widget.get()->m_impl->Branch( UID(0, 0), UID::AllDevices(), ola::NewSingleCallback(this, &RobeWidgetTest::ValidateBranchStatus, static_cast(NULL), static_cast(0))); m_ss.Run(); m_endpoint->Verify(); delete[] expected_request_frame; // now try an actual response, the data doesn't actually have to be valid // because it's just passed straight to the callback. auto_ptr discovery_request2( ola::rdm::NewDiscoveryUniqueBranchRequest( SOURCE, UID(0, 0), UID::AllDevices(), m_transaction_number++)); expected_request_frame = PackRDMRequest( discovery_request2.get(), &expected_request_frame_size); // the response, can be anything really, last 4 bytes is trimmed uint8_t response_frame2[] = {1, 2, 3, 4, 0, 0, 0, 0}; // add the expected response, send and verify m_endpoint->AddExpectedRobeDataAndReturn( BaseRobeWidget::RDM_DISCOVERY, expected_request_frame, expected_request_frame_size, BaseRobeWidget::RDM_DISCOVERY_RESPONSE, response_frame2, sizeof(response_frame2)); m_widget.get()->m_impl->Branch( UID(0, 0), UID::AllDevices(), ola::NewSingleCallback( this, &RobeWidgetTest::ValidateBranchStatus, static_cast(response_frame2), // minus the 4 padding bytes static_cast(sizeof(response_frame2) - 4))); m_ss.Run(); m_endpoint->Verify(); delete[] expected_request_frame; } /* * Test receiving works. */ void RobeWidgetTest::testReceive() { DmxBuffer buffer; buffer.SetFromString("0,1,2,3,4"); // change to recv mode & setup the callback m_endpoint->AddExpectedRobeMessage( DMX_IN_REQUEST_LABEL, NULL, 0, ola::NewSingleCallback(this, &RobeWidgetTest::Terminate)); m_widget->ChangeToReceiveMode(); m_ss.Run(); m_endpoint->Verify(); m_widget->SetDmxCallback( ola::NewCallback(this, &RobeWidgetTest::NewDMXData)); OLA_ASSERT_FALSE(m_new_dmx_data); // now send some data m_endpoint->SendUnsolicitedRobeData(DMX_IN_RESPONSE_LABEL, buffer.GetRaw(), buffer.Size()); m_ss.Run(); OLA_ASSERT(m_new_dmx_data); const DmxBuffer &new_data = m_widget->FetchDMX(); OLA_ASSERT(buffer == new_data); } ola-0.10.5.nojsmin/plugins/usbpro/MockEndpoint.h0000644000175000017500000001312613023355232021217 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * MockEndpoint.h * This allows unittest of data received on a ConnectedDescriptor. The general * use case is: * * ola::io::PipeSocket pipe; * pipe.Init(); * ola::io::PipeSocket *other_end = pip.OppositeEnd(); * MockEndpoint endpoint(other_end) * ola::io::SelectServer ss; * ss.AddReadDescriptor(&pipe); * ss.AddReadDescriptor(other_end); * // Do the test here * ss.Run(); * endpoint.Verify(); // make sure there are no calls remaining * Copyright (C) 2011 Simon Newton */ #ifndef PLUGINS_USBPRO_MOCKENDPOINT_H_ #define PLUGINS_USBPRO_MOCKENDPOINT_H_ #include #include #include "ola/Callback.h" #include "ola/io/Descriptor.h" /** * The MockEndpoint, this is used for the unittests. */ class MockEndpoint { public: explicit MockEndpoint(ola::io::ConnectedDescriptor *descriptor); ~MockEndpoint(); typedef ola::SingleUseCallback0 NotificationCallback; void AddExpectedData(const uint8_t *request_data, unsigned int request_size, NotificationCallback *callback = NULL); // This does the same as above, but puts the data inside a Usb Pro style // frame. void AddExpectedUsbProMessage(uint8_t label, const uint8_t *request_payload_data, unsigned int request_payload_size, NotificationCallback *callback = NULL); // This does the same as above, but puts the data inside a Robe style // frame. void AddExpectedRobeMessage(uint8_t label, const uint8_t *request_payload_data, unsigned int request_payload_size, NotificationCallback *callback = NULL); void AddExpectedDataAndReturn(const uint8_t *request_data, unsigned int request_size, const uint8_t *response_data, unsigned int response_size, NotificationCallback *callback = NULL); // This does the same as above, but puts the data inside a Usb Pro style // frame. void AddExpectedUsbProDataAndReturn(uint8_t request_label, const uint8_t *request_payload_data, unsigned int request_payload_size, uint8_t response_label, const uint8_t *response_payload_data, unsigned int response_payload_size, NotificationCallback *callback = NULL); // This does the same as above, but puts the data inside a Robe style // frame. void AddExpectedRobeDataAndReturn(uint8_t request_label, const uint8_t *request_payload_data, unsigned int request_payload_size, uint8_t response_label, const uint8_t *response_payload_data, unsigned int response_payload_size, NotificationCallback *callback = NULL); void SendUnsolicited(const uint8_t *data, unsigned int length); void SendUnsolicitedUsbProData(uint8_t label, const uint8_t *response_payload_data, unsigned int response_payload_size); void SendUnsolicitedRobeData(uint8_t label, const uint8_t *response_payload_data, unsigned int response_payload_size); void Verify(); private: ola::io::ConnectedDescriptor *m_descriptor; typedef struct { unsigned int length; const uint8_t *data; } data_frame; typedef struct { bool send_response; bool free_request; bool free_response; data_frame expected_data_frame; data_frame return_data_frame; NotificationCallback *callback; } expected_data; std::queue m_expected_data; void DescriptorReady(); uint8_t *BuildUsbProMessage(uint8_t label, const uint8_t *data, unsigned int data_size, unsigned int *total_size); uint8_t *BuildRobeMessage(uint8_t label, const uint8_t *data, unsigned int data_size, unsigned int *total_size); enum {MAX_DATA_SIZE = 600}; static const unsigned int FOOTER_SIZE = 1; static const unsigned int HEADER_SIZE = 4; static const unsigned int ROBE_FOOTER_SIZE = 1; static const unsigned int ROBE_HEADER_SIZE = 5; }; #endif // PLUGINS_USBPRO_MOCKENDPOINT_H_ ola-0.10.5.nojsmin/plugins/usbpro/EnttecUsbProWidget.cpp0000644000175000017500000006763513023355232022717 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * EnttecUsbProWidget.cpp * The Enttec USB Pro Widget * Copyright (C) 2010 Simon Newton */ #include #include #include #include #include #include #include "ola/Callback.h" #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/io/ByteString.h" #include "ola/rdm/RDMCommand.h" #include "ola/rdm/RDMCommandSerializer.h" #include "ola/rdm/RDMEnums.h" #include "ola/rdm/UID.h" #include "ola/rdm/UIDSet.h" #include "ola/stl/STLUtils.h" #include "ola/strings/Format.h" #include "plugins/usbpro/BaseUsbProWidget.h" #include "plugins/usbpro/EnttecUsbProWidget.h" #include "plugins/usbpro/EnttecUsbProWidgetImpl.h" namespace ola { namespace plugin { namespace usbpro { using ola::io::ByteString; using ola::rdm::RDMCommand; using ola::rdm::RDMCommandSerializer; using ola::rdm::RDMReply; using ola::rdm::RunRDMCallback; using ola::rdm::RDMRequest; using ola::rdm::RDMResponse; using ola::rdm::UID; using ola::rdm::UIDSet; using ola::strings::IntToString; using ola::strings::ToHex; using std::auto_ptr; using std::string; using std::vector; const uint16_t EnttecUsbProWidget::ENTTEC_ESTA_ID = 0x454E; OperationLabels OperationLabels::Port1Operations() { OperationLabels ops = { GET_PARAMS_1, SET_PARAMS_1, RECEIVED_DMX_LABEL_1, SEND_DMX_1, SEND_RDM_1, CHANGE_TO_RX_1, COS_DMX_1, RDM_TIMEOUT_1, RDM_DISCOVERY_1, }; return ops; } OperationLabels OperationLabels::Port2Operations() { // These labels are specific to OLA and are tied to the OLA API key. OperationLabels ops = { GET_PARAMS_2, SET_PARAMS_2, RECEIVED_DMX_LABEL_2, SEND_DMX_2, SEND_RDM_2, CHANGE_TO_RX_2, COS_DMX_2, RDM_TIMEOUT_2, RDM_DISCOVERY_2, }; return ops; } EnttecPortImpl::EnttecPortImpl(const OperationLabels &ops, const UID &uid, SendCallback *send_cb) : m_send_cb(send_cb), m_ops(ops), m_active(true), m_watchdog(WATCHDOG_LIMIT, NewCallback(this, &EnttecPortImpl::WatchdogFired)), m_discovery_agent(this), m_uid(uid), m_transaction_number(0), m_rdm_request_callback(NULL), m_pending_request(NULL), m_mute_callback(NULL), m_unmute_callback(NULL), m_branch_callback(NULL), m_discovery_response(NULL), m_discovery_response_size(0) { } void EnttecPortImpl::Stop() { m_active = false; m_dmx_callback.reset(); // empty params struct usb_pro_parameters params; while (!m_outstanding_param_callbacks.empty()) { usb_pro_params_callback *callback = m_outstanding_param_callbacks.front(); m_outstanding_param_callbacks.pop_front(); callback->Run(false, params); } m_discovery_agent.Abort(); } /** * Send a DMX message */ bool EnttecPortImpl::SendDMX(const DmxBuffer &buffer) { struct { uint8_t start_code; uint8_t dmx[DMX_UNIVERSE_SIZE]; } widget_dmx; widget_dmx.start_code = DMX512_START_CODE; unsigned int length = DMX_UNIVERSE_SIZE; buffer.Get(widget_dmx.dmx, &length); return m_send_cb->Run(m_ops.send_dmx, reinterpret_cast(&widget_dmx), length + 1); } /** * Set the callback to run when new DMX data arrives */ void EnttecPortImpl::SetDMXCallback(ola::Callback0 *callback) { m_dmx_callback.reset(callback); } /* * Put the device back into recv mode * @return true on success, false on failure */ bool EnttecPortImpl::ChangeToReceiveMode(bool change_only) { if (!m_active) { return false; } uint8_t mode = change_only; bool status = m_send_cb->Run(m_ops.change_to_rx_mode, &mode, sizeof(mode)); if (status && change_only) { m_input_buffer.Blackout(); } return status; } /** * Send a request for the widget's parameters. * TODO(simon): add timers to these */ void EnttecPortImpl::GetParameters(usb_pro_params_callback *callback) { m_outstanding_param_callbacks.push_back(callback); uint16_t user_size = 0; bool r = m_send_cb->Run(m_ops.get_params, reinterpret_cast(&user_size), sizeof(user_size)); if (!r) { // failed m_outstanding_param_callbacks.pop_back(); usb_pro_parameters params = {0, 0, 0, 0, 0}; callback->Run(false, params); } } /** * Set the widget's parameters. Due to the lack of confirmation, this returns * immediately. */ bool EnttecPortImpl::SetParameters(uint8_t break_time, uint8_t mab_time, uint8_t rate) { PACK( struct widget_params_s { uint16_t length; uint8_t break_time; uint8_t mab_time; uint8_t rate; }); widget_params_s widget_parameters = { 0, break_time, mab_time, rate}; bool ret = m_send_cb->Run( m_ops.set_params, reinterpret_cast(&widget_parameters), sizeof(widget_parameters)); if (!ret) { OLA_WARN << "Failed to send a set params message"; } return ret; } /** * Send an RDM Request. */ void EnttecPortImpl::SendRDMRequest(RDMRequest *request_ptr, ola::rdm::RDMCallback *on_complete) { auto_ptr request(request_ptr); if (m_rdm_request_callback) { OLA_WARN << "Previous request hasn't completed yet, dropping request"; RunRDMCallback(on_complete, ola::rdm::RDM_FAILED_TO_SEND); return; } request->SetSourceUID(m_uid); request->SetTransactionNumber(m_transaction_number++); request->SetPortId(PORT_ID); m_pending_request.reset(request.release()); m_rdm_request_callback = on_complete; bool ok = PackAndSendRDMRequest( m_pending_request->IsDUB() ? m_ops.rdm_discovery : m_ops.send_rdm, m_pending_request.get()); if (!ok) { m_pending_request.reset(); m_rdm_request_callback = NULL; RunRDMCallback(on_complete, ola::rdm::RDM_FAILED_TO_SEND); } } /** * Start full discovery for this widget. */ void EnttecPortImpl::RunFullDiscovery( ola::rdm::RDMDiscoveryCallback *callback) { OLA_INFO << "Full discovery triggered"; m_discovery_agent.StartFullDiscovery( ola::NewSingleCallback(this, &EnttecPortImpl::DiscoveryComplete, callback)); } /** * Start incremental discovery for this widget */ void EnttecPortImpl::RunIncrementalDiscovery( ola::rdm::RDMDiscoveryCallback *callback) { OLA_INFO << "Incremental discovery triggered"; m_discovery_agent.StartIncrementalDiscovery( ola::NewSingleCallback(this, &EnttecPortImpl::DiscoveryComplete, callback)); } /** * Mute a responder * @param target the UID to mute * @param mute_complete the callback to run once the mute request * completes. */ void EnttecPortImpl::MuteDevice(const ola::rdm::UID &target, MuteDeviceCallback *mute_complete) { OLA_INFO << "Muting " << target << ", TN: " << static_cast(m_transaction_number); auto_ptr mute_request( ola::rdm::NewMuteRequest(m_uid, target, m_transaction_number++)); if (PackAndSendRDMRequest(m_ops.send_rdm, mute_request.get())) { m_mute_callback = mute_complete; } else { mute_complete->Run(false); } } /** * Unmute all responders * @param unmute_complete the callback to run once the unmute request * completes. */ void EnttecPortImpl::UnMuteAll(UnMuteDeviceCallback *unmute_complete) { OLA_INFO << "Un-muting all devices, TN: " << static_cast(m_transaction_number); auto_ptr unmute_request( ola::rdm::NewUnMuteRequest(m_uid, ola::rdm::UID::AllDevices(), m_transaction_number++)); if (PackAndSendRDMRequest(m_ops.send_rdm, unmute_request.get())) { m_unmute_callback = unmute_complete; } else { OLA_WARN << "Failed to send Unmute all request"; unmute_complete->Run(); } } /** * Send a Discovery Unique Branch */ void EnttecPortImpl::Branch(const ola::rdm::UID &lower, const ola::rdm::UID &upper, BranchCallback *callback) { auto_ptr branch_request( ola::rdm::NewDiscoveryUniqueBranchRequest(m_uid, lower, upper, m_transaction_number++)); OLA_INFO << "Sending DUB packet: " << lower << " - " << upper; if (PackAndSendRDMRequest(m_ops.rdm_discovery, branch_request.get())) { m_branch_callback = callback; } else { callback->Run(NULL, 0); } } /** * Called to indicate the completion of an RDM request. * According to the spec: * The timeout message will follow the RDM discovery reply message, whether or * not the reply is partial or complete. * The timeout message will follow the RDM reply message (GET or SET), only * when the reply is incomplete or unrecognizable. * * Experiments suggest that sending another RDM message before this 'timeout' * is received results in Bad Things Happening. * * The length of this message should be 0. */ void EnttecPortImpl::HandleRDMTimeout(unsigned int length) { if (length) { OLA_WARN << "Strange RDM timeout message, length was " << length; } m_watchdog.Disable(); // check what operation we were waiting on if (m_unmute_callback) { UnMuteDeviceCallback *callback = m_unmute_callback; m_unmute_callback = NULL; callback->Run(); } else if (m_mute_callback) { MuteDeviceCallback *callback = m_mute_callback; m_mute_callback = NULL; OLA_INFO << "Unable to mute device"; callback->Run(false); } else if (m_branch_callback) { BranchCallback *callback = m_branch_callback; m_branch_callback = NULL; callback->Run(m_discovery_response, m_discovery_response_size); if (m_discovery_response) { delete[] m_discovery_response; m_discovery_response = NULL; m_discovery_response_size = 0; } } else if (m_rdm_request_callback && m_pending_request.get()) { ola::rdm::RDMStatusCode status_code; if (m_pending_request->IsDUB()) { status_code = ola::rdm::RDM_TIMEOUT; } else { status_code = ( m_pending_request->DestinationUID().IsBroadcast() ? ola::rdm::RDM_WAS_BROADCAST : ola::rdm::RDM_TIMEOUT); } ola::rdm::RDMCallback *callback = m_rdm_request_callback; m_rdm_request_callback = NULL; m_pending_request.reset(); RunRDMCallback(callback, status_code); } } /* * Called when we get new parameters from the widget. */ void EnttecPortImpl::HandleParameters(const uint8_t *data, unsigned int length) { if (m_outstanding_param_callbacks.empty()) { return; } if (length < sizeof(usb_pro_parameters)) { return; } usb_pro_parameters params; memcpy(¶ms, data, sizeof(usb_pro_parameters)); usb_pro_params_callback *callback = m_outstanding_param_callbacks.front(); m_outstanding_param_callbacks.pop_front(); callback->Run(true, params); } /** * Handle an incoming frame. * @param data the incoming data buffer * @param length the length of the data buffer. * * The first byte is a status code: 0: good, non-0: bad * The second byte is the start code * The remaining bytes are the actual data. */ void EnttecPortImpl::HandleIncomingDataMessage(const uint8_t *data, unsigned int length) { bool waiting_for_dub_response = ( m_branch_callback != NULL || ( (m_rdm_request_callback && m_pending_request->IsDUB()))); // if we're not waiting for a DUB response, and this isn't an RDM frame, then // let the super class handle it. if (!waiting_for_dub_response && length >= 2 && data[1] != ola::rdm::START_CODE) { HandleDMX(data, length); return; } // It's not clear what happens if we get an overrun on an RDM response. // Do we still get the timeout message or is this the only response? // I need to check with Nic. if (data[0]) { OLA_WARN << "Incoming frame corrupted"; return; } m_watchdog.Disable(); // skip over the status bit data++; length--; if (m_branch_callback) { // discovery responses are *always* followed by the timeout message and // it's important that we wait for this before sending the next command if (m_discovery_response) { OLA_WARN << "Multiple discovery responses received, ignoring all but " "the first."; return; } uint8_t *response_data = new uint8_t[length]; memcpy(response_data, data, length); m_discovery_response = response_data; m_discovery_response_size = length; } else if (m_mute_callback) { // we take any response as a mute acknowledgment here, which isn't great, // but it seems to work. MuteDeviceCallback *callback = m_mute_callback; m_mute_callback = NULL; OLA_INFO << "Probably muted device"; callback->Run(true); } else if (m_rdm_request_callback) { ola::rdm::RDMCallback *callback = m_rdm_request_callback; m_rdm_request_callback = NULL; auto_ptr request(m_pending_request.release()); auto_ptr reply; if (waiting_for_dub_response) { reply.reset(RDMReply::DUBReply(rdm::RDMFrame(data, length))); } else { reply.reset(RDMReply::FromFrame(rdm::RDMFrame(data, length), request.get())); } callback->Run(reply.get()); } } /* * Handle the dmx change of state frame */ void EnttecPortImpl::HandleDMXDiff(const uint8_t *data, unsigned int length) { typedef struct { uint8_t start; uint8_t changed[5]; uint8_t data[40]; } widget_data_changed; if (length < sizeof(widget_data_changed)) { OLA_WARN << "Change of state packet was too small: " << length; return; } const widget_data_changed *widget_reply = reinterpret_cast(data); unsigned int start_channel = widget_reply->start * 8; unsigned int offset = 0; // skip non-0 start codes, this code is pretty messed up because the USB Pro // doesn't seem to provide a guarantee on the ordering of packets. Packets // with non-0 start codes are almost certainly going to cause problems. if (start_channel == 0 && (widget_reply->changed[0] & 0x01) && widget_reply->data[offset]) { return; } for (int i = 0; i < 40; i++) { if (start_channel + i > DMX_UNIVERSE_SIZE + 1 || offset + 6 >= length) { break; } if (widget_reply->changed[i/8] & (1 << (i % 8)) && start_channel + i != 0) { m_input_buffer.SetChannel(start_channel + i - 1, widget_reply->data[offset]); offset++; } } if (m_dmx_callback.get()) { m_dmx_callback->Run(); } } /* * Handle the dmx frame */ void EnttecPortImpl::HandleDMX(const uint8_t *data, unsigned int length) { typedef struct { uint8_t status; uint8_t dmx[DMX_UNIVERSE_SIZE + 1]; } widget_dmx; if (length < 2) { return; } const widget_dmx *widget_reply = reinterpret_cast(data); if (widget_reply->status) { OLA_WARN << "UsbPro got corrupted packet, status: " << static_cast(widget_reply->status); return; } // only handle start code = 0 if (length > 2 && widget_reply->dmx[0] == 0) { m_input_buffer.Set(widget_reply->dmx + 1, length - 2); if (m_dmx_callback.get()) { m_dmx_callback->Run(); } } return; } /** * Called when the discovery process finally completes * @param callback the callback passed to StartFullDiscovery or * StartIncrementalDiscovery that we should execute. * @param status true if discovery worked, false otherwise * @param uids the UIDSet of UIDs that were found. */ void EnttecPortImpl::DiscoveryComplete(ola::rdm::RDMDiscoveryCallback *callback, bool, const UIDSet &uids) { OLA_DEBUG << "Enttec Pro discovery complete: " << uids; if (callback) { callback->Run(uids); } } /** * Send a RDM request to the widget */ bool EnttecPortImpl::PackAndSendRDMRequest(uint8_t label, const RDMRequest *request) { ByteString data; if (!RDMCommandSerializer::PackWithStartCode(*request, &data)) { return false; } bool ok = m_send_cb->Run(label, data.data(), data.size()); if (ok) { m_watchdog.Enable(); } return ok; } void EnttecPortImpl::ClockWatchdog() { m_watchdog.Clock(); } void EnttecPortImpl::WatchdogFired() { if (m_branch_callback) { OLA_WARN << "Timeout waiting for DUB response"; BranchCallback *callback = m_branch_callback; m_branch_callback = NULL; callback->Run(NULL, 0); } else if (m_mute_callback) { OLA_WARN << "Timeout waiting for mute response"; MuteDeviceCallback *callback = m_mute_callback; m_mute_callback = NULL; callback->Run(false); } else if (m_unmute_callback) { OLA_WARN << "Timeout waiting for unmute response"; UnMuteDeviceCallback *callback = m_unmute_callback; m_unmute_callback = NULL; callback->Run(); } else if (m_rdm_request_callback) { OLA_WARN << "Timeout waiting for RDM response"; ola::rdm::RDMCallback *callback = m_rdm_request_callback; m_rdm_request_callback = NULL; m_pending_request.reset(); RunRDMCallback(callback, ola::rdm::RDM_FAILED_TO_SEND); } } // EnttecPort // ---------------------------------------------------------------------------- /** * EnttecUsbProWidget Constructor */ EnttecPort::EnttecPort(EnttecPortImpl *impl, unsigned int queue_size, bool enable_rdm) : m_impl(impl), m_enable_rdm(enable_rdm), m_controller( new ola::rdm::DiscoverableQueueingRDMController(m_impl, queue_size)) { } bool EnttecPort::SendDMX(const DmxBuffer &buffer) { return m_impl->SendDMX(buffer); } const DmxBuffer &EnttecPort::FetchDMX() const { return m_impl->FetchDMX(); } void EnttecPort::SetDMXCallback(ola::Callback0 *callback) { m_impl->SetDMXCallback(callback); } bool EnttecPort::ChangeToReceiveMode(bool change_only) { return m_impl->ChangeToReceiveMode(change_only); } void EnttecPort::GetParameters(usb_pro_params_callback *callback) { m_impl->GetParameters(callback); } bool EnttecPort::SetParameters(uint8_t break_time, uint8_t mab_time, uint8_t rate) { return m_impl->SetParameters(break_time, mab_time, rate); } void EnttecPort::SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *on_complete) { if (m_enable_rdm) { m_controller->SendRDMRequest(request, on_complete); } else { RunRDMCallback(on_complete, ola::rdm::RDM_FAILED_TO_SEND); delete request; } } void EnttecPort::RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { if (m_enable_rdm) { m_controller->RunFullDiscovery(callback); } else { UIDSet uids; callback->Run(uids); } } void EnttecPort::RunIncrementalDiscovery( ola::rdm::RDMDiscoveryCallback *callback) { if (m_enable_rdm) { m_controller->RunIncrementalDiscovery(callback); } else { UIDSet uids; callback->Run(uids); } } // EnttecUsbProWidgetImpl // ---------------------------------------------------------------------------- /* * An Enttec DMX USB PRO Widget implementation. We separate the Widget from the * implementation because we don't want to expose internal methods. */ class EnttecUsbProWidgetImpl : public BaseUsbProWidget { public: EnttecUsbProWidgetImpl( ola::thread::SchedulerInterface *scheduler, ola::io::ConnectedDescriptor *descriptor, const EnttecUsbProWidget::EnttecUsbProWidgetOptions &options); ~EnttecUsbProWidgetImpl(); void GetPortAssignments( EnttecUsbProWidget::EnttecUsbProPortAssignmentCallback *callback); void Stop(); unsigned int PortCount() const { return m_ports.size(); } EnttecPort *GetPort(unsigned int i); bool SendCommand(uint8_t label, const uint8_t *data, unsigned int length); private: typedef vector PortAssignmentCallbacks; ola::thread::SchedulerInterface *m_scheduler; ola::thread::timeout_id m_watchdog_timer_id; vector m_ports; vector m_port_impls; auto_ptr m_send_cb; UID m_uid; PortAssignmentCallbacks m_port_assignment_callbacks; // We override handle message to catch the messages, and dispatch them to // the correct port. void HandleMessage(uint8_t label, const uint8_t *data, unsigned int length); void HandleLabel(EnttecPortImpl *port, const OperationLabels &ops, uint8_t label, const uint8_t *data, unsigned int length); void HandlePortAssignment(const uint8_t *data, unsigned int length); void AddPort(const OperationLabels &ops, unsigned int queue_size, bool enable_rdm); void EnableSecondPort(); bool Watchdog(); static const uint8_t PORT_ASSIGNMENT_LABEL = 141; static const uint8_t SET_PORT_ASSIGNMENT_LABEL = 145; }; /* * New Enttec Usb Pro Device. * This also works for the RDM Pro with the standard firmware loaded. */ EnttecUsbProWidgetImpl::EnttecUsbProWidgetImpl( ola::thread::SchedulerInterface *scheduler, ola::io::ConnectedDescriptor *descriptor, const EnttecUsbProWidget::EnttecUsbProWidgetOptions &options) : BaseUsbProWidget(descriptor), m_scheduler(scheduler), m_watchdog_timer_id(ola::thread::INVALID_TIMEOUT), m_send_cb(NewCallback(this, &EnttecUsbProWidgetImpl::SendCommand)), m_uid(options.esta_id ? options.esta_id : EnttecUsbProWidget::ENTTEC_ESTA_ID, options.serial) { AddPort(OperationLabels::Port1Operations(), options.queue_size, options.enable_rdm); if (options.dual_ports) { AddPort(OperationLabels::Port2Operations(), options.queue_size, options.enable_rdm); EnableSecondPort(); } m_watchdog_timer_id = m_scheduler->RegisterRepeatingTimeout( TimeInterval(1, 0), NewCallback(this, &EnttecUsbProWidgetImpl::Watchdog)); } EnttecUsbProWidgetImpl::~EnttecUsbProWidgetImpl() { Stop(); STLDeleteElements(&m_ports); STLDeleteElements(&m_port_impls); } void EnttecUsbProWidgetImpl::GetPortAssignments( EnttecUsbProWidget::EnttecUsbProPortAssignmentCallback *callback) { if (m_ports.size() == 1) { // fake a response callback->Run(true, 1, 0); return; } m_port_assignment_callbacks.push_back(callback); if (!SendCommand(PORT_ASSIGNMENT_LABEL, NULL, 0)) { callback->Run(false, 1, 0); } } /** * Stop this widget */ void EnttecUsbProWidgetImpl::Stop() { if (m_watchdog_timer_id != ola::thread::INVALID_TIMEOUT) { m_scheduler->RemoveTimeout(m_watchdog_timer_id); m_watchdog_timer_id = ola::thread::INVALID_TIMEOUT; } vector::iterator iter = m_port_impls.begin(); for (; iter != m_port_impls.end(); ++iter) { (*iter)->Stop(); } PortAssignmentCallbacks::iterator cb_iter = m_port_assignment_callbacks.begin(); for (; cb_iter != m_port_assignment_callbacks.end(); ++cb_iter) { (*cb_iter)->Run(false, 0, 0); } m_port_assignment_callbacks.clear(); } /** * Given an index, return the EnttecPort */ EnttecPort *EnttecUsbProWidgetImpl::GetPort(unsigned int i) { if (i >= m_ports.size()) { return NULL; } return m_ports[i]; } /** * Send a command to the widget */ bool EnttecUsbProWidgetImpl::SendCommand(uint8_t label, const uint8_t *data, unsigned int length) { OLA_DEBUG << "TX: " << IntToString(label) << ", length " << length; return SendMessage(label, data, length); } /* * Handle a message received from the widget */ void EnttecUsbProWidgetImpl::HandleMessage(uint8_t label, const uint8_t *data, unsigned int length) { OLA_DEBUG << "RX: " << IntToString(label) << ", length " << length; if (label == PORT_ASSIGNMENT_LABEL) { HandlePortAssignment(data, length); } else if (label > 128 && m_ports.size() > 1) { HandleLabel(m_port_impls[1], OperationLabels::Port2Operations(), label, data, length); } else { HandleLabel(m_port_impls[0], OperationLabels::Port1Operations(), label, data, length); } } void EnttecUsbProWidgetImpl::HandleLabel(EnttecPortImpl *port, const OperationLabels &ops, uint8_t label, const uint8_t *data, unsigned int length) { if (ops.get_params == label) { port->HandleParameters(data, length); } else if (ops.rdm_timeout == label) { port->HandleRDMTimeout(length); } else if (ops.recv_dmx == label) { port->HandleIncomingDataMessage(data, length); } else if (ops.cos_dmx == label) { port->HandleDMXDiff(data, length); } else { OLA_WARN << "Unknown message type " << ToHex(label) << ", length " << length; } } /** * Handle a port assignment message */ void EnttecUsbProWidgetImpl::HandlePortAssignment(const uint8_t *data, unsigned int length) { bool ok = false; uint8_t port1_assignment = 0; uint8_t port2_assignment = 0; if (length == 2) { ok = true; port1_assignment = data[0]; port2_assignment = data[1]; } PortAssignmentCallbacks::iterator iter = m_port_assignment_callbacks.begin(); for (; iter != m_port_assignment_callbacks.end(); ++iter) { (*iter)->Run(ok, port1_assignment, port2_assignment); } m_port_assignment_callbacks.clear(); } /** * Add a port to this widget with the given operations. */ void EnttecUsbProWidgetImpl::AddPort(const OperationLabels &ops, unsigned int queue_size, bool enable_rdm) { EnttecPortImpl *impl = new EnttecPortImpl(ops, m_uid, m_send_cb.get()); m_port_impls.push_back(impl); EnttecPort *port = new EnttecPort(impl, queue_size, enable_rdm); m_ports.push_back(port); } void EnttecUsbProWidgetImpl::EnableSecondPort() { uint8_t data[] = {1, 1}; if (!SendCommand(SET_PORT_ASSIGNMENT_LABEL, data, sizeof(data))) { OLA_INFO << "Failed to enable second port"; } } bool EnttecUsbProWidgetImpl::Watchdog() { vector::iterator iter = m_port_impls.begin(); for (; iter != m_port_impls.end(); ++iter) { (*iter)->ClockWatchdog(); } return true; } // EnttecUsbProWidget // ---------------------------------------------------------------------------- /** * EnttecUsbProWidget Constructor */ EnttecUsbProWidget::EnttecUsbProWidget( ola::thread::SchedulerInterface *scheduler, ola::io::ConnectedDescriptor *descriptor, const EnttecUsbProWidgetOptions &options) { m_impl = new EnttecUsbProWidgetImpl(scheduler, descriptor, options); } EnttecUsbProWidget::~EnttecUsbProWidget() { // delete the controller after the impl because the controller owns the // callback delete m_impl; } void EnttecUsbProWidget::GetPortAssignments( EnttecUsbProPortAssignmentCallback *callback) { m_impl->GetPortAssignments(callback); } void EnttecUsbProWidget::Stop() { m_impl->Stop(); } unsigned int EnttecUsbProWidget::PortCount() const { return m_impl->PortCount(); } EnttecPort *EnttecUsbProWidget::GetPort(unsigned int i) { return m_impl->GetPort(i); } ola::io::ConnectedDescriptor *EnttecUsbProWidget::GetDescriptor() const { return m_impl->GetDescriptor(); } } // namespace usbpro } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbpro/CommonWidgetTest.cpp0000644000175000017500000000436213023355232022416 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * CommonWidgetTest.cpp * Common code shared amongst many of the widget test classes. * Copyright (C) 2011 Simon Newton */ #include "plugins/usbpro/CommonWidgetTest.h" /** * Set up the PipeDescriptor and the MockEndpoint */ void CommonWidgetTest::setUp() { m_descriptor.Init(); m_other_end.reset(m_descriptor.OppositeEnd()); m_endpoint.reset(new MockEndpoint(m_other_end.get())); m_ss.AddReadDescriptor(&m_descriptor); m_ss.AddReadDescriptor(m_other_end.get()); } /** * Clean up */ void CommonWidgetTest::tearDown() { m_endpoint->Verify(); m_ss.RemoveReadDescriptor(&m_descriptor); m_ss.RemoveReadDescriptor(m_other_end.get()); m_other_end.get()->Close(); m_descriptor.Close(); } /** * Pack data into a Usb Pro style frame. * @param label the message label * @param data the message data * @param data_size the data size * @param total_size, pointer which is updated with the message size. */ uint8_t *CommonWidgetTest::BuildUsbProMessage(uint8_t label, const uint8_t *data, unsigned int data_size, unsigned int *total_size) { uint8_t *frame = new uint8_t[data_size + HEADER_SIZE + FOOTER_SIZE]; frame[0] = 0x7e; // som frame[1] = label; frame[2] = data_size & 0xff; // len frame[3] = (data_size + 1) >> 8; // len hi memcpy(frame + 4, data, data_size); frame[data_size + HEADER_SIZE] = 0xe7; *total_size = data_size + HEADER_SIZE + FOOTER_SIZE; return frame; } ola-0.10.5.nojsmin/plugins/usbpro/DmxterDevice.cpp0000644000175000017500000000342513023355232021544 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DmxterDevice.cpp * A Goddard Design Dmxter. * Copyright (C) 2010 Simon Newton */ #include #include #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/network/NetworkUtils.h" #include "ola/rdm/UID.h" #include "ola/rdm/UIDSet.h" #include "plugins/usbpro/DmxterDevice.h" #include "plugins/usbpro/DmxterWidget.h" namespace ola { namespace plugin { namespace usbpro { using std::string; using ola::rdm::UID; /* * New DMXter device */ DmxterDevice::DmxterDevice(ola::AbstractPlugin *owner, const string &name, DmxterWidget *widget, uint16_t esta_id, uint16_t device_id, uint32_t serial): UsbSerialDevice(owner, name, widget) { std::ostringstream str; str << std::hex << esta_id << "-" << device_id << "-" << serial; m_device_id = str.str(); ola::BasicOutputPort *port = new DmxterOutputPort(this, widget); AddPort(port); } } // namespace usbpro } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbpro/UsbProDevice.cpp0000644000175000017500000002443713023355232021521 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * UsbProDevice.cpp * An Enttec Usb Pro device * Copyright (C) 2006 Simon Newton * * The device creates two ports, one in and one out, but you can only use one * at a time. */ #include #include #include #include "common/rpc/RpcController.h" #include "ola/Callback.h" #include "ola/Constants.h" #include "ola/Logging.h" #include "olad/Preferences.h" #include "plugins/usbpro/UsbProDevice.h" #include "plugins/usbpro/UsbProWidgetDetector.h" namespace ola { namespace plugin { namespace usbpro { using ola::plugin::usbpro::Reply; using ola::plugin::usbpro::Request; using ola::rpc::RpcController; using std::ostringstream; using std::string; /* * Create a new device * @param owner the plugin that owns this device * @param name the device name * @param dev_path path to the pro widget */ UsbProDevice::UsbProDevice(ola::PluginAdaptor *plugin_adaptor, ola::AbstractPlugin *owner, const string &name, EnttecUsbProWidget *widget, uint32_t serial, uint16_t firmware_version, unsigned int fps_limit) : UsbSerialDevice(owner, name, widget), m_pro_widget(widget), m_serial(SerialToString(serial)) { ostringstream str; str << name << ", Serial #: " << m_serial << ", firmware " << (firmware_version >> 8) << "." << (firmware_version & 0xff); SetName(str.str()); for (unsigned int i = 0; i < widget->PortCount(); i++) { EnttecPort *enttec_port = widget->GetPort(i); if (!enttec_port) { OLA_WARN << "GetPort() returned NULL"; continue; } ostringstream port_description; if (widget->PortCount() > 1) { port_description << "DMX" << IntToString(i+1); } UsbProInputPort *input_port = new UsbProInputPort( this, enttec_port, i, plugin_adaptor, port_description.str()); enttec_port->SetDMXCallback( NewCallback(static_cast(input_port), &InputPort::DmxChanged)); AddPort(input_port); OutputPort *output_port = new UsbProOutputPort( this, enttec_port, i, port_description.str(), plugin_adaptor->WakeUpTime(), 5, // allow up to 5 burst frames fps_limit); // 200 frames per second seems to be the limit AddPort(output_port); PortParams port_params = {false, 0, 0, 0}; m_port_params.push_back(port_params); enttec_port->GetParameters( NewSingleCallback(this, &UsbProDevice::UpdateParams, i)); } } /* * Stop this device */ void UsbProDevice::PrePortStop() { m_pro_widget->Stop(); } /* * Handle device config messages * @param controller An RpcController * @param request the request data * @param response the response to return * @param done the closure to call once the request is complete */ void UsbProDevice::Configure(RpcController *controller, const string &request, string *response, ConfigureCallback *done) { Request request_pb; if (!request_pb.ParseFromString(request)) { controller->SetFailed("Invalid Request"); done->Run(); return; } switch (request_pb.type()) { case ola::plugin::usbpro::Request::USBPRO_PARAMETER_REQUEST: HandleParametersRequest(controller, &request_pb, response, done); break; case ola::plugin::usbpro::Request::USBPRO_SERIAL_REQUEST: HandleSerialRequest(controller, &request_pb, response, done); break; case ola::plugin::usbpro::Request::USBPRO_PORT_ASSIGNMENT_REQUEST: HandlePortAssignmentRequest(controller, &request_pb, response, done); break; default: controller->SetFailed("Invalid Request"); done->Run(); } } /** * Update the cached param values */ void UsbProDevice::UpdateParams(unsigned int port_id, bool status, const usb_pro_parameters ¶ms) { if (port_id >= m_port_params.size()) return; if (status) { PortParams &port_params = m_port_params[port_id]; port_params.got_parameters = true; port_params.break_time = params.break_time; port_params.mab_time = params.mab_time; port_params.rate = params.rate; } } /* * Handle a parameter request. This may set some parameters in the widget. * If no parameters are set we simply fetch the parameters and return them to * the client. If we are setting parameters, we send a SetParam() request and * then another GetParam() request in order to return the latest values to the * client. */ void UsbProDevice::HandleParametersRequest(RpcController *controller, const Request *request, string *response, ConfigureCallback *done) { if (!request->has_parameters()) { controller->SetFailed("Invalid request"); done->Run(); } unsigned int port_id = request->parameters().port_id(); EnttecPort *enttec_port = m_pro_widget->GetPort(port_id); if (enttec_port == NULL) { controller->SetFailed("Invalid port id"); done->Run(); return; } if (request->has_parameters() && (request->parameters().has_break_time() || request->parameters().has_mab_time() || request->parameters().has_rate())) { PortParams &port_params = m_port_params[port_id]; if (!port_params.got_parameters) { controller->SetFailed("SetParameters failed, startup not complete"); done->Run(); return; } bool ret = enttec_port->SetParameters( request->parameters().has_break_time() ? request->parameters().break_time() : port_params.break_time, request->parameters().has_mab_time() ? request->parameters().mab_time() : port_params.mab_time, request->parameters().has_rate() ? request->parameters().rate() : port_params.rate); if (!ret) { controller->SetFailed("SetParameters failed"); done->Run(); return; } } enttec_port->GetParameters(NewSingleCallback( this, &UsbProDevice::HandleParametersResponse, controller, response, done, port_id)); } /** * Handle the GetParameters response */ void UsbProDevice::HandleParametersResponse(RpcController *controller, string *response, ConfigureCallback *done, unsigned int port_id, bool status, const usb_pro_parameters ¶ms) { if (!status) { controller->SetFailed("GetParameters failed"); } else { UpdateParams(port_id, true, params); Reply reply; reply.set_type(ola::plugin::usbpro::Reply::USBPRO_PARAMETER_REPLY); ola::plugin::usbpro::ParameterReply *parameters_reply = reply.mutable_parameters(); parameters_reply->set_firmware_high(params.firmware_high); parameters_reply->set_firmware(params.firmware); parameters_reply->set_break_time(params.break_time); parameters_reply->set_mab_time(params.mab_time); parameters_reply->set_rate(params.rate); reply.SerializeToString(response); } done->Run(); } /* * Handle a Serial number Configure RPC. We can just return the cached number. */ void UsbProDevice::HandleSerialRequest(RpcController*, const Request*, string *response, ConfigureCallback *done) { Reply reply; reply.set_type(ola::plugin::usbpro::Reply::USBPRO_SERIAL_REPLY); ola::plugin::usbpro::SerialNumberReply *serial_reply = reply.mutable_serial_number(); serial_reply->set_serial(m_serial); reply.SerializeToString(response); done->Run(); } /* * Handle a port assignment request. */ void UsbProDevice::HandlePortAssignmentRequest(RpcController *controller, const Request*, string *response, ConfigureCallback *done) { m_pro_widget->GetPortAssignments(NewSingleCallback( this, &UsbProDevice::HandlePortAssignmentResponse, controller, response, done)); } /** * Handle a PortAssignment response. */ void UsbProDevice::HandlePortAssignmentResponse(RpcController *controller, string *response, ConfigureCallback *done, bool status, uint8_t port1_assignment, uint8_t port2_assignment) { if (!status) { controller->SetFailed("Get Port Assignments failed"); } else { Reply reply; reply.set_type(ola::plugin::usbpro::Reply::USBPRO_PORT_ASSIGNMENT_REPLY); ola::plugin::usbpro::PortAssignmentReply *port_assignment_reply = reply.mutable_port_assignment(); port_assignment_reply->set_port_assignment1(port1_assignment); port_assignment_reply->set_port_assignment2(port2_assignment); reply.SerializeToString(response); } done->Run(); } string UsbProDevice::SerialToString(uint32_t serial) { ostringstream str; str << std::setfill('0'); uint8_t *ptr = reinterpret_cast(&serial); for (int i = UsbProWidgetInformation::SERIAL_LENGTH - 1; i >= 0; i--) { int digit = (10 * (ptr[i] & 0xf0) >> 4) + (ptr[i] & 0x0f); str << std::setw(2) << digit; } return str.str(); } } // namespace usbpro } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbpro/BaseRobeWidgetTest.cpp0000644000175000017500000001400113023355232022637 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * BaseRobeWidgetTest.cpp * Test fixture for the BaseRobeWidget class * Copyright (C) 2010 Simon Newton */ #include #include #include #include "ola/Callback.h" #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/network/NetworkUtils.h" #include "plugins/usbpro/BaseRobeWidget.h" #include "plugins/usbpro/CommonWidgetTest.h" #include "ola/testing/TestUtils.h" using ola::DmxBuffer; using std::auto_ptr; using std::queue; class BaseRobeWidgetTest: public CommonWidgetTest { CPPUNIT_TEST_SUITE(BaseRobeWidgetTest); CPPUNIT_TEST(testSend); CPPUNIT_TEST(testReceive); CPPUNIT_TEST(testRemove); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void testSend(); void testReceive(); void testRemove(); private: auto_ptr m_widget; bool m_removed; typedef struct { uint8_t label; unsigned int size; const uint8_t *data; } expected_message; queue m_messages; void Terminate() { m_ss.Terminate(); } void AddExpectedMessage(uint8_t label, unsigned int size, const uint8_t *data); void ReceiveMessage(uint8_t label, const uint8_t *data, unsigned int size); void DeviceRemoved() { m_removed = true; m_ss.Terminate(); } }; CPPUNIT_TEST_SUITE_REGISTRATION(BaseRobeWidgetTest); void BaseRobeWidgetTest::setUp() { CommonWidgetTest::setUp(); m_widget.reset( new ola::plugin::usbpro::DispatchingRobeWidget( &m_descriptor, ola::NewCallback(this, &BaseRobeWidgetTest::ReceiveMessage))); m_removed = false; m_ss.RegisterSingleTimeout( 30, // 30ms should be enough ola::NewSingleCallback(this, &BaseRobeWidgetTest::Terminate)); } void BaseRobeWidgetTest::AddExpectedMessage(uint8_t label, unsigned int size, const uint8_t *data) { expected_message message = { label, size, data}; m_messages.push(message); } /** * Called when a new message arrives */ void BaseRobeWidgetTest::ReceiveMessage(uint8_t label, const uint8_t *data, unsigned int size) { OLA_ASSERT(m_messages.size()); expected_message message = m_messages.front(); m_messages.pop(); OLA_ASSERT_EQ(message.label, label); OLA_ASSERT_EQ(message.size, size); OLA_ASSERT_FALSE(memcmp(message.data, data, size)); if (m_messages.empty()) m_ss.Terminate(); } /* * Test sending works */ void BaseRobeWidgetTest::testSend() { // simple empty frame uint8_t expected1[] = {0xa5, 0, 0, 0, 0xa5, 0x4a}; m_endpoint->AddExpectedData( expected1, sizeof(expected1), ola::NewSingleCallback(this, &BaseRobeWidgetTest::Terminate)); OLA_ASSERT(m_widget->SendMessage(0, NULL, 0)); m_ss.Run(); m_endpoint->Verify(); // try a different label uint8_t expected2[] = {0xa5, 0x0a, 0, 0, 0xaf, 0x5e}; m_endpoint->AddExpectedData( expected2, sizeof(expected2), ola::NewSingleCallback(this, &BaseRobeWidgetTest::Terminate)); OLA_ASSERT(m_widget->SendMessage(10, NULL, 0)); m_ss.Run(); m_endpoint->Verify(); // frame with data uint8_t expected3[] = {0xa5, 0x0b, 4, 0, 0xb4, 0xde, 0xad, 0xbe, 0xef, 0xa0}; m_endpoint->AddExpectedData( expected3, sizeof(expected3), ola::NewSingleCallback(this, &BaseRobeWidgetTest::Terminate)); uint32_t data = ola::network::HostToNetwork(0xdeadbeef); OLA_ASSERT(m_widget->SendMessage(11, reinterpret_cast(&data), sizeof(data))); // try to send an incorrect frame OLA_ASSERT_FALSE(m_widget->SendMessage(10, NULL, 4)); m_ss.Run(); m_endpoint->Verify(); } /* * Test receiving works. */ void BaseRobeWidgetTest::testReceive() { uint8_t data[] = { 0xa5, 0, 0, 0, 0xa5, 0x4a, 0xa5, 0x0b, 4, 0, 0xb4, 0xde, 0xad, 0xbe, 0xef, 0xa0, 0xaa, 0xbb, // some random bytes 0xa5, 0xff, 0xff, 0xff, 0xa2, 0x44, // msg is too long 0xa5, 0xa, 4, 0, 0xb3, 0xa5, 0xa5, 0xaa, 0xaa, 0x04, // data contains 0xa5 // invalid header checksum 0xa5, 2, 4, 0, 0x00, 0xde, 0xad, 0xbe, 0xef, 0xaa, // invalid data checksum 0xa5, 2, 4, 0, 0xab, 0xde, 0xad, 0xbe, 0xef, 0x00, }; uint32_t data_chunk = ola::network::HostToNetwork(0xdeadbeef); AddExpectedMessage(0x0, 0, NULL); AddExpectedMessage(0x0b, sizeof(data_chunk), reinterpret_cast(&data_chunk)); uint32_t data_chunk2 = ola::network::HostToNetwork(0xa5a5aaaa); AddExpectedMessage(0x0a, sizeof(data_chunk2), reinterpret_cast(&data_chunk2)); ssize_t bytes_sent = m_other_end->Send(data, sizeof(data)); OLA_ASSERT_EQ(static_cast(sizeof(data)), bytes_sent); m_ss.Run(); OLA_ASSERT_EQ(static_cast(0), m_messages.size()); } /** * Test on remove works. */ void BaseRobeWidgetTest::testRemove() { m_widget->GetDescriptor()->SetOnClose( ola::NewSingleCallback(this, &BaseRobeWidgetTest::DeviceRemoved)); m_other_end->Close(); m_ss.Run(); OLA_ASSERT(m_removed); } ola-0.10.5.nojsmin/plugins/usbpro/DmxTriWidget.cpp0000644000175000017500000007523313023355232021542 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DmxTriWidget.cpp * The Jese DMX TRI device. * Copyright (C) 2010 Simon Newton */ #include #include #include #include #include #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/base/Array.h" #include "ola/io/ByteString.h" #include "ola/network/NetworkUtils.h" #include "ola/rdm/RDMCommand.h" #include "ola/rdm/RDMCommandSerializer.h" #include "ola/rdm/RDMEnums.h" #include "ola/rdm/UID.h" #include "ola/rdm/UIDSet.h" #include "ola/stl/STLUtils.h" #include "ola/strings/Format.h" #include "plugins/usbpro/BaseUsbProWidget.h" #include "plugins/usbpro/DmxTriWidget.h" namespace ola { namespace plugin { namespace usbpro { using ola::io::ByteString; using ola::network::HostToNetwork; using ola::network::NetworkToHost; using ola::rdm::RDMCommand; using ola::rdm::RDMCommandSerializer; using ola::rdm::RDMDiscoveryCallback; using ola::rdm::RDMReply; using ola::rdm::RDMRequest; using ola::rdm::RunRDMCallback; using ola::rdm::UID; using ola::rdm::UIDSet; using ola::strings::ToHex; using std::auto_ptr; using std::map; using std::string; using std::vector; /* * New DMX TRI Widget */ DmxTriWidgetImpl::DmxTriWidgetImpl( ola::thread::SchedulerInterface *scheduler, ola::io::ConnectedDescriptor *descriptor, bool use_raw_rdm) : BaseUsbProWidget(descriptor), m_scheduler(scheduler), m_uid_count(0), m_last_esta_id(UID::ALL_MANUFACTURERS), m_use_raw_rdm(use_raw_rdm), m_disc_stat_timeout_id(ola::thread::INVALID_TIMEOUT), m_discovery_callback(NULL), m_discovery_state(NO_DISCOVERY_ACTION), m_rdm_request_callback(NULL), m_pending_rdm_request(NULL), m_transaction_number(0), m_last_command(RESERVED_COMMAND_ID), m_expected_command(RESERVED_COMMAND_ID) { } /* * Shutdown */ DmxTriWidgetImpl::~DmxTriWidgetImpl() { Stop(); } /** * Stop the rdm discovery process if it's running */ void DmxTriWidgetImpl::Stop() { if (m_disc_stat_timeout_id != ola::thread::INVALID_TIMEOUT) { m_scheduler->RemoveTimeout(m_disc_stat_timeout_id); m_disc_stat_timeout_id = ola::thread::INVALID_TIMEOUT; } // timeout any existing message if (m_rdm_request_callback) { HandleRDMError(ola::rdm::RDM_TIMEOUT); } if (m_discovery_callback) { RDMDiscoveryCallback *callback = m_discovery_callback; m_discovery_callback = NULL; RunDiscoveryCallback(callback); } } /** * Send a DMX frame. This may queue the frame if there is a transaction * pending. */ bool DmxTriWidgetImpl::SendDMX(const DmxBuffer &buffer) { // Update the buffer, if there is already a frame pending, we send take the // latest one. if (m_outgoing_dmx.Size()) { OLA_INFO << "TRI widget dropping frame"; } m_outgoing_dmx = buffer; MaybeSendNextRequest(); return true; } /* * Send an RDM request. Because this is wrapped in a QueueingRDMController it's * only going to be called one-at-a-time. This will queue the RDM request if * there is a transaction pending. */ void DmxTriWidgetImpl::SendRDMRequest(RDMRequest *request_ptr, ola::rdm::RDMCallback *on_complete) { auto_ptr request(request_ptr); if (request->CommandClass() == RDMCommand::DISCOVER_COMMAND && !m_use_raw_rdm) { RunRDMCallback(on_complete, ola::rdm::RDM_PLUGIN_DISCOVERY_NOT_SUPPORTED); return; } if (m_rdm_request_callback) { OLA_FATAL << "Previous request hasn't completed yet, dropping request"; RunRDMCallback(on_complete, ola::rdm::RDM_FAILED_TO_SEND); return; } // store pointers m_pending_rdm_request.reset(request.release()); m_rdm_request_callback = on_complete; MaybeSendNextRequest(); } /** * Start the discovery process */ void DmxTriWidgetImpl::RunFullDiscovery(RDMDiscoveryCallback *callback) { // Right now there is no difference between full and incremental discovery. RunIncrementalDiscovery(callback); } /** * Start incremental discovery, which on the TRI is the same as full. */ void DmxTriWidgetImpl::RunIncrementalDiscovery( RDMDiscoveryCallback *callback) { if (m_discovery_callback) { OLA_FATAL << "Call to RunFullDiscovery while discovery is already running" << ", the DiscoverableQueueingRDMController has broken!"; // the best we can do is run the callback now RunDiscoveryCallback(callback); return; } m_discovery_callback = callback; m_discovery_state = DISCOVER_AUTO_REQUIRED; MaybeSendNextRequest(); } /** * Send the outstanding DMXBuffer. */ void DmxTriWidgetImpl::SendDMXBuffer() { // CommandID, Options, Start Code + data uint8_t send_buffer[3 + DMX_UNIVERSE_SIZE]; send_buffer[0] = SINGLE_TX_COMMAND_ID; send_buffer[1] = 0; // wait for command completion send_buffer[2] = DMX512_START_CODE; unsigned int length = DMX_UNIVERSE_SIZE; m_outgoing_dmx.Get(send_buffer + 3, &length); m_outgoing_dmx.Reset(); SendCommandToTRI(EXTENDED_COMMAND_LABEL, send_buffer, length + 3); } /** * Send the queued up RDM command. */ void DmxTriWidgetImpl::SendQueuedRDMCommand() { // If we can't find this UID, fail now. const UID &dest_uid = m_pending_rdm_request->DestinationUID(); if (!dest_uid.IsBroadcast() && !STLContains(m_uid_index_map, dest_uid)) { HandleRDMError(ola::rdm::RDM_UNKNOWN_UID); return; } if (m_use_raw_rdm) { SendRawRDMRequest(); return; } if (dest_uid.IsBroadcast() && dest_uid.ManufacturerId() != m_last_esta_id) { // we have to send a Set filter command uint16_t esta_id = dest_uid.ManufacturerId(); uint8_t data[] = {SET_FILTER_COMMAND_ID, static_cast(esta_id >> 8), static_cast(esta_id & 0xff) }; if (!SendCommandToTRI(EXTENDED_COMMAND_LABEL, reinterpret_cast(&data), sizeof(data))) { OLA_INFO << "Failed to send set filter, aborting request"; HandleRDMError(ola::rdm::RDM_FAILED_TO_SEND); } return; } else { DispatchRequest(); } } /** * Call the UIDSet handler with the latest UID list. */ void DmxTriWidgetImpl::RunDiscoveryCallback(RDMDiscoveryCallback *callback) { if (!callback) return; UIDSet uid_set; UIDToIndexMap::iterator iter = m_uid_index_map.begin(); for (; iter != m_uid_index_map.end(); ++iter) { uid_set.AddUID(iter->first); } callback->Run(uid_set); } /* * Check the status of the RDM discovery process. * This is called periodically while discovery is running */ bool DmxTriWidgetImpl::CheckDiscoveryStatus() { m_discovery_state = DISCOVER_STATUS_REQUIRED; MaybeSendNextRequest(); return true; } /* * Handle a message received from the widget */ void DmxTriWidgetImpl::HandleMessage(uint8_t label, const uint8_t *data, unsigned int length) { if (label == EXTENDED_COMMAND_LABEL) { if (length < DATA_OFFSET) { OLA_WARN << "DMX-TRI frame too small"; return; } uint8_t command_id = data[0]; uint8_t return_code = data[1]; length -= DATA_OFFSET; data = length ? data + DATA_OFFSET: NULL; if (command_id != m_expected_command) { OLA_WARN << "Received an unexpected command response, expected " << ToHex(m_expected_command) << ", got " << ToHex(command_id); } m_last_command = m_expected_command; m_expected_command = RESERVED_COMMAND_ID; switch (command_id) { case SINGLE_TX_COMMAND_ID: HandleSingleTXResponse(return_code); break; case DISCOVER_AUTO_COMMAND_ID: HandleDiscoveryAutoResponse(return_code, data, length); break; case DISCOVER_STATUS_COMMAND_ID: HandleDiscoverStatResponse(return_code, data, length); break; case REMOTE_UID_COMMAND_ID: HandleRemoteUIDResponse(return_code, data, length); break; case RAW_RDM_COMMAND_ID: HandleRawRDMResponse(return_code, data, length); break; case REMOTE_GET_COMMAND_ID: HandleRemoteRDMResponse(return_code, data, length); break; case REMOTE_SET_COMMAND_ID: HandleRemoteRDMResponse(return_code, data, length); break; case QUEUED_GET_COMMAND_ID: HandleQueuedGetResponse(return_code, data, length); break; case SET_FILTER_COMMAND_ID: HandleSetFilterResponse(return_code, data, length); break; default: OLA_WARN << "Unknown DMX-TRI CI: " << ToHex(command_id); } } else { OLA_INFO << "DMX-TRI got response " << static_cast(label); } } /* * Send a DiscoAuto message to begin the discovery process. */ void DmxTriWidgetImpl::SendDiscoveryAuto() { m_discovery_state = NO_DISCOVERY_ACTION; uint8_t command_id = DISCOVER_AUTO_COMMAND_ID; if (!SendCommandToTRI(EXTENDED_COMMAND_LABEL, &command_id, sizeof(command_id))) { OLA_WARN << "Unable to begin RDM discovery"; RDMDiscoveryCallback *callback = m_discovery_callback; m_discovery_callback = NULL; RunDiscoveryCallback(callback); } else { // setup a stat every RDM_STATUS_INTERVAL_MS until we're done m_disc_stat_timeout_id = m_scheduler->RegisterRepeatingTimeout( RDM_STATUS_INTERVAL_MS, NewCallback(this, &DmxTriWidgetImpl::CheckDiscoveryStatus)); } } /* * Send a RemoteUID message to fetch UID in TRI register. */ void DmxTriWidgetImpl::FetchNextUID() { m_discovery_state = NO_DISCOVERY_ACTION; if (!m_uid_count) return; OLA_INFO << "Fetching index " << static_cast(m_uid_count); uint8_t data[] = {REMOTE_UID_COMMAND_ID, m_uid_count}; SendCommandToTRI(EXTENDED_COMMAND_LABEL, data, sizeof(data)); } /* * Send a DiscoStat message to get status of the discovery process. */ void DmxTriWidgetImpl::SendDiscoveryStat() { m_discovery_state = NO_DISCOVERY_ACTION; uint8_t command = DISCOVER_STATUS_COMMAND_ID; if (!SendCommandToTRI(EXTENDED_COMMAND_LABEL, &command, sizeof(command))) { RDMDiscoveryCallback *callback = m_discovery_callback; m_discovery_callback = NULL; RunDiscoveryCallback(callback); } } /** * Send a raw RDM command, bypassing all the handling the RDM-TRI does. */ void DmxTriWidgetImpl::SendRawRDMRequest() { m_pending_rdm_request->SetTransactionNumber(m_transaction_number); m_pending_rdm_request->SetPortId(1); // port id is always 1 // add two bytes for the command & option field ByteString data; data.push_back(RAW_RDM_COMMAND_ID); // a 2 means we don't wait for a break in the response. data.push_back(m_pending_rdm_request->IsDUB() ? 2 : 0); if (!RDMCommandSerializer::Pack(*m_pending_rdm_request, &data)) { OLA_WARN << "Failed to pack RDM request"; HandleRDMError(ola::rdm::RDM_FAILED_TO_SEND); return; } OLA_INFO << "Sending raw request to " << m_pending_rdm_request->DestinationUID() << " with command " << ToHex(m_pending_rdm_request->CommandClass()) << " and param " << ToHex(m_pending_rdm_request->ParamId()); if (SendCommandToTRI(EXTENDED_COMMAND_LABEL, data.data(), data.size())) { m_transaction_number++; } else { HandleRDMError(ola::rdm::RDM_FAILED_TO_SEND); } } /* * Send the next RDM request, this assumes that SetFilter has been called */ void DmxTriWidgetImpl::DispatchRequest() { const ola::rdm::RDMRequest *request = m_pending_rdm_request.get(); if (request->ParamId() == ola::rdm::PID_QUEUED_MESSAGE && request->CommandClass() == RDMCommand::GET_COMMAND) { // these are special if (request->ParamDataSize()) { DispatchQueuedGet(); } else { OLA_WARN << "Missing param data in queued message get"; HandleRDMError(ola::rdm::RDM_FAILED_TO_SEND); } return; } PACK( struct rdm_message { uint8_t command; uint8_t index; uint16_t sub_device; uint16_t param_id; uint8_t data[RDMCommandSerializer::MAX_PARAM_DATA_LENGTH]; }); rdm_message message; if (request->CommandClass() == RDMCommand::GET_COMMAND) { message.command = REMOTE_GET_COMMAND_ID; } else if (request->CommandClass() == RDMCommand::SET_COMMAND) { message.command = REMOTE_SET_COMMAND_ID; } else { OLA_WARN << "Request was not get or set: " << static_cast(request->CommandClass()); HandleRDMError(ola::rdm::RDM_FAILED_TO_SEND); return; } if (request->DestinationUID().IsBroadcast()) { message.index = 0; } else { UIDToIndexMap::const_iterator iter = m_uid_index_map.find(request->DestinationUID()); if (iter == m_uid_index_map.end()) { OLA_WARN << request->DestinationUID() << " not found in uid map"; HandleRDMError(ola::rdm::RDM_UNKNOWN_UID); return; } message.index = iter->second; } message.sub_device = HostToNetwork(request->SubDevice()); message.param_id = HostToNetwork(request->ParamId()); if (request->ParamDataSize()) memcpy(message.data, request->ParamData(), request->ParamDataSize()); unsigned int size = sizeof(message) - RDMCommandSerializer::MAX_PARAM_DATA_LENGTH + request->ParamDataSize(); OLA_INFO << "Sending request to " << request->DestinationUID() << " with command " << ToHex(request->CommandClass()) << " and param " << ToHex(request->ParamId()); bool r = SendCommandToTRI(EXTENDED_COMMAND_LABEL, reinterpret_cast(&message), size); if (!r) { HandleRDMError(ola::rdm::RDM_FAILED_TO_SEND); } } /* * Send a queued get message */ void DmxTriWidgetImpl::DispatchQueuedGet() { UIDToIndexMap::const_iterator iter = m_uid_index_map.find(m_pending_rdm_request->DestinationUID()); if (iter == m_uid_index_map.end()) { OLA_WARN << m_pending_rdm_request->DestinationUID() << " not found in uid map"; HandleRDMError(ola::rdm::RDM_FAILED_TO_SEND); return; } uint8_t data[3] = {QUEUED_GET_COMMAND_ID, iter->second, m_pending_rdm_request->ParamData()[0]}; if (!SendCommandToTRI(EXTENDED_COMMAND_LABEL, reinterpret_cast(&data), arraysize(data))) { HandleRDMError(ola::rdm::RDM_FAILED_TO_SEND); } } /* * Stop the discovery process */ void DmxTriWidgetImpl::StopDiscovery() { if (m_disc_stat_timeout_id != ola::thread::INVALID_TIMEOUT) { m_scheduler->RemoveTimeout(m_disc_stat_timeout_id); m_disc_stat_timeout_id = ola::thread::INVALID_TIMEOUT; } } /** * Handle the response from Single TX. */ void DmxTriWidgetImpl::HandleSingleTXResponse(uint8_t return_code) { if (return_code != EC_NO_ERROR) OLA_WARN << "Error sending DMX data. TRI return code was " << ToHex(return_code); MaybeSendNextRequest(); } /* * Handle the response from calling DiscoAuto */ void DmxTriWidgetImpl::HandleDiscoveryAutoResponse(uint8_t return_code, const uint8_t*, unsigned int) { if (return_code != EC_NO_ERROR) { if (return_code == EC_UNKNOWN_COMMAND) OLA_INFO << "This DMX-TRI doesn't support RDM"; else OLA_WARN << "DMX_TRI discovery returned error " << static_cast(return_code); StopDiscovery(); RDMDiscoveryCallback *callback = m_discovery_callback; m_discovery_callback = NULL; RunDiscoveryCallback(callback); } } /* * Handle the response from calling discovery stat */ void DmxTriWidgetImpl::HandleDiscoverStatResponse(uint8_t return_code, const uint8_t *data, unsigned int length) { if (return_code == EC_NO_ERROR || return_code == EC_RESPONSE_UNEXPECTED) { if (return_code == EC_RESPONSE_UNEXPECTED) OLA_INFO << "Got an unexpected RDM response during discovery"; if (length < 1) { // don't cancel the timer, try again after RDM_STATUS_INTERVAL_MS OLA_WARN << "DiscoStat command too short, was " << length; return; } if (data[1] == 0) { OLA_DEBUG << "Discovery process has completed, " << static_cast(data[0]) << " devices found"; StopDiscovery(); m_uid_count = data[0]; m_uid_index_map.clear(); if (m_uid_count) { m_discovery_state = FETCH_UID_REQUIRED; MaybeSendNextRequest(); } else { RDMDiscoveryCallback *callback = m_discovery_callback; m_discovery_callback = NULL; RunDiscoveryCallback(callback); } } } else { // These are all fatal switch (return_code) { case EC_RESPONSE_MUTE: OLA_WARN << "Unable to mute device, aborting discovery"; break; case EC_RESPONSE_DISCOVERY: OLA_WARN << "Duplicated or erroneous device detected, aborting discovery"; break; default: OLA_WARN << "DMX_TRI discovery returned error " << static_cast(return_code); break; } // clear out the old map m_uid_index_map.clear(); StopDiscovery(); RDMDiscoveryCallback *callback = m_discovery_callback; m_discovery_callback = NULL; RunDiscoveryCallback(callback); } } /* * Handle the response to a RemoteGet command */ void DmxTriWidgetImpl::HandleRemoteUIDResponse(uint8_t return_code, const uint8_t *data, unsigned int length) { if (!m_uid_count) { // not expecting any responses OLA_INFO << "Got an unexpected RemoteUID response"; return; } if (return_code == EC_NO_ERROR) { if (length < ola::rdm::UID::UID_SIZE) { OLA_INFO << "Short RemoteUID response, was " << length; } else { const UID uid(data); m_uid_index_map[uid] = m_uid_count; } } else if (return_code == EC_CONSTRAINT) { // this is returned if the index is wrong OLA_INFO << "RemoteUID returned RC_Constraint, some how we botched the" << " discovery process, subtracting 1 and attempting to continue"; } else { OLA_INFO << "RemoteUID returned " << static_cast(return_code); } m_uid_count--; if (m_uid_count) { m_discovery_state = FETCH_UID_REQUIRED; MaybeSendNextRequest(); } else { RDMDiscoveryCallback *callback = m_discovery_callback; m_discovery_callback = NULL; RunDiscoveryCallback(callback); } } /* * Handle the response to a raw RDM command * data will be NULL, if length is 0. */ void DmxTriWidgetImpl::HandleRawRDMResponse(uint8_t return_code, const uint8_t *data, unsigned int length) { OLA_INFO << "got raw RDM response with code: " << ToHex(return_code) << ", length: " << length; auto_ptr request(m_pending_rdm_request); ola::rdm::RDMCallback *callback = m_rdm_request_callback; m_pending_rdm_request.reset(); m_rdm_request_callback = NULL; if (callback == NULL || request.get() == NULL) { OLA_FATAL << "Got a response but missing callback or request object!"; return; } if (return_code == EC_UNKNOWN_COMMAND) { // This means raw mode isn't supported and we should fall back to the // default mode m_use_raw_rdm = false; OLA_WARN << "Raw RDM mode not supported, switching back to the managed RDM mode"; SendRDMRequest(request.release(), callback); return; } // handle responses to DUB commands if (request->IsDUB()) { if (return_code == EC_RESPONSE_NONE) { RunRDMCallback(callback, ola::rdm::RDM_TIMEOUT); } else if (return_code == EC_NO_ERROR || return_code == EC_RESPONSE_DISCOVERY) { rdm::RDMFrame frame(data, length); auto_ptr reply(RDMReply::DUBReply(frame)); callback->Run(reply.get()); } else { OLA_WARN << "Un-handled DUB response " << ToHex(return_code); RunRDMCallback(callback, ola::rdm::RDM_INVALID_RESPONSE); } return; } const UID &dest_uid = request->DestinationUID(); if (dest_uid.IsBroadcast()) { if (return_code != EC_RESPONSE_NONE) { OLA_WARN << "Unexpected response to broadcast message"; } RunRDMCallback(callback, ola::rdm::RDM_WAS_BROADCAST); return; } if (return_code == EC_RESPONSE_NONE) { RunRDMCallback(callback, ola::rdm::RDM_TIMEOUT); return; } rdm::RDMFrame::Options options; options.prepend_start_code = true; auto_ptr reply(RDMReply::FromFrame( rdm::RDMFrame(data, length, options))); callback->Run(reply.get()); } /* * Handle the response to a Remote Get/Set command */ void DmxTriWidgetImpl::HandleRemoteRDMResponse(uint8_t return_code, const uint8_t *data, unsigned int length) { if (m_pending_rdm_request.get() == NULL) { OLA_FATAL << "Got a response but missing callback or request object!"; return; } OLA_INFO << "Received RDM response with code " << ToHex(return_code) << ", " << length << " bytes, param " << ToHex(m_pending_rdm_request->ParamId()); HandleGenericRDMResponse(return_code, m_pending_rdm_request->ParamId(), data, length); } /* * Handle the response to a QueuedGet command */ void DmxTriWidgetImpl::HandleQueuedGetResponse(uint8_t return_code, const uint8_t *data, unsigned int length) { if (length < 2) { OLA_FATAL << "Queued response too small, was " << length << " bytes"; HandleRDMError(ola::rdm::RDM_INVALID_RESPONSE); return; } uint16_t pid; memcpy(reinterpret_cast(&pid), data, sizeof(pid)); pid = NetworkToHost(pid); data += 2; length -= 2; OLA_INFO << "Received queued message response with code " << ToHex(return_code) << ", " << length << " bytes, param " << ToHex(pid); if (!length) data = NULL; HandleGenericRDMResponse(return_code, pid, data, length); } /* * Handle a RDM response for both queued and normal messages. */ void DmxTriWidgetImpl::HandleGenericRDMResponse(uint8_t return_code, uint16_t pid, const uint8_t *data, unsigned int length) { auto_ptr request(m_pending_rdm_request.release()); ola::rdm::RDMCallback *callback = m_rdm_request_callback; m_rdm_request_callback = NULL; if (callback == NULL || request.get() == NULL) { OLA_FATAL << "Got a response but missing callback or request object!"; return; } ola::rdm::RDMResponse *response = NULL; ola::rdm::RDMStatusCode code = ola::rdm::RDM_COMPLETED_OK; ola::rdm::rdm_nack_reason reason; if (ReturnCodeToNackReason(return_code, &reason)) { response = ola::rdm::NackWithReason(request.get(), reason); code = ola::rdm::RDM_COMPLETED_OK; } else if (return_code == EC_NO_ERROR) { if (request->DestinationUID().IsBroadcast()) { code = ola::rdm::RDM_WAS_BROADCAST; } else { code = ola::rdm::RDM_COMPLETED_OK; response = ola::rdm::GetResponseWithPid( request.get(), pid, data, length); } } else if (return_code == EC_RESPONSE_TIME) { response = ola::rdm::GetResponseWithPid(request.get(), pid, data, length, ola::rdm::RDM_ACK_TIMER); } else if (return_code == EC_RESPONSE_WAIT) { // this is a hack, there is no way to expose # of queued messages response = ola::rdm::GetResponseWithPid(request.get(), pid, data, length, ola::rdm::RDM_ACK, 1); } else if (return_code == EC_RESPONSE_MORE) { response = ola::rdm::GetResponseWithPid(request.get(), pid, data, length, ola::rdm::ACK_OVERFLOW); } else if (!TriToOlaReturnCode(return_code, &code)) { OLA_WARN << "Response was returned with " << ToHex(return_code); code = ola::rdm::RDM_INVALID_RESPONSE; } // Unfortunately we don't get to see the raw response here, which limits the // use of the TRI for testing. For testing use the raw mode. RDMReply reply(code, response); callback->Run(&reply); } /* * Handle a setfilter response */ void DmxTriWidgetImpl::HandleSetFilterResponse(uint8_t return_code, const uint8_t*, unsigned int) { if (!m_pending_rdm_request.get()) { OLA_WARN << "Set filter response but no RDM message to send!"; return; } if (return_code == EC_NO_ERROR) { m_last_esta_id = m_pending_rdm_request->DestinationUID().ManufacturerId(); DispatchRequest(); } else { OLA_WARN << "SetFilter returned " << static_cast(return_code) << ", we have no option but to drop the rdm request"; HandleRDMError(ola::rdm::RDM_FAILED_TO_SEND); } } /** * Return true if there is an outstanding transaction pending. */ bool DmxTriWidgetImpl::PendingTransaction() const { return m_expected_command != RESERVED_COMMAND_ID; } /** * Check if there is anything waiting to be sent. */ void DmxTriWidgetImpl::MaybeSendNextRequest() { // sending may fail, so we loop until there is nothing to do or there is a // transaction pending. bool first = true; while (true) { if (PendingTransaction()) { if (first) OLA_DEBUG << "Transaction in progress, delaying send"; return; } first = false; if (m_outgoing_dmx.Size() && m_last_command != SINGLE_TX_COMMAND_ID) { // avoid starving out DMX frames SendDMXBuffer(); } else if (m_pending_rdm_request.get()) { // there is an RDM command to send SendQueuedRDMCommand(); } else if (m_discovery_state == DISCOVER_AUTO_REQUIRED) { SendDiscoveryAuto(); } else if (m_discovery_state == DISCOVER_STATUS_REQUIRED) { SendDiscoveryStat(); } else if (m_discovery_state == FETCH_UID_REQUIRED) { FetchNextUID(); } else if (m_outgoing_dmx.Size()) { // there is a DMX frame to send SendDMXBuffer(); } else { return; } } } /** * Return an error on the RDM callback and handle the clean up. This assumes * that m_pending_rdm_request and m_rdm_request_callback are non-null. */ void DmxTriWidgetImpl::HandleRDMError(ola::rdm::RDMStatusCode status_code) { ola::rdm::RDMCallback *callback = m_rdm_request_callback; m_rdm_request_callback = NULL; m_pending_rdm_request.reset(); if (callback) { RunRDMCallback(callback, status_code); } } /** * Send data to the TRI, and set the flag indicating a transaction is pending. */ bool DmxTriWidgetImpl::SendCommandToTRI(uint8_t label, const uint8_t *data, unsigned int length) { bool r = SendMessage(label, data, length); if (r && label == EXTENDED_COMMAND_LABEL && length) { OLA_DEBUG << "Sent command " << ToHex(data[0]); m_expected_command = data[0]; } return r; } /** * Convert a DMX TRI return code to the appropriate RDMStatusCode * @return true if this was a matching code, false otherwise */ bool DmxTriWidgetImpl::TriToOlaReturnCode( uint8_t return_code, ola::rdm::RDMStatusCode *code) { switch (return_code) { case EC_RESPONSE_TRANSACTION: *code = ola::rdm::RDM_TRANSACTION_MISMATCH; break; case EC_RESPONSE_SUB_DEVICE: *code = ola::rdm::RDM_SUB_DEVICE_MISMATCH; break; case EC_RESPONSE_FORMAT: *code = ola::rdm::RDM_INVALID_RESPONSE; break; case EC_RESPONSE_CHECKSUM: *code = ola::rdm::RDM_CHECKSUM_INCORRECT; break; case EC_RESPONSE_NONE: *code = ola::rdm::RDM_TIMEOUT; break; case EC_RESPONSE_IDENTITY: *code = ola::rdm::RDM_SRC_UID_MISMATCH; break; default: return false; } return true; } /** * Convert a DMX-TRI return code to Nack reason code if appropriate */ bool DmxTriWidgetImpl::ReturnCodeToNackReason( uint8_t return_code, ola::rdm::rdm_nack_reason *reason) { switch (return_code) { case EC_UNKNOWN_PID: *reason = ola::rdm::NR_UNKNOWN_PID; break; case EC_FORMAT_ERROR: *reason = ola::rdm::NR_FORMAT_ERROR; break; case EC_HARDWARE_FAULT: *reason = ola::rdm::NR_HARDWARE_FAULT; break; case EC_PROXY_REJECT: *reason = ola::rdm::NR_PROXY_REJECT; break; case EC_WRITE_PROTECT: *reason = ola::rdm::NR_WRITE_PROTECT; break; case EC_UNSUPPORTED_COMMAND_CLASS: *reason = ola::rdm::NR_UNSUPPORTED_COMMAND_CLASS; break; case EC_OUT_OF_RANGE: *reason = ola::rdm::NR_DATA_OUT_OF_RANGE; break; case EC_BUFFER_FULL: *reason = ola::rdm::NR_BUFFER_FULL; break; case EC_FRAME_OVERFLOW: *reason = ola::rdm::NR_PACKET_SIZE_UNSUPPORTED; break; case EC_SUBDEVICE_UNKNOWN: *reason = ola::rdm::NR_SUB_DEVICE_OUT_OF_RANGE; break; case EC_PROXY_BUFFER_FULL: *reason = ola::rdm::NR_PROXY_BUFFER_FULL; break; default: return false; } return true; } /** * DmxTriWidget Constructor */ DmxTriWidget::DmxTriWidget(ola::thread::SchedulerInterface *scheduler, ola::io::ConnectedDescriptor *descriptor, unsigned int queue_size, bool use_raw_rdm) { m_impl = new DmxTriWidgetImpl(scheduler, descriptor, use_raw_rdm); m_controller = new ola::rdm::DiscoverableQueueingRDMController(m_impl, queue_size); } DmxTriWidget::~DmxTriWidget() { // delete the controller after the impl because the controller owns the // callback delete m_impl; delete m_controller; } } // namespace usbpro } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbpro/BaseRobeWidget.h0000644000175000017500000000775313023355232021464 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * BaseRobeWidget.h * Read and Write to a USB Widget that implements the Robe frame format. * Copyright (C) 2011 Simon Newton */ #ifndef PLUGINS_USBPRO_BASEROBEWIDGET_H_ #define PLUGINS_USBPRO_BASEROBEWIDGET_H_ #include #include "ola/Callback.h" #include "ola/DmxBuffer.h" #include "ola/io/Descriptor.h" #include "plugins/usbpro/SerialWidgetInterface.h" namespace ola { namespace plugin { namespace usbpro { /* * A widget that implements the Robe frame format. */ class BaseRobeWidget: public SerialWidgetInterface { public: explicit BaseRobeWidget(ola::io::ConnectedDescriptor *descriptor); virtual ~BaseRobeWidget(); ola::io::ConnectedDescriptor *GetDescriptor() const { return m_descriptor; } bool SendMessage(uint8_t label, const uint8_t *data, unsigned int length) const; static const uint8_t CHANNEL_A_OUT = 0x06; static const uint8_t INFO_REQUEST = 0x14; static const uint8_t INFO_RESPONSE = 0x15; static const uint8_t RDM_DISCOVERY = 0x12; static const uint8_t RDM_DISCOVERY_RESPONSE = 0x13; static const uint8_t RDM_REQUEST = 0x10; static const uint8_t RDM_RESPONSE = 0x11; static const uint8_t UID_REQUEST = 0x24; static const uint8_t UID_RESPONSE = 0x25; static const uint8_t DMX_IN_REQUEST = 0x04; static const uint8_t DMX_IN_RESPONSE = 0x05; private: typedef enum { PRE_SOM, RECV_PACKET_TYPE, RECV_SIZE_LO, RECV_SIZE_HI, RECV_HEADER_CRC, RECV_BODY, RECV_CRC, } receive_state; enum {MAX_DATA_SIZE = 522}; typedef struct { uint8_t som; uint8_t packet_type; uint8_t len; uint8_t len_hi; uint8_t header_crc; } message_header; ola::io::ConnectedDescriptor *m_descriptor; receive_state m_state; unsigned int m_bytes_received, m_data_size; uint8_t m_crc; message_header m_header; uint8_t m_recv_buffer[MAX_DATA_SIZE]; void DescriptorReady(); void ReceiveMessage(); virtual void HandleMessage(uint8_t label, const uint8_t *data, unsigned int length) = 0; static const uint8_t SOM = 0xa5; static const unsigned int HEADER_SIZE; }; /* * DispatchingRobeWidget */ class DispatchingRobeWidget: public BaseRobeWidget { public: typedef ola::Callback3 MessageCallback; DispatchingRobeWidget(ola::io::ConnectedDescriptor *descriptor, MessageCallback *callback = NULL) : BaseRobeWidget(descriptor), m_callback(callback) { } ~DispatchingRobeWidget() { Stop(); } void Stop() { if (m_callback) delete m_callback; } void SetHandler(MessageCallback *callback) { if (m_callback) delete m_callback; m_callback = callback; } private: MessageCallback *m_callback; void HandleMessage(uint8_t label, const uint8_t *data, unsigned int length) { m_callback->Run(label, data, length); } }; } // namespace usbpro } // namespace plugin } // namespace ola #endif // PLUGINS_USBPRO_BASEROBEWIDGET_H_ ola-0.10.5.nojsmin/plugins/usbpro/BaseRobeWidget.cpp0000644000175000017500000001415113134123277022012 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * BaseRobeWidget.cpp * Read and Write to a Robe USB Widget. * Copyright (C) 2011 Simon Newton */ #include #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/base/Macro.h" #include "plugins/usbpro/BaseRobeWidget.h" namespace ola { namespace plugin { namespace usbpro { const unsigned int BaseRobeWidget::HEADER_SIZE = sizeof(BaseRobeWidget::message_header); const uint8_t BaseRobeWidget::CHANNEL_A_OUT; const uint8_t BaseRobeWidget::INFO_REQUEST; const uint8_t BaseRobeWidget::INFO_RESPONSE; const uint8_t BaseRobeWidget::RDM_DISCOVERY; const uint8_t BaseRobeWidget::RDM_DISCOVERY_RESPONSE; const uint8_t BaseRobeWidget::RDM_REQUEST; const uint8_t BaseRobeWidget::RDM_RESPONSE; const uint8_t BaseRobeWidget::UID_REQUEST; const uint8_t BaseRobeWidget::UID_RESPONSE; const uint8_t BaseRobeWidget::DMX_IN_REQUEST; const uint8_t BaseRobeWidget::DMX_IN_RESPONSE; const uint8_t BaseRobeWidget::SOM; BaseRobeWidget::BaseRobeWidget(ola::io::ConnectedDescriptor *descriptor) : m_descriptor(descriptor), m_state(PRE_SOM), m_bytes_received(0), m_data_size(0), m_crc(0) { memset(&m_header, 0, sizeof(m_header)); m_descriptor->SetOnData(NewCallback(this, &BaseRobeWidget::DescriptorReady)); } BaseRobeWidget::~BaseRobeWidget() { m_descriptor->SetOnData(NULL); } /* * Send the msg * @return true if successful, false otherwise */ bool BaseRobeWidget::SendMessage(uint8_t packet_type, const uint8_t *data, unsigned int length) const { if (length && !data) return false; ssize_t frame_size = HEADER_SIZE + length + 1; uint8_t frame[frame_size]; message_header *header = reinterpret_cast(frame); header->som = SOM; header->packet_type = packet_type; header->len = length & 0xFF; header->len_hi = (length & 0xFF00) >> 8; uint8_t crc = SOM + packet_type + (length & 0xFF) + ((length & 0xFF00) >> 8); header->header_crc = crc; crc += crc; for (unsigned int i = 0; i < length; i++) crc += data[i]; memcpy(frame + sizeof(message_header), data, length); frame[frame_size - 1] = crc; ssize_t bytes_sent = m_descriptor->Send(frame, frame_size); if (bytes_sent != frame_size) // we've probably screwed framing at this point return false; return true; } /* * Read data from the widget */ void BaseRobeWidget::DescriptorReady() { while (m_descriptor->DataRemaining() > 0) { ReceiveMessage(); } } /* * Read the data and handle the messages. */ void BaseRobeWidget::ReceiveMessage() { unsigned int count; switch (m_state) { case PRE_SOM: do { m_descriptor->Receive(&m_header.som, 1, count); if (count != 1) return; } while (m_header.som != SOM); m_state = RECV_PACKET_TYPE; // if we don't return, fallthrough OLA_FALLTHROUGH case RECV_PACKET_TYPE: m_descriptor->Receive(&m_header.packet_type, 1, count); if (count != 1) return; m_state = RECV_SIZE_LO; // if we don't return, fallthrough OLA_FALLTHROUGH case RECV_SIZE_LO: m_descriptor->Receive(&m_header.len, 1, count); if (count != 1) return; m_state = RECV_SIZE_HI; // if we don't return, fallthrough OLA_FALLTHROUGH case RECV_SIZE_HI: m_descriptor->Receive(&m_header.len_hi, 1, count); if (count != 1) return; m_data_size = (m_header.len_hi << 8) + m_header.len; if (m_data_size > MAX_DATA_SIZE) { m_state = PRE_SOM; return; } m_bytes_received = 0; m_state = RECV_HEADER_CRC; // if we don't return, fallthrough OLA_FALLTHROUGH case RECV_HEADER_CRC: m_descriptor->Receive(&m_header.header_crc, 1, count); if (count != 1) return; m_crc = SOM + m_header.packet_type + m_header.len + m_header.len_hi; if (m_crc != m_header.header_crc) { OLA_WARN << "Mismatched header crc: " << std::hex << static_cast(m_crc) << " != " << static_cast(m_header.header_crc); m_state = PRE_SOM; return; } m_crc += m_header.header_crc; if (m_data_size) m_state = RECV_BODY; else m_state = RECV_CRC; // if we don't return, fallthrough OLA_FALLTHROUGH case RECV_BODY: m_descriptor->Receive( reinterpret_cast(&m_recv_buffer) + m_bytes_received, m_data_size - m_bytes_received, count); if (!count) return; m_bytes_received += count; if (m_bytes_received != m_data_size) return; m_state = RECV_CRC; // if we don't return, fallthrough OLA_FALLTHROUGH case RECV_CRC: // check this is a valid frame uint8_t crc; m_descriptor->Receive(&crc, 1, count); if (count != 1) return; for (unsigned int i = 0; i < m_data_size; i++) m_crc += m_recv_buffer[i]; if (m_crc != crc) { OLA_WARN << "Mismatched data crc: " << std::hex << static_cast(m_crc) << " != " << std::hex << static_cast(crc); } else { HandleMessage(m_header.packet_type, m_data_size ? m_recv_buffer : NULL, m_data_size); } m_state = PRE_SOM; // if we don't return, fallthrough OLA_FALLTHROUGH } return; } } // namespace usbpro } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbpro/WidgetDetectorThread.h0000644000175000017500000001640013023355232022670 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * WidgetDetectorThread.h * A thread that periodically looks for usb serial devices, and runs the * callbacks if they are valid widgets. * Copyright (C) 2011 Simon Newton */ #ifndef PLUGINS_USBPRO_WIDGETDETECTORTHREAD_H_ #define PLUGINS_USBPRO_WIDGETDETECTORTHREAD_H_ #include #include #include #include #include #include "ola/Callback.h" #include "ola/io/Descriptor.h" #include "ola/io/SelectServer.h" #include "ola/thread/Thread.h" #include "plugins/usbpro/BaseUsbProWidget.h" #include "plugins/usbpro/RobeWidget.h" #include "plugins/usbpro/RobeWidgetDetector.h" #include "plugins/usbpro/UsbProWidgetDetector.h" #include "plugins/usbpro/SerialWidgetInterface.h" #include "plugins/usbpro/WidgetDetectorInterface.h" namespace ola { namespace plugin { namespace usbpro { /** * The interface to implement to catch new widgets from the * WidgetDetectorThread. * * We overload the NewWidget method based on the type of widget * discovered. */ class NewWidgetHandler { public: virtual ~NewWidgetHandler() {} virtual void NewWidget(class ArduinoWidget *widget, const UsbProWidgetInformation &information) = 0; virtual void NewWidget(class EnttecUsbProWidget *widget, const UsbProWidgetInformation &information) = 0; virtual void NewWidget(class DmxTriWidget *widget, const UsbProWidgetInformation &information) = 0; virtual void NewWidget(class DmxterWidget *widget, const UsbProWidgetInformation &information) = 0; virtual void NewWidget(class RobeWidget *widget, const RobeWidgetInformation &information) = 0; virtual void NewWidget(class UltraDMXProWidget *widget, const UsbProWidgetInformation &information) = 0; }; /* * Discovers new USB Serial widgets and calls the handler. */ class WidgetDetectorThread: public ola::thread::Thread { public: explicit WidgetDetectorThread(NewWidgetHandler *widget_handler, ola::io::SelectServerInterface *ss, unsigned int usb_pro_timeout = 200, unsigned int robe_timeout = 200); ~WidgetDetectorThread() {} // Must be called before Run() void SetDeviceDirectory(const std::string &directory); // Must be called before Run() void SetDevicePrefixes(const std::vector &prefixes); // Must be called before Run() void SetIgnoredDevices(const std::vector &devices); // Start the thread, this will call the SuccessHandler whenever a new // Widget is located. void *Run(); // Stop the thread. bool Join(void *ptr); // Used to release a widget. Should be called from the thread running the // SelectServerInterface that was passed to the constructor. void FreeWidget(SerialWidgetInterface *widget); // blocks until the thread is running void WaitUntilRunning(); protected: virtual bool RunScan(); void PerformDiscovery(const std::string &path, ola::io::ConnectedDescriptor *descriptor); private: ola::io::SelectServerInterface *m_other_ss; ola::io::SelectServer m_ss; // ss for this thread std::vector m_widget_detectors; std::string m_directory; // directory to look for widgets in std::vector m_prefixes; // prefixes to try std::set m_ignored_devices; // devices to ignore NewWidgetHandler *m_handler; bool m_is_running; unsigned int m_usb_pro_timeout; unsigned int m_robe_timeout; ola::thread::Mutex m_mutex; ola::thread::ConditionVariable m_condition; // those paths that are either in discovery, or in use std::set m_active_paths; // holds the path and current widget detector offset typedef std::pair DescriptorInfo; // map of descriptor to DescriptorInfo typedef std::map ActiveDescriptors; // the descriptors that are in the discovery process ActiveDescriptors m_active_descriptors; // called when we find new widgets of a particular type void UsbProWidgetReady(ola::io::ConnectedDescriptor *descriptor, const UsbProWidgetInformation *info); void RobeWidgetReady(ola::io::ConnectedDescriptor *descriptor, const RobeWidgetInformation *info); void DescriptorFailed(ola::io::ConnectedDescriptor *descriptor); void PerformNextDiscoveryStep(ola::io::ConnectedDescriptor *descriptor); void InternalFreeWidget(SerialWidgetInterface *widget); void FreeDescriptor(ola::io::ConnectedDescriptor *descriptor); template void DispatchWidget(WidgetType *widget, const InfoType *information); // All of these are called in a separate thread. template void SignalNewWidget(WidgetType *widget, const InfoType *information); void MarkAsRunning(); static const unsigned int SCAN_INTERVAL_MS = 20000; // This is how device identification is done, see // https://wiki.openlighting.org/index.php/USB_Protocol_Extensions // OPEN_LIGHTING_ESTA_CODE is in Constants.h // DmxKing Device Models static const uint16_t DMX_KING_DMX512_ID = 0; static const uint16_t DMX_KING_ULTRA_ID = 1; static const uint16_t DMX_KING_ULTRA_PRO_ID = 2; static const uint16_t DMX_KING_ULTRA_MICRO_ID = 3; static const uint16_t DMX_KING_ULTRA_RDM_ID = 4; // Jese device models. static const uint16_t JESE_DMX_TRI_MK1_ID = 1; // Original DMX-TRI static const uint16_t JESE_RDM_TRI_MK1_ID = 2; // Original RDM-TRI static const uint16_t JESE_RDM_TRI_MK2_ID = 3; static const uint16_t JESE_RDM_TXI_MK2_ID = 4; // DMX-TRI, with new hardware static const uint16_t JESE_DMX_TRI_MK1_SE_ID = 5; // Goddard device models static const uint16_t GODDARD_DMXTER4_ID = 0x444d; static const uint16_t GODDARD_MINI_DMXTER4_ID = 0x4d49; static const uint16_t GODDARD_DMXTER4A_ID = 0x3441; // Open Lighting device models static const uint16_t OPEN_LIGHTING_PACKETHEADS_ID = 2; static const uint16_t OPEN_LIGHTING_RGB_MIXER_ID = 1; // ESTA Ids static const uint16_t DMX_KING_ESTA_ID = 0x6a6b; static const uint16_t GODDARD_ESTA_ID = 0x4744; static const uint16_t JESE_ESTA_ID = 0x6864; }; } // namespace usbpro } // namespace plugin } // namespace ola #endif // PLUGINS_USBPRO_WIDGETDETECTORTHREAD_H_ ola-0.10.5.nojsmin/plugins/usbpro/WidgetDetectorThread.cpp0000644000175000017500000003407713023355232023235 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * WidgetDetectorThread.cpp * A thread that periodically looks for USB Pro devices, and runs the callback * if they are valid widgets. * Copyright (C) 2011 Simon Newton */ #include #include #include #include "ola/Callback.h" #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/StringUtils.h" #include "ola/file/Util.h" #include "ola/io/Descriptor.h" #include "ola/io/Serial.h" #include "ola/stl/STLUtils.h" #include "plugins/usbpro/ArduinoWidget.h" #include "plugins/usbpro/BaseUsbProWidget.h" #include "plugins/usbpro/DmxTriWidget.h" #include "plugins/usbpro/DmxterWidget.h" #include "plugins/usbpro/EnttecUsbProWidget.h" #include "plugins/usbpro/RobeWidget.h" #include "plugins/usbpro/RobeWidgetDetector.h" #include "plugins/usbpro/UltraDMXProWidget.h" #include "plugins/usbpro/UsbProWidgetDetector.h" #include "plugins/usbpro/WidgetDetectorThread.h" namespace ola { namespace plugin { namespace usbpro { using ola::io::ConnectedDescriptor; using std::string; using std::vector; /** * Constructor * @param handler the NewWidgetHandler object to call when we find new widgets. * @param ss the SelectServer to use when calling the handler object. This is * also used by some of the widgets so it should be the same SelectServer that * you intend to use the Widgets with. * @param usb_pro_timeout the time in ms between each USB Pro discovery message. * @param robe_timeout the time in ms between each Robe discovery message. */ WidgetDetectorThread::WidgetDetectorThread( NewWidgetHandler *handler, ola::io::SelectServerInterface *ss, unsigned int usb_pro_timeout, unsigned int robe_timeout) : ola::thread::Thread(), m_other_ss(ss), m_handler(handler), m_is_running(false), m_usb_pro_timeout(usb_pro_timeout), m_robe_timeout(robe_timeout) { if (!m_handler) OLA_FATAL << "No new widget handler registered."; } /** * Set the directory in which to look for usb widgets. This should be called * before Run() since it doesn't do any locking. * @param directory the directory path e.g. /dev */ void WidgetDetectorThread::SetDeviceDirectory(const string &directory) { m_directory = directory; } /** * Set the list of prefixes to consider as possible devices. This should be * called before Run() since it doesn't do any locking. * @param prefixes a vector of strings e.g. ["ttyUSB"] */ void WidgetDetectorThread::SetDevicePrefixes(const vector &prefixes) { m_prefixes = prefixes; } /** * Set the list of devices we wish to ignore * @param devices a list of devices paths, e.g. /dev/ttyUSB0.NNNNNN */ void WidgetDetectorThread::SetIgnoredDevices(const vector &devices) { m_ignored_devices.clear(); vector::const_iterator iter = devices.begin(); for (; iter != devices.end(); ++iter) { m_ignored_devices.insert(*iter); } } /** * Run the discovery thread. */ void *WidgetDetectorThread::Run() { if (!m_widget_detectors.empty()) { OLA_WARN << "List of widget detectors isn't empty!"; } else { m_widget_detectors.push_back(new UsbProWidgetDetector( &m_ss, ola::NewCallback(this, &WidgetDetectorThread::UsbProWidgetReady), ola::NewCallback(this, &WidgetDetectorThread::DescriptorFailed), m_usb_pro_timeout)); m_widget_detectors.push_back(new RobeWidgetDetector( &m_ss, ola::NewCallback(this, &WidgetDetectorThread::RobeWidgetReady), ola::NewCallback(this, &WidgetDetectorThread::DescriptorFailed), m_robe_timeout)); } RunScan(); m_ss.RegisterRepeatingTimeout( SCAN_INTERVAL_MS, ola::NewCallback(this, &WidgetDetectorThread::RunScan)); m_ss.Execute( ola::NewSingleCallback(this, &WidgetDetectorThread::MarkAsRunning)); m_ss.Run(); m_ss.DrainCallbacks(); // This will trigger a call to InternalFreeWidget for any remaining widgets STLDeleteElements(&m_widget_detectors); if (!m_active_descriptors.empty()) OLA_WARN << m_active_descriptors.size() << " are still active"; ActiveDescriptors::const_iterator iter = m_active_descriptors.begin(); for (; iter != m_active_descriptors.end(); ++iter) { OLA_INFO << iter->first; } m_widget_detectors.clear(); return NULL; } /** * Stop the discovery thread. */ bool WidgetDetectorThread::Join(void *ptr) { m_ss.Terminate(); return ola::thread::Thread::Join(ptr); } /** * Indicate that this widget is no longer is use and can be deleted. */ void WidgetDetectorThread::FreeWidget(SerialWidgetInterface *widget) { // We have to remove the descriptor from the ss before closing. m_other_ss->RemoveReadDescriptor(widget->GetDescriptor()); widget->GetDescriptor()->Close(); m_ss.Execute( ola::NewSingleCallback(this, &WidgetDetectorThread::InternalFreeWidget, widget)); } /** * Block until the thread is up and running */ void WidgetDetectorThread::WaitUntilRunning() { m_mutex.Lock(); if (!m_is_running) m_condition.Wait(&m_mutex); m_mutex.Unlock(); } /** * Scan for widgets, and launch the discovery process for any that we don't * already know about. */ bool WidgetDetectorThread::RunScan() { vector device_paths; if (!ola::file::FindMatchingFiles(m_directory, m_prefixes, &device_paths)) { // We want to run the scan next time in case the problem is resolved. return true; } vector::iterator it; for (it = device_paths.begin(); it != device_paths.end(); ++it) { if (m_active_paths.find(*it) != m_active_paths.end()) { continue; } if (m_ignored_devices.find(*it) != m_ignored_devices.end()) { continue; } // FreeBSD has .init and .lock files which we want to skip if (StringEndsWith(*it, ".init") || StringEndsWith(*it, ".lock")) { continue; } OLA_INFO << "Found potential USB Serial device at " << *it; ConnectedDescriptor *descriptor = BaseUsbProWidget::OpenDevice(*it); if (!descriptor) { continue; } OLA_DEBUG << "New descriptor @ " << descriptor << " for " << *it; PerformDiscovery(*it, descriptor); } return true; } /** * Start the discovery sequence for a widget. */ void WidgetDetectorThread::PerformDiscovery(const string &path, ConnectedDescriptor *descriptor) { m_active_descriptors[descriptor] = DescriptorInfo(path, -1); m_active_paths.insert(path); PerformNextDiscoveryStep(descriptor); } /** * Called when a new widget becomes ready. Ownership of both objects transferrs * to use. */ void WidgetDetectorThread::UsbProWidgetReady( ConnectedDescriptor *descriptor, const UsbProWidgetInformation *information) { // we're no longer interested in events from this widget m_ss.RemoveReadDescriptor(descriptor); if (!m_handler) { OLA_WARN << "No callback defined for new Usb Pro Widgets."; FreeDescriptor(descriptor); delete information; return; } switch (information->esta_id) { case DMX_KING_ESTA_ID: if (information->device_id == DMX_KING_ULTRA_PRO_ID) { // The Ultra device has two outputs DispatchWidget( new UltraDMXProWidget(descriptor), information); return; } else { // DMXKing devices are drop in replacements for a Usb Pro EnttecUsbProWidget::EnttecUsbProWidgetOptions options( information->esta_id, information->serial); if (information->device_id == DMX_KING_ULTRA_RDM_ID) { options.enable_rdm = true; } DispatchWidget( new EnttecUsbProWidget(m_other_ss, descriptor, options), information); return; } case GODDARD_ESTA_ID: if (information->device_id == GODDARD_DMXTER4_ID || information->device_id == GODDARD_DMXTER4A_ID || information->device_id == GODDARD_MINI_DMXTER4_ID) { DispatchWidget( new DmxterWidget( descriptor, information->esta_id, information->serial), information); return; } break; case JESE_ESTA_ID: if (information->device_id == JESE_DMX_TRI_MK1_ID || information->device_id == JESE_RDM_TRI_MK1_ID || information->device_id == JESE_RDM_TRI_MK2_ID || information->device_id == JESE_RDM_TXI_MK2_ID || information->device_id == JESE_DMX_TRI_MK1_SE_ID) { DispatchWidget( new DmxTriWidget( m_other_ss, descriptor), information); return; } break; case OPEN_LIGHTING_ESTA_CODE: if (information->device_id == OPEN_LIGHTING_RGB_MIXER_ID || information->device_id == OPEN_LIGHTING_PACKETHEADS_ID) { DispatchWidget( new ArduinoWidget( descriptor, information->esta_id, information->serial), information); return; } break; } OLA_WARN << "Defaulting to a Usb Pro device"; if (information->dual_port) { OLA_INFO << "Found and unlocked an Enttec USB Pro Mk II"; } EnttecUsbProWidget::EnttecUsbProWidgetOptions options( information->esta_id, information->serial); options.dual_ports = information->dual_port; if (information->has_firmware_version) { // 2.4 is the first version that properly supports RDM. options.enable_rdm = information->firmware_version >= 0x0204; if (!options.enable_rdm) { OLA_WARN << "USB Pro Firmware >= 2.4 is required for RDM support, this " << "widget is running " << (information->firmware_version >> 8) << "." << (information->firmware_version & 0xff); } } DispatchWidget( new EnttecUsbProWidget(m_other_ss, descriptor, options), information); } /** * Called when we discovery a robe widget. */ void WidgetDetectorThread::RobeWidgetReady( ConnectedDescriptor *descriptor, const RobeWidgetInformation *info) { // we're no longer interested in events from this descriptor m_ss.RemoveReadDescriptor(descriptor); RobeWidget *widget = new RobeWidget(descriptor, info->uid); if (m_handler) { DispatchWidget(widget, info); } else { OLA_WARN << "No callback defined for new Robe Widgets."; InternalFreeWidget(widget); delete info; } } /** * Called when this descriptor fails discovery */ void WidgetDetectorThread::DescriptorFailed( ConnectedDescriptor *descriptor) { m_ss.RemoveReadDescriptor(descriptor); if (descriptor->ValidReadDescriptor()) { PerformNextDiscoveryStep(descriptor); } else { FreeDescriptor(descriptor); } } /** * Perform the next step in discovery for this descriptor. * @pre the descriptor exists in m_active_descriptors */ void WidgetDetectorThread::PerformNextDiscoveryStep( ConnectedDescriptor *descriptor) { DescriptorInfo &descriptor_info = m_active_descriptors[descriptor]; descriptor_info.second++; if (static_cast(descriptor_info.second) == m_widget_detectors.size()) { OLA_INFO << "no more detectors to try for " << descriptor; FreeDescriptor(descriptor); } else { OLA_INFO << "trying stage " << descriptor_info.second << " for " << descriptor; m_ss.AddReadDescriptor(descriptor); bool ok = m_widget_detectors[descriptor_info.second]->Discover(descriptor); if (!ok) { m_ss.RemoveReadDescriptor(descriptor); FreeDescriptor(descriptor); } } } /** * Free the widget and the associated descriptor. */ void WidgetDetectorThread::InternalFreeWidget(SerialWidgetInterface *widget) { ConnectedDescriptor *descriptor = widget->GetDescriptor(); // remove descriptor from our ss if it's still there if (descriptor->ValidReadDescriptor()) { m_ss.RemoveReadDescriptor(descriptor); } delete widget; FreeDescriptor(descriptor); } /** * Free a descriptor and remove it from the map. * @param descriptor the ConnectedDescriptor to free */ void WidgetDetectorThread::FreeDescriptor(ConnectedDescriptor *descriptor) { DescriptorInfo &descriptor_info = m_active_descriptors[descriptor]; m_active_paths.erase(descriptor_info.first); io::ReleaseUUCPLock(descriptor_info.first); m_active_descriptors.erase(descriptor); delete descriptor; } /** * Dispatch the widget to the caller's thread */ template void WidgetDetectorThread::DispatchWidget(WidgetType *widget, const InfoType *information) { // default the on remove to us widget->GetDescriptor()->SetOnClose(NewSingleCallback( this, &WidgetDetectorThread::FreeWidget, reinterpret_cast(widget))); ola::SingleUseCallback0 *cb = ola::NewSingleCallback( this, &WidgetDetectorThread::SignalNewWidget, widget, information); m_other_ss->Execute(cb); } /** * Call the handler to indicate there is a new widget available. */ template void WidgetDetectorThread::SignalNewWidget(WidgetType *widget, const InfoType *information) { const InfoType info(*information); delete information; m_other_ss->AddReadDescriptor(widget->GetDescriptor()); m_handler->NewWidget(widget, info); } /** * Mark this thread as running */ void WidgetDetectorThread::MarkAsRunning() { m_mutex.Lock(); m_is_running = true; m_mutex.Unlock(); m_condition.Signal(); } } // namespace usbpro } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbpro/RobeWidgetDetector.cpp0000644000175000017500000002254013023355232022705 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RobeWidgetDetector.cpp * Runs the Robe discovery routine and handles creating RobeWidget objects. * Copyright (C) 2011 Simon Newton * * This class accepts a ConnectedDescriptor and runs the discovery process * to determine if the widget behaves like a Robe device. * * The discovery process sends the following request messages: * - INFO_REQUEST * - RDM_UID_REQUEST * * Early Robe Universe Interface widgets are 'locked' meaning they can only be * used with the Robe software. You can unlocked these by upgrading the widget * firmware, see http://www.robe.cz/nc/support/search-for/DSU%20RUNIT/. * * The newer WTX widgets aren't locked. We can tell the type of widget from the * RDM UID. */ #include #include #include "ola/Logging.h" #include "ola/io/Descriptor.h" #include "ola/rdm/UID.h" #include "plugins/usbpro/RobeWidget.h" #include "plugins/usbpro/RobeWidgetDetector.h" namespace ola { namespace plugin { namespace usbpro { /** * Constructor * @param scheduler a instance of SchedulerInterface used to register events. * @param on_success A callback to run if discovery succeeds. * @param on_failure A callback to run if discovery fails. * @param timeout the time in ms between each discovery message. */ RobeWidgetDetector::RobeWidgetDetector( ola::thread::SchedulingExecutorInterface *scheduler, SuccessHandler *on_success, FailureHandler *on_failure, unsigned int timeout) : m_scheduler(scheduler), m_timeout_ms(timeout), m_callback(on_success), m_failure_callback(on_failure) { if (!on_success) OLA_WARN << "on_success callback not set, this will leak memory!"; if (!on_failure) OLA_WARN << "on_failure callback not set, this will leak memory!"; } /* * Fail any widgets that are still in the discovery process. */ RobeWidgetDetector::~RobeWidgetDetector() { m_scheduler->DrainCallbacks(); WidgetStateMap::iterator iter; for (iter = m_widgets.begin(); iter != m_widgets.end(); ++iter) { RemoveTimeout(&iter->second); CleanupWidget(iter->first); } m_widgets.clear(); } /* * Start the discovery process for a widget * @param widget, the RobeWidget to run discovery on. * @return true if the process started ok, false otherwise. */ bool RobeWidgetDetector::Discover( ola::io::ConnectedDescriptor *descriptor) { DispatchingRobeWidget *widget = new DispatchingRobeWidget(descriptor); widget->SetHandler( NewCallback(this, &RobeWidgetDetector::HandleMessage, widget)); if (!widget->SendMessage(BaseRobeWidget::INFO_REQUEST, NULL, 0)) { delete widget; return false; } // Set the onclose handler so we can mark this as failed. descriptor->SetOnClose(NewSingleCallback(this, &RobeWidgetDetector::WidgetRemoved, widget)); // Register a timeout for this widget SetupTimeout(widget, &m_widgets[widget]); return true; } /* * Called by the widgets when they receive a response. */ void RobeWidgetDetector::HandleMessage(DispatchingRobeWidget *widget, uint8_t label, const uint8_t *data, unsigned int length) { switch (label) { case BaseRobeWidget::INFO_RESPONSE: HandleInfoMessage(widget, data, length); break; case BaseRobeWidget::UID_RESPONSE: HandleUidMessage(widget, data, length); break; default: OLA_WARN << "Unknown response label: 0x" << std::hex << static_cast(label) << ", size is " << length; } } /** * Handle a INFO message */ void RobeWidgetDetector::HandleInfoMessage(DispatchingRobeWidget *widget, const uint8_t *data, unsigned int length) { struct { uint8_t hardware_version; uint8_t software_version; uint8_t eeprom_version; uint8_t empty; uint8_t empty2; } info_response; WidgetStateMap::iterator iter = m_widgets.find(widget); if (iter == m_widgets.end()) return; if (length != sizeof(info_response)) { OLA_WARN << "Info response size " << length << " != " << sizeof(info_response); return; } else { memcpy(reinterpret_cast(&info_response), data, sizeof(info_response)); iter->second.information.hardware_version = info_response.hardware_version; iter->second.information.software_version = info_response.software_version; iter->second.information.eeprom_version = info_response.eeprom_version; } RemoveTimeout(&iter->second); SetupTimeout(widget, &iter->second); widget->SendMessage(BaseRobeWidget::UID_REQUEST, NULL, 0); } /** * Handle a RDM UID Message */ void RobeWidgetDetector::HandleUidMessage(DispatchingRobeWidget *widget, const uint8_t *data, unsigned int length) { WidgetStateMap::iterator iter = m_widgets.find(widget); if (iter == m_widgets.end()) return; if (length != ola::rdm::UID::UID_SIZE) { OLA_INFO << "Robe widget returned invalid UID size: " << length; return; } iter->second.information.uid = ola::rdm::UID(data); if (!IsUnlocked(iter->second.information)) { OLA_WARN << "This Robe widget isn't unlocked, please visit " "http://www.robe.cz/nc/support/search-for/DSU%20RUNIT/ to download " "the new firmware."; return; } // ok this is a good interface at this point RemoveTimeout(&iter->second); const RobeWidgetInformation *widget_info = new RobeWidgetInformation( iter->second.information); m_widgets.erase(iter); OLA_INFO << "Detected Robe Device, UID : " << widget_info->uid << ", Hardware version: 0x" << std::hex << static_cast(widget_info->hardware_version) << ", software version: 0x" << static_cast(widget_info->software_version) << ", eeprom version 0x" << static_cast(widget_info->eeprom_version); // given that we've been called via the widget's stack, schedule execution of // the method that deletes the widget. m_scheduler->Execute( NewSingleCallback(this, &RobeWidgetDetector::DispatchWidget, widget, widget_info)); } /** * Called if a widget is removed. */ void RobeWidgetDetector::WidgetRemoved(DispatchingRobeWidget *widget) { widget->GetDescriptor()->Close(); FailWidget(widget); } /* * Called if a widget fails to respond in a given interval or responds with an * invalid message. */ void RobeWidgetDetector::FailWidget(DispatchingRobeWidget *widget) { WidgetStateMap::iterator iter = m_widgets.find(widget); if (iter != m_widgets.end()) { m_scheduler->RemoveTimeout(&iter->second); m_widgets.erase(iter); } CleanupWidget(widget); } /** * Delete a widget and run the failure callback. */ void RobeWidgetDetector::CleanupWidget(DispatchingRobeWidget *widget) { ola::io::ConnectedDescriptor *descriptor = widget->GetDescriptor(); descriptor->SetOnClose(NULL); delete widget; if (m_failure_callback.get()) m_failure_callback->Run(descriptor); } /** * Called once we have confirmed a new widget */ void RobeWidgetDetector::DispatchWidget( DispatchingRobeWidget *widget, const RobeWidgetInformation *info) { ola::io::ConnectedDescriptor *descriptor = widget->GetDescriptor(); descriptor->SetOnClose(NULL); delete widget; if (m_callback.get()) { m_callback->Run(descriptor, info); } else { OLA_FATAL << "No listener provided, leaking descriptor"; delete info; } } /** * Remove a timeout for a widget. */ void RobeWidgetDetector::RemoveTimeout(DiscoveryState *discovery_state) { if (discovery_state->timeout_id != ola::thread::INVALID_TIMEOUT) m_scheduler->RemoveTimeout(discovery_state->timeout_id); } /** * Setup a timeout for a widget */ void RobeWidgetDetector::SetupTimeout(DispatchingRobeWidget *widget, DiscoveryState *discovery_state) { discovery_state->timeout_id = m_scheduler->RegisterSingleTimeout( m_timeout_ms, NewSingleCallback(this, &RobeWidgetDetector::FailWidget, widget)); } /** * Returns true if the Robe interface is 'unlocked'. */ bool RobeWidgetDetector::IsUnlocked(const RobeWidgetInformation &info) { switch (info.uid.DeviceId() & MODEL_MASK) { case RUI_DEVICE_PREFIX: // RUI are unlocked past a certain version # return info.software_version >= RUI_MIN_UNLOCKED_SOFTWARE_VERSION; case WTX_DEVICE_PREFIX: return info.software_version >= WTX_MIN_SOFTWARE_VERSION; default: // default to no return false; } } } // namespace usbpro } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbpro/UltraDMXProWidgetTest.cpp0000644000175000017500000000726513023355232023314 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * UltraDMXProWidgetTest.cpp * Test fixture for the UltraDMXProWidget class * Copyright (C) 2011 Simon Newton */ #include #include #include "ola/Callback.h" #include "ola/Constants.h" #include "ola/DmxBuffer.h" #include "ola/Logging.h" #include "plugins/usbpro/UltraDMXProWidget.h" #include "plugins/usbpro/CommonWidgetTest.h" using std::auto_ptr; using ola::DmxBuffer; class UltraDMXProWidgetTest: public CommonWidgetTest { CPPUNIT_TEST_SUITE(UltraDMXProWidgetTest); CPPUNIT_TEST(testPrimarySendDMX); CPPUNIT_TEST(testSecondarySendDMX); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void testPrimarySendDMX(); void testSecondarySendDMX(); private: auto_ptr m_widget; void Terminate() { m_ss.Terminate(); } static const uint8_t PRIMARY_DMX_LABEL = 100; static const uint8_t SECONDARY_DMX_LABEL = 101; }; CPPUNIT_TEST_SUITE_REGISTRATION(UltraDMXProWidgetTest); void UltraDMXProWidgetTest::setUp() { CommonWidgetTest::setUp(); m_widget.reset( new ola::plugin::usbpro::UltraDMXProWidget(&m_descriptor)); } /** * Check that we can send DMX on the primary port */ void UltraDMXProWidgetTest::testPrimarySendDMX() { // dmx data DmxBuffer buffer; buffer.SetFromString("0,1,2,3,4"); // expected message uint8_t dmx_frame_data[] = {ola::DMX512_START_CODE, 0, 1, 2, 3, 4}; m_endpoint->AddExpectedUsbProMessage( PRIMARY_DMX_LABEL, dmx_frame_data, sizeof(dmx_frame_data), ola::NewSingleCallback(this, &UltraDMXProWidgetTest::Terminate)); m_widget->SendDMX(buffer); m_ss.Run(); m_endpoint->Verify(); // now test an empty frame DmxBuffer buffer2; uint8_t empty_frame_data[] = {ola::DMX512_START_CODE}; // just the start code m_endpoint->AddExpectedUsbProMessage( PRIMARY_DMX_LABEL, empty_frame_data, sizeof(empty_frame_data), ola::NewSingleCallback(this, &UltraDMXProWidgetTest::Terminate)); m_widget->SendDMX(buffer2); m_ss.Run(); m_endpoint->Verify(); } /** * Check that we can send DMX on the secondary port */ void UltraDMXProWidgetTest::testSecondarySendDMX() { // dmx data DmxBuffer buffer; buffer.SetFromString("0,1,2,3,4"); // expected message uint8_t dmx_frame_data[] = {ola::DMX512_START_CODE, 0, 1, 2, 3, 4}; m_endpoint->AddExpectedUsbProMessage( SECONDARY_DMX_LABEL, dmx_frame_data, sizeof(dmx_frame_data), ola::NewSingleCallback(this, &UltraDMXProWidgetTest::Terminate)); m_widget->SendSecondaryDMX(buffer); m_ss.Run(); m_endpoint->Verify(); // now test an empty frame DmxBuffer buffer2; uint8_t empty_frame_data[] = {ola::DMX512_START_CODE}; // just the start code m_endpoint->AddExpectedUsbProMessage( SECONDARY_DMX_LABEL, empty_frame_data, sizeof(empty_frame_data), ola::NewSingleCallback(this, &UltraDMXProWidgetTest::Terminate)); m_widget->SendSecondaryDMX(buffer2); m_ss.Run(); m_endpoint->Verify(); } ola-0.10.5.nojsmin/plugins/usbpro/UsbSerialPlugin.h0000644000175000017500000000711313023355232021674 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * UsbSerialPlugin.h * Interface for the usbpro plugin class * Copyright (C) 2006 Simon Newton */ #ifndef PLUGINS_USBPRO_USBSERIALPLUGIN_H_ #define PLUGINS_USBPRO_USBSERIALPLUGIN_H_ #include #include #include "ola/io/Descriptor.h" #include "ola/plugin_id.h" #include "olad/Plugin.h" #include "plugins/usbpro/UsbSerialDevice.h" #include "plugins/usbpro/WidgetDetectorThread.h" namespace ola { namespace plugin { namespace usbpro { class UsbSerialPlugin: public ola::Plugin, public NewWidgetHandler { public: explicit UsbSerialPlugin(PluginAdaptor *plugin_adaptor); std::string Name() const { return PLUGIN_NAME; } std::string Description() const; ola_plugin_id Id() const { return OLA_PLUGIN_USBPRO; } void DeviceRemoved(UsbSerialDevice *device); std::string PluginPrefix() const { return PLUGIN_PREFIX; } void NewWidget(ArduinoWidget *widget, const UsbProWidgetInformation &information); void NewWidget(EnttecUsbProWidget *widget, const UsbProWidgetInformation &information); void NewWidget(DmxTriWidget *widget, const UsbProWidgetInformation &information); void NewWidget(DmxterWidget *widget, const UsbProWidgetInformation &information); void NewWidget(RobeWidget *widget, const RobeWidgetInformation &information); void NewWidget(UltraDMXProWidget *widget, const UsbProWidgetInformation &information); private: void AddDevice(UsbSerialDevice *device); bool StartHook(); bool StopHook(); bool SetDefaultPreferences(); void DeleteDevice(UsbSerialDevice *device); std::string GetDeviceName(const UsbProWidgetInformation &information); unsigned int GetProFrameLimit(); unsigned int GetDmxTriFrameLimit(); unsigned int GetUltraDMXProFrameLimit(); std::vector m_devices; // list of our devices WidgetDetectorThread m_detector_thread; static const char DEFAULT_DEVICE_DIR[]; static const char DEVICE_DIR_KEY[]; static const char DEVICE_PREFIX_KEY[]; static const char IGNORED_DEVICES_KEY[]; static const char LINUX_DEVICE_PREFIX[]; static const char BSD_DEVICE_PREFIX[]; static const char MAC_DEVICE_PREFIX[]; static const char PLUGIN_NAME[]; static const char PLUGIN_PREFIX[]; static const char ROBE_DEVICE_NAME[]; static const char TRI_USE_RAW_RDM_KEY[]; static const char USBPRO_DEVICE_NAME[]; static const char USB_PRO_FPS_LIMIT_KEY[]; static const char ULTRA_FPS_LIMIT_KEY[]; static const uint8_t DEFAULT_PRO_FPS_LIMIT = 190; static const uint8_t DEFAULT_ULTRA_FPS_LIMIT = 40; static const unsigned int MAX_PRO_FPS_LIMIT = 1000; static const unsigned int MAX_ULTRA_FPS_LIMIT = 1000; }; } // namespace usbpro } // namespace plugin } // namespace ola #endif // PLUGINS_USBPRO_USBSERIALPLUGIN_H_ ola-0.10.5.nojsmin/plugins/usbpro/ArduinoRGBDevice.cpp0000644000175000017500000000527213023355232022237 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ArduinoRGBDevice.cpp * The Arduino RGB Mixer device. * Copyright (C) 2010 Simon Newton */ #include #include #include #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/StringUtils.h" #include "ola/io/SelectServerInterface.h" #include "ola/strings/Format.h" #include "plugins/usbpro/ArduinoRGBDevice.h" namespace ola { namespace plugin { namespace usbpro { using std::string; /* * New Arduino RGB Device */ ArduinoRGBDevice::ArduinoRGBDevice(ola::io::SelectServerInterface *ss, ola::AbstractPlugin *owner, const string &name, ArduinoWidget *widget, uint16_t esta_id, uint16_t device_id, uint32_t serial): UsbSerialDevice(owner, name, widget) { std::ostringstream str; str << std::hex << esta_id << "-" << device_id << "-" << serial; m_device_id = str.str(); OutputPort *output_port = new ArduinoRGBOutputPort( this, widget, serial, ss->WakeUpTime(), 5, // start with 5 tokens in the bucket 20); // 22 frames per second seems to be the limit AddPort(output_port); } ArduinoRGBOutputPort::ArduinoRGBOutputPort(ArduinoRGBDevice *parent, ArduinoWidget *widget, uint32_t serial, const TimeStamp *wake_time, unsigned int initial_count, unsigned int rate) : BasicOutputPort(parent, 0, true, true), m_widget(widget), m_bucket(initial_count, rate, rate, *wake_time), m_wake_time(wake_time) { std::ostringstream str; str << "Serial #: " << strings::ToHex(serial); m_description = str.str(); } } // namespace usbpro } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbpro/RobeWidgetDetector.h0000644000175000017500000001104313023355232022346 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RobeWidgetDetector.h * Runs the Robe discovery routine. * Copyright (C) 2011 Simon Newton */ #ifndef PLUGINS_USBPRO_ROBEWIDGETDETECTOR_H_ #define PLUGINS_USBPRO_ROBEWIDGETDETECTOR_H_ #include #include #include #include #include #include #include "plugins/usbpro/BaseRobeWidget.h" #include "plugins/usbpro/WidgetDetectorInterface.h" namespace ola { namespace plugin { namespace usbpro { /* * Contains information about the Robe USB device. */ class RobeWidgetInformation { public: RobeWidgetInformation() : uid(0, 0), hardware_version(0), software_version(0), eeprom_version(0) { } RobeWidgetInformation(const RobeWidgetInformation &other): uid(other.uid), hardware_version(other.hardware_version), software_version(other.software_version), eeprom_version(other.eeprom_version) { } ola::rdm::UID uid; uint8_t hardware_version; uint8_t software_version; uint8_t eeprom_version; }; /* * Handles widget discovery for Robe devices. */ class RobeWidgetDetector: public WidgetDetectorInterface { public: typedef ola::Callback2 SuccessHandler; typedef ola::Callback1 FailureHandler; RobeWidgetDetector( ola::thread::SchedulingExecutorInterface *scheduler, SuccessHandler *on_success, FailureHandler *on_failure, unsigned int timeout = 200); ~RobeWidgetDetector(); bool Discover(ola::io::ConnectedDescriptor *descriptor); private: // Hold the discovery state for a widget class DiscoveryState { public: DiscoveryState(): discovery_state(INFO_SENT), timeout_id(ola::thread::INVALID_TIMEOUT) { } ~DiscoveryState() {} typedef enum { INFO_SENT, UID_SENT, } widget_state; RobeWidgetInformation information; widget_state discovery_state; ola::thread::timeout_id timeout_id; }; ola::thread::SchedulingExecutorInterface *m_scheduler; const unsigned int m_timeout_ms; std::auto_ptr m_callback; std::auto_ptr m_failure_callback; typedef std::map WidgetStateMap; WidgetStateMap m_widgets; void HandleMessage(DispatchingRobeWidget *widget, uint8_t label, const uint8_t *data, unsigned int length); void HandleInfoMessage(DispatchingRobeWidget *widget, const uint8_t *data, unsigned int length); void HandleUidMessage(DispatchingRobeWidget *widget, const uint8_t *data, unsigned int length); void WidgetRemoved(DispatchingRobeWidget *widget); void FailWidget(DispatchingRobeWidget *widget); void CleanupWidget(DispatchingRobeWidget *widget); void DispatchWidget(DispatchingRobeWidget *widget, const RobeWidgetInformation *info); void RemoveTimeout(DiscoveryState *discovery_state); void SetupTimeout(DispatchingRobeWidget *widget, DiscoveryState *discovery_state); bool IsUnlocked(const RobeWidgetInformation &info); static const uint32_t MODEL_MASK = 0xffff0000; static const uint32_t RUI_DEVICE_PREFIX = 0x01000000; static const uint32_t WTX_DEVICE_PREFIX = 0x02000000; // 0x14 is good, 0xe is bad. actual version is probably somewhere in // between. static const uint8_t RUI_MIN_UNLOCKED_SOFTWARE_VERSION = 0x14; // we need at least v 11 for decent RDM support static const uint8_t WTX_MIN_SOFTWARE_VERSION = 0x0b; }; } // namespace usbpro } // namespace plugin } // namespace ola #endif // PLUGINS_USBPRO_ROBEWIDGETDETECTOR_H_ ola-0.10.5.nojsmin/plugins/usbpro/DmxterDevice.h0000644000175000017500000000502413023355232021206 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DmxterDevice.h * The Goddard Design Dmxter RDM and miniDmxter * Copyright (C) 2010 Simon Newton */ #ifndef PLUGINS_USBPRO_DMXTERDEVICE_H_ #define PLUGINS_USBPRO_DMXTERDEVICE_H_ #include #include "ola/DmxBuffer.h" #include "plugins/usbpro/DmxterWidget.h" #include "plugins/usbpro/UsbSerialDevice.h" namespace ola { namespace plugin { namespace usbpro { /* * An DMXter Device */ class DmxterDevice: public UsbSerialDevice { public: DmxterDevice(ola::AbstractPlugin *owner, const std::string &name, DmxterWidget *widget, uint16_t esta_id, uint16_t device_id, uint32_t serial); std::string DeviceId() const { return m_device_id; } private: std::string m_device_id; }; /* * A single Output port per device */ class DmxterOutputPort: public BasicOutputPort { public: DmxterOutputPort(DmxterDevice *parent, DmxterWidget *widget) : BasicOutputPort(parent, 0, true, true), m_widget(widget) {} bool WriteDMX(OLA_UNUSED const DmxBuffer &buffer, OLA_UNUSED uint8_t priority) { // this device can't output DMX return true; } void SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *callback) { m_widget->SendRDMRequest(request, callback); } void RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *on_complete) { m_widget->RunFullDiscovery(on_complete); } void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *on_complete) { m_widget->RunIncrementalDiscovery(on_complete); } std::string Description() const { return "RDM Only"; } private: DmxterWidget *m_widget; }; } // namespace usbpro } // namespace plugin } // namespace ola #endif // PLUGINS_USBPRO_DMXTERDEVICE_H_ ola-0.10.5.nojsmin/plugins/usbpro/DmxterWidget.h0000644000175000017500000001267413023355232021243 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DmxterWidget.h * The Goddard Design Dmxter RDM and miniDmxter * Copyright (C) 2010 Simon Newton */ #ifndef PLUGINS_USBPRO_DMXTERWIDGET_H_ #define PLUGINS_USBPRO_DMXTERWIDGET_H_ #include #include "ola/io/SelectServerInterface.h" #include "ola/rdm/UID.h" #include "ola/rdm/UIDSet.h" #include "ola/rdm/RDMControllerInterface.h" #include "ola/rdm/QueueingRDMController.h" #include "plugins/usbpro/BaseUsbProWidget.h" namespace ola { namespace plugin { namespace usbpro { /* * A DMXter Widget implementation. We separate the Widget from the * implementation so we can leverage the QueueingRDMController. */ class DmxterWidgetImpl: public BaseUsbProWidget, public ola::rdm::DiscoverableRDMControllerInterface { public: DmxterWidgetImpl(ola::io::ConnectedDescriptor *descriptor, uint16_t esta_id, uint32_t serial); ~DmxterWidgetImpl(); void Stop(); void SendRDMRequest(ola::rdm::RDMRequest *request_ptr, ola::rdm::RDMCallback *on_complete); void RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback); void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback); private: ola::rdm::UID m_uid; ola::rdm::UIDSet m_uids; ola::rdm::RDMDiscoveryCallback *m_discovery_callback; std::auto_ptr m_pending_request; ola::rdm::RDMCallback *m_rdm_request_callback; uint8_t m_transaction_number; void HandleMessage(uint8_t label, const uint8_t *data, unsigned int length); void HandleTodResponse(const uint8_t *data, unsigned int length); void HandleRDMResponse(const uint8_t *data, unsigned int length); void HandleBroadcastRDMResponse(const uint8_t *data, unsigned int length); void HandleShutdown(const uint8_t *data, unsigned int length); static const uint8_t RDM_REQUEST_LABEL; static const uint8_t RDM_BCAST_REQUEST_LABEL; static const uint8_t TOD_LABEL; static const uint8_t DISCOVERY_BRANCH_LABEL; static const uint8_t FULL_DISCOVERY_LABEL; static const uint8_t INCREMENTAL_DISCOVERY_LABEL; static const uint8_t SHUTDOWN_LABAEL; typedef enum { RC_CHECKSUM_ERROR = 1, RC_FRAMING_ERROR = 2, RC_FRAMING_ERROR2 = 3, RC_BAD_STARTCODE = 4, RC_BAD_SUB_STARTCODE = 5, RC_WRONG_PDL = 6, RC_BAD_PDL = 7, RC_PACKET_TOO_SHORT = 8, RC_PACKET_TOO_LONG = 9, RC_PHYSICAL_LENGTH_MISMATCH = 10, RC_PDL_LENGTH_MISMATCH = 11, RC_TRANSACTION_MISMATCH = 12, RC_BAD_RESPONSE_TYPE = 13, RC_GOOD_RESPONSE = 14, RC_ACK_TIMER = 15, RC_ACK_OVERFLOW = 16, RC_TIMED_OUT = 17, RC_IDLE_LEVEL = 18, RC_GOOD_LEVEL = 19, RC_BAD_LEVEL = 20, RC_BROADCAST = 21, RC_VENDORCAST = 22, RC_NACK = 23, RC_NACK_UNKNOWN_PID = 24, RC_NACK_FORMAT_ERROR = 25, RC_NACK_HARDWARE_FAULT = 26, RC_NACK_PROXY_REJECT = 27, RC_NACK_WRITE_PROECT = 28, RC_NACK_COMMAND_CLASS = 29, RC_NACK_DATA_RANGE = 30, RC_NACK_BUFFER_FULL = 31, RC_NACK_PACKET_SIZE = 32, RC_NACK_SUB_DEVICE_RANGE = 33, RC_NACK_PROXY_QUEUE_BUFFER_FULL = 34, RC_DEST_UID_MISMATCH = 40, RC_SRC_UID_MISMATCH = 41, RC_SUBDEVICE_MISMATCH = 42, RC_COMMAND_CLASS_MISMATCH = 43, RC_PARAM_ID_MISMATCH = 44, RC_DATA_RECEIVED_NO_BREAK = 46, } response_code; }; /* * A DMXter Widget. This mostly just wraps the implementation. */ class DmxterWidget: public SerialWidgetInterface, public ola::rdm::DiscoverableRDMControllerInterface { public: DmxterWidget(ola::io::ConnectedDescriptor *descriptor, uint16_t esta_id, uint32_t serial, unsigned int queue_size = 20); ~DmxterWidget(); void Stop() { m_impl->Stop(); } void SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *on_complete) { m_controller->SendRDMRequest(request, on_complete); } void RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { m_controller->RunFullDiscovery(callback); } void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { m_controller->RunIncrementalDiscovery(callback); } ola::io::ConnectedDescriptor *GetDescriptor() const { return m_impl->GetDescriptor(); } private: // we need to control the order of construction & destruction here so these // are pointers. DmxterWidgetImpl *m_impl; ola::rdm::DiscoverableQueueingRDMController *m_controller; }; } // namespace usbpro } // namespace plugin } // namespace ola #endif // PLUGINS_USBPRO_DMXTERWIDGET_H_ ola-0.10.5.nojsmin/plugins/usbpro/ArduinoWidgetTest.cpp0000644000175000017500000004073213023355232022570 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ArduinoWidgetTest.cpp * Test fixture for the ArduinoWidget class * Copyright (C) 2011 Simon Newton */ #include #include #include #include #include #include "common/rdm/TestHelper.h" #include "ola/Callback.h" #include "ola/Logging.h" #include "ola/rdm/RDMCommandSerializer.h" #include "plugins/usbpro/ArduinoWidget.h" #include "plugins/usbpro/CommonWidgetTest.h" #include "ola/testing/TestUtils.h" using ola::io::ByteString; using ola::plugin::usbpro::ArduinoWidget; using ola::rdm::GetResponseFromData; using ola::rdm::RDMCommandSerializer; using ola::rdm::RDMFrame; using ola::rdm::RDMFrames; using ola::rdm::RDMReply; using ola::rdm::RDMRequest; using ola::rdm::RDMResponse; using ola::rdm::UID; using std::auto_ptr; using std::string; using std::vector; class ArduinoWidgetTest: public CommonWidgetTest { CPPUNIT_TEST_SUITE(ArduinoWidgetTest); CPPUNIT_TEST(testDiscovery); CPPUNIT_TEST(testSendRDMRequest); CPPUNIT_TEST(testErrorCodes); CPPUNIT_TEST(testErrorConditions); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void testDiscovery(); void testSendRDMRequest(); void testErrorCodes(); void testErrorConditions(); private: auto_ptr m_arduino; unsigned int m_tod_counter; uint8_t m_transaction_number; void ValidateTod(const ola::rdm::UIDSet &uids); void ValidateResponse(RDMReply *reply); void ValidateStatus(ola::rdm::RDMStatusCode expected_code, RDMFrames expected_frames, RDMReply *reply); RDMRequest *NewRequest(const UID &destination, const uint8_t *data = NULL, unsigned int length = 0); uint8_t *PackRDMRequest(const RDMRequest *request, unsigned int *size); uint8_t *PackRDMResponse(const RDMResponse *response, unsigned int *size); uint8_t *PackRDMError(uint8_t error_code, unsigned int *size); static const uint16_t ESTA_ID = 0x7890; static const uint32_t SERIAL_NUMBER = 0x01020304; static const uint8_t RDM_REQUEST_LABEL = 0x52; static const uint8_t BROADCAST_STATUS_CODE = 1; static const unsigned int FOOTER_SIZE = 1; static const unsigned int HEADER_SIZE = 4; static const UID SOURCE; static const UID DESTINATION; static const UID BCAST_DESTINATION; static const uint8_t TEST_RDM_DATA[]; }; const UID ArduinoWidgetTest::SOURCE(1, 2); const UID ArduinoWidgetTest::DESTINATION(ESTA_ID, SERIAL_NUMBER); const UID ArduinoWidgetTest::BCAST_DESTINATION(ESTA_ID, 0xffffffff); const uint8_t ArduinoWidgetTest::TEST_RDM_DATA[] = {0x5a, 0x5a, 0x5a, 0x5a}; CPPUNIT_TEST_SUITE_REGISTRATION(ArduinoWidgetTest); /** * Setup the descriptors, ss and the MockEndpoint */ void ArduinoWidgetTest::setUp() { CommonWidgetTest::setUp(); m_tod_counter = 0; m_transaction_number = 0; m_arduino.reset(new ola::plugin::usbpro::ArduinoWidget( &m_descriptor, ESTA_ID, SERIAL_NUMBER)); } /** * Called when the widget returns a new TOD. Check this matches what we expect. */ void ArduinoWidgetTest::ValidateTod(const ola::rdm::UIDSet &uids) { UID uid1(ESTA_ID, SERIAL_NUMBER); OLA_ASSERT_EQ((unsigned int) 1, uids.Size()); OLA_ASSERT(uids.Contains(uid1)); m_tod_counter++; } /* * Check the response matches what we expected. */ void ArduinoWidgetTest::ValidateResponse(RDMReply *reply) { OLA_ASSERT_EQ(ola::rdm::RDM_COMPLETED_OK, reply->StatusCode()); OLA_ASSERT(reply->Response()); const ola::rdm::RDMResponse *response = reply->Response(); OLA_ASSERT_EQ( static_cast(sizeof(TEST_RDM_DATA)), response->ParamDataSize()); OLA_ASSERT(0 == memcmp(TEST_RDM_DATA, response->ParamData(), response->ParamDataSize())); OLA_ASSERT_EQ((size_t) 1, reply->Frames().size()); const ola::rdm::RDMFrame frame = reply->Frames()[0]; ola::rdm::RDMStatusCode raw_code; auto_ptr raw_response( ola::rdm::RDMResponse::InflateFromData(frame.data.data() + 1, frame.data.size() - 1, &raw_code)); OLA_ASSERT_TRUE(*raw_response.get() == *response); m_ss.Terminate(); } /* * Check that this request returned the expected status code & frames. */ void ArduinoWidgetTest::ValidateStatus(ola::rdm::RDMStatusCode expected_code, RDMFrames expected_frames, RDMReply *reply) { OLA_ASSERT_EQ(expected_code, reply->StatusCode()); OLA_ASSERT_NULL(reply->Response()); const RDMFrames &frames = reply->Frames(); OLA_ASSERT_EQ(expected_frames.size(), frames.size()); for (unsigned int i = 0; i < frames.size(); i++) { const ByteString &expected = expected_frames[i].data; const ByteString &actual = frames[i].data; OLA_ASSERT_DATA_EQUALS(expected.data(), expected.size(), actual.data(), actual.size()); } m_ss.Terminate(); } /* * Helper method to create new GetRDMRequest objects. * @param destination the destination UID * @param data the RDM Request data * @param length the size of the RDM data. */ RDMRequest *ArduinoWidgetTest::NewRequest(const UID &destination, const uint8_t *data, unsigned int length) { return new ola::rdm::RDMGetRequest( SOURCE, destination, m_transaction_number++, // transaction # 1, // port id 10, // sub device 296, // param id data, length); } /** * Pack a RDM request into a buffer */ uint8_t *ArduinoWidgetTest::PackRDMRequest(const RDMRequest *request, unsigned int *size) { unsigned int request_size = RDMCommandSerializer::RequiredSize(*request); uint8_t rdm_data[request_size + 1]; rdm_data[0] = ola::rdm::RDMCommand::START_CODE; OLA_ASSERT(RDMCommandSerializer::Pack(*request, rdm_data + 1, &request_size)); uint8_t *frame = BuildUsbProMessage(RDM_REQUEST_LABEL, rdm_data, request_size + 1, size); return frame; } /** * Pack a RDM Response into a buffer */ uint8_t *ArduinoWidgetTest::PackRDMResponse(const RDMResponse *response, unsigned int *size) { unsigned int response_size = RDMCommandSerializer::RequiredSize(*response); uint8_t rdm_data[response_size + 2]; rdm_data[0] = ola::rdm::RDM_COMPLETED_OK; rdm_data[1] = ola::rdm::RDMCommand::START_CODE; OLA_ASSERT( RDMCommandSerializer::Pack(*response, rdm_data + 2, &response_size)); uint8_t *frame = BuildUsbProMessage(RDM_REQUEST_LABEL, rdm_data, response_size + 2, size); return frame; } /** * Pack a RDM response which just contains an error code * @param error_code the error status code * @param total_size, pointer which is updated with the message size. */ uint8_t *ArduinoWidgetTest::PackRDMError(uint8_t error_code, unsigned int *size) { uint8_t *frame = BuildUsbProMessage(RDM_REQUEST_LABEL, &error_code, sizeof(error_code), size); return frame; } /** * Check that discovery works. */ void ArduinoWidgetTest::testDiscovery() { OLA_ASSERT_EQ((unsigned int) 0, m_tod_counter); m_arduino->RunFullDiscovery( ola::NewSingleCallback(this, &ArduinoWidgetTest::ValidateTod)); OLA_ASSERT_EQ((unsigned int) 1, m_tod_counter); m_arduino->RunIncrementalDiscovery( ola::NewSingleCallback(this, &ArduinoWidgetTest::ValidateTod)); OLA_ASSERT_EQ((unsigned int) 2, m_tod_counter); } /** * Check that we send RDM messages correctly. */ void ArduinoWidgetTest::testSendRDMRequest() { // request RDMRequest *rdm_request = NewRequest(DESTINATION); unsigned int expected_request_frame_size; uint8_t *expected_request_frame = PackRDMRequest( rdm_request, &expected_request_frame_size); // response auto_ptr response( GetResponseFromData(rdm_request, TEST_RDM_DATA, sizeof(TEST_RDM_DATA))); unsigned int response_size; uint8_t *response_frame = PackRDMResponse(response.get(), &response_size); // add the expected response, send and verify m_endpoint->AddExpectedDataAndReturn( expected_request_frame, expected_request_frame_size, response_frame, response_size); m_arduino->SendRDMRequest( rdm_request, ola::NewSingleCallback(this, &ArduinoWidgetTest::ValidateResponse)); m_ss.Run(); m_endpoint->Verify(); // now check broadcast messages // request rdm_request = NewRequest(BCAST_DESTINATION); uint8_t *expected_bcast_request_frame = PackRDMRequest( rdm_request, &expected_request_frame_size); // must match ArduinoWidgetImpl::RESPONSE_WAS_BROADCAST uint8_t *broadcast_response_frame = PackRDMError( BROADCAST_STATUS_CODE, &response_size); // add the expected response, send and verify m_endpoint->AddExpectedDataAndReturn( expected_bcast_request_frame, expected_request_frame_size, broadcast_response_frame, response_size); RDMFrames frames; m_arduino->SendRDMRequest( rdm_request, ola::NewSingleCallback(this, &ArduinoWidgetTest::ValidateStatus, ola::rdm::RDM_WAS_BROADCAST, frames)); m_ss.Run(); m_endpoint->Verify(); // cleanup time delete[] expected_request_frame; delete[] expected_bcast_request_frame; delete[] response_frame; delete[] broadcast_response_frame; } /* * Check that we handle invalid responses ok */ void ArduinoWidgetTest::testErrorCodes() { RDMFrames frames; // request RDMRequest *rdm_request = NewRequest(DESTINATION); unsigned int expected_request_frame_size; uint8_t *expected_request_frame = PackRDMRequest( rdm_request, &expected_request_frame_size); // response auto_ptr response(GetResponseFromData(rdm_request)); unsigned int response_size; uint8_t *response_frame = PackRDMResponse(response.get(), &response_size); // verify a checksum error is detected // twiddle the penultimate bit so that the checksum fails response_frame[response_size - 2] += 1; frames.push_back(RDMFrame(response_frame + 5, RDMCommandSerializer::RequiredSize(*response) + 1)); // add the expected response, send and verify m_endpoint->AddExpectedDataAndReturn( expected_request_frame, expected_request_frame_size, response_frame, response_size); m_arduino->SendRDMRequest( rdm_request, ola::NewSingleCallback(this, &ArduinoWidgetTest::ValidateStatus, ola::rdm::RDM_CHECKSUM_INCORRECT, frames)); m_ss.Run(); m_endpoint->Verify(); frames.clear(); delete[] expected_request_frame; delete[] response_frame; // now try a packet which is too short rdm_request = NewRequest(DESTINATION); expected_request_frame = PackRDMRequest( rdm_request, &expected_request_frame_size); // we truncate the response here response.reset(GetResponseFromData(rdm_request)); response_size = RDMCommandSerializer::RequiredSize(*response); uint8_t rdm_data[response_size + 2]; rdm_data[0] = ola::rdm::RDM_COMPLETED_OK; rdm_data[1] = ola::rdm::RDMCommand::START_CODE; OLA_ASSERT( RDMCommandSerializer::Pack(*response, rdm_data + 2, &response_size)); response_frame = BuildUsbProMessage( RDM_REQUEST_LABEL, rdm_data, 10, // only send 10 bytes of the response &response_size); // only return the first 10 bytes of the rdm response frames.push_back(RDMFrame(response_frame + 5, 9)); m_endpoint->AddExpectedDataAndReturn( expected_request_frame, expected_request_frame_size, response_frame, response_size); m_arduino->SendRDMRequest( rdm_request, ola::NewSingleCallback(this, &ArduinoWidgetTest::ValidateStatus, ola::rdm::RDM_PACKET_TOO_SHORT, frames)); m_ss.Run(); m_endpoint->Verify(); frames.clear(); delete[] expected_request_frame; delete[] response_frame; // now test a transaction # mismatch rdm_request = NewRequest(DESTINATION); expected_request_frame = PackRDMRequest( rdm_request, &expected_request_frame_size); response.reset(GetResponseFromData(rdm_request)); response_size = RDMCommandSerializer::RequiredSize(*response); OLA_ASSERT( RDMCommandSerializer::Pack(*response, rdm_data + 2, &response_size)); // twiddle the transaction number rdm_data[16] += 1; // 'correct' the checksum rdm_data[response_size + 2 - 1] += 1; frames.push_back(RDMFrame(rdm_data + 1, response_size + 1)); response_frame = BuildUsbProMessage( RDM_REQUEST_LABEL, rdm_data, response_size + 2, &response_size); m_endpoint->AddExpectedDataAndReturn( expected_request_frame, expected_request_frame_size, response_frame, response_size); m_arduino->SendRDMRequest( rdm_request, ola::NewSingleCallback(this, &ArduinoWidgetTest::ValidateStatus, ola::rdm::RDM_TRANSACTION_MISMATCH, frames)); m_ss.Run(); m_endpoint->Verify(); frames.clear(); delete[] expected_request_frame; delete[] response_frame; // sub device mismatch rdm_request = NewRequest(DESTINATION); expected_request_frame = PackRDMRequest( rdm_request, &expected_request_frame_size); response.reset(GetResponseFromData(rdm_request)); response_size = RDMCommandSerializer::RequiredSize(*response); // change the sub device rdm_data[20] += 1; // 'correct' the checksum rdm_data[response_size + 2 - 1] += 1; frames.push_back(RDMFrame(rdm_data + 1, response_size + 1)); response_frame = BuildUsbProMessage( RDM_REQUEST_LABEL, rdm_data, response_size + 2, &response_size); m_endpoint->AddExpectedDataAndReturn( expected_request_frame, expected_request_frame_size, response_frame, response_size); m_arduino->SendRDMRequest( rdm_request, ola::NewSingleCallback(this, &ArduinoWidgetTest::ValidateStatus, ola::rdm::RDM_SUB_DEVICE_MISMATCH, frames)); m_ss.Run(); m_endpoint->Verify(); frames.clear(); delete[] expected_request_frame; delete[] response_frame; } /* * Check some of the error conditions */ void ArduinoWidgetTest::testErrorConditions() { RDMFrames frames; uint8_t ERROR_CODES[] = {2, 3, 4, 5}; // test each of the error codes. for (unsigned int i = 0; i < sizeof(ERROR_CODES); ++i) { // request RDMRequest *request = NewRequest(DESTINATION); unsigned int expected_request_frame_size; uint8_t *expected_request_frame = PackRDMRequest( request, &expected_request_frame_size); // expected response unsigned int response_size; uint8_t *response_frame = PackRDMError( ERROR_CODES[i], &response_size); m_endpoint->AddExpectedDataAndReturn( expected_request_frame, expected_request_frame_size, response_frame, response_size); m_arduino->SendRDMRequest( request, ola::NewSingleCallback(this, &ArduinoWidgetTest::ValidateStatus, ola::rdm::RDM_FAILED_TO_SEND, frames)); m_ss.Run(); m_endpoint->Verify(); delete[] expected_request_frame; delete[] response_frame; } } ola-0.10.5.nojsmin/plugins/usbpro/ArduinoRGBDevice.h0000644000175000017500000000571313023355232021704 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ArduinoRGBDevice.h * The Arduino RGB Mixer device. * Copyright (C) 2010 Simon Newton */ #ifndef PLUGINS_USBPRO_ARDUINORGBDEVICE_H_ #define PLUGINS_USBPRO_ARDUINORGBDEVICE_H_ #include #include "ola/DmxBuffer.h" #include "olad/TokenBucket.h" #include "plugins/usbpro/ArduinoWidget.h" #include "plugins/usbpro/UsbSerialDevice.h" namespace ola { namespace plugin { namespace usbpro { /* * An Arduino RGB Mixer Device */ class ArduinoRGBDevice: public UsbSerialDevice { public: ArduinoRGBDevice(ola::io::SelectServerInterface *ss, ola::AbstractPlugin *owner, const std::string &name, ArduinoWidget *widget, uint16_t esta_id, uint16_t device_id, uint32_t serial); std::string DeviceId() const { return m_device_id; } private: std::string m_device_id; }; /* * A single Output port per device */ class ArduinoRGBOutputPort: public BasicOutputPort { public: ArduinoRGBOutputPort(ArduinoRGBDevice *parent, ArduinoWidget *widget, uint32_t serial, const TimeStamp *wake_time, unsigned int initial_count, unsigned int rate); std::string Description() const { return m_description; } bool WriteDMX(const DmxBuffer &buffer, uint8_t) { if (m_bucket.GetToken(*m_wake_time)) return m_widget->SendDMX(buffer); else OLA_INFO << "Port rated limited, dropping frame"; return true; } void SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *callback) { return m_widget->SendRDMRequest(request, callback); } void RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { m_widget->RunFullDiscovery(callback); } void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { m_widget->RunIncrementalDiscovery(callback); } private: ArduinoWidget *m_widget; TokenBucket m_bucket; const TimeStamp *m_wake_time; std::string m_description; }; } // namespace usbpro } // namespace plugin } // namespace ola #endif // PLUGINS_USBPRO_ARDUINORGBDEVICE_H_ ola-0.10.5.nojsmin/plugins/usbpro/UltraDMXProDevice.cpp0000644000175000017500000001760513023355232022427 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * UltraDMXProDevice.cpp * A DMX King Ultra DMX Pro Device * Copyright (C) 2011 Simon Newton * * This device creates 3 ports, 1 input and 2 output. */ #include #include #include #include "common/rpc/RpcController.h" #include "ola/Callback.h" #include "ola/Constants.h" #include "ola/Logging.h" #include "plugins/usbpro/UltraDMXProDevice.h" #include "plugins/usbpro/UsbProWidgetDetector.h" namespace ola { namespace plugin { namespace usbpro { using ola::plugin::usbpro::Request; using ola::plugin::usbpro::Reply; using ola::rpc::RpcController; using std::string; /* * Create a new device * @param owner the plugin that owns this device * @param name the device name * @param dev_path path to the pro widget */ UltraDMXProDevice::UltraDMXProDevice(ola::PluginAdaptor *plugin_adaptor, ola::AbstractPlugin *owner, const string &name, UltraDMXProWidget *widget, OLA_UNUSED uint16_t esta_id, OLA_UNUSED uint16_t device_id, uint32_t serial, uint16_t firmware_version, unsigned int fps_limit): UsbSerialDevice(owner, name, widget), m_ultra_widget(widget), m_serial(), m_got_parameters(false), m_break_time(0), m_mab_time(0), m_rate(0) { std::ostringstream str; str << std::setfill('0'); uint8_t *ptr = reinterpret_cast(&serial); for (int i = UsbProWidgetInformation::SERIAL_LENGTH - 1; i >= 0; i--) { int digit = (10 * (ptr[i] & 0xf0) >> 4) + (ptr[i] & 0x0f); str << std::setw(2) << digit; } m_serial = str.str(); str.str(""); str << "Serial #: " << m_serial << ", firmware " << (firmware_version >> 8) << "." << (firmware_version & 0xff); m_ultra_widget->GetParameters(NewSingleCallback( this, &UltraDMXProDevice::UpdateParams)); UltraDMXProInputPort *input_port = new UltraDMXProInputPort( this, m_ultra_widget, 0, plugin_adaptor, str.str()); m_ultra_widget->SetDMXCallback( NewCallback( static_cast(input_port), &InputPort::DmxChanged)); AddPort(input_port); // add the primary port OutputPort *output_port = new UltraDMXProOutputPort( this, m_ultra_widget, 0, str.str(), plugin_adaptor->WakeUpTime(), 5, // allow up to 5 burst frames fps_limit, true); AddPort(output_port); // add the secondary port output_port = new UltraDMXProOutputPort( this, m_ultra_widget, 1, str.str(), plugin_adaptor->WakeUpTime(), 5, // allow up to 5 burst frames fps_limit, false); AddPort(output_port); } /* * Stop this device */ void UltraDMXProDevice::PrePortStop() { m_ultra_widget->Stop(); } /* * Handle device config messages * @param controller An RpcController * @param request the request data * @param response the response to return * @param done the closure to call once the request is complete */ void UltraDMXProDevice::Configure(RpcController *controller, const string &request, string *response, ConfigureCallback *done) { Request request_pb; if (!request_pb.ParseFromString(request)) { controller->SetFailed("Invalid Request"); done->Run(); return; } switch (request_pb.type()) { case ola::plugin::usbpro::Request::USBPRO_PARAMETER_REQUEST: HandleParametersRequest(controller, &request_pb, response, done); break; case ola::plugin::usbpro::Request::USBPRO_SERIAL_REQUEST: HandleSerialRequest(controller, &request_pb, response, done); break; default: controller->SetFailed("Invalid Request"); done->Run(); } } /** * Update the cached param values */ void UltraDMXProDevice::UpdateParams(bool status, const usb_pro_parameters ¶ms) { if (status) { m_got_parameters = true; m_break_time = params.break_time; m_mab_time = params.mab_time; m_rate = params.rate; } } /* * Handle a parameter request. This may set some parameters in the widget. * If no parameters are set we simply fetch the parameters and return them to * the client. If we are setting parameters, we send a SetParam() request and * then another GetParam() request in order to return the latest values to the * client. */ void UltraDMXProDevice::HandleParametersRequest(RpcController *controller, const Request *request, string *response, ConfigureCallback *done) { if (request->has_parameters() && (request->parameters().has_break_time() || request->parameters().has_mab_time() || request->parameters().has_rate())) { if (!m_got_parameters) { controller->SetFailed("SetParameters failed, startup not complete"); done->Run(); return; } bool ret = m_ultra_widget->SetParameters( request->parameters().has_break_time() ? request->parameters().break_time() : m_break_time, request->parameters().has_mab_time() ? request->parameters().mab_time() : m_mab_time, request->parameters().has_rate() ? request->parameters().rate() : m_rate); if (!ret) { controller->SetFailed("SetParameters failed"); done->Run(); return; } } m_ultra_widget->GetParameters(NewSingleCallback( this, &UltraDMXProDevice::HandleParametersResponse, controller, response, done)); } /** * Handle the GetParameters response */ void UltraDMXProDevice::HandleParametersResponse( RpcController *controller, string *response, ConfigureCallback *done, bool status, const usb_pro_parameters ¶ms) { if (!status) { controller->SetFailed("GetParameters failed"); } else { UpdateParams(true, params); Reply reply; reply.set_type(ola::plugin::usbpro::Reply::USBPRO_PARAMETER_REPLY); ola::plugin::usbpro::ParameterReply *parameters_reply = reply.mutable_parameters(); parameters_reply->set_firmware_high(params.firmware_high); parameters_reply->set_firmware(params.firmware); parameters_reply->set_break_time(params.break_time); parameters_reply->set_mab_time(params.mab_time); parameters_reply->set_rate(params.rate); reply.SerializeToString(response); } done->Run(); } /* * Handle a Serial number Configure RPC. We can just return the cached number. */ void UltraDMXProDevice::HandleSerialRequest( RpcController *controller, const Request *request, string *response, ConfigureCallback *done) { Reply reply; reply.set_type(ola::plugin::usbpro::Reply::USBPRO_SERIAL_REPLY); ola::plugin::usbpro::SerialNumberReply *serial_reply = reply.mutable_serial_number(); serial_reply->set_serial(m_serial); reply.SerializeToString(response); done->Run(); (void) controller; (void) request; } } // namespace usbpro } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbpro/UltraDMXProWidget.cpp0000644000175000017500000000355313023355232022450 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * UltraDMXProWidget.cpp * The DMXKing Ultra DMX Pro Widget. * Copyright (C) 2011 Simon Newton */ #include "ola/Constants.h" #include "plugins/usbpro/UltraDMXProWidget.h" namespace ola { namespace plugin { namespace usbpro { /** * UltraDMXProWidget Constructor */ UltraDMXProWidget::UltraDMXProWidget( ola::io::ConnectedDescriptor *descriptor) : GenericUsbProWidget(descriptor) { } bool UltraDMXProWidget::SendDMX(const DmxBuffer &buffer) { return SendDMXWithLabel(DMX_PRIMARY_PORT, buffer); } bool UltraDMXProWidget::SendSecondaryDMX(const DmxBuffer &buffer) { return SendDMXWithLabel(DMX_SECONDARY_PORT, buffer); } bool UltraDMXProWidget::SendDMXWithLabel(uint8_t label, const DmxBuffer &data) { struct { uint8_t start_code; uint8_t dmx[DMX_UNIVERSE_SIZE]; } widget_dmx; widget_dmx.start_code = DMX512_START_CODE; unsigned int length = DMX_UNIVERSE_SIZE; data.Get(widget_dmx.dmx, &length); return SendMessage(label, reinterpret_cast(&widget_dmx), length + 1); } } // namespace usbpro } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbpro/RobeWidgetDetectorTest.cpp0000644000175000017500000001735113023355232023551 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RobeWidgetDetectorTest.cpp * Test fixture for the RobeWidgetDetector class * Copyright (C) 2011 Simon Newton */ #include #include #include "ola/testing/TestUtils.h" #include "ola/Callback.h" #include "ola/Logging.h" #include "ola/rdm/UID.h" #include "ola/network/NetworkUtils.h" #include "plugins/usbpro/CommonWidgetTest.h" #include "plugins/usbpro/RobeWidget.h" #include "plugins/usbpro/RobeWidgetDetector.h" using ola::io::ConnectedDescriptor; using ola::plugin::usbpro::RobeWidget; using ola::plugin::usbpro::RobeWidgetDetector; using ola::plugin::usbpro::RobeWidgetInformation; using ola::rdm::UID; using std::auto_ptr; class RobeWidgetDetectorTest: public CommonWidgetTest { CPPUNIT_TEST_SUITE(RobeWidgetDetectorTest); CPPUNIT_TEST(testRUIDevice); CPPUNIT_TEST(testLockedRUIDevice); CPPUNIT_TEST(testOldWTXDevice); CPPUNIT_TEST(testWTXDevice); CPPUNIT_TEST(testUnknownDevice); CPPUNIT_TEST(testTimeout); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void testRUIDevice(); void testLockedRUIDevice(); void testOldWTXDevice(); void testWTXDevice(); void testUnknownDevice(); void testTimeout(); private: auto_ptr m_detector; RobeWidgetInformation m_device_info; bool m_found_widget; bool m_failed_widget; void NewWidget(ConnectedDescriptor *descriptor, const RobeWidgetInformation *info); void FailedWidget(ConnectedDescriptor *descriptor); void Timeout() { m_ss.Terminate(); } static const uint8_t INFO_REQUEST_LABEL = 0x14; static const uint8_t INFO_RESPONSE_LABEL = 0x15; static const uint8_t UID_REQUEST_LABEL = 0x24; static const uint8_t UID_RESPONSE_LABEL = 0x25; }; CPPUNIT_TEST_SUITE_REGISTRATION(RobeWidgetDetectorTest); void RobeWidgetDetectorTest::setUp() { CommonWidgetTest::setUp(); m_found_widget = false; m_failed_widget = false; m_detector.reset(new RobeWidgetDetector( &m_ss, ola::NewCallback(this, &RobeWidgetDetectorTest::NewWidget), ola::NewCallback(this, &RobeWidgetDetectorTest::FailedWidget), 10)); m_ss.RegisterSingleTimeout( 4000, // This should only take 40ms, but on slow platforms takes longer ola::NewSingleCallback(this, &RobeWidgetDetectorTest::Timeout)); } void RobeWidgetDetectorTest::NewWidget(ConnectedDescriptor *descriptor, const RobeWidgetInformation *info) { OLA_ASSERT_EQ( static_cast(&m_descriptor), descriptor); m_found_widget = true; m_device_info = *info; m_ss.Terminate(); delete info; } void RobeWidgetDetectorTest::FailedWidget(ConnectedDescriptor *descriptor) { OLA_ASSERT_EQ( static_cast(&m_descriptor), descriptor); m_failed_widget = true; m_ss.Terminate(); } /* * Check that discovery works with a RUI device. */ void RobeWidgetDetectorTest::testRUIDevice() { // software version unlocked (>= 0x14) uint8_t info_data[] = {1, 0x14, 3, 0, 0}; uint8_t uid_data[] = {0x52, 0x53, 1, 0, 0, 10}; m_endpoint->AddExpectedRobeDataAndReturn( INFO_REQUEST_LABEL, NULL, 0, INFO_RESPONSE_LABEL, info_data, sizeof(info_data)); m_endpoint->AddExpectedRobeDataAndReturn( UID_REQUEST_LABEL, NULL, 0, UID_RESPONSE_LABEL, uid_data, sizeof(uid_data)); m_detector->Discover(&m_descriptor); m_ss.Run(); OLA_ASSERT(m_found_widget); OLA_ASSERT_FALSE(m_failed_widget); OLA_ASSERT_EQ(static_cast(1), m_device_info.hardware_version); OLA_ASSERT_EQ(static_cast(20), m_device_info.software_version); OLA_ASSERT_EQ(static_cast(3), m_device_info.eeprom_version); OLA_ASSERT_EQ(UID(0x5253, 0x100000a), m_device_info.uid); } /* * Check that discovery fails with a locked RUI device. */ void RobeWidgetDetectorTest::testLockedRUIDevice() { // software version locked (0xe) uint8_t info_data[] = {1, 0xe, 3, 0, 0}; uint8_t uid_data[] = {0x52, 0x53, 1, 0, 0, 10}; m_endpoint->AddExpectedRobeDataAndReturn( INFO_REQUEST_LABEL, NULL, 0, INFO_RESPONSE_LABEL, info_data, sizeof(info_data)); m_endpoint->AddExpectedRobeDataAndReturn( UID_REQUEST_LABEL, NULL, 0, UID_RESPONSE_LABEL, uid_data, sizeof(uid_data)); m_detector->Discover(&m_descriptor); m_ss.Run(); OLA_ASSERT_FALSE(m_found_widget); OLA_ASSERT(m_failed_widget); } /* * Check that discovery fails with an old WTX device. */ void RobeWidgetDetectorTest::testOldWTXDevice() { uint8_t info_data[] = {1, 2, 3, 0, 0}; uint8_t uid_data[] = {0x52, 0x53, 2, 0, 0, 10}; m_endpoint->AddExpectedRobeDataAndReturn( INFO_REQUEST_LABEL, NULL, 0, INFO_RESPONSE_LABEL, info_data, sizeof(info_data)); m_endpoint->AddExpectedRobeDataAndReturn( UID_REQUEST_LABEL, NULL, 0, UID_RESPONSE_LABEL, uid_data, sizeof(uid_data)); m_detector->Discover(&m_descriptor); m_ss.Run(); OLA_ASSERT_FALSE(m_found_widget); OLA_ASSERT(m_failed_widget); } /* * Check that discovery works with a WTX device. */ void RobeWidgetDetectorTest::testWTXDevice() { uint8_t info_data[] = {1, 11, 3, 0, 0}; uint8_t uid_data[] = {0x52, 0x53, 2, 0, 0, 10}; m_endpoint->AddExpectedRobeDataAndReturn( INFO_REQUEST_LABEL, NULL, 0, INFO_RESPONSE_LABEL, info_data, sizeof(info_data)); m_endpoint->AddExpectedRobeDataAndReturn( UID_REQUEST_LABEL, NULL, 0, UID_RESPONSE_LABEL, uid_data, sizeof(uid_data)); m_detector->Discover(&m_descriptor); m_ss.Run(); OLA_ASSERT(m_found_widget); OLA_ASSERT_FALSE(m_failed_widget); OLA_ASSERT_EQ(static_cast(1), m_device_info.hardware_version); OLA_ASSERT_EQ(static_cast(11), m_device_info.software_version); OLA_ASSERT_EQ(static_cast(3), m_device_info.eeprom_version); OLA_ASSERT_EQ(UID(0x5253, 0x200000a), m_device_info.uid); } /* * Check that discovery fails for an unknown device. */ void RobeWidgetDetectorTest::testUnknownDevice() { uint8_t info_data[] = {1, 2, 3, 0, 0}; uint8_t uid_data[] = {0x52, 0x53, 3, 0, 0, 10}; m_endpoint->AddExpectedRobeDataAndReturn( INFO_REQUEST_LABEL, NULL, 0, INFO_RESPONSE_LABEL, info_data, sizeof(info_data)); m_endpoint->AddExpectedRobeDataAndReturn( UID_REQUEST_LABEL, NULL, 0, UID_RESPONSE_LABEL, uid_data, sizeof(uid_data)); m_detector->Discover(&m_descriptor); m_ss.Run(); OLA_ASSERT_FALSE(m_found_widget); OLA_ASSERT(m_failed_widget); } /** * Check a widget that fails to respond */ void RobeWidgetDetectorTest::testTimeout() { m_endpoint->AddExpectedRobeMessage(INFO_REQUEST_LABEL, NULL, 0); m_detector->Discover(&m_descriptor); m_ss.Run(); OLA_ASSERT_FALSE(m_found_widget); OLA_ASSERT(m_failed_widget); } ola-0.10.5.nojsmin/plugins/usbpro/DmxTriWidget.h0000644000175000017500000002130113023355232021172 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DmxTriWidget.h * The Jese DMX-TRI/RDM-TRI widget. * Copyright (C) 2010 Simon Newton */ #ifndef PLUGINS_USBPRO_DMXTRIWIDGET_H_ #define PLUGINS_USBPRO_DMXTRIWIDGET_H_ #include #include #include #include "ola/Callback.h" #include "ola/DmxBuffer.h" #include "ola/rdm/QueueingRDMController.h" #include "ola/rdm/RDMControllerInterface.h" #include "ola/rdm/UIDSet.h" #include "ola/thread/SchedulerInterface.h" #include "plugins/usbpro/BaseUsbProWidget.h" namespace ola { namespace plugin { namespace usbpro { /* * A DMX TRI Widget implementation. We separate the Widget from the * implementation so we can leverage the QueueingRDMController. */ class DmxTriWidgetImpl: public BaseUsbProWidget, public ola::rdm::DiscoverableRDMControllerInterface { public: DmxTriWidgetImpl(ola::thread::SchedulerInterface *executor, ola::io::ConnectedDescriptor *descriptor, bool use_raw_rdm); ~DmxTriWidgetImpl(); void UseRawRDM(bool use_raw_rdm) { m_use_raw_rdm = use_raw_rdm; } void Stop(); bool SendDMX(const DmxBuffer &buffer); void SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *on_complete); void RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback); void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback); private: typedef enum { SINGLE_TX_COMMAND_ID = 0x21, DISCOVER_AUTO_COMMAND_ID = 0x33, DISCOVER_STATUS_COMMAND_ID = 0x34, REMOTE_UID_COMMAND_ID = 0x35, RAW_RDM_COMMAND_ID = 0x37, REMOTE_GET_COMMAND_ID = 0x38, REMOTE_SET_COMMAND_ID = 0x39, QUEUED_GET_COMMAND_ID = 0x3a, SET_FILTER_COMMAND_ID = 0x3d, RESERVED_COMMAND_ID = 0xff, } TriCommandId; typedef enum { NO_DISCOVERY_ACTION, DISCOVER_AUTO_REQUIRED, DISCOVER_STATUS_REQUIRED, FETCH_UID_REQUIRED, } TriDiscoveryState; typedef std::map UIDToIndexMap; ola::thread::SchedulerInterface *m_scheduler; UIDToIndexMap m_uid_index_map; uint8_t m_uid_count; uint16_t m_last_esta_id; bool m_use_raw_rdm; // State for sending DMX DmxBuffer m_outgoing_dmx; // State for handling RDM discovery ola::thread::timeout_id m_disc_stat_timeout_id; ola::rdm::RDMDiscoveryCallback *m_discovery_callback; TriDiscoveryState m_discovery_state; // State for sending RDM Gets/Sets // This holds pointers to the RDMRequest and Callback that is queued or in // flight. ola::rdm::RDMCallback *m_rdm_request_callback; std::auto_ptr m_pending_rdm_request; uint8_t m_transaction_number; // The command id that we expect to see in the response. uint8_t m_last_command, m_expected_command; void SendDMXBuffer(); void SendQueuedRDMCommand(); void RunDiscoveryCallback(ola::rdm::RDMDiscoveryCallback *callback); bool CheckDiscoveryStatus(); void HandleMessage(uint8_t label, const uint8_t *data, unsigned int length); void SendDiscoveryAuto(); void SendDiscoveryStat(); void FetchNextUID(); void SendRawRDMRequest(); void DispatchRequest(); void DispatchQueuedGet(); void StopDiscovery(); void HandleSingleTXResponse(uint8_t return_code); void HandleDiscoveryAutoResponse(uint8_t return_code, const uint8_t *data, unsigned int length); void HandleDiscoverStatResponse(uint8_t return_code, const uint8_t *data, unsigned int length); void HandleRemoteUIDResponse(uint8_t return_code, const uint8_t *data, unsigned int length); void HandleRawRDMResponse(uint8_t return_code, const uint8_t *data, unsigned int length); void HandleRemoteRDMResponse(uint8_t return_code, const uint8_t *data, unsigned int length); void HandleQueuedGetResponse(uint8_t return_code, const uint8_t *data, unsigned int length); void HandleGenericRDMResponse(uint8_t return_code, uint16_t pid, const uint8_t *data, unsigned int length); void HandleSetFilterResponse(uint8_t return_code, const uint8_t *data, unsigned int length); bool PendingTransaction() const; void MaybeSendNextRequest(); void HandleRDMError(ola::rdm::RDMStatusCode error_code); bool SendCommandToTRI(uint8_t label, const uint8_t *data, unsigned int length); bool TriToOlaReturnCode(uint8_t return_code, ola::rdm::RDMStatusCode *code); bool ReturnCodeToNackReason(uint8_t return_code, ola::rdm::rdm_nack_reason *reason); typedef enum { EC_NO_ERROR = 0, EC_CONSTRAINT = 1, EC_UNKNOWN_COMMAND = 2, EC_INVALID_OPTION = 3, EC_FRAME_FORMAT = 4, EC_DATA_TOO_LONG = 5, EC_DATA_MISSING = 6, EC_SYSTEM_MODE = 7, EC_SYSTEM_BUSY = 8, EC_DATA_CHECKSUM = 0x0a, EC_INCOMPATIBLE = 0x0b, EC_RESPONSE_TIME = 0x10, EC_RESPONSE_WAIT = 0x11, EC_RESPONSE_MORE = 0x12, EC_RESPONSE_TRANSACTION = 0x13, EC_RESPONSE_SUB_DEVICE = 0x14, EC_RESPONSE_FORMAT = 0x15, EC_RESPONSE_CHECKSUM = 0x16, EC_RESPONSE_NONE = 0x18, EC_RESPONSE_IDENTITY = 0x1a, EC_RESPONSE_MUTE = 0x1b, EC_RESPONSE_DISCOVERY = 0x1c, EC_RESPONSE_UNEXPECTED = 0x1d, EC_UNKNOWN_PID = 0x20, EC_FORMAT_ERROR = 0x21, EC_HARDWARE_FAULT = 0x22, EC_PROXY_REJECT = 0x23, EC_WRITE_PROTECT = 0x24, EC_UNSUPPORTED_COMMAND_CLASS = 0x25, EC_OUT_OF_RANGE = 0x26, EC_BUFFER_FULL = 0x27, EC_FRAME_OVERFLOW = 0x28, EC_SUBDEVICE_UNKNOWN = 0x29, EC_PROXY_BUFFER_FULL = 0x2a, // this isn't included in the docs } dmx_tri_error_codes; static const unsigned int DATA_OFFSET = 2; // first two bytes are CI & RC static const uint8_t EXTENDED_COMMAND_LABEL = 88; // 'X' // The ms delay between checking on the RDM discovery process static const unsigned int RDM_STATUS_INTERVAL_MS = 100; }; /* * A DMX TRI Widget */ class DmxTriWidget: public SerialWidgetInterface, public ola::rdm::DiscoverableRDMControllerInterface { public: DmxTriWidget(ola::thread::SchedulerInterface *ss, ola::io::ConnectedDescriptor *descriptor, unsigned int queue_size = 20, bool use_raw_rdm = false); ~DmxTriWidget(); void UseRawRDM(bool use_raw_rdm) { m_impl->UseRawRDM(use_raw_rdm); } void Stop() { m_impl->Stop(); } bool SendDMX(const DmxBuffer &buffer) const { return m_impl->SendDMX(buffer); } void SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *on_complete) { m_controller->SendRDMRequest(request, on_complete); } void RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { m_controller->RunFullDiscovery(callback); } void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { m_controller->RunIncrementalDiscovery(callback); } ola::io::ConnectedDescriptor *GetDescriptor() const { return m_impl->GetDescriptor(); } private: // we need to control the order of construction & destruction here so these // are pointers. DmxTriWidgetImpl *m_impl; ola::rdm::DiscoverableQueueingRDMController *m_controller; void ResumeRDMCommands() { m_controller->Resume(); } }; } // namespace usbpro } // namespace plugin } // namespace ola #endif // PLUGINS_USBPRO_DMXTRIWIDGET_H_ ola-0.10.5.nojsmin/plugins/usbpro/GenericUsbProWidget.cpp0000644000175000017500000001703613023355232023037 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * GenericUsbProWidget.cpp * This class implements a generic Usb Pro style widget, which can send and * receive DMX as well and get/set widget parameters. * Copyright (C) 2011 Simon Newton */ #include #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/strings/Format.h" #include "plugins/usbpro/BaseUsbProWidget.h" #include "plugins/usbpro/GenericUsbProWidget.h" namespace ola { namespace plugin { namespace usbpro { /* * New Generic Usb Pro Device. * This also works for the RDM Pro with the standard firmware loaded. */ GenericUsbProWidget::GenericUsbProWidget( ola::io::ConnectedDescriptor *descriptor) : BaseUsbProWidget(descriptor), m_active(true), m_dmx_callback(NULL) { } /* * Shutdown */ GenericUsbProWidget::~GenericUsbProWidget() { GenericStop(); } /** * Set the callback to run when new DMX data arrives */ void GenericUsbProWidget::SetDMXCallback(ola::Callback0 *callback) { if (m_dmx_callback) { delete m_dmx_callback; } m_dmx_callback = callback; } /** * Stop the rdm discovery process if it's running */ void GenericUsbProWidget::GenericStop() { m_active = false; if (m_dmx_callback) { delete m_dmx_callback; m_dmx_callback = NULL; } // empty params struct usb_pro_parameters params; while (!m_outstanding_param_callbacks.empty()) { usb_pro_params_callback *callback = m_outstanding_param_callbacks.front(); m_outstanding_param_callbacks.pop_front(); callback->Run(false, params); } } /* * Send a DMX message * @returns true if we sent ok, false otherwise */ bool GenericUsbProWidget::SendDMX(const DmxBuffer &buffer) { if (!m_active) { return false; } return BaseUsbProWidget::SendDMX(buffer); } /* * Put the device back into recv mode * @return true on success, false on failure */ bool GenericUsbProWidget::ChangeToReceiveMode(bool change_only) { if (!m_active) { return false; } uint8_t mode = change_only; bool status = SendMessage(DMX_RX_MODE_LABEL, &mode, sizeof(mode)); if (status && change_only) { m_input_buffer.Blackout(); } return status; } /** * Return the latest DMX data */ const DmxBuffer &GenericUsbProWidget::FetchDMX() const { return m_input_buffer; } /** * Send a request for the widget's parameters. * TODO(simon): add timers to these */ void GenericUsbProWidget::GetParameters(usb_pro_params_callback *callback) { m_outstanding_param_callbacks.push_back(callback); uint16_t user_size = 0; bool r = SendMessage(PARAMETERS_LABEL, reinterpret_cast(&user_size), sizeof(user_size)); if (!r) { // failed m_outstanding_param_callbacks.pop_back(); usb_pro_parameters params = {0, 0, 0, 0, 0}; callback->Run(false, params); } } /** * Set the widget's parameters. Due to the lack of confirmation, this returns * immediately. */ bool GenericUsbProWidget::SetParameters(uint8_t break_time, uint8_t mab_time, uint8_t rate) { PACK( struct widget_params_s { uint16_t length; uint8_t break_time; uint8_t mab_time; uint8_t rate; }); widget_params_s widget_parameters = { 0, break_time, mab_time, rate}; bool ret = SendMessage( SET_PARAMETERS_LABEL, reinterpret_cast(&widget_parameters), sizeof(widget_parameters)); if (!ret) { OLA_WARN << "Failed to send a set params message"; } return ret; } /* * Handle a message received from the widget */ void GenericUsbProWidget::HandleMessage(uint8_t label, const uint8_t *data, unsigned int length) { switch (label) { case REPROGRAM_FIRMWARE_LABEL: break; case PARAMETERS_LABEL: HandleParameters(data, length); break; case RECEIVED_DMX_LABEL: HandleDMX(data, length); break; case DMX_CHANGED_LABEL: HandleDMXDiff(data, length); break; case BaseUsbProWidget::SERIAL_LABEL: break; default: OLA_WARN << "Unknown message type " << ola::strings::ToHex(label) << ", length " << length; } } /* * Handle the dmx frame */ void GenericUsbProWidget::HandleDMX(const uint8_t *data, unsigned int length) { typedef struct { uint8_t status; uint8_t dmx[DMX_UNIVERSE_SIZE + 1]; } widget_dmx; if (length < 2) { return; } const widget_dmx *widget_reply = reinterpret_cast(data); if (widget_reply->status) { OLA_WARN << "UsbPro got corrupted packet, status: " << static_cast(widget_reply->status); return; } // only handle start code = 0 if (length > 2 && widget_reply->dmx[0] == 0) { m_input_buffer.Set(widget_reply->dmx + 1, length - 2); if (m_dmx_callback) { m_dmx_callback->Run(); } } return; } /* * Called when we get new parameters from the widget. */ void GenericUsbProWidget::HandleParameters(const uint8_t *data, unsigned int length) { if (m_outstanding_param_callbacks.empty()) { return; } if (length < sizeof(usb_pro_parameters)) { return; } usb_pro_parameters params; memcpy(¶ms, data, sizeof(usb_pro_parameters)); usb_pro_params_callback *callback = m_outstanding_param_callbacks.front(); m_outstanding_param_callbacks.pop_front(); callback->Run(true, params); } /* * Handle the dmx change of state frame */ void GenericUsbProWidget::HandleDMXDiff(const uint8_t *data, unsigned int length) { typedef struct { uint8_t start; uint8_t changed[5]; uint8_t data[40]; } widget_data_changed; if (length < sizeof(widget_data_changed)) { OLA_WARN << "Change of state packet was too small: " << length; return; } const widget_data_changed *widget_reply = reinterpret_cast(data); unsigned int start_channel = widget_reply->start * 8; unsigned int offset = 0; // skip non-0 start codes, this code is pretty messed up because the USB Pro // doesn't seem to provide a guarantee on the ordering of packets. Packets // with non-0 start codes are almost certainly going to cause problems. if (start_channel == 0 && (widget_reply->changed[0] & 0x01) && widget_reply->data[offset]) { return; } for (int i = 0; i < 40; i++) { if (start_channel + i > DMX_UNIVERSE_SIZE + 1 || offset + 6 >= length) { break; } if (widget_reply->changed[i/8] & (1 << (i % 8)) && start_channel + i != 0) { m_input_buffer.SetChannel(start_channel + i - 1, widget_reply->data[offset]); offset++; } } if (m_dmx_callback) { m_dmx_callback->Run(); } } } // namespace usbpro } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbpro/WidgetDetectorInterface.h0000644000175000017500000000301213023355232023354 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * WidgetDetectorInterface.h * The interface for WidgetDetectors. * Copyright (C) 2011 Simon Newton */ #ifndef PLUGINS_USBPRO_WIDGETDETECTORINTERFACE_H_ #define PLUGINS_USBPRO_WIDGETDETECTORINTERFACE_H_ namespace ola { namespace io { class ConnectedDescriptor; } namespace plugin { namespace usbpro { /* * A WidgetDetector takes a ConnectedDescriptor and performs a discovery * routine on it. Individual WidgetDetector specify the behaviour when the * discovery routine passes or fails. */ class WidgetDetectorInterface { public: WidgetDetectorInterface() {} virtual ~WidgetDetectorInterface() {} virtual bool Discover(ola::io::ConnectedDescriptor *descriptor) = 0; }; } // namespace usbpro } // namespace plugin } // namespace ola #endif // PLUGINS_USBPRO_WIDGETDETECTORINTERFACE_H_ ola-0.10.5.nojsmin/plugins/usbpro/ArduinoWidget.cpp0000644000175000017500000001604713023355232021732 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ArduinoWidget.cpp * The Arduino RGB Mixer widget. * Copyright (C) 2011 Simon Newton */ #include #include #include #include #include "ola/io/ByteString.h" #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/rdm/RDMCommand.h" #include "ola/rdm/RDMCommandSerializer.h" #include "ola/strings/Format.h" #include "plugins/usbpro/ArduinoRGBDevice.h" #include "plugins/usbpro/BaseUsbProWidget.h" #include "plugins/usbpro/ArduinoWidget.h" namespace ola { namespace plugin { namespace usbpro { using ola::rdm::RDMCommandSerializer; using ola::rdm::RDMReply; using ola::rdm::RDMRequest; using ola::rdm::RunRDMCallback; using std::auto_ptr; using std::ostringstream; using std::string; using std::vector; const uint8_t ArduinoWidgetImpl::RDM_REQUEST_LABEL = 'R'; const uint8_t ArduinoWidgetImpl::RESPONSE_OK = 0; const uint8_t ArduinoWidgetImpl::RESPONSE_WAS_BROADCAST = 1; const uint8_t ArduinoWidgetImpl::RESPONSE_FAILED = 2; const uint8_t ArduinoWidgetImpl::RESPONSE_FAILED_CHECKSUM = 3; const uint8_t ArduinoWidgetImpl::RESONSE_INVALID_DESTINATION = 4; const uint8_t ArduinoWidgetImpl::RESPONSE_INVALID_COMMAND = 5; /* * New ArduinoWidget device * @param descriptor the ConnectedDescriptor for this widget. * @param esta_id the ESTA id. * @param serial the 4 byte serial which forms part of the UID */ ArduinoWidgetImpl::ArduinoWidgetImpl( ola::io::ConnectedDescriptor *descriptor, uint16_t esta_id, uint32_t serial) : BaseUsbProWidget(descriptor), m_transaction_id(0), m_uid(esta_id, serial), m_rdm_request_callback(NULL) { } /** * Clean up */ ArduinoWidgetImpl::~ArduinoWidgetImpl() { Stop(); } /** * Stop the widget */ void ArduinoWidgetImpl::Stop() { // timeout any existing message if (m_rdm_request_callback) { ola::rdm::RDMCallback *callback = m_rdm_request_callback; m_rdm_request_callback = NULL; RunRDMCallback(callback, ola::rdm::RDM_TIMEOUT); } } /** * Handle an RDM request by passing it through to the Arduino */ void ArduinoWidgetImpl::SendRDMRequest(RDMRequest *request_ptr, ola::rdm::RDMCallback *on_complete) { auto_ptr request(request_ptr); if (request->CommandClass() == ola::rdm::RDMCommand::DISCOVER_COMMAND) { RunRDMCallback(on_complete, ola::rdm::RDM_PLUGIN_DISCOVERY_NOT_SUPPORTED); return; } if (m_rdm_request_callback) { OLA_FATAL << "Previous request hasn't completed yet, dropping request"; RunRDMCallback(on_complete, ola::rdm::RDM_FAILED_TO_SEND); return; } request->SetTransactionNumber(m_transaction_id++); request->SetPortId(1); ola::io::ByteString data; if (!RDMCommandSerializer::PackWithStartCode(*request, &data)) { OLA_WARN << "Failed to pack message, dropping request"; RunRDMCallback(on_complete, ola::rdm::RDM_FAILED_TO_SEND); return; } m_rdm_request_callback = on_complete; m_pending_request.reset(request.release()); if (SendMessage(RDM_REQUEST_LABEL, data.data(), data.size())) { return; } m_rdm_request_callback = NULL; m_pending_request.reset(); RunRDMCallback(on_complete, ola::rdm::RDM_FAILED_TO_SEND); } /** * Called when a new packet arrives */ void ArduinoWidgetImpl::HandleMessage(uint8_t label, const uint8_t *data, unsigned int length) { switch (label) { case RDM_REQUEST_LABEL: HandleRDMResponse(data, length); break; default: OLA_WARN << "Unknown label: " << strings::ToHex(label); } } /** * Handle a RDM response. */ void ArduinoWidgetImpl::HandleRDMResponse(const uint8_t *data, unsigned int length) { if (m_rdm_request_callback == NULL) { OLA_FATAL << "Got a response but no callback to run!"; return; } ola::rdm::RDMCallback *callback = m_rdm_request_callback; m_rdm_request_callback = NULL; std::auto_ptr request( m_pending_request.release()); if (length == 0) { // invalid response RunRDMCallback(callback, ola::rdm::RDM_INVALID_RESPONSE); return; } if (data[0]) { switch (data[0]) { case RESPONSE_WAS_BROADCAST: RunRDMCallback(callback, ola::rdm::RDM_WAS_BROADCAST); return; case RESPONSE_FAILED: break; case RESPONSE_FAILED_CHECKSUM: OLA_WARN << "USB Device reports checksum mismatch"; break; case RESONSE_INVALID_DESTINATION: OLA_WARN << "USB Device reports invalid destination"; break; case RESPONSE_INVALID_COMMAND: OLA_WARN << "USB Device reports invalid command"; break; default: OLA_WARN << "Invalid response code from USB device: " << static_cast(data[0]); } RunRDMCallback(callback, ola::rdm::RDM_FAILED_TO_SEND); return; } // response status was RESPONSE_OK if (length == 1) { // invalid response OLA_WARN << "RDM Response was too short"; RunRDMCallback(callback, ola::rdm::RDM_INVALID_RESPONSE); return; } if (data[1] != ola::rdm::START_CODE) { OLA_WARN << "Wrong start code, was " << strings::ToHex(data[1]) << " required " << strings::ToHex(ola::rdm::START_CODE); RunRDMCallback(callback, ola::rdm::RDM_INVALID_RESPONSE); return; } rdm::RDMFrame frame(data + 1, length - 1); auto_ptr reply(RDMReply::FromFrame(frame, request.get())); callback->Run(reply.get()); } /** * Return the UID Set to the client */ void ArduinoWidgetImpl::GetUidSet(ola::rdm::RDMDiscoveryCallback *callback) { ola::rdm::UIDSet uid_set; uid_set.AddUID(m_uid); callback->Run(uid_set); } /** * ArduinoWidget Constructor */ ArduinoWidget::ArduinoWidget(ola::io::ConnectedDescriptor *descriptor, uint16_t esta_id, uint32_t serial, unsigned int queue_size) { m_impl = new ArduinoWidgetImpl(descriptor, esta_id, serial); m_controller = new ola::rdm::DiscoverableQueueingRDMController(m_impl, queue_size); } ArduinoWidget::~ArduinoWidget() { // delete the controller after the impl because the controller owns the // callback delete m_impl; delete m_controller; } } // namespace usbpro } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbpro/RobeDevice.cpp0000644000175000017500000000403613023355232021167 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RobeDevice.cpp * A Robe Universal Interface device. * Copyright (C) 2011 Simon Newton */ #include #include #include #include "ola/Constants.h" #include "ola/io/SelectServerInterface.h" #include "plugins/usbpro/RobeDevice.h" #include "plugins/usbpro/RobeWidget.h" namespace ola { namespace plugin { namespace usbpro { using std::string; /* * New RobeDevice. */ RobeDevice::RobeDevice(ola::PluginAdaptor *plugin_adaptor, ola::AbstractPlugin *owner, const string &name, RobeWidget *widget) : UsbSerialDevice(owner, name, widget) { std::ostringstream str; str << 1; m_device_id = str.str(); m_output_port = new RobeOutputPort(this, widget); AddPort(m_output_port); m_input_port = new RobeInputPort(this, widget, plugin_adaptor); AddPort(m_input_port); } /** * Create a new Robe Output Port */ RobeOutputPort::RobeOutputPort(RobeDevice *parent, RobeWidget *widget) : BasicOutputPort(parent, 0, true, true), m_widget(widget) { } /** * Write DMX to the output port */ bool RobeOutputPort::WriteDMX(const DmxBuffer &buffer, uint8_t priority) { m_widget->SendDMX(buffer); (void) priority; return true; } } // namespace usbpro } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbpro/DmxTriDevice.h0000644000175000017500000000512613023355232021155 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DmxTriDevice.h * The Jese DMX-TRI device. * Copyright (C) 2010 Simon Newton */ #ifndef PLUGINS_USBPRO_DMXTRIDEVICE_H_ #define PLUGINS_USBPRO_DMXTRIDEVICE_H_ #include #include "ola/DmxBuffer.h" #include "plugins/usbpro/DmxTriWidget.h" #include "plugins/usbpro/UsbSerialDevice.h" namespace ola { namespace plugin { namespace usbpro { /* * An DMX TRI Device */ class DmxTriDevice: public UsbSerialDevice { public: DmxTriDevice(ola::AbstractPlugin *owner, const std::string &name, DmxTriWidget *widget, uint16_t esta_id, uint16_t device_id, uint32_t serial, uint16_t firmware_version); ~DmxTriDevice() {} std::string DeviceId() const { return m_device_id; } void PrePortStop(); private: std::string m_device_id; DmxTriWidget *m_tri_widget; }; /* * A single output port per device */ class DmxTriOutputPort: public BasicOutputPort { public: DmxTriOutputPort(DmxTriDevice *parent, DmxTriWidget *widget, const std::string &description); ~DmxTriOutputPort(); bool WriteDMX(const DmxBuffer &buffer, uint8_t priority); std::string Description() const { return m_description; } void SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *callback) { m_tri_widget->SendRDMRequest(request, callback); } void RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { m_tri_widget->RunFullDiscovery(callback); } void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { m_tri_widget->RunIncrementalDiscovery(callback); } private: DmxTriWidget *m_tri_widget; const std::string m_description; }; } // namespace usbpro } // namespace plugin } // namespace ola #endif // PLUGINS_USBPRO_DMXTRIDEVICE_H_ ola-0.10.5.nojsmin/plugins/usbpro/CommonWidgetTest.h0000644000175000017500000000347013023355232022062 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * CommonWidgetTest.h * Common code shared amongst many of the widget test classes. * Copyright (C) 2011 Simon Newton */ #include #include #include "ola/Logging.h" #include "ola/io/Descriptor.h" #include "ola/io/SelectServer.h" #include "plugins/usbpro/MockEndpoint.h" #ifndef PLUGINS_USBPRO_COMMONWIDGETTEST_H_ #define PLUGINS_USBPRO_COMMONWIDGETTEST_H_ class CommonWidgetTest: public CppUnit::TestFixture { public: virtual void setUp(); virtual void tearDown(); protected: ola::io::SelectServer m_ss; ola::io::PipeDescriptor m_descriptor; std::auto_ptr m_other_end; std::auto_ptr m_endpoint; void Terminate() { m_ss.Terminate(); } uint8_t *BuildUsbProMessage(uint8_t label, const uint8_t *data, unsigned int data_size, unsigned int *total_size); static const unsigned int FOOTER_SIZE = 1; static const unsigned int HEADER_SIZE = 4; }; #endif // PLUGINS_USBPRO_COMMONWIDGETTEST_H_ ola-0.10.5.nojsmin/plugins/usbpro/MockEndpoint.cpp0000644000175000017500000002725113023355232021556 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * MockEndpoint.cpp * This allows unittest of data received on a ConnectedDescriptor. * Copyright (C) 2011 Simon Newton */ #include #include #include #include #include "ola/Callback.h" #include "ola/Logging.h" #include "ola/testing/TestUtils.h" #include "plugins/usbpro/MockEndpoint.h" MockEndpoint::MockEndpoint(ola::io::ConnectedDescriptor *descriptor) : m_descriptor(descriptor) { m_descriptor->SetOnData( ola::NewCallback(this, &MockEndpoint::DescriptorReady)); } MockEndpoint::~MockEndpoint() { m_descriptor->SetOnData(NULL); } /** * Add an expected data frame to the queue. * @param request_data the data we expect in the request * @param request_size the size of the request data * @param callback a callback to run when this frame arrives */ void MockEndpoint::AddExpectedData( const uint8_t *request_data, unsigned int request_size, NotificationCallback *callback) { expected_data call = { false, false, false, {request_size, request_data}, {0, NULL}, callback }; m_expected_data.push(call); } /** * Add an expected Usb Pro frame, using the supplied data * @param label the message label * @param request_payload_data the payload data * @param request_payload_size size of the payload data * @param callback a callback to run when this frame arrives */ void MockEndpoint::AddExpectedUsbProMessage( uint8_t label, const uint8_t *request_payload_data, unsigned int request_payload_size, NotificationCallback *callback) { unsigned int request_size; uint8_t *request = BuildUsbProMessage(label, request_payload_data, request_payload_size, &request_size); expected_data call = { false, true, false, {request_size, request}, {0, NULL}, callback }; m_expected_data.push(call); } /** * Add an expected Robe frame, using the supplied data * @param label the message label * @param request_payload_data the payload data * @param request_payload_size size of the payload data * @param callback a callback to run when this frame arrives */ void MockEndpoint::AddExpectedRobeMessage( uint8_t label, const uint8_t *request_payload_data, unsigned int request_payload_size, NotificationCallback *callback) { unsigned int request_size; uint8_t *request = BuildRobeMessage(label, request_payload_data, request_payload_size, &request_size); expected_data call = { false, true, false, {request_size, request}, {0, NULL}, callback }; m_expected_data.push(call); } /** * Add an expected data frame, and when we get it send a response */ void MockEndpoint::AddExpectedDataAndReturn(const uint8_t *request_data, unsigned int request_size, const uint8_t *response_data, unsigned int response_size, NotificationCallback *callback) { expected_data call = { true, false, false, {request_size, request_data}, {response_size, response_data}, callback }; m_expected_data.push(call); } /** * Add an expected Usb Pro frame, using the supplied data. When this arrives * return the supplied Usb Pro Frame. * @param label the request message label * @param request_payload_data the payload data * @param response_payload_size size of the payload data * @param label the response message label * @param response_payload_data the payload data * @param response_payload_size size of the payload data */ void MockEndpoint::AddExpectedUsbProDataAndReturn( uint8_t request_label, const uint8_t *request_payload_data, unsigned int request_payload_size, uint8_t response_label, const uint8_t *response_payload_data, unsigned int response_payload_size, NotificationCallback *callback) { unsigned int request_size; uint8_t *request = BuildUsbProMessage(request_label, request_payload_data, request_payload_size, &request_size); unsigned int response_size; uint8_t *response = BuildUsbProMessage(response_label, response_payload_data, response_payload_size, &response_size); expected_data call = { true, true, true, {request_size, request}, {response_size, response}, callback }; m_expected_data.push(call); } /** * Add an expected Robe frame, using the supplied data. When this arrives * return the supplied Robe Frame. * @param label the request message label * @param request_payload_data the payload data * @param response_payload_size size of the payload data * @param label the response message label * @param response_payload_data the payload data * @param response_payload_size size of the payload data */ void MockEndpoint::AddExpectedRobeDataAndReturn( uint8_t request_label, const uint8_t *request_payload_data, unsigned int request_payload_size, uint8_t response_label, const uint8_t *response_payload_data, unsigned int response_payload_size, NotificationCallback *callback) { unsigned int request_size; uint8_t *request = BuildRobeMessage(request_label, request_payload_data, request_payload_size, &request_size); unsigned int response_size; uint8_t *response = BuildRobeMessage(response_label, response_payload_data, response_payload_size, &response_size); expected_data call = { true, true, true, {request_size, request}, {response_size, response}, callback }; m_expected_data.push(call); } /** * Send some data from this endpoint without having first received anything */ void MockEndpoint::SendUnsolicited(const uint8_t *data, unsigned int length) { OLA_ASSERT_TRUE(m_descriptor->Send(data, length)); } /** * Send an unsolicited Usb Pro message */ void MockEndpoint::SendUnsolicitedUsbProData( uint8_t response_label, const uint8_t *response_payload_data, unsigned int response_payload_size) { unsigned int response_size; uint8_t *response = BuildUsbProMessage(response_label, response_payload_data, response_payload_size, &response_size); OLA_ASSERT_TRUE(m_descriptor->Send(response, response_size)); delete[] response; } /** * Send an unsolicited Robe messages */ void MockEndpoint::SendUnsolicitedRobeData( uint8_t response_label, const uint8_t *response_payload_data, unsigned int response_payload_size) { unsigned int response_size; uint8_t *response = BuildRobeMessage(response_label, response_payload_data, response_payload_size, &response_size); OLA_ASSERT_TRUE(m_descriptor->Send(response, response_size)); delete[] response; } /** * Verify no data remains */ void MockEndpoint::Verify() { std::ostringstream str; str << m_expected_data.size() << " messages remain, " << m_descriptor->DataRemaining() << " bytes remaing"; OLA_ASSERT_EQ_MSG(static_cast(0), m_expected_data.size(), str.str()); } /** * Called when there is new data available. Make sure it matches what we * expected and if there is return data send it. */ void MockEndpoint::DescriptorReady() { OLA_ASSERT_FALSE(m_expected_data.empty()); while (m_descriptor->DataRemaining()) { expected_data call = m_expected_data.front(); m_expected_data.pop(); uint8_t data[call.expected_data_frame.length]; unsigned int data_received = 0; while (data_received != call.expected_data_frame.length) { unsigned int offset = data_received; m_descriptor->Receive(data + offset, call.expected_data_frame.length - offset, data_received); data_received += offset; } OLA_ASSERT_DATA_EQUALS(call.expected_data_frame.data, call.expected_data_frame.length, data, data_received); if (call.free_request) delete[] call.expected_data_frame.data; if (call.send_response) OLA_ASSERT_TRUE(m_descriptor->Send(call.return_data_frame.data, call.return_data_frame.length)); if (call.callback) call.callback->Run(); if (call.free_response) delete[] call.return_data_frame.data; } } /** * Pack data into a Usb Pro style frame. * @param label the message label * @param data the message data * @param data_size the data size * @param total_size, pointer which is updated with the message size. */ uint8_t *MockEndpoint::BuildUsbProMessage(uint8_t label, const uint8_t *data, unsigned int data_size, unsigned int *total_size) { uint8_t *frame = new uint8_t[data_size + HEADER_SIZE + FOOTER_SIZE]; frame[0] = 0x7e; // som frame[1] = label; frame[2] = data_size & 0xff; // len frame[3] = (data_size + 1) >> 8; // len hi memcpy(frame + 4, data, data_size); frame[data_size + HEADER_SIZE] = 0xe7; *total_size = data_size + HEADER_SIZE + FOOTER_SIZE; return frame; } /** * Pack data into a Robe style frame. * @param label the message label * @param data the message data * @param data_size the data size * @param total_size, pointer which is updated with the message size. */ uint8_t *MockEndpoint::BuildRobeMessage(uint8_t label, const uint8_t *data, unsigned int data_size, unsigned int *total_size) { uint8_t *frame = new uint8_t[data_size + ROBE_HEADER_SIZE + ROBE_FOOTER_SIZE]; frame[0] = 0xa5; // som frame[1] = label; frame[2] = data_size & 0xff; // len frame[3] = (data_size + 1) >> 8; // len hi // header crc uint8_t crc = 0; for (unsigned int i = 0; i < 4; i++) crc += frame[i]; frame[4] = crc; // data & final crc crc += frame[4]; memcpy(frame + ROBE_HEADER_SIZE, data, data_size); for (unsigned int i = 0; i < data_size; i++) crc += data[i]; frame[data_size + ROBE_HEADER_SIZE] = crc; *total_size = data_size + ROBE_HEADER_SIZE + ROBE_FOOTER_SIZE; return frame; } ola-0.10.5.nojsmin/plugins/usbpro/EnttecUsbProWidgetImpl.h0000644000175000017500000001230113023355232023162 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * EnttecUsbProWidgetImpl.h * The Enttec USB Pro Widget * Copyright (C) 2013 Simon Newton */ #ifndef PLUGINS_USBPRO_ENTTECUSBPROWIDGETIMPL_H_ #define PLUGINS_USBPRO_ENTTECUSBPROWIDGETIMPL_H_ #include #include #include "ola/Callback.h" #include "ola/Constants.h" #include "ola/rdm/RDMCommand.h" #include "ola/rdm/UID.h" #include "ola/rdm/UIDSet.h" #include "ola/util/Watchdog.h" namespace ola { namespace plugin { namespace usbpro { enum { // port 1 labels GET_PARAMS_1 = 3, SET_PARAMS_1 = 4, RECEIVED_DMX_LABEL_1 = 5, SEND_DMX_1 = 6, SEND_RDM_1 = 7, CHANGE_TO_RX_1 = 8, COS_DMX_1 = 9, RDM_DISCOVERY_1 = 11, RDM_TIMEOUT_1 = 12, // port 2 labels, these are tied to the OLA API key. GET_PARAMS_2 = 137, SET_PARAMS_2 = 180, RECEIVED_DMX_LABEL_2 = 156, SEND_DMX_2 = 135, SEND_RDM_2 = 236, CHANGE_TO_RX_2 = 197, COS_DMX_2 = 164, RDM_DISCOVERY_2 = 196, RDM_TIMEOUT_2 = 201, }; // Maps operations to label values struct OperationLabels { uint8_t get_params; uint8_t set_params; uint8_t recv_dmx; uint8_t send_dmx; uint8_t send_rdm; uint8_t change_to_rx_mode; uint8_t cos_dmx; uint8_t rdm_timeout; uint8_t rdm_discovery; static OperationLabels Port1Operations(); static OperationLabels Port2Operations(); }; /** * The internal implementation of an Enttec port */ class EnttecPortImpl : public ola::rdm::DiscoverableRDMControllerInterface, public ola::rdm::DiscoveryTargetInterface { public: typedef ola::Callback3 SendCallback; EnttecPortImpl(const OperationLabels &ops, const ola::rdm::UID &uid, SendCallback *send_cb); void Stop(); bool SendDMX(const DmxBuffer &buffer); const DmxBuffer &FetchDMX() const { return m_input_buffer; } void SetDMXCallback(ola::Callback0 *callback); bool ChangeToReceiveMode(bool change_only); void GetParameters(usb_pro_params_callback *callback); bool SetParameters(uint8_t break_time, uint8_t mab_time, uint8_t rate); // the following are from DiscoverableRDMControllerInterface void SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *on_complete); void RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback); void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback); // The following are the implementation of DiscoveryTargetInterface void MuteDevice(const ola::rdm::UID &target, MuteDeviceCallback *mute_complete); void UnMuteAll(UnMuteDeviceCallback *unmute_complete); void Branch(const ola::rdm::UID &lower, const ola::rdm::UID &upper, BranchCallback *callback); // Called by the EnttecUsbProWidgetImpl void HandleRDMTimeout(unsigned int length); void HandleParameters(const uint8_t *data, unsigned int length); void HandleIncomingDataMessage(const uint8_t *data, unsigned int length); void HandleDMXDiff(const uint8_t *data, unsigned int length); void ClockWatchdog(); void WatchdogFired(); private: SendCallback *m_send_cb; OperationLabels m_ops; bool m_active; Watchdog m_watchdog; // RX DMX DmxBuffer m_input_buffer; std::auto_ptr > m_dmx_callback; // widget params std::deque m_outstanding_param_callbacks; // RDM send ola::rdm::DiscoveryAgent m_discovery_agent; const ola::rdm::UID m_uid; uint8_t m_transaction_number; ola::rdm::RDMCallback *m_rdm_request_callback; std::auto_ptr m_pending_request; // RDM Discovery MuteDeviceCallback *m_mute_callback; UnMuteDeviceCallback *m_unmute_callback; BranchCallback *m_branch_callback; // holds the discovery response while we're waiting for the timeout message const uint8_t *m_discovery_response; unsigned int m_discovery_response_size; void HandleDMX(const uint8_t *data, unsigned int length); void DiscoveryComplete(ola::rdm::RDMDiscoveryCallback *callback, bool status, const ola::rdm::UIDSet &uids); bool PackAndSendRDMRequest(uint8_t label, const ola::rdm::RDMRequest *request); bool IsDUBRequest(const ola::rdm::RDMRequest *request); static const unsigned int PORT_ID = 1; // This gives a limit between 1 and 2s. static const unsigned int WATCHDOG_LIMIT = 2; }; } // namespace usbpro } // namespace plugin } // namespace ola #endif // PLUGINS_USBPRO_ENTTECUSBPROWIDGETIMPL_H_ ola-0.10.5.nojsmin/plugins/usbpro/RobeWidget.cpp0000644000175000017500000002736213023355232021222 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RobeWidget.cpp * Read and Write to a Robe USB Widget. * Copyright (C) 2011 Simon Newton */ #include #include #include #include #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/io/ByteString.h" #include "ola/rdm/RDMCommand.h" #include "ola/rdm/RDMCommandSerializer.h" #include "ola/rdm/UID.h" #include "ola/rdm/UIDSet.h" #include "ola/strings/Format.h" #include "plugins/usbpro/BaseRobeWidget.h" #include "plugins/usbpro/RobeWidget.h" namespace ola { namespace plugin { namespace usbpro { using ola::io::ByteString; using ola::rdm::RDMCommandSerializer; using ola::rdm::RDMReply; using ola::rdm::RunRDMCallback; using ola::rdm::RDMRequest; using ola::rdm::RDMResponse; using ola::rdm::UID; using ola::rdm::UIDSet; using std::auto_ptr; using std::string; using std::vector; // The DMX frames have an extra 4 bytes at the end const int RobeWidgetImpl::DMX_FRAME_DATA_SIZE = DMX_UNIVERSE_SIZE + 4; RobeWidgetImpl::RobeWidgetImpl(ola::io::ConnectedDescriptor *descriptor, const ola::rdm::UID &uid) : BaseRobeWidget(descriptor), m_rdm_request_callback(NULL), m_mute_callback(NULL), m_unmute_callback(NULL), m_branch_callback(NULL), m_discovery_agent(this), m_dmx_callback(NULL), m_pending_request(NULL), m_uid(uid), m_transaction_number(0) { } /** * Stop the widget. */ void RobeWidgetImpl::Stop() { if (m_rdm_request_callback) { ola::rdm::RDMCallback *callback = m_rdm_request_callback; m_rdm_request_callback = NULL; RunRDMCallback(callback, ola::rdm::RDM_TIMEOUT); } m_discovery_agent.Abort(); } /** * Send DMX * @param buffer the DMX data */ bool RobeWidgetImpl::SendDMX(const DmxBuffer &buffer) { // the data is 512 + an extra 4 bytes uint8_t output_data[DMX_FRAME_DATA_SIZE]; memset(output_data, 0, DMX_FRAME_DATA_SIZE); unsigned int length = DMX_UNIVERSE_SIZE; buffer.Get(output_data, &length); return SendMessage(CHANNEL_A_OUT, reinterpret_cast(&output_data), length + 4); } /** * Send a RDM Message */ void RobeWidgetImpl::SendRDMRequest(RDMRequest *request_ptr, ola::rdm::RDMCallback *on_complete) { auto_ptr request(request_ptr); if (m_rdm_request_callback) { OLA_FATAL << "Previous request hasn't completed yet, dropping request"; RunRDMCallback(on_complete, ola::rdm::RDM_FAILED_TO_SEND); return; } // prepare the buffer for the RDM data, we don't need to include the start // code. We need to include 4 bytes at the end, these bytes can be any value. ByteString data; unsigned int this_transaction_number = m_transaction_number++; unsigned int port_id = 1; request->SetSourceUID(m_uid); request->SetTransactionNumber(this_transaction_number); request->SetPortId(port_id); if (!RDMCommandSerializer::Pack(*request, &data)) { OLA_WARN << "Failed to pack message, dropping request"; RunRDMCallback(on_complete, ola::rdm::RDM_FAILED_TO_SEND); return; } // Append the extra padding bytes, which can be set to any value. data.append(RDM_PADDING_BYTES, 0); OLA_DEBUG << "Sending RDM command. CC: " << strings::ToHex(request->CommandClass()) << ", PID " << strings::ToHex(request->ParamId()) << ", TN: " << this_transaction_number; m_rdm_request_callback = on_complete; m_pending_request.reset(request.release()); const uint8_t label = m_pending_request->IsDUB() ? RDM_DISCOVERY : RDM_REQUEST; bool sent_ok = SendMessage(label, data.data(), data.size()); if (!sent_ok) { m_rdm_request_callback = NULL; m_pending_request.reset(); RunRDMCallback(on_complete, ola::rdm::RDM_FAILED_TO_SEND); } } /** * Perform full discovery. */ void RobeWidgetImpl::RunFullDiscovery( ola::rdm::RDMDiscoveryCallback *callback) { OLA_INFO << "Full discovery"; m_discovery_agent.StartFullDiscovery( ola::NewSingleCallback(this, &RobeWidgetImpl::DiscoveryComplete, callback)); } /** * Perform incremental discovery. */ void RobeWidgetImpl::RunIncrementalDiscovery( ola::rdm::RDMDiscoveryCallback *callback) { OLA_INFO << "Incremental discovery"; m_discovery_agent.StartIncrementalDiscovery( ola::NewSingleCallback(this, &RobeWidgetImpl::DiscoveryComplete, callback)); } /** * Change to receive mode. */ bool RobeWidgetImpl::ChangeToReceiveMode() { m_buffer.Reset(); return SendMessage(DMX_IN_REQUEST, NULL, 0); } void RobeWidgetImpl::SetDmxCallback(Callback0 *callback) { m_dmx_callback.reset(callback); } /** * Mute a responder * @param target the UID to mute * @param mute_complete the callback to run once the mute request * completes. */ void RobeWidgetImpl::MuteDevice(const UID &target, MuteDeviceCallback *mute_complete) { auto_ptr mute_request( ola::rdm::NewMuteRequest(m_uid, target, m_transaction_number++)); OLA_DEBUG << "Muting " << target; if (PackAndSendRDMRequest(RDM_REQUEST, mute_request.get())) m_mute_callback = mute_complete; else mute_complete->Run(false); } /** * Unmute all responders * @param unmute_complete the callback to run once the unmute request * completes. */ void RobeWidgetImpl::UnMuteAll(UnMuteDeviceCallback *unmute_complete) { auto_ptr unmute_request( ola::rdm::NewUnMuteRequest(m_uid, ola::rdm::UID::AllDevices(), m_transaction_number++)); OLA_DEBUG << "UnMuting all devices"; if (PackAndSendRDMRequest(RDM_REQUEST, unmute_request.get())) { m_unmute_callback = unmute_complete; } else { OLA_WARN << "Failed to send Unmute all request"; unmute_complete->Run(); } } /** * Send a Discovery Unique Branch */ void RobeWidgetImpl::Branch(const UID &lower, const UID &upper, BranchCallback *callback) { auto_ptr branch_request( ola::rdm::NewDiscoveryUniqueBranchRequest( m_uid, lower, upper, m_transaction_number++)); if (PackAndSendRDMRequest(RDM_DISCOVERY, branch_request.get())) m_branch_callback = callback; else callback->Run(NULL, 0); } /** * Handle a Robe message */ void RobeWidgetImpl::HandleMessage(uint8_t label, const uint8_t *data, unsigned int length) { switch (label) { case BaseRobeWidget::RDM_RESPONSE: HandleRDMResponse(data, length); return; case BaseRobeWidget::RDM_DISCOVERY_RESPONSE: HandleDiscoveryResponse(data, length); return; case DMX_IN_RESPONSE: HandleDmxFrame(data, length); return; default: OLA_INFO << "Unknown message from Robe widget " << strings::ToHex(label); } } /** * Handle a RDM response */ void RobeWidgetImpl::HandleRDMResponse(const uint8_t *data, unsigned int length) { OLA_DEBUG << "Got RDM Response from Robe Widget, length " << length; if (m_unmute_callback) { UnMuteDeviceCallback *callback = m_unmute_callback; m_unmute_callback = NULL; callback->Run(); return; } if (m_mute_callback) { MuteDeviceCallback *callback = m_mute_callback; m_mute_callback = NULL; // TODO(simon): actually check the response here callback->Run(length > RDM_PADDING_BYTES); return; } if (m_rdm_request_callback == NULL) { OLA_FATAL << "Got a RDM response but no callback to run!"; return; } ola::rdm::RDMCallback *callback = m_rdm_request_callback; m_rdm_request_callback = NULL; auto_ptr request(m_pending_request.release()); // this was a broadcast request if (request->DestinationUID().IsBroadcast()) { RunRDMCallback(callback, ola::rdm::RDM_WAS_BROADCAST); return; } if (length == RDM_PADDING_BYTES) { // this indicates that no request was received RunRDMCallback(callback, ola::rdm::RDM_TIMEOUT); return; } // The widget response data doesn't contain a start code so we prepend it. rdm::RDMFrame frame(data, length, rdm::RDMFrame::Options(true)); auto_ptr reply(RDMReply::FromFrame(frame, request.get())); callback->Run(reply.get()); } /** * Handle a response to a Discovery unique branch request */ void RobeWidgetImpl::HandleDiscoveryResponse(const uint8_t *data, unsigned int length) { if (m_branch_callback) { BranchCallback *callback = m_branch_callback; m_branch_callback = NULL; // there are always 4 bytes padded on the end of the response if (length <= RDM_PADDING_BYTES) callback->Run(NULL, 0); else callback->Run(data, length - RDM_PADDING_BYTES); } else if (m_rdm_request_callback) { ola::rdm::RDMCallback *callback = m_rdm_request_callback; m_rdm_request_callback = NULL; auto_ptr request(m_pending_request.release()); if (length <= RDM_PADDING_BYTES) { // this indicates that no request was received RunRDMCallback(callback, ola::rdm::RDM_TIMEOUT); } else { auto_ptr reply(RDMReply::DUBReply( rdm::RDMFrame(data, length - RDM_PADDING_BYTES))); callback->Run(reply.get()); } } else { OLA_WARN << "Got response to DUB but no callbacks defined!"; } } /** * Called when the discovery process finally completes * @param callback the callback passed to StartFullDiscovery or * StartIncrementalDiscovery that we should execute. * @param status true if discovery worked, false otherwise * @param uids the UIDSet of UIDs that were found. */ void RobeWidgetImpl::DiscoveryComplete( ola::rdm::RDMDiscoveryCallback *callback, bool status, const UIDSet &uids) { if (callback) callback->Run(uids); (void) status; } /** * Handle DMX data */ void RobeWidgetImpl::HandleDmxFrame(const uint8_t *data, unsigned int length) { m_buffer.Set(data, length); if (m_dmx_callback.get()) m_dmx_callback->Run(); } /** * Send a RDM request to the widget */ bool RobeWidgetImpl::PackAndSendRDMRequest(uint8_t label, const RDMRequest *request) { ByteString frame; if (!RDMCommandSerializer::Pack(*request, &frame)) { return false; } frame.append(RDM_PADDING_BYTES, 0); return SendMessage(label, frame.data(), frame.size()); } /** * RobeWidget Constructor */ RobeWidget::RobeWidget(ola::io::ConnectedDescriptor *descriptor, const ola::rdm::UID &uid, unsigned int queue_size) { m_impl = new RobeWidgetImpl(descriptor, uid); m_controller = new ola::rdm::DiscoverableQueueingRDMController(m_impl, queue_size); } RobeWidget::~RobeWidget() { // delete the controller after the impl because the controller owns the // callback delete m_impl; delete m_controller; } } // namespace usbpro } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbpro/GenericUsbProWidget.h0000644000175000017500000000623713023355232022505 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * GenericUsbProWidget.h * This class implements a generic Usb Pro style widget, which can send and * receive DMX as well and get/set widget parameters. * Copyright (C) 2011 Simon Newton */ #ifndef PLUGINS_USBPRO_GENERICUSBPROWIDGET_H_ #define PLUGINS_USBPRO_GENERICUSBPROWIDGET_H_ #include #include #include "ola/Callback.h" #include "ola/DmxBuffer.h" #include "ola/thread/SchedulerInterface.h" #include "plugins/usbpro/BaseUsbProWidget.h" namespace ola { namespace plugin { namespace usbpro { typedef struct { uint8_t firmware; uint8_t firmware_high; uint8_t break_time; uint8_t mab_time; uint8_t rate; } usb_pro_parameters; typedef ola::SingleUseCallback2 usb_pro_params_callback; /* * An Generic DMX USB PRO Widget. This just handles the base functionality, * other features like RDM, multi-universe support etc. can be layered on top * of this. */ class GenericUsbProWidget: public BaseUsbProWidget { public: explicit GenericUsbProWidget(ola::io::ConnectedDescriptor *descriptor); ~GenericUsbProWidget(); void SetDMXCallback(ola::Callback0 *callback); void GenericStop(); virtual bool SendDMX(const DmxBuffer &buffer); bool ChangeToReceiveMode(bool change_only); const DmxBuffer &FetchDMX() const; void GetParameters(usb_pro_params_callback *callback); bool SetParameters(uint8_t break_time, uint8_t mab_time, uint8_t rate); static const uint8_t RECEIVED_DMX_LABEL = 5; protected: // child classes can intercept this. virtual void HandleMessage(uint8_t label, const uint8_t *data, unsigned int length); void HandleDMX(const uint8_t *data, unsigned int length); private: bool m_active; DmxBuffer m_input_buffer; ola::Callback0 *m_dmx_callback; std::deque m_outstanding_param_callbacks; void HandleParameters(const uint8_t *data, unsigned int length); void HandleDMXDiff(const uint8_t *data, unsigned int length); static const uint8_t REPROGRAM_FIRMWARE_LABEL = 2; static const uint8_t PARAMETERS_LABEL = 3; static const uint8_t SET_PARAMETERS_LABEL = 4; static const uint8_t DMX_RX_MODE_LABEL = 8; static const uint8_t DMX_CHANGED_LABEL = 9; }; } // namespace usbpro } // namespace plugin } // namespace ola #endif // PLUGINS_USBPRO_GENERICUSBPROWIDGET_H_ ola-0.10.5.nojsmin/plugins/usbpro/RobeDevice.h0000644000175000017500000000626013023355232020635 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RobeDevice.h * The Robe Universal Interface Device. * Copyright (C) 2011 Simon Newton */ #ifndef PLUGINS_USBPRO_ROBEDEVICE_H_ #define PLUGINS_USBPRO_ROBEDEVICE_H_ #include #include "ola/DmxBuffer.h" #include "plugins/usbpro/RobeWidget.h" #include "plugins/usbpro/UsbSerialDevice.h" namespace ola { namespace plugin { namespace usbpro { /* * The device for a Robe Universe Interface. */ class RobeDevice: public UsbSerialDevice { public: RobeDevice(ola::PluginAdaptor *plugin_adaptor, ola::AbstractPlugin *owner, const std::string &name, RobeWidget *widget); std::string DeviceId() const { return m_device_id; } private: std::string m_device_id; class RobeOutputPort *m_output_port; class RobeInputPort *m_input_port; }; /* * The Input port */ class RobeInputPort: public BasicInputPort { public: RobeInputPort(RobeDevice *parent, RobeWidget *widget, ola::PluginAdaptor *plugin_adaptor) : BasicInputPort(parent, 0, plugin_adaptor), m_widget(widget) { m_widget->SetDmxCallback(NewCallback( static_cast(this), &BasicInputPort::DmxChanged)); } const DmxBuffer &ReadDMX() const { return m_widget->FetchDMX(); } void PostSetUniverse(Universe*, Universe *new_universe) { if (new_universe) m_widget->ChangeToReceiveMode(); } std::string Description() const { return ""; } private: std::string m_path; RobeWidget *m_widget; }; /* * For now we just support a single port per device. Some devices may have two * ports, but I haven't figured out how to use that yet. */ class RobeOutputPort: public BasicOutputPort { public: RobeOutputPort(RobeDevice *parent, RobeWidget *widget); std::string Description() const { return ""; } bool WriteDMX(const DmxBuffer &buffer, uint8_t priority); void SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *callback) { m_widget->SendRDMRequest(request, callback); } void RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { m_widget->RunFullDiscovery(callback); } void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { m_widget->RunIncrementalDiscovery(callback); } private: RobeWidget *m_widget; }; } // namespace usbpro } // namespace plugin } // namespace ola #endif // PLUGINS_USBPRO_ROBEDEVICE_H_ ola-0.10.5.nojsmin/plugins/usbpro/DmxterWidgetTest.cpp0000644000175000017500000005142213023355232022430 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DmxterWidgetTest.cpp * Test fixture for the DmxterWidget class * Copyright (C) 2010 Simon Newton */ #include #include #include #include #include #include "common/rdm/TestHelper.h" #include "ola/Callback.h" #include "ola/Logging.h" #include "ola/base/Array.h" #include "ola/rdm/RDMCommandSerializer.h" #include "plugins/usbpro/DmxterWidget.h" #include "plugins/usbpro/CommonWidgetTest.h" #include "ola/testing/TestUtils.h" using ola::plugin::usbpro::DmxterWidget; using ola::rdm::GetResponseFromData; using ola::rdm::RDMCommandSerializer; using ola::rdm::RDMFrame; using ola::rdm::RDMFrames; using ola::rdm::RDMReply; using ola::rdm::RDMRequest; using ola::rdm::RDMResponse; using ola::rdm::UID; using std::auto_ptr; using std::string; using std::vector; class DmxterWidgetTest: public CommonWidgetTest { CPPUNIT_TEST_SUITE(DmxterWidgetTest); CPPUNIT_TEST(testTod); CPPUNIT_TEST(testSendRDMRequest); CPPUNIT_TEST(testSendRDMMute); CPPUNIT_TEST(testSendRDMDUB); CPPUNIT_TEST(testErrorCodes); CPPUNIT_TEST(testErrorConditions); CPPUNIT_TEST(testShutdown); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void testTod(); void testSendRDMRequest(); void testSendRDMMute(); void testSendRDMDUB(); void testErrorCodes(); void testErrorConditions(); void testShutdown(); private: auto_ptr m_widget; unsigned int m_tod_counter; void Terminate() { m_ss.Terminate(); } void CloseAndTerminate() { m_ss.RemoveReadDescriptor(&m_descriptor); m_ss.RemoveReadDescriptor(m_other_end.get()); m_descriptor.Close(); m_other_end->Close(); m_ss.Terminate(); } void ValidateTod(const ola::rdm::UIDSet &uids); void ValidateResponse(RDMReply *reply); void ValidateStatus(ola::rdm::RDMStatusCode expected_code, RDMFrames expected_frames, RDMReply *reply); RDMRequest *NewRequest(const UID &source, const UID &destination, const uint8_t *data, unsigned int length); static const uint8_t TEST_RDM_DATA[]; }; const uint8_t DmxterWidgetTest::TEST_RDM_DATA[] = {0x5a, 0x5a, 0x5a, 0x5a}; CPPUNIT_TEST_SUITE_REGISTRATION(DmxterWidgetTest); void DmxterWidgetTest::setUp() { CommonWidgetTest::setUp(); m_widget.reset( new ola::plugin::usbpro::DmxterWidget(&m_descriptor, 0x4744, 0x12345678)); m_tod_counter = 0; } /** * Check the TOD matches what we expect */ void DmxterWidgetTest::ValidateTod(const ola::rdm::UIDSet &uids) { UID uid1(0x707a, 0xffffff00); UID uid2(0x5252, 0x12345678); OLA_ASSERT_EQ((unsigned int) 2, uids.Size()); OLA_ASSERT(uids.Contains(uid1)); OLA_ASSERT(uids.Contains(uid2)); m_tod_counter++; m_ss.Terminate(); } /** * Check the response matches what we expected. */ void DmxterWidgetTest::ValidateResponse(RDMReply *reply) { OLA_ASSERT_EQ(ola::rdm::RDM_COMPLETED_OK, reply->StatusCode()); OLA_ASSERT_NOT_NULL(reply->Response()); const RDMResponse *response = reply->Response(); uint8_t expected_data[] = {0x5a, 0x5a, 0x5a, 0x5a}; OLA_ASSERT_DATA_EQUALS(expected_data, arraysize(expected_data), response->ParamData(), response->ParamDataSize()); const RDMFrames &frames = reply->Frames(); OLA_ASSERT_EQ((size_t) 1, frames.size()); ola::rdm::RDMStatusCode raw_code; auto_ptr raw_response( ola::rdm::RDMResponse::InflateFromData( frames[0].data.substr(1), &raw_code)); OLA_ASSERT_TRUE(*raw_response == *response); m_ss.Terminate(); } /* * Check that we got an unknown UID code */ void DmxterWidgetTest::ValidateStatus( ola::rdm::RDMStatusCode expected_code, RDMFrames expected_frames, RDMReply *reply) { OLA_ASSERT_EQ(expected_code, reply->StatusCode()); OLA_ASSERT_NULL(reply->Response()); const RDMFrames &frames = reply->Frames(); OLA_ASSERT_EQ(expected_frames.size(), frames.size()); for (unsigned int i = 0; i < frames.size(); i++) { OLA_ASSERT_DATA_EQUALS(expected_frames[i].data.data(), expected_frames[i].data.size(), frames[i].data.data(), frames[i].data.size()); OLA_ASSERT_TRUE(expected_frames[i] == frames[i]); } m_ss.Terminate(); } /** * Helper method to create new request objects */ RDMRequest *DmxterWidgetTest::NewRequest(const UID &source, const UID &destination, const uint8_t *data, unsigned int length) { return new ola::rdm::RDMGetRequest( source, destination, 0, // transaction # 1, // port id 10, // sub device 296, // param id data, length); } /** * Check that discovery works for a device that just implements the serial # */ void DmxterWidgetTest::testTod() { uint8_t FULL_DISCOVERY_LABEL = 0x84; uint8_t INCREMENTAL_DISCOVERY_LABEL = 0x85; uint8_t TOD_LABEL = 0x82; uint8_t return_packet[] = { 0x70, 0x7a, 0xff, 0xff, 0xff, 0x00, 0x52, 0x52, 0x12, 0x34, 0x56, 0x78, }; m_endpoint->AddExpectedUsbProDataAndReturn( FULL_DISCOVERY_LABEL, NULL, 0, TOD_LABEL, return_packet, sizeof(return_packet)); OLA_ASSERT_EQ((unsigned int) 0, m_tod_counter); m_widget->RunFullDiscovery( ola::NewSingleCallback(this, &DmxterWidgetTest::ValidateTod)); m_ss.Run(); m_endpoint->Verify(); OLA_ASSERT_EQ((unsigned int) 1, m_tod_counter); m_endpoint->AddExpectedUsbProDataAndReturn( INCREMENTAL_DISCOVERY_LABEL, NULL, 0, TOD_LABEL, return_packet, sizeof(return_packet)); m_widget->RunIncrementalDiscovery( ola::NewSingleCallback(this, &DmxterWidgetTest::ValidateTod)); m_ss.Run(); m_endpoint->Verify(); OLA_ASSERT_EQ((unsigned int) 2, m_tod_counter); } /** * Check that we send messages correctly. */ void DmxterWidgetTest::testSendRDMRequest() { uint8_t RDM_REQUEST_LABEL = 0x80; uint8_t RDM_BROADCAST_REQUEST_LABEL = 0x81; UID source(0x4744, 0x12345678); UID destination(3, 4); UID bcast_destination(3, 0xffffffff); RDMRequest *request = NewRequest(source, destination, NULL, 0); unsigned int size = RDMCommandSerializer::RequiredSize(*request); uint8_t *expected_packet = new uint8_t[size + 1]; expected_packet[0] = 0xcc; OLA_ASSERT(RDMCommandSerializer::Pack(*request, expected_packet + 1, &size)); uint8_t return_packet[] = { 0x00, 14, // response code 'ok' 0xcc, 1, 28, // sub code & length 0x47, 0x44, 0x12, 0x34, 0x56, 0x78, // dst uid 0, 3, 0, 0, 0, 4, // src uid 0, 1, 0, 0, 10, // transaction, port id, msg count & sub device 0x21, 0x1, 0x28, 4, // command, param id, param data length 0x5a, 0x5a, 0x5a, 0x5a, // param data 0x04, 0x50 // checksum }; m_endpoint->AddExpectedUsbProDataAndReturn( RDM_REQUEST_LABEL, expected_packet, size + 1, RDM_REQUEST_LABEL, return_packet, sizeof(return_packet)); m_widget->SendRDMRequest( request, ola::NewSingleCallback(this, &DmxterWidgetTest::ValidateResponse)); m_ss.Run(); m_endpoint->Verify(); // now check broadcast request = NewRequest(source, bcast_destination, NULL, 0); request->SetTransactionNumber(1); OLA_ASSERT(RDMCommandSerializer::Pack(*request, expected_packet + 1, &size)); m_endpoint->AddExpectedUsbProDataAndReturn( RDM_BROADCAST_REQUEST_LABEL, expected_packet, size + 1, RDM_BROADCAST_REQUEST_LABEL, static_cast(NULL), 0); RDMFrames frames; m_widget->SendRDMRequest( request, ola::NewSingleCallback(this, &DmxterWidgetTest::ValidateStatus, ola::rdm::RDM_WAS_BROADCAST, frames)); delete[] expected_packet; m_ss.Run(); m_endpoint->Verify(); } /** * Check that RDM Mute requests work */ void DmxterWidgetTest::testSendRDMMute() { uint8_t RDM_REQUEST_LABEL = 0x80; const UID source(0x4744, 0x12345678); const UID destination(3, 4); // request RDMRequest *rdm_request = new ola::rdm::RDMDiscoveryRequest( source, destination, 0, // transaction # 1, // port id 0, // sub device ola::rdm::PID_DISC_MUTE, // param id NULL, 0); unsigned int request_size = RDMCommandSerializer::RequiredSize(*rdm_request); uint8_t *expected_request_frame = new uint8_t[request_size + 1]; expected_request_frame[0] = 0xcc; OLA_ASSERT(RDMCommandSerializer::Pack(*rdm_request, expected_request_frame + 1, &request_size)); // response // to keep things simple here we return the TEST_RDM_DATA. auto_ptr response( GetResponseFromData(rdm_request, TEST_RDM_DATA, sizeof(TEST_RDM_DATA))); unsigned int response_size = RDMCommandSerializer::RequiredSize( *response.get()); uint8_t *response_frame = new uint8_t[response_size + 3]; response_frame[0] = 0; // version response_frame[1] = 14; // status ok response_frame[2] = ola::rdm::RDMCommand::START_CODE; memset(&response_frame[3], 0, response_size); OLA_ASSERT(RDMCommandSerializer::Pack(*response, &response_frame[3], &response_size)); response_size += 3; // add the expected response, send and verify m_endpoint->AddExpectedUsbProDataAndReturn( RDM_REQUEST_LABEL, expected_request_frame, request_size + 1, RDM_REQUEST_LABEL, response_frame, response_size); m_widget->SendRDMRequest( rdm_request, ola::NewSingleCallback(this, &DmxterWidgetTest::ValidateResponse)); m_ss.Run(); m_endpoint->Verify(); delete[] expected_request_frame; delete[] response_frame; } /** * Check that we send RDM discovery messages correctly. */ void DmxterWidgetTest::testSendRDMDUB() { uint8_t RDM_DUB_LABEL = 0x83; const UID source(0x4744, 0x12345678); const UID destination = UID::AllDevices(); static const uint8_t REQUEST_DATA[] = { 0x7a, 0x70, 0, 0, 0, 0, 0x7a, 0x70, 0xff, 0xff, 0xff, 0xff }; // request RDMRequest *rdm_request = new ola::rdm::RDMDiscoveryRequest( source, destination, 0, // transaction # 1, // port id 0, // sub device ola::rdm::PID_DISC_UNIQUE_BRANCH, // param id REQUEST_DATA, sizeof(REQUEST_DATA)); unsigned int request_size = RDMCommandSerializer::RequiredSize(*rdm_request); uint8_t *expected_request_frame = new uint8_t[request_size + 1]; expected_request_frame[0] = 0xcc; OLA_ASSERT(RDMCommandSerializer::Pack(*rdm_request, expected_request_frame + 1, &request_size)); // a 4 byte response means a timeout static const uint8_t TIMEOUT_RESPONSE[] = {0, 17}; // add the expected response, send and verify m_endpoint->AddExpectedUsbProDataAndReturn( RDM_DUB_LABEL, expected_request_frame, request_size + 1, RDM_DUB_LABEL, TIMEOUT_RESPONSE, sizeof(TIMEOUT_RESPONSE)); RDMFrames frames; m_widget->SendRDMRequest( rdm_request, ola::NewSingleCallback(this, &DmxterWidgetTest::ValidateStatus, ola::rdm::RDM_TIMEOUT, frames)); m_ss.Run(); m_endpoint->Verify(); delete[] expected_request_frame; // now try a dub response that returns something rdm_request = new ola::rdm::RDMDiscoveryRequest( source, destination, 1, // transaction # 1, // port id 0, // sub device ola::rdm::PID_DISC_UNIQUE_BRANCH, // param id REQUEST_DATA, sizeof(REQUEST_DATA)); request_size = RDMCommandSerializer::RequiredSize(*rdm_request); expected_request_frame = new uint8_t[request_size + 1]; expected_request_frame[0] = 0xcc; OLA_ASSERT(RDMCommandSerializer::Pack(*rdm_request, expected_request_frame + 1, &request_size)); // something that looks like a DUB response static const uint8_t FAKE_RESPONSE[] = {0x00, 19, 0xfe, 0xfe, 0xaa, 0xaa}; // add the expected response, send and verify m_endpoint->AddExpectedUsbProDataAndReturn( RDM_DUB_LABEL, expected_request_frame, request_size + 1, RDM_DUB_LABEL, FAKE_RESPONSE, sizeof(FAKE_RESPONSE)); frames.push_back(RDMFrame(&FAKE_RESPONSE[2], arraysize(FAKE_RESPONSE) - 2)); m_widget->SendRDMRequest( rdm_request, ola::NewSingleCallback(this, &DmxterWidgetTest::ValidateStatus, ola::rdm::RDM_DUB_RESPONSE, frames)); m_ss.Run(); m_endpoint->Verify(); delete[] expected_request_frame; } /** * Check that we handle invalid responses ok */ void DmxterWidgetTest::testErrorCodes() { uint8_t RDM_REQUEST_LABEL = 0x80; UID source(0x4744, 0x12345678); UID destination(3, 4); RDMFrames frames; RDMRequest *request = NewRequest(source, destination, NULL, 0); unsigned int size = RDMCommandSerializer::RequiredSize(*request); uint8_t *expected_packet = new uint8_t[size + 1]; expected_packet[0] = 0xcc; OLA_ASSERT(RDMCommandSerializer::Pack(*request, expected_packet + 1, &size)); uint8_t return_packet[] = { 0x00, 1, // checksum failure }; m_endpoint->AddExpectedUsbProDataAndReturn( RDM_REQUEST_LABEL, expected_packet, size + 1, RDM_REQUEST_LABEL, return_packet, sizeof(return_packet)); m_widget->SendRDMRequest( request, ola::NewSingleCallback(this, &DmxterWidgetTest::ValidateStatus, ola::rdm::RDM_CHECKSUM_INCORRECT, frames)); m_ss.Run(); m_endpoint->Verify(); return_packet[1] = 8; // packet too short // Update TN & Checksum expected_packet[15]++; expected_packet[25]++; request = NewRequest(source, destination, NULL, 0); m_endpoint->AddExpectedUsbProDataAndReturn( RDM_REQUEST_LABEL, expected_packet, size + 1, RDM_REQUEST_LABEL, return_packet, sizeof(return_packet)); m_widget->SendRDMRequest( request, ola::NewSingleCallback(this, &DmxterWidgetTest::ValidateStatus, ola::rdm::RDM_PACKET_TOO_SHORT, frames)); m_ss.Run(); m_endpoint->Verify(); // update transaction # & checksum expected_packet[15]++; expected_packet[25] = 0xe1; return_packet[1] = 12; // transaction mismatch request = NewRequest(source, destination, NULL, 0); m_endpoint->AddExpectedUsbProDataAndReturn( RDM_REQUEST_LABEL, expected_packet, size + 1, RDM_REQUEST_LABEL, return_packet, sizeof(return_packet)); m_widget->SendRDMRequest( request, ola::NewSingleCallback(this, &DmxterWidgetTest::ValidateStatus, ola::rdm::RDM_TRANSACTION_MISMATCH, frames)); m_ss.Run(); m_endpoint->Verify(); // update transaction # & checksum expected_packet[15]++; expected_packet[25] = 0xe2; return_packet[1] = 17; // timeout request = NewRequest(source, destination, NULL, 0); m_endpoint->AddExpectedUsbProDataAndReturn( RDM_REQUEST_LABEL, expected_packet, size + 1, RDM_REQUEST_LABEL, return_packet, sizeof(return_packet)); m_widget->SendRDMRequest( request, ola::NewSingleCallback(this, &DmxterWidgetTest::ValidateStatus, ola::rdm::RDM_TIMEOUT, frames)); m_ss.Run(); m_endpoint->Verify(); // update transaction # & checksum expected_packet[15]++; expected_packet[25] = 0xe3; return_packet[1] = 41; // device mismatch request = NewRequest(source, destination, NULL, 0); m_endpoint->AddExpectedUsbProDataAndReturn( RDM_REQUEST_LABEL, expected_packet, size + 1, RDM_REQUEST_LABEL, return_packet, sizeof(return_packet)); m_widget->SendRDMRequest( request, ola::NewSingleCallback(this, &DmxterWidgetTest::ValidateStatus, ola::rdm::RDM_SRC_UID_MISMATCH, frames)); m_ss.Run(); m_endpoint->Verify(); // update transaction # & checksum expected_packet[15]++; expected_packet[25] = 0xe4; return_packet[1] = 42; // sub device mismatch request = NewRequest(source, destination, NULL, 0); m_endpoint->AddExpectedUsbProDataAndReturn( RDM_REQUEST_LABEL, expected_packet, size + 1, RDM_REQUEST_LABEL, return_packet, sizeof(return_packet)); m_widget->SendRDMRequest( request, ola::NewSingleCallback(this, &DmxterWidgetTest::ValidateStatus, ola::rdm::RDM_SUB_DEVICE_MISMATCH, frames)); m_ss.Run(); m_endpoint->Verify(); delete[] expected_packet; } /* * Check some of the error conditions */ void DmxterWidgetTest::testErrorConditions() { uint8_t RDM_REQUEST_LABEL = 0x80; UID source(0x4744, 0x12345678); UID destination(3, 4); RDMFrames frames; RDMRequest *request = NewRequest(source, destination, NULL, 0); unsigned int size = RDMCommandSerializer::RequiredSize(*request); uint8_t *expected_packet = new uint8_t[size + 1]; expected_packet[0] = 0xcc; OLA_ASSERT(RDMCommandSerializer::Pack(*request, expected_packet + 1, &size)); // to small to be valid uint8_t return_packet[] = {0x00}; m_endpoint->AddExpectedUsbProDataAndReturn( RDM_REQUEST_LABEL, expected_packet, size + 1, RDM_REQUEST_LABEL, return_packet, sizeof(return_packet)); m_widget->SendRDMRequest( request, ola::NewSingleCallback(this, &DmxterWidgetTest::ValidateStatus, ola::rdm::RDM_INVALID_RESPONSE, frames)); m_ss.Run(); m_endpoint->Verify(); // check mismatched version request = NewRequest(source, destination, NULL, 0); request->SetTransactionNumber(1); OLA_ASSERT(RDMCommandSerializer::Pack(*request, expected_packet + 1, &size)); // non-0 version uint8_t return_packet2[] = {0x01, 0x11, 0xcc}; m_endpoint->AddExpectedUsbProDataAndReturn( RDM_REQUEST_LABEL, expected_packet, size + 1, RDM_REQUEST_LABEL, return_packet2, sizeof(return_packet2)); m_widget->SendRDMRequest( request, ola::NewSingleCallback(this, &DmxterWidgetTest::ValidateStatus, ola::rdm::RDM_INVALID_RESPONSE, frames)); delete[] expected_packet; m_ss.Run(); m_endpoint->Verify(); } /* * Check that the shutdown message works */ void DmxterWidgetTest::testShutdown() { uint8_t SHUTDOWN_LABEL = 0xf0; m_descriptor.SetOnClose( ola::NewSingleCallback(this, &DmxterWidgetTest::Terminate)); OLA_ASSERT(m_descriptor.ValidReadDescriptor()); OLA_ASSERT(m_descriptor.ValidWriteDescriptor()); // first try a bad message uint8_t data = 1; m_endpoint->SendUnsolicitedUsbProData(SHUTDOWN_LABEL, &data, 1); // an invalid message doesn't generate a callback so we need to set a timer // here. m_ss.RegisterSingleTimeout( 30, // 30ms should be enough ola::NewSingleCallback(this, &DmxterWidgetTest::Terminate)); m_ss.Run(); m_endpoint->Verify(); OLA_ASSERT(m_descriptor.ValidReadDescriptor()); OLA_ASSERT(m_descriptor.ValidWriteDescriptor()); m_descriptor.SetOnClose( ola::NewSingleCallback(this, &DmxterWidgetTest::CloseAndTerminate)); // now send a valid shutdown message m_endpoint->SendUnsolicitedUsbProData(SHUTDOWN_LABEL, NULL, 0); m_ss.Run(); m_endpoint->Verify(); OLA_ASSERT_FALSE(m_descriptor.ValidReadDescriptor()); OLA_ASSERT_FALSE(m_descriptor.ValidWriteDescriptor()); } ola-0.10.5.nojsmin/plugins/usbpro/BaseUsbProWidgetTest.cpp0000644000175000017500000001563513023355232023200 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * BaseUsbProWidgetTest.cpp * Test fixture for the BaseUsbProWidget class * Copyright (C) 2010 Simon Newton */ #include #include #include #include "ola/testing/TestUtils.h" #include "ola/Callback.h" #include "ola/Constants.h" #include "ola/DmxBuffer.h" #include "ola/Logging.h" #include "ola/network/NetworkUtils.h" #include "plugins/usbpro/BaseUsbProWidget.h" #include "plugins/usbpro/CommonWidgetTest.h" using ola::DmxBuffer; using std::auto_ptr; using std::queue; class BaseUsbProWidgetTest: public CommonWidgetTest { CPPUNIT_TEST_SUITE(BaseUsbProWidgetTest); CPPUNIT_TEST(testSend); CPPUNIT_TEST(testSendDMX); CPPUNIT_TEST(testReceive); CPPUNIT_TEST(testRemove); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void testSend(); void testSendDMX(); void testReceive(); void testRemove(); private: auto_ptr m_widget; bool m_removed; typedef struct { uint8_t label; unsigned int size; const uint8_t *data; } expected_message; queue m_messages; void Terminate() { m_ss.Terminate(); } void AddExpectedMessage(uint8_t label, unsigned int size, const uint8_t *data); void ReceiveMessage(uint8_t label, const uint8_t *data, unsigned int size); void DeviceRemoved() { m_removed = true; m_ss.Terminate(); } static const uint8_t DMX_FRAME_LABEL = 0x06; }; CPPUNIT_TEST_SUITE_REGISTRATION(BaseUsbProWidgetTest); void BaseUsbProWidgetTest::setUp() { CommonWidgetTest::setUp(); m_widget.reset( new ola::plugin::usbpro::DispatchingUsbProWidget( &m_descriptor, ola::NewCallback(this, &BaseUsbProWidgetTest::ReceiveMessage))); m_removed = false; m_ss.RegisterSingleTimeout( 30, // 30ms should be enough ola::NewSingleCallback(this, &BaseUsbProWidgetTest::Terminate)); } void BaseUsbProWidgetTest::AddExpectedMessage(uint8_t label, unsigned int size, const uint8_t *data) { expected_message message = { label, size, data}; m_messages.push(message); } /** * Called when a new message arrives */ void BaseUsbProWidgetTest::ReceiveMessage(uint8_t label, const uint8_t *data, unsigned int size) { OLA_ASSERT(m_messages.size()); expected_message message = m_messages.front(); m_messages.pop(); OLA_ASSERT_EQ(message.label, label); OLA_ASSERT_EQ(message.size, size); OLA_ASSERT_FALSE(memcmp(message.data, data, size)); if (m_messages.empty()) m_ss.Terminate(); } /* * Test sending works */ void BaseUsbProWidgetTest::testSend() { // simple empty frame uint8_t expected1[] = {0x7e, 0, 0, 0, 0xe7}; m_endpoint->AddExpectedData( expected1, sizeof(expected1), ola::NewSingleCallback(this, &BaseUsbProWidgetTest::Terminate)); OLA_ASSERT(m_widget->SendMessage(0, NULL, 0)); m_ss.Run(); m_endpoint->Verify(); // try a different label uint8_t expected2[] = {0x7e, 0x0a, 0, 0, 0xe7}; m_endpoint->AddExpectedData( expected2, sizeof(expected2), ola::NewSingleCallback(this, &BaseUsbProWidgetTest::Terminate)); OLA_ASSERT(m_widget->SendMessage(10, NULL, 0)); m_ss.Run(); m_endpoint->Verify(); // frame with data uint8_t expected3[] = {0x7e, 0x0b, 4, 0, 0xde, 0xad, 0xbe, 0xef, 0xe7}; m_endpoint->AddExpectedData( expected3, sizeof(expected3), ola::NewSingleCallback(this, &BaseUsbProWidgetTest::Terminate)); uint32_t data = ola::network::HostToNetwork(0xdeadbeef); OLA_ASSERT(m_widget->SendMessage(11, reinterpret_cast(&data), sizeof(data))); // try to send an incorrect frame OLA_ASSERT_FALSE(m_widget->SendMessage(10, NULL, 4)); m_ss.Run(); m_endpoint->Verify(); } /** * Check that we can send DMX */ void BaseUsbProWidgetTest::testSendDMX() { // dmx data DmxBuffer buffer; buffer.SetFromString("0,1,2,3,4"); // expected message uint8_t dmx_frame_data[] = {ola::DMX512_START_CODE, 0, 1, 2, 3, 4}; m_endpoint->AddExpectedUsbProMessage( DMX_FRAME_LABEL, dmx_frame_data, sizeof(dmx_frame_data), ola::NewSingleCallback(this, &BaseUsbProWidgetTest::Terminate)); m_widget->SendDMX(buffer); m_ss.Run(); m_endpoint->Verify(); // now test an empty frame DmxBuffer buffer2; uint8_t empty_frame_data[] = {ola::DMX512_START_CODE}; // just the start code m_endpoint->AddExpectedUsbProMessage( DMX_FRAME_LABEL, empty_frame_data, sizeof(empty_frame_data), ola::NewSingleCallback(this, &BaseUsbProWidgetTest::Terminate)); m_widget->SendDMX(buffer2); m_ss.Run(); m_endpoint->Verify(); } /* * Test receiving works. */ void BaseUsbProWidgetTest::testReceive() { uint8_t data[] = { 0x7e, 0, 0, 0, 0xe7, 0x7e, 0x0b, 4, 0, 0xde, 0xad, 0xbe, 0xef, 0xe7, 0xaa, 0xbb, // some random bytes 0x7e, 0xff, 0xff, 0xff, 0xe7, // msg is too long 0x7e, 0xa, 4, 0, 0xe7, 0xe7, 0x7e, 0xe7, 0xe7, // data contains 0xe7 0x7e, 2, 4, 0, 0xde, 0xad, 0xbe, 0xef, 0xaa, // missing EOM }; uint32_t data_chunk = ola::network::HostToNetwork(0xdeadbeef); AddExpectedMessage(0x0, 0, NULL); AddExpectedMessage(0x0b, sizeof(data_chunk), reinterpret_cast(&data_chunk)); uint32_t data_chunk2 = ola::network::HostToNetwork(0xe7e77ee7); AddExpectedMessage(0x0a, sizeof(data_chunk2), reinterpret_cast(&data_chunk2)); ssize_t bytes_sent = m_other_end->Send(data, sizeof(data)); OLA_ASSERT_EQ(static_cast(sizeof(data)), bytes_sent); m_ss.Run(); OLA_ASSERT_EQ(static_cast(0), m_messages.size()); } /** * Test on remove works. */ void BaseUsbProWidgetTest::testRemove() { m_widget->GetDescriptor()->SetOnClose( ola::NewSingleCallback(this, &BaseUsbProWidgetTest::DeviceRemoved)); m_other_end->Close(); m_ss.Run(); OLA_ASSERT(m_removed); } ola-0.10.5.nojsmin/plugins/usbpro/UltraDMXProWidget.h0000644000175000017500000000341613023355232022113 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * UltraDMXProWidget.h * The DMXKing Ultra DMX Pro Widget. * This is similar to the Enttec Usb Pro, but it has two output ports. * Copyright (C) 2011 Simon Newton */ #ifndef PLUGINS_USBPRO_ULTRADMXPROWIDGET_H_ #define PLUGINS_USBPRO_ULTRADMXPROWIDGET_H_ #include #include #include "ola/Callback.h" #include "ola/DmxBuffer.h" #include "plugins/usbpro/GenericUsbProWidget.h" namespace ola { namespace plugin { namespace usbpro { /* * An Ultra DMX Pro Widget */ class UltraDMXProWidget: public GenericUsbProWidget { public: explicit UltraDMXProWidget(ola::io::ConnectedDescriptor *descriptor); ~UltraDMXProWidget() {} void Stop() { GenericStop(); } bool SendDMX(const DmxBuffer &buffer); bool SendSecondaryDMX(const DmxBuffer &buffer); private: bool SendDMXWithLabel(uint8_t label, const DmxBuffer &data); static const uint8_t DMX_PRIMARY_PORT = 100; static const uint8_t DMX_SECONDARY_PORT = 101; }; } // namespace usbpro } // namespace plugin } // namespace ola #endif // PLUGINS_USBPRO_ULTRADMXPROWIDGET_H_ ola-0.10.5.nojsmin/plugins/usbpro/UsbSerialDevice.h0000644000175000017500000000341713023355232021640 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * UsbSerialDevice.h * Interface for the usb devices * Copyright (C) 2010 Simon Newton */ #ifndef PLUGINS_USBPRO_USBSERIALDEVICE_H_ #define PLUGINS_USBPRO_USBSERIALDEVICE_H_ #include #include "ola/Callback.h" #include "olad/Device.h" #include "plugins/usbpro/SerialWidgetInterface.h" namespace ola { namespace plugin { namespace usbpro { /* * A USB device */ class UsbSerialDevice: public ola::Device { public: UsbSerialDevice(ola::AbstractPlugin *owner, const std::string &name, SerialWidgetInterface *widget): Device(owner, name), m_widget(widget) {} virtual ~UsbSerialDevice() {} void PrePortStop() { m_widget->Stop(); } void SetOnRemove(ola::SingleUseCallback0 *on_close) { m_widget->GetDescriptor()->SetOnClose(on_close); } SerialWidgetInterface *GetWidget() const { return m_widget; } protected: SerialWidgetInterface *m_widget; }; } // namespace usbpro } // namespace plugin } // namespace ola #endif // PLUGINS_USBPRO_USBSERIALDEVICE_H_ ola-0.10.5.nojsmin/plugins/usbpro/DmxTriWidgetTest.cpp0000644000175000017500000006766613023355232022415 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DmxTriWidgetTest.cpp * Test fixture for the DmxTriWidget class * Copyright (C) 2010 Simon Newton */ #include #include #include #include #include "common/rdm/TestHelper.h" #include "ola/Callback.h" #include "ola/DmxBuffer.h" #include "ola/Logging.h" #include "ola/rdm/RDMCommand.h" #include "ola/testing/TestUtils.h" #include "plugins/usbpro/CommonWidgetTest.h" #include "plugins/usbpro/DmxTriWidget.h" using ola::DmxBuffer; using ola::NewSingleCallback; using ola::plugin::usbpro::DmxTriWidget; using ola::rdm::NewDiscoveryUniqueBranchRequest; using ola::rdm::RDMDiscoveryRequest; using ola::rdm::RDMReply; using ola::rdm::RDMRequest; using ola::rdm::RDMResponse; using ola::rdm::UID; using std::auto_ptr; using std::string; using std::vector; class DmxTriWidgetTest: public CommonWidgetTest { CPPUNIT_TEST_SUITE(DmxTriWidgetTest); CPPUNIT_TEST(testTod); CPPUNIT_TEST(testTodFailure); CPPUNIT_TEST(testLockedTod); CPPUNIT_TEST(testSendDMX); CPPUNIT_TEST(testSendRDM); CPPUNIT_TEST(testSendRDMErrors); CPPUNIT_TEST(testSendRDMBroadcast); CPPUNIT_TEST(testRawDiscovery); CPPUNIT_TEST(testNack); CPPUNIT_TEST(testAckTimer); CPPUNIT_TEST(testAckOverflow); CPPUNIT_TEST(testQueuedMessages); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void testTod(); void testTodFailure(); void testLockedTod(); void testSendDMX(); void testSendRDM(); void testSendRDMErrors(); void testSendRDMBroadcast(); void testRawDiscovery(); void testNack(); void testAckTimer(); void testAckOverflow(); void testQueuedMessages(); private: auto_ptr m_widget; unsigned int m_tod_counter; bool m_expect_uids_in_tod; void AckSingleTX(); void AckSingleTxAndTerminate(); void AckSingleTxAndExpectData(); void PopulateTod(); void ValidateTod(const ola::rdm::UIDSet &uids); void ValidateResponse(ola::rdm::RDMStatusCode expected_code, const RDMResponse *expected_response, RDMReply *reply); void ValidateStatus(ola::rdm::RDMStatusCode expected_code, RDMReply *reply); RDMRequest *NewRequest(const UID &source, const UID &destination, const uint8_t *data, unsigned int length); RDMRequest *NewQueuedMessageRequest(const UID &source, const UID &destination, uint8_t code); static const uint8_t EXTENDED_LABEL = 0x58; }; CPPUNIT_TEST_SUITE_REGISTRATION(DmxTriWidgetTest); void DmxTriWidgetTest::setUp() { CommonWidgetTest::setUp(); m_widget.reset( new ola::plugin::usbpro::DmxTriWidget(&m_ss, &m_descriptor)); m_tod_counter = 0; m_expect_uids_in_tod = false; } /** * Check the TOD matches what we expect */ void DmxTriWidgetTest::ValidateTod(const ola::rdm::UIDSet &uids) { if (m_expect_uids_in_tod) { UID uid1(0x707a, 0xffffff00); UID uid2(0x5252, 0x12345678); OLA_ASSERT_EQ((unsigned int) 2, uids.Size()); OLA_ASSERT(uids.Contains(uid1)); OLA_ASSERT(uids.Contains(uid2)); } else { OLA_ASSERT_EQ((unsigned int) 0, uids.Size()); } m_tod_counter++; m_ss.Terminate(); } /** * Check the response matches what we expected. */ void DmxTriWidgetTest::ValidateResponse( ola::rdm::RDMStatusCode expected_code, const RDMResponse *expected_response, RDMReply *reply) { OLA_ASSERT_EQ(expected_code, reply->StatusCode()); OLA_ASSERT(reply->Response()); OLA_ASSERT_TRUE(*expected_response == *reply->Response()); // the TRIs can't return the actual packets OLA_ASSERT_EMPTY(reply->Frames()); m_ss.Terminate(); } /* * Check that we received the correct status code. */ void DmxTriWidgetTest::ValidateStatus( ola::rdm::RDMStatusCode expected_code, RDMReply *reply) { OLA_ASSERT_EQ(expected_code, reply->StatusCode()); OLA_ASSERT_NULL(reply->Response()); // the TRIs can't return the actual packets OLA_ASSERT_EMPTY(reply->Frames()); m_ss.Terminate(); } /** * Helper method to create new request objects */ RDMRequest *DmxTriWidgetTest::NewRequest(const UID &source, const UID &destination, const uint8_t *data, unsigned int length) { return new ola::rdm::RDMGetRequest( source, destination, 0, // transaction # 1, // port id 10, // sub device 296, // param id data, length); } /** * Helper method to create a new queued request object */ RDMRequest *DmxTriWidgetTest::NewQueuedMessageRequest( const UID &source, const UID &destination, uint8_t code) { return new ola::rdm::RDMGetRequest( source, destination, 0, // transaction # 1, // port id 10, // sub device ola::rdm::PID_QUEUED_MESSAGE, &code, sizeof(code)); } void DmxTriWidgetTest::AckSingleTX() { uint8_t ack_response[] = {0x21, 0}; m_endpoint->SendUnsolicitedUsbProData( EXTENDED_LABEL, ack_response, sizeof(ack_response)); } void DmxTriWidgetTest::AckSingleTxAndTerminate() { AckSingleTX(); m_ss.Terminate(); } void DmxTriWidgetTest::AckSingleTxAndExpectData() { AckSingleTX(); uint8_t expected_dmx_command[] = {0x21, 0x00, 0x00, 3, 2, 3, 45}; m_endpoint->AddExpectedUsbProMessage( EXTENDED_LABEL, expected_dmx_command, sizeof(expected_dmx_command), NewSingleCallback(this, &DmxTriWidgetTest::AckSingleTxAndTerminate)); } /** * Run the sequence of commands to populate the TOD */ void DmxTriWidgetTest::PopulateTod() { uint8_t expected_discovery = 0x33; uint8_t discovery_ack[] = {0x33, 0x00}; m_endpoint->AddExpectedUsbProDataAndReturn( EXTENDED_LABEL, &expected_discovery, sizeof(expected_discovery), EXTENDED_LABEL, discovery_ack, sizeof(discovery_ack)); uint8_t expected_stat = 0x34; uint8_t stat_ack[] = {0x34, 0x00, 0x02, 0x00}; m_endpoint->AddExpectedUsbProDataAndReturn( EXTENDED_LABEL, &expected_stat, sizeof(expected_stat), EXTENDED_LABEL, stat_ack, sizeof(stat_ack)); uint8_t expected_fetch_uid1[] = {0x35, 0x02}; uint8_t expected_fetch_response1[] = { 0x35, 0x00, 0x70, 0x7a, 0xff, 0xff, 0xff, 0x00}; m_endpoint->AddExpectedUsbProDataAndReturn( EXTENDED_LABEL, expected_fetch_uid1, sizeof(expected_fetch_uid1), EXTENDED_LABEL, expected_fetch_response1, sizeof(expected_fetch_response1)); uint8_t expected_fetch_uid2[] = {0x35, 0x01}; uint8_t expected_fetch_response2[] = { 0x35, 0x00, 0x52, 0x52, 0x12, 0x34, 0x56, 0x78}; m_endpoint->AddExpectedUsbProDataAndReturn( EXTENDED_LABEL, expected_fetch_uid2, sizeof(expected_fetch_uid2), EXTENDED_LABEL, expected_fetch_response2, sizeof(expected_fetch_response2)); OLA_ASSERT_EQ((unsigned int) 0, m_tod_counter); m_expect_uids_in_tod = true; m_widget->RunFullDiscovery( NewSingleCallback(this, &DmxTriWidgetTest::ValidateTod)); m_ss.Run(); m_endpoint->Verify(); } /** * Check that the discovery sequence works correctly. */ void DmxTriWidgetTest::testTod() { PopulateTod(); OLA_ASSERT_EQ((unsigned int) 1, m_tod_counter); m_endpoint->Verify(); // check that where there are no devices, things work // this also tests multiple stat commands uint8_t expected_discovery = 0x33; uint8_t discovery_ack[] = {0x33, 0x00}; m_endpoint->AddExpectedUsbProDataAndReturn( EXTENDED_LABEL, &expected_discovery, sizeof(expected_discovery), EXTENDED_LABEL, discovery_ack, sizeof(discovery_ack)); uint8_t expected_stat = 0x34; uint8_t stat_in_progress_ack[] = {0x34, 0x00, 0x00, 0x01}; m_endpoint->AddExpectedUsbProDataAndReturn( EXTENDED_LABEL, &expected_stat, sizeof(expected_stat), EXTENDED_LABEL, stat_in_progress_ack, sizeof(stat_in_progress_ack)); uint8_t stat_nil_devices_ack[] = {0x34, 0x00, 0x00, 0x00}; m_endpoint->AddExpectedUsbProDataAndReturn( EXTENDED_LABEL, &expected_stat, sizeof(expected_stat), EXTENDED_LABEL, stat_nil_devices_ack, sizeof(stat_nil_devices_ack)); m_expect_uids_in_tod = false; m_widget->RunFullDiscovery( NewSingleCallback(this, &DmxTriWidgetTest::ValidateTod)); m_ss.Run(); OLA_ASSERT_EQ((unsigned int) 2, m_tod_counter); m_endpoint->Verify(); // check that an error behaves like we expect m_endpoint->AddExpectedUsbProDataAndReturn( EXTENDED_LABEL, &expected_discovery, sizeof(expected_discovery), EXTENDED_LABEL, discovery_ack, sizeof(discovery_ack)); uint8_t stat_error_ack[] = {0x34, 0x1b, 0x00, 0x00}; m_endpoint->AddExpectedUsbProDataAndReturn( EXTENDED_LABEL, &expected_stat, sizeof(expected_stat), EXTENDED_LABEL, stat_error_ack, sizeof(stat_error_ack)); m_expect_uids_in_tod = false; m_widget->RunFullDiscovery( NewSingleCallback(this, &DmxTriWidgetTest::ValidateTod)); m_ss.Run(); OLA_ASSERT_EQ((unsigned int) 3, m_tod_counter); m_endpoint->Verify(); } /** * Check what happens if a DiscoAuto command fails. */ void DmxTriWidgetTest::testTodFailure() { PopulateTod(); OLA_ASSERT_EQ((unsigned int) 1, m_tod_counter); m_endpoint->Verify(); m_descriptor.Close(); m_other_end->Close(); // Failures cause the last Tod to be returned. m_expect_uids_in_tod = true; m_widget->RunFullDiscovery( NewSingleCallback(this, &DmxTriWidgetTest::ValidateTod)); OLA_ASSERT_EQ((unsigned int) 2, m_tod_counter); m_endpoint->Verify(); } /** * Check that the discovery works when the widget doesn't support RDM */ void DmxTriWidgetTest::testLockedTod() { uint8_t expected_discovery = 0x33; uint8_t discovery_ack[] = {0x33, 0x02}; m_endpoint->AddExpectedUsbProDataAndReturn( EXTENDED_LABEL, &expected_discovery, sizeof(expected_discovery), EXTENDED_LABEL, discovery_ack, sizeof(discovery_ack)); m_expect_uids_in_tod = false; m_widget->RunFullDiscovery( NewSingleCallback(this, &DmxTriWidgetTest::ValidateTod)); m_ss.Run(); m_endpoint->Verify(); } /** * Check that we send DMX correctly. */ void DmxTriWidgetTest::testSendDMX() { DmxBuffer data, data2, data3; data.SetFromString("1,2,3,45"); data2.SetFromString("2,2,3,45"); data3.SetFromString("3,2,3,45"); m_widget->SendDMX(data); m_widget->SendDMX(data2); m_widget->SendDMX(data3); uint8_t expected_dmx_command1[] = {0x21, 0x0, 0x00, 1, 2, 3, 45}; m_endpoint->AddExpectedUsbProMessage( EXTENDED_LABEL, expected_dmx_command1, sizeof(expected_dmx_command1), NewSingleCallback(this, &DmxTriWidgetTest::AckSingleTxAndExpectData)); m_ss.Run(); // The ss may terminate before the widget has a chance to read from the // descriptor. Run the ss once more to catch this case. m_ss.RunOnce(ola::TimeInterval(1, 0)); m_endpoint->Verify(); } /** * Check that we send RDM messages correctly. */ void DmxTriWidgetTest::testSendRDM() { UID source(1, 2); UID destination(0x707a, 0xffffff00); uint8_t param_data[] = {0xa1, 0xb2}; RDMRequest *request = NewRequest( source, destination, param_data, sizeof(param_data)); // first of all confirm we can't send to a UID not in the TOD m_widget->SendRDMRequest( request, NewSingleCallback(this, &DmxTriWidgetTest::ValidateStatus, ola::rdm::RDM_UNKNOWN_UID)); // now populate the TOD PopulateTod(); request = NewRequest( source, destination, param_data, sizeof(param_data)); uint8_t expected_rdm_command[] = {0x38, 0x02, 0x00, 0x0a, 0x01, 0x28, 0xa1, 0xb2}; uint8_t command_response[] = {0x38, 0x00, 0x5a, 0xa5, 0x5a, 0xa5}; m_endpoint->AddExpectedUsbProDataAndReturn( EXTENDED_LABEL, expected_rdm_command, sizeof(expected_rdm_command), EXTENDED_LABEL, command_response, sizeof(command_response)); uint8_t return_data[] = {0x5a, 0xa5, 0x5a, 0xa5}; ola::rdm::RDMGetResponse response( destination, source, 0, // transaction # 1, // port id 0, // message count 10, // sub device 296, // param id return_data, sizeof(return_data)); // data length m_widget->SendRDMRequest( request, NewSingleCallback(this, &DmxTriWidgetTest::ValidateResponse, ola::rdm::RDM_COMPLETED_OK, static_cast(&response))); m_ss.Run(); m_endpoint->Verify(); // confirm a queued message shows up in the counter request = NewRequest( source, destination, param_data, sizeof(param_data)); uint8_t queued_command_response[] = {0x38, 0x11, 0x5a, 0xa5, 0x5a, 0xa5}; m_endpoint->AddExpectedUsbProDataAndReturn( EXTENDED_LABEL, expected_rdm_command, sizeof(expected_rdm_command), EXTENDED_LABEL, queued_command_response, sizeof(queued_command_response)); ola::rdm::RDMGetResponse response2( destination, source, 0, // transaction # ola::rdm::RDM_ACK, 1, // message count 10, // sub device 296, // param id return_data, sizeof(return_data)); // data length m_widget->SendRDMRequest( request, NewSingleCallback( this, &DmxTriWidgetTest::ValidateResponse, ola::rdm::RDM_COMPLETED_OK, static_cast(&response2))); m_ss.Run(); m_endpoint->Verify(); } /** * Check that various errors are handled correctly */ void DmxTriWidgetTest::testSendRDMErrors() { UID source(1, 2); UID destination(0x707a, 0xffffff00); // populate the TOD PopulateTod(); uint8_t expected_rdm_command[] = {0x38, 0x02, 0x00, 0x0a, 0x01, 0x28}; // confirm transaction mis-match works RDMRequest *request = NewRequest(source, destination, NULL, 0); uint8_t transaction_mismatch_response[] = {0x38, 0x13}; m_endpoint->AddExpectedUsbProDataAndReturn( EXTENDED_LABEL, expected_rdm_command, sizeof(expected_rdm_command), EXTENDED_LABEL, transaction_mismatch_response, sizeof(transaction_mismatch_response)); m_widget->SendRDMRequest( request, NewSingleCallback(this, &DmxTriWidgetTest::ValidateStatus, ola::rdm::RDM_TRANSACTION_MISMATCH)); m_ss.Run(); m_endpoint->Verify(); // confirm wrong sub device works request = NewRequest(source, destination, NULL, 0); uint8_t wrong_subdevice_response[] = {0x38, 0x14}; m_endpoint->AddExpectedUsbProDataAndReturn( EXTENDED_LABEL, expected_rdm_command, sizeof(expected_rdm_command), EXTENDED_LABEL, wrong_subdevice_response, sizeof(wrong_subdevice_response)); m_widget->SendRDMRequest( request, NewSingleCallback(this, &DmxTriWidgetTest::ValidateStatus, ola::rdm::RDM_SUB_DEVICE_MISMATCH)); m_ss.Run(); m_endpoint->Verify(); // confirm a invalid reponse behaves request = NewRequest(source, destination, NULL, 0); uint8_t invalid_response[] = {0x38, 0x15}; m_endpoint->AddExpectedUsbProDataAndReturn( EXTENDED_LABEL, expected_rdm_command, sizeof(expected_rdm_command), EXTENDED_LABEL, invalid_response, sizeof(invalid_response)); m_widget->SendRDMRequest( request, NewSingleCallback(this, &DmxTriWidgetTest::ValidateStatus, ola::rdm::RDM_INVALID_RESPONSE)); m_ss.Run(); m_endpoint->Verify(); // confirm a checksum mismatch fails request = NewRequest(source, destination, NULL, 0); uint8_t bad_checksum_response[] = {0x38, 0x16}; m_endpoint->AddExpectedUsbProDataAndReturn( EXTENDED_LABEL, expected_rdm_command, sizeof(expected_rdm_command), EXTENDED_LABEL, bad_checksum_response, sizeof(bad_checksum_response)); m_widget->SendRDMRequest( request, NewSingleCallback(this, &DmxTriWidgetTest::ValidateStatus, ola::rdm::RDM_CHECKSUM_INCORRECT)); m_ss.Run(); m_endpoint->Verify(); // confirm a timeout behaves request = NewRequest(source, destination, NULL, 0); uint8_t timeout_response[] = {0x38, 0x18}; m_endpoint->AddExpectedUsbProDataAndReturn( EXTENDED_LABEL, expected_rdm_command, sizeof(expected_rdm_command), EXTENDED_LABEL, timeout_response, sizeof(timeout_response)); m_widget->SendRDMRequest( request, NewSingleCallback(this, &DmxTriWidgetTest::ValidateStatus, ola::rdm::RDM_TIMEOUT)); m_ss.Run(); m_endpoint->Verify(); // confirm a wrong device works request = NewRequest(source, destination, NULL, 0); uint8_t wrong_device_response[] = {0x38, 0x1a}; m_endpoint->AddExpectedUsbProDataAndReturn( EXTENDED_LABEL, expected_rdm_command, sizeof(expected_rdm_command), EXTENDED_LABEL, wrong_device_response, sizeof(wrong_device_response)); m_widget->SendRDMRequest( request, NewSingleCallback(this, &DmxTriWidgetTest::ValidateStatus, ola::rdm::RDM_SRC_UID_MISMATCH)); m_ss.Run(); m_endpoint->Verify(); } /* * Check that broadcast / vendorcast works */ void DmxTriWidgetTest::testSendRDMBroadcast() { UID source(1, 2); UID vendor_cast_destination(0x707a, 0xffffffff); UID bcast_destination(0xffff, 0xffffffff); PopulateTod(); RDMRequest *request = NewRequest( source, vendor_cast_destination, NULL, 0); uint8_t expected_set_filter[] = {0x3d, 0x70, 0x7a}; uint8_t set_filter_response[] = {0x3d, 0x00}; m_endpoint->AddExpectedUsbProDataAndReturn( EXTENDED_LABEL, expected_set_filter, sizeof(expected_set_filter), EXTENDED_LABEL, set_filter_response, sizeof(set_filter_response)); uint8_t expected_rdm_command[] = {0x38, 0x00, 0x00, 0x0a, 0x01, 0x28}; uint8_t command_response[] = {0x38, 0x00}; m_endpoint->AddExpectedUsbProDataAndReturn( EXTENDED_LABEL, expected_rdm_command, sizeof(expected_rdm_command), EXTENDED_LABEL, command_response, sizeof(command_response)); m_widget->SendRDMRequest( request, NewSingleCallback(this, &DmxTriWidgetTest::ValidateStatus, ola::rdm::RDM_WAS_BROADCAST)); m_ss.Run(); m_endpoint->Verify(); // check broad cast request = NewRequest(source, bcast_destination, NULL, 0); uint8_t expected_bcast_set_filter[] = {0x3d, 0xff, 0xff}; m_endpoint->AddExpectedUsbProDataAndReturn( EXTENDED_LABEL, expected_bcast_set_filter, sizeof(expected_bcast_set_filter), EXTENDED_LABEL, set_filter_response, sizeof(set_filter_response)); m_endpoint->AddExpectedUsbProDataAndReturn( EXTENDED_LABEL, expected_rdm_command, sizeof(expected_rdm_command), EXTENDED_LABEL, command_response, sizeof(command_response)); m_widget->SendRDMRequest( request, NewSingleCallback(this, &DmxTriWidgetTest::ValidateStatus, ola::rdm::RDM_WAS_BROADCAST)); m_ss.Run(); m_endpoint->Verify(); // check that we don't call set filter if it's the same uid request = NewRequest(source, bcast_destination, NULL, 0); m_endpoint->AddExpectedUsbProDataAndReturn( EXTENDED_LABEL, expected_rdm_command, sizeof(expected_rdm_command), EXTENDED_LABEL, command_response, sizeof(command_response)); m_widget->SendRDMRequest( request, NewSingleCallback(this, &DmxTriWidgetTest::ValidateStatus, ola::rdm::RDM_WAS_BROADCAST)); m_ss.Run(); m_endpoint->Verify(); // check that we fail correctly if set filter fails request = NewRequest(source, vendor_cast_destination, NULL, 0); uint8_t failed_set_filter_response[] = {0x3d, 0x02}; m_endpoint->AddExpectedUsbProDataAndReturn( EXTENDED_LABEL, expected_set_filter, sizeof(expected_set_filter), EXTENDED_LABEL, failed_set_filter_response, sizeof(failed_set_filter_response)); m_widget->SendRDMRequest( request, NewSingleCallback(this, &DmxTriWidgetTest::ValidateStatus, ola::rdm::RDM_FAILED_TO_SEND)); m_ss.Run(); m_endpoint->Verify(); } /* * Check that raw discovery commands work. */ void DmxTriWidgetTest::testRawDiscovery() { UID source(1, 2); UID lower(0, 0); UID upper(0xffff, 0xfffffff); PopulateTod(); RDMDiscoveryRequest *dub_request = NewDiscoveryUniqueBranchRequest( source, lower, upper, 1); // Verify we can't send raw commands with the non-raw widget. m_widget->SendRDMRequest( dub_request, NewSingleCallback(this, &DmxTriWidgetTest::ValidateStatus, ola::rdm::RDM_PLUGIN_DISCOVERY_NOT_SUPPORTED)); m_endpoint->Verify(); } /* * Check that nacks work as expected. */ void DmxTriWidgetTest::testNack() { UID source(1, 2); UID destination(0x707a, 0xffffff00); PopulateTod(); RDMRequest *request = NewRequest(source, destination, NULL, 0); uint8_t expected_rdm_command[] = {0x38, 0x02, 0x00, 0x0a, 0x01, 0x28}; uint8_t nack_pid_response[] = {0x38, 0x20}; // unknown pid m_endpoint->AddExpectedUsbProDataAndReturn( EXTENDED_LABEL, expected_rdm_command, sizeof(expected_rdm_command), EXTENDED_LABEL, nack_pid_response, sizeof(nack_pid_response)); RDMResponse *response = ola::rdm::NackWithReason( request, ola::rdm::NR_UNKNOWN_PID); m_widget->SendRDMRequest( request, NewSingleCallback(this, &DmxTriWidgetTest::ValidateResponse, ola::rdm::RDM_COMPLETED_OK, static_cast(response))); m_ss.Run(); m_endpoint->Verify(); delete response; // try a proxy buffer full request = NewRequest(source, destination, NULL, 0); uint8_t nack_proxy_response[] = {0x38, 0x2a}; // bad proxy m_endpoint->AddExpectedUsbProDataAndReturn( EXTENDED_LABEL, expected_rdm_command, sizeof(expected_rdm_command), EXTENDED_LABEL, nack_proxy_response, sizeof(nack_proxy_response)); response = ola::rdm::NackWithReason( request, ola::rdm::NR_PROXY_BUFFER_FULL); m_widget->SendRDMRequest( request, NewSingleCallback(this, &DmxTriWidgetTest::ValidateResponse, ola::rdm::RDM_COMPLETED_OK, static_cast(response))); m_ss.Run(); m_endpoint->Verify(); delete response; } /* * Check that ack timer works as expected. */ void DmxTriWidgetTest::testAckTimer() { UID source(1, 2); UID destination(0x707a, 0xffffff00); PopulateTod(); RDMRequest *request = NewRequest(source, destination, NULL, 0); uint8_t expected_rdm_command[] = {0x38, 0x02, 0x00, 0x0a, 0x01, 0x28}; uint8_t ack_timer_response[] = {0x38, 0x10, 0x00, 0x10}; // ack timer, 1.6s m_endpoint->AddExpectedUsbProDataAndReturn( EXTENDED_LABEL, expected_rdm_command, sizeof(expected_rdm_command), EXTENDED_LABEL, ack_timer_response, sizeof(ack_timer_response)); uint8_t return_data[] = {0x00, 0x10}; ola::rdm::RDMGetResponse response( destination, source, 0, // transaction # ola::rdm::RDM_ACK_TIMER, 0, // message count 10, // sub device 296, // param id return_data, sizeof(return_data)); // data length m_widget->SendRDMRequest( request, NewSingleCallback(this, &DmxTriWidgetTest::ValidateResponse, ola::rdm::RDM_COMPLETED_OK, static_cast(&response))); m_ss.Run(); m_endpoint->Verify(); } /* * Check that ack overflow works as expected. */ void DmxTriWidgetTest::testAckOverflow() { UID source(1, 2); UID destination(0x707a, 0xffffff00); PopulateTod(); RDMRequest *request = NewRequest(source, destination, NULL, 0); uint8_t expected_rdm_command[] = {0x38, 0x02, 0x00, 0x0a, 0x01, 0x28}; uint8_t ack_overflow_response[] = {0x38, 0x12, 0x12, 0x34}; // ack overflow uint8_t ack_response[] = {0x38, 0x0, 0x56, 0x78}; // ack overflow m_endpoint->AddExpectedUsbProDataAndReturn( EXTENDED_LABEL, expected_rdm_command, sizeof(expected_rdm_command), EXTENDED_LABEL, ack_overflow_response, sizeof(ack_overflow_response)); m_endpoint->AddExpectedUsbProDataAndReturn( EXTENDED_LABEL, expected_rdm_command, sizeof(expected_rdm_command), EXTENDED_LABEL, ack_response, sizeof(ack_response)); uint8_t return_data[] = {0x12, 0x34, 0x56, 0x78}; ola::rdm::RDMGetResponse response( destination, source, 0, // transaction # ola::rdm::RDM_ACK, 0, // message count 10, // sub device 296, // param id return_data, sizeof(return_data)); // data length m_widget->SendRDMRequest( request, NewSingleCallback(this, &DmxTriWidgetTest::ValidateResponse, ola::rdm::RDM_COMPLETED_OK, static_cast(&response))); m_ss.Run(); m_endpoint->Verify(); } /* * Check that queued messages work. */ void DmxTriWidgetTest::testQueuedMessages() { UID source(1, 2); UID destination(0x707a, 0xffffff00); PopulateTod(); // first try a response which is too short RDMRequest *request = NewQueuedMessageRequest(source, destination, 1); uint8_t expected_rdm_command[] = {0x3a, 0x02, 0x01}; uint8_t small_response[] = {0x3a, 0x04}; m_endpoint->AddExpectedUsbProDataAndReturn( EXTENDED_LABEL, expected_rdm_command, sizeof(expected_rdm_command), EXTENDED_LABEL, small_response, sizeof(small_response)); m_widget->SendRDMRequest( request, NewSingleCallback(this, &DmxTriWidgetTest::ValidateStatus, ola::rdm::RDM_INVALID_RESPONSE)); m_ss.Run(); m_endpoint->Verify(); // now try a proper response request = NewQueuedMessageRequest(source, destination, 1); uint8_t queued_response[] = {0x3a, 0x00, 0x00, 0x60, 0x52}; m_endpoint->AddExpectedUsbProDataAndReturn( EXTENDED_LABEL, expected_rdm_command, sizeof(expected_rdm_command), EXTENDED_LABEL, queued_response, sizeof(queued_response)); uint8_t return_data = 0x52; ola::rdm::RDMGetResponse response( destination, source, 0, // transaction # ola::rdm::RDM_ACK, 0, // message count 10, // sub device 0x0060, // param id &return_data, sizeof(return_data)); // data length m_widget->SendRDMRequest( request, NewSingleCallback(this, &DmxTriWidgetTest::ValidateResponse, ola::rdm::RDM_COMPLETED_OK, static_cast(&response))); m_ss.Run(); m_endpoint->Verify(); } ola-0.10.5.nojsmin/plugins/usbpro/UsbProWidgetDetector.cpp0000644000175000017500000004440713134123277023243 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * UsbProWidgetDetector.cpp * Handles the discovery process for widgets that implement the Usb Pro frame * format. * Copyright (C) 2010 Simon Newton * * This class accepts a ConnectedDescriptor objects and runs the discovery * process to determine if the widget behaves like a Usb Pro device. * * The discovery process sends the following request messages: * - MANUFACTURER_LABEL * - DEVICE_LABEL * - SERIAL_LABEL * - HARDWARE_VERSION (optional) * * Requests are sent at an interval specified by message_interval in the * constructor. Of these, the only message a widget must respond to is * SERIAL_LABEL. The other two messages are part of the Usb Pro Extensions * (https://wiki.openlighting.org/index.php/USB_Protocol_Extensions) and allow * us to determine more specfically what type of device this is. * * If the widget responds to SERIAL_LABEL the on_success callback is run. * Otherwise on_failure is run. It's important you register callbacks for each * of these otherwise you'll leak ConnectedDescriptor objects. */ #include #include #include #include "ola/Logging.h" #include "ola/io/Descriptor.h" #include "ola/network/NetworkUtils.h" #include "ola/strings/Format.h" #include "ola/util/Utils.h" #include "plugins/usbpro/BaseUsbProWidget.h" #include "plugins/usbpro/GenericUsbProWidget.h" #include "plugins/usbpro/UsbProWidgetDetector.h" namespace ola { namespace plugin { namespace usbpro { using ola::strings::ToHex; using std::string; UsbProWidgetInformation& UsbProWidgetInformation::operator=( const UsbProWidgetInformation &other) { esta_id = other.esta_id; device_id = other.device_id; manufacturer = other.manufacturer; device = other.device; serial = other.serial; has_firmware_version = other.has_firmware_version; firmware_version = other.firmware_version; return *this; } /** * Constructor * @param scheduler a SchedulingExecutorInterface to use to register events. * @param on_success A callback to run if discovery succeeds. * @param on_failure A callback to run if discovery fails. * @param message_interval the time in ms between each discovery message. */ UsbProWidgetDetector::UsbProWidgetDetector( ola::thread::SchedulingExecutorInterface *scheduler, SuccessHandler *on_success, FailureHandler *on_failure, unsigned int message_interval) : m_scheduler(scheduler), m_callback(on_success), m_failure_callback(on_failure), m_timeout_ms(message_interval) { if (!on_success) { OLA_WARN << "on_success callback not set, this will leak memory!"; } if (!on_failure) { OLA_WARN << "on_failure callback not set, this will leak memory!"; } } /* * Fail any widgets that are still in the discovery process. */ UsbProWidgetDetector::~UsbProWidgetDetector() { m_scheduler->DrainCallbacks(); WidgetStateMap::iterator iter; for (iter = m_widgets.begin(); iter != m_widgets.end(); ++iter) { iter->first->GetDescriptor()->SetOnClose(NULL); if (m_failure_callback.get()) { m_failure_callback->Run(iter->first->GetDescriptor()); } RemoveTimeout(&iter->second); } m_widgets.clear(); } /* * Start the discovery process for a widget * @param widget, the DispatchingUsbProWidget to run discovery on. * @return true if the process started ok, false otherwise. */ bool UsbProWidgetDetector::Discover( ola::io::ConnectedDescriptor *descriptor) { DispatchingUsbProWidget *widget = new DispatchingUsbProWidget( descriptor, NULL); widget->SetHandler( NewCallback(this, &UsbProWidgetDetector::HandleMessage, widget)); if (!widget->SendMessage(BaseUsbProWidget::MANUFACTURER_LABEL, NULL, 0)) { delete widget; return false; } // Set the onclose handler so we can mark this as failed. descriptor->SetOnClose( NewSingleCallback(this, &UsbProWidgetDetector::WidgetRemoved, widget)); // register a timeout for this widget SetupTimeout(widget, &m_widgets[widget]); return true; } /* * Called by the widgets when they receive a response. */ void UsbProWidgetDetector::HandleMessage(DispatchingUsbProWidget *widget, uint8_t label, const uint8_t *data, unsigned int length) { switch (label) { case BaseUsbProWidget::MANUFACTURER_LABEL: HandleIdResponse(widget, length, data, false); break; case BaseUsbProWidget::DEVICE_LABEL: HandleIdResponse(widget, length, data, true); break; case BaseUsbProWidget::SERIAL_LABEL: HandleSerialResponse(widget, length, data); break; case BaseUsbProWidget::GET_PARAMS: HandleGetParams(widget, length, data); break; case BaseUsbProWidget::HARDWARE_VERSION_LABEL: HandleHardwareVersionResponse(widget, length, data); break; case ENTTEC_SNIFFER_LABEL: HandleSnifferPacket(widget); break; case GenericUsbProWidget::RECEIVED_DMX_LABEL: break; default: OLA_WARN << "Unknown response label: " << ToHex(label) << ", length " << length; } } /** * Called if the widget is removed mid-discovery process */ void UsbProWidgetDetector::WidgetRemoved(DispatchingUsbProWidget *widget) { WidgetStateMap::iterator iter = m_widgets.find(widget); if (iter == m_widgets.end()) { OLA_FATAL << "Widget " << widget << " removed but it doesn't exist in the widget map"; } else { RemoveTimeout(&(iter->second)); m_widgets.erase(iter); } ola::io::ConnectedDescriptor *descriptor = widget->GetDescriptor(); delete widget; descriptor->SetOnClose(NULL); descriptor->Close(); if (m_failure_callback.get()) { m_failure_callback->Run(descriptor); } } /** * Setup a timeout for a widget */ void UsbProWidgetDetector::SetupTimeout(DispatchingUsbProWidget *widget, DiscoveryState *discovery_state) { discovery_state->timeout_id = m_scheduler->RegisterSingleTimeout( m_timeout_ms, NewSingleCallback(this, &UsbProWidgetDetector::DiscoveryTimeout, widget)); } /** * Remove a timeout for a widget. */ void UsbProWidgetDetector::RemoveTimeout(DiscoveryState *discovery_state) { if (discovery_state->timeout_id != ola::thread::INVALID_TIMEOUT) { m_scheduler->RemoveTimeout(discovery_state->timeout_id); } } /** * Send a DEVICE_LABEL request */ void UsbProWidgetDetector::SendNameRequest(DispatchingUsbProWidget *widget) { widget->SendMessage(DispatchingUsbProWidget::DEVICE_LABEL, NULL, 0); DiscoveryState &discovery_state = m_widgets[widget]; discovery_state.discovery_state = DiscoveryState::DEVICE_SENT; SetupTimeout(widget, &discovery_state); } /** * Set a SERIAL_LABEL request */ void UsbProWidgetDetector::SendSerialRequest(DispatchingUsbProWidget *widget) { widget->SendMessage(DispatchingUsbProWidget::SERIAL_LABEL, NULL, 0); DiscoveryState &discovery_state = m_widgets[widget]; discovery_state.discovery_state = DiscoveryState::SERIAL_SENT; SetupTimeout(widget, &discovery_state); } /** * Set a GET_PARAMS request */ void UsbProWidgetDetector::SendGetParams(DispatchingUsbProWidget *widget) { uint16_t data = 0; widget->SendMessage(DispatchingUsbProWidget::GET_PARAMS, reinterpret_cast(&data), sizeof(data)); DiscoveryState &discovery_state = m_widgets[widget]; discovery_state.discovery_state = DiscoveryState::GET_PARAM_SENT; SetupTimeout(widget, &discovery_state); } /** * Send a Hardware version message, this is only valid for Enttec Usb Pro MkII * widgets. */ void UsbProWidgetDetector::MaybeSendHardwareVersionRequest( DispatchingUsbProWidget *widget) { WidgetStateMap::iterator iter = m_widgets.find(widget); if (iter == m_widgets.end()) { return; } UsbProWidgetInformation &information = iter->second.information; if (information.esta_id == 0 && information.device_id == 0) { // This widget didn't respond to Manufacturer or Device messages, // but did respond to GetSerial, so it's probably a USB Pro. Now we // need to check if it's a MK II widget. widget->SendMessage( DispatchingUsbProWidget::HARDWARE_VERSION_LABEL, NULL, 0); DiscoveryState &discovery_state = m_widgets[widget]; discovery_state.discovery_state = DiscoveryState::HARDWARE_VERSION_SENT; SetupTimeout(widget, &discovery_state); } else { // otherwise there are no more messages to send. CompleteWidgetDiscovery(widget); } } /** * Send OLA's API key to unlock the second port of a Usb Pro MkII Widget. * Note: The labels for the messages used to control the 2nd port of the Mk II * depend on this key value. If you're writing other software you can obtain a * key by emailing Enttec, rather than just copying the value here. */ void UsbProWidgetDetector::SendAPIRequest(DispatchingUsbProWidget *widget) { uint32_t key = ola::network::LittleEndianToHost(USB_PRO_MKII_API_KEY); widget->SendMessage(USB_PRO_MKII_API_LABEL, reinterpret_cast(&key), sizeof(key)); } /* * Called if a widget fails to respond in a given interval */ void UsbProWidgetDetector::DiscoveryTimeout(DispatchingUsbProWidget *widget) { WidgetStateMap::iterator iter = m_widgets.find(widget); if (iter != m_widgets.end()) { iter->second.timeout_id = ola::thread::INVALID_TIMEOUT; switch (iter->second.discovery_state) { case DiscoveryState::MANUFACTURER_SENT: SendNameRequest(widget); break; case DiscoveryState::DEVICE_SENT: SendSerialRequest(widget); break; case DiscoveryState::GET_PARAM_SENT: MaybeSendHardwareVersionRequest(widget); break; case DiscoveryState::HARDWARE_VERSION_SENT: CompleteWidgetDiscovery(widget); break; default: OLA_WARN << "USB Widget didn't respond to messages, esta id " << iter->second.information.esta_id << ", device id " << iter->second.information.device_id; OLA_WARN << "Is device in USB Controller mode if it's a Goddard?"; ola::io::ConnectedDescriptor *descriptor = widget->GetDescriptor(); descriptor->SetOnClose(NULL); delete widget; if (m_failure_callback.get()) { m_failure_callback->Run(descriptor); } m_widgets.erase(iter); } } } /* * Handle a Device Manufacturer or Device Name response. * @param widget the DispatchingUsbProWidget * @param length length of the response * @param data pointer to the response data * @param is_device true if this is a device response, false if it's a * manufacturer response. */ void UsbProWidgetDetector::HandleIdResponse(DispatchingUsbProWidget *widget, unsigned int length, const uint8_t *data, bool is_device) { struct { uint8_t id_low; uint8_t id_high; char text[32]; uint8_t terminator; } response; memset(&response, 0, sizeof(response)); memcpy(&response, data, length); WidgetStateMap::iterator iter = m_widgets.find(widget); if (iter == m_widgets.end()) { return; } uint16_t id = ola::utils::JoinUInt8(response.id_high, response.id_low); if (length < sizeof(id)) { OLA_WARN << "Received small response packet"; return; } if (is_device) { iter->second.information.device_id = id; iter->second.information.device = string(response.text); if (iter->second.discovery_state == DiscoveryState::DEVICE_SENT) { RemoveTimeout(&iter->second); SendSerialRequest(widget); } } else { iter->second.information.esta_id = id; iter->second.information.manufacturer = string(response.text); if (iter->second.discovery_state == DiscoveryState::MANUFACTURER_SENT) { RemoveTimeout(&iter->second); SendNameRequest(widget); } } } /* * Handle a serial response, this ends the device detection phase. */ void UsbProWidgetDetector::HandleSerialResponse( DispatchingUsbProWidget *widget, unsigned int length, const uint8_t *data) { WidgetStateMap::iterator iter = m_widgets.find(widget); if (iter == m_widgets.end()) { return; } RemoveTimeout(&iter->second); UsbProWidgetInformation information = iter->second.information; if (length == sizeof(information.serial)) { UsbProWidgetInformation::DeviceSerialNumber serial; memcpy(reinterpret_cast(&serial), data, sizeof(serial)); iter->second.information.serial = ola::network::LittleEndianToHost(serial); } else { OLA_WARN << "Serial number response size " << length << " != " << sizeof(information.serial); } SendGetParams(widget); } void UsbProWidgetDetector::HandleGetParams(DispatchingUsbProWidget *widget, unsigned int length, const uint8_t *data) { WidgetStateMap::iterator iter = m_widgets.find(widget); if (iter == m_widgets.end()) { return; } struct widget_params { uint8_t firmware_lo; uint8_t firmware_hi; uint8_t break_time; uint8_t mab_time; uint8_t output_rate; }; if (length < sizeof(widget_params)) { OLA_WARN << "Response to GET_PARAMS too small, ignoring"; } else { const widget_params *params = reinterpret_cast(data); UsbProWidgetInformation &information = iter->second.information; information.SetFirmware((params->firmware_hi << 8) + params->firmware_lo); } MaybeSendHardwareVersionRequest(widget); } /* * Handle a hardware version response. */ void UsbProWidgetDetector::HandleHardwareVersionResponse( DispatchingUsbProWidget *widget, unsigned int length, const uint8_t *data) { if (length != 1) { OLA_WARN << "Wrong size of hardware version response, was " << length; return; } OLA_DEBUG << "Hardware version response was " << ToHex(data[0]); WidgetStateMap::iterator iter = m_widgets.find(widget); if (iter == m_widgets.end()) { return; } RemoveTimeout(&iter->second); if ((data[0] == DMX_PRO_MKII_VERSION) || (data[0] == DMX_PRO_MKII_B_VERSION)) { iter->second.information.dual_port = true; SendAPIRequest(widget); } CompleteWidgetDiscovery(widget); } /** * Handle a possible sniffer packet. * Enttec sniffers are very boisterous and continuously send frames. This * causes all sorts of problems and for now we don't want to use these devices. * We track the number of sniffer frames received and if it's more than one we * declare this device a sniffer. */ void UsbProWidgetDetector::HandleSnifferPacket( DispatchingUsbProWidget *widget) { WidgetStateMap::iterator iter = m_widgets.find(widget); if (iter == m_widgets.end()) { return; } OLA_DEBUG << "Received Enttec Sniffer Packet"; iter->second.sniffer_packets++; } /** * Called when the last timeout expires, or we receive the final message. This * cleans up state and executes the m_callback in the scheduler thread. */ void UsbProWidgetDetector::CompleteWidgetDiscovery( DispatchingUsbProWidget *widget) { WidgetStateMap::iterator iter = m_widgets.find(widget); if (iter == m_widgets.end()) { return; } unsigned int sniffer_packets = iter->second.sniffer_packets; const UsbProWidgetInformation information = iter->second.information; m_widgets.erase(iter); if (sniffer_packets > 1) { OLA_WARN << "Enttec sniffer found (" << sniffer_packets << " packets), discarding"; // we can't delete the widget here since it called us. // instead schedule a call in the other thread. widget->GetDescriptor()->SetOnData(NULL); m_scheduler->Execute( NewSingleCallback(this, &UsbProWidgetDetector::HandleSniffer, widget)); return; } std::ostringstream str; str << "ESTA Id: " << ToHex(information.esta_id); if (!information.manufacturer.empty()) { str << " (" << information.manufacturer << ")"; } str << ", device Id: " << ToHex(information.device_id); if (!information.device.empty()) { str << " (" << information.device << ")"; } str << ", serial: " << ToHex(information.serial) << ", f/w version: "; if (information.has_firmware_version) { str << (information.firmware_version >> 8) << "." << (information.firmware_version & 0xff); } else { str << "N/A"; } OLA_INFO << "Detected USB Device: " << str.str(); const UsbProWidgetInformation *widget_info = new UsbProWidgetInformation( information); // Given that we've been called via the widget's stack, schedule execution of // the method that deletes the widget. m_scheduler->Execute( NewSingleCallback(this, &UsbProWidgetDetector::DispatchWidget, widget, widget_info)); } /** * Called once we have confirmed a new widget. This runs in the scheduler * thread, so it can't access any non-const member data. */ void UsbProWidgetDetector::DispatchWidget( DispatchingUsbProWidget *widget, const UsbProWidgetInformation *info) { ola::io::ConnectedDescriptor *descriptor = widget->GetDescriptor(); descriptor->SetOnClose(NULL); delete widget; if (m_callback.get()) { m_callback->Run(descriptor, info); } else { delete info; OLA_FATAL << "No listener provided, leaking descriptors"; } } /** * Delete a widget which we've decided belongs to a sniffer. */ void UsbProWidgetDetector::HandleSniffer(DispatchingUsbProWidget *widget) { ola::io::ConnectedDescriptor *descriptor = widget->GetDescriptor(); delete widget; descriptor->SetOnClose(NULL); if (m_failure_callback.get()) { m_failure_callback->Run(descriptor); } } } // namespace usbpro } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbpro/DmxterWidget.cpp0000644000175000017500000003217213023355232021571 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DmxterWidget.cpp * The Goddard Design Dmxter RDM and miniDmxter * Copyright (C) 2010 Simon Newton */ #include #include #include #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/io/ByteString.h" #include "ola/rdm/RDMCommandSerializer.h" #include "ola/rdm/UID.h" #include "ola/rdm/UIDSet.h" #include "plugins/usbpro/DmxterWidget.h" namespace ola { namespace plugin { namespace usbpro { using ola::io::ByteString; using ola::rdm::RDMCommandSerializer; using ola::rdm::RDMReply; using ola::rdm::RDMRequest; using ola::rdm::RunRDMCallback; using ola::rdm::UID; using ola::rdm::UIDSet; using std::auto_ptr; using std::string; using std::vector; const uint8_t DmxterWidgetImpl::RDM_REQUEST_LABEL = 0x80; const uint8_t DmxterWidgetImpl::RDM_BCAST_REQUEST_LABEL = 0x81; const uint8_t DmxterWidgetImpl::TOD_LABEL = 0x82; const uint8_t DmxterWidgetImpl::DISCOVERY_BRANCH_LABEL = 0x83; const uint8_t DmxterWidgetImpl::FULL_DISCOVERY_LABEL = 0x84; const uint8_t DmxterWidgetImpl::INCREMENTAL_DISCOVERY_LABEL = 0x85; const uint8_t DmxterWidgetImpl::SHUTDOWN_LABAEL = 0xf0; /* * New DMXter device * @param ss A pointer to a SelectServerInterface * @param widget the underlying UsbWidget * @param esta_id the ESTA id, should normally be GODDARD Design * @param serial the 4 byte serial which forms part of the UID */ DmxterWidgetImpl::DmxterWidgetImpl( ola::io::ConnectedDescriptor *descriptor, uint16_t esta_id, uint32_t serial) : BaseUsbProWidget(descriptor), m_uid(esta_id, serial), m_discovery_callback(NULL), m_rdm_request_callback(NULL), m_transaction_number(0) { } /** * Clean up */ DmxterWidgetImpl::~DmxterWidgetImpl() { Stop(); } /** * Stop the widget */ void DmxterWidgetImpl::Stop() { // timeout any existing message if (m_rdm_request_callback) { ola::rdm::RDMCallback *callback = m_rdm_request_callback; m_rdm_request_callback = NULL; RunRDMCallback(callback, ola::rdm::RDM_TIMEOUT); } if (m_discovery_callback) { ola::rdm::UIDSet uids; ola::rdm::RDMDiscoveryCallback *callback = m_discovery_callback; m_discovery_callback = NULL; callback->Run(uids); } } /** * Send an RDM request. By wrapping this in a QueueingRDMController, we ensure * that this is only called one-at-a-time. * @param request_ptr the RDMRequest object * @param on_complete the callback to run when the request completes or fails */ void DmxterWidgetImpl::SendRDMRequest(RDMRequest *request_ptr, ola::rdm::RDMCallback *on_complete) { auto_ptr request(request_ptr); if (m_rdm_request_callback) { OLA_FATAL << "Previous request hasn't completed yet, dropping request"; RunRDMCallback(on_complete, ola::rdm::RDM_FAILED_TO_SEND); return; } request->SetSourceUID(m_uid); request->SetTransactionNumber(m_transaction_number++); request->SetPortId(1); ByteString data; if (!RDMCommandSerializer::PackWithStartCode(*request, &data)) { OLA_WARN << "Failed to pack message, dropping request"; RunRDMCallback(on_complete, ola::rdm::RDM_FAILED_TO_SEND); return; } uint8_t label; if (request->IsDUB()) { label = DISCOVERY_BRANCH_LABEL; } else { label = request->DestinationUID().IsBroadcast() ? RDM_BCAST_REQUEST_LABEL : RDM_REQUEST_LABEL; } m_rdm_request_callback = on_complete; m_pending_request.reset(request.release()); if (SendMessage(label, data.data(), data.size())) { return; } m_rdm_request_callback = NULL; m_pending_request.reset(); RunRDMCallback(on_complete, ola::rdm::RDM_FAILED_TO_SEND); } /** * Trigger full RDM discovery for the widget. */ void DmxterWidgetImpl::RunFullDiscovery( ola::rdm::RDMDiscoveryCallback *callback) { m_discovery_callback = callback; if (!SendMessage(FULL_DISCOVERY_LABEL, NULL, 0)) { OLA_WARN << "Failed to send full dmxter discovery command"; m_discovery_callback = NULL; // return the existing set of UIDs callback->Run(m_uids); } } /** * Trigger incremental RDM discovery for the widget. */ void DmxterWidgetImpl::RunIncrementalDiscovery( ola::rdm::RDMDiscoveryCallback *callback) { m_discovery_callback = callback; if (!SendMessage(INCREMENTAL_DISCOVERY_LABEL, NULL, 0)) { OLA_WARN << "Failed to send incremental dmxter discovery command"; m_discovery_callback = NULL; // return the existing set of UIDs callback->Run(m_uids); } } /** * Called when a new packet arrives */ void DmxterWidgetImpl::HandleMessage(uint8_t label, const uint8_t *data, unsigned int length) { switch (label) { case TOD_LABEL: HandleTodResponse(data, length); break; case DISCOVERY_BRANCH_LABEL: HandleRDMResponse(data, length); break; case RDM_REQUEST_LABEL: HandleRDMResponse(data, length); break; case RDM_BCAST_REQUEST_LABEL: HandleBroadcastRDMResponse(data, length); break; case SHUTDOWN_LABAEL: HandleShutdown(data, length); break; default: OLA_WARN << "Unknown label: 0x" << std::hex << static_cast(label); } } /** * Handle a TOD response */ void DmxterWidgetImpl::HandleTodResponse(const uint8_t *data, unsigned int length) { (void) data; if (length % UID::UID_SIZE) { OLA_WARN << "Response length " << length << " not divisible by " << static_cast(ola::rdm::UID::UID_SIZE) << ", ignoring packet"; return; } m_uids.Clear(); for (unsigned int i = 0; i < length; i+= UID::UID_SIZE) { UID uid(data + i); OLA_INFO << "added " << uid.ToString(); m_uids.AddUID(uid); } if (m_discovery_callback) { ola::rdm::RDMDiscoveryCallback *callback = m_discovery_callback; m_discovery_callback = NULL; callback->Run(m_uids); } } /** * Handle a RDM response. */ void DmxterWidgetImpl::HandleRDMResponse(const uint8_t *data, unsigned int length) { struct ResponseHeader { uint8_t version; uint8_t response_code; }; if (m_rdm_request_callback == NULL) { OLA_FATAL << "Got a response but no callback to run!"; return; } bool waiting_for_dub_response = m_pending_request->IsDUB(); ola::rdm::RDMCallback *callback = m_rdm_request_callback; m_rdm_request_callback = NULL; auto_ptr request(m_pending_request.release()); if (length < sizeof(ResponseHeader)) { OLA_WARN << "Invalid RDM response from the widget"; RunRDMCallback(callback, ola::rdm::RDM_INVALID_RESPONSE); return; } const ResponseHeader *header = reinterpret_cast(data); if (header->version != 0) { OLA_WARN << "Unknown version # in widget response: " << static_cast(header->version); RunRDMCallback(callback, ola::rdm::RDM_INVALID_RESPONSE); return; } ola::rdm::RDMStatusCode status_code = ola::rdm::RDM_COMPLETED_OK; switch (header->response_code) { case RC_CHECKSUM_ERROR: status_code = ola::rdm::RDM_CHECKSUM_INCORRECT; break; case RC_FRAMING_ERROR: case RC_FRAMING_ERROR2: case RC_BAD_STARTCODE: status_code = ola::rdm::RDM_INVALID_RESPONSE; break; case RC_BAD_SUB_STARTCODE: status_code = ola::rdm::RDM_WRONG_SUB_START_CODE; break; case RC_WRONG_PDL: case RC_BAD_PDL: status_code = ola::rdm::RDM_INVALID_RESPONSE; break; case RC_PACKET_TOO_SHORT: status_code = ola::rdm::RDM_PACKET_TOO_SHORT; break; case RC_PACKET_TOO_LONG: status_code = ola::rdm::RDM_INVALID_RESPONSE; break; case RC_PHYSICAL_LENGTH_MISMATCH: status_code = ola::rdm::RDM_PACKET_LENGTH_MISMATCH; break; case RC_PDL_LENGTH_MISMATCH: status_code = ola::rdm::RDM_PARAM_LENGTH_MISMATCH; break; case RC_TRANSACTION_MISMATCH: status_code = ola::rdm::RDM_TRANSACTION_MISMATCH; break; case RC_BAD_RESPONSE_TYPE: status_code = ola::rdm::RDM_INVALID_RESPONSE_TYPE; break; case RC_GOOD_LEVEL: if (waiting_for_dub_response) { status_code = ola::rdm::RDM_DUB_RESPONSE; } else { OLA_INFO << "Got response code " << static_cast(header->response_code); status_code = ola::rdm::RDM_INVALID_RESPONSE; } break; case RC_BAD_LEVEL: case RC_BROADCAST: case RC_VENDORCAST: OLA_INFO << "Got response status_code " << static_cast(header->response_code); status_code = ola::rdm::RDM_INVALID_RESPONSE; break; case RC_GOOD_RESPONSE: case RC_ACK_TIMER: case RC_ACK_OVERFLOW: case RC_NACK: case RC_NACK_UNKNOWN_PID: case RC_NACK_FORMAT_ERROR: case RC_NACK_HARDWARE_FAULT: case RC_NACK_PROXY_REJECT: case RC_NACK_WRITE_PROECT: case RC_NACK_COMMAND_CLASS: case RC_NACK_DATA_RANGE: case RC_NACK_BUFFER_FULL: case RC_NACK_PACKET_SIZE: case RC_NACK_SUB_DEVICE_RANGE: case RC_NACK_PROXY_QUEUE_BUFFER_FULL: status_code = ola::rdm::RDM_COMPLETED_OK; break; case RC_IDLE_LEVEL: case RC_TIMED_OUT: OLA_INFO << "Request timed out"; status_code = ola::rdm::RDM_TIMEOUT; break; case RC_SUBDEVICE_MISMATCH: status_code = ola::rdm::RDM_SUB_DEVICE_MISMATCH; break; case RC_SRC_UID_MISMATCH: status_code = ola::rdm::RDM_SRC_UID_MISMATCH; break; case RC_DEST_UID_MISMATCH: status_code = ola::rdm::RDM_DEST_UID_MISMATCH; break; case RC_COMMAND_CLASS_MISMATCH: status_code = ola::rdm::RDM_COMMAND_CLASS_MISMATCH; break; case RC_PARAM_ID_MISMATCH: // this should *hopefully* be caught higher up the stack status_code = ola::rdm::RDM_COMPLETED_OK; break; case RC_DATA_RECEIVED_NO_BREAK: OLA_INFO << "Got data with no break"; status_code = ola::rdm::RDM_INVALID_RESPONSE; break; default: OLA_WARN << "Unknown response status_code " << static_cast(header->response_code); status_code = ola::rdm::RDM_INVALID_RESPONSE; } data += sizeof(ResponseHeader); length -= sizeof(ResponseHeader); auto_ptr reply; if (status_code == ola::rdm::RDM_COMPLETED_OK) { rdm::RDMFrame frame(data, length); reply.reset(RDMReply::FromFrame(frame, request.get())); } else { rdm::RDMFrames frames; if (length > 0) { frames.push_back(rdm::RDMFrame(data, length)); } reply.reset(new RDMReply(status_code, NULL, frames)); } callback->Run(reply.get()); } /** * Handle a broadcast response */ void DmxterWidgetImpl::HandleBroadcastRDMResponse(const uint8_t *data, unsigned int length) { if (m_rdm_request_callback == NULL) { OLA_FATAL << "Got a response but no callback to run!"; return; } if (length != 0 || data != NULL) { OLA_WARN << "Got strange broadcast response, length was " << length << ", data was " << data; } ola::rdm::RDMCallback *callback = m_rdm_request_callback; m_rdm_request_callback = NULL; RunRDMCallback(callback, ola::rdm::RDM_WAS_BROADCAST); } /** * Handle a shutdown message */ void DmxterWidgetImpl::HandleShutdown(const uint8_t *data, unsigned int length) { if (length || data) { OLA_WARN << "Invalid shutdown message, length was " << length; } else { OLA_INFO << "Received shutdown message from the Dmxter"; // Run the on close handler which calls WidgetDetectorThread::FreeWidget. // This removes the descriptor from the SS and closes the FD. // This is the same behaviour as if the remote end closed the connection // i.e. the device was plugged. ola::io::ConnectedDescriptor::OnCloseCallback *on_close = GetDescriptor()->TransferOnClose(); on_close->Run(); } } /** * DmxterWidget Constructor */ DmxterWidget::DmxterWidget(ola::io::ConnectedDescriptor *descriptor, uint16_t esta_id, uint32_t serial, unsigned int queue_size) { m_impl = new DmxterWidgetImpl(descriptor, esta_id, serial); m_controller = new ola::rdm::DiscoverableQueueingRDMController(m_impl, queue_size); } DmxterWidget::~DmxterWidget() { // delete the controller after the impl because the controller owns the // callback delete m_impl; delete m_controller; } } // namespace usbpro } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbpro/UsbProDevice.h0000644000175000017500000001406613023355232021163 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * UsbProDevice.h * A Enttec USB Pro device * Copyright (C) 2006 Simon Newton */ #ifndef PLUGINS_USBPRO_USBPRODEVICE_H_ #define PLUGINS_USBPRO_USBPRODEVICE_H_ #include #include #include "ola/DmxBuffer.h" #include "olad/TokenBucket.h" #include "olad/PluginAdaptor.h" #include "olad/Port.h" #include "plugins/usbpro/EnttecUsbProWidget.h" #include "plugins/usbpro/UsbSerialDevice.h" #include "plugins/usbpro/messages/UsbProConfigMessages.pb.h" namespace ola { namespace plugin { namespace usbpro { /* * An Enttec Usb Pro device */ class UsbProDevice: public UsbSerialDevice { public: UsbProDevice(ola::PluginAdaptor *plugin_adaptor, ola::AbstractPlugin *owner, const std::string &name, EnttecUsbProWidget *widget, uint32_t serial, uint16_t firmware_version, unsigned int fps_limit); std::string DeviceId() const { return m_serial; } void Configure(ola::rpc::RpcController *controller, const std::string &request, std::string *response, ConfigureCallback *done); bool AllowMultiPortPatching() const { return true; } protected: void PrePortStop(); private: struct PortParams { bool got_parameters; uint8_t break_time; uint8_t mab_time; uint8_t rate; }; void UpdateParams(unsigned int port_id, bool status, const usb_pro_parameters ¶ms); void HandleParametersRequest(ola::rpc::RpcController *controller, const ola::plugin::usbpro::Request *request, std::string *response, ConfigureCallback *done); void HandleParametersResponse(ola::rpc::RpcController *controller, std::string *response, ConfigureCallback *done, unsigned int port_id, bool status, const usb_pro_parameters ¶ms); void HandleSerialRequest(ola::rpc::RpcController *controller, const ola::plugin::usbpro::Request *request, std::string *response, ConfigureCallback *done); void HandlePortAssignmentRequest(ola::rpc::RpcController *controller, const ola::plugin::usbpro::Request *request, std::string *response, ConfigureCallback *done); void HandlePortAssignmentResponse(ola::rpc::RpcController *controller, std::string *response, ConfigureCallback *done, bool status, uint8_t port1_assignment, uint8_t port2_assignment); static std::string SerialToString(uint32_t serial); EnttecUsbProWidget *m_pro_widget; std::string m_serial; std::vector m_port_params; }; /* * The Input port */ class UsbProInputPort: public BasicInputPort { public: // The EnttecPort is owner by the caller. UsbProInputPort(UsbProDevice *parent, EnttecPort *port, unsigned int id, ola::PluginAdaptor *plugin_adaptor, const std::string &description) : BasicInputPort(parent, id, plugin_adaptor), m_description(description), m_port(port) {} const DmxBuffer &ReadDMX() const { return m_port->FetchDMX(); } std::string Description() const { return m_description; } private: const std::string m_description; EnttecPort *m_port; }; /* * The output port */ class UsbProOutputPort: public BasicOutputPort { public: // The EnttecPort is owner by the caller. UsbProOutputPort(UsbProDevice *parent, EnttecPort *port, unsigned int id, const std::string &description, const TimeStamp *wake_time, unsigned int max_burst, unsigned int rate) : BasicOutputPort(parent, id, port->SupportsRDM(), port->SupportsRDM()), m_description(description), m_port(port), m_bucket(max_burst, rate, max_burst, *wake_time), m_wake_time(wake_time) {} bool WriteDMX(const DmxBuffer &buffer, uint8_t) { if (m_bucket.GetToken(*m_wake_time)) return m_port->SendDMX(buffer); else OLA_INFO << "Port rated limited, dropping frame"; return true; } void PostSetUniverse(Universe*, Universe *new_universe) { if (!new_universe) m_port->ChangeToReceiveMode(false); } void SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *callback) { m_port->SendRDMRequest(request, callback); } void RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { m_port->RunFullDiscovery(callback); } void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { m_port->RunIncrementalDiscovery(callback); } std::string Description() const { return m_description; } private: const std::string m_description; EnttecPort *m_port; TokenBucket m_bucket; const TimeStamp *m_wake_time; }; } // namespace usbpro } // namespace plugin } // namespace ola #endif // PLUGINS_USBPRO_USBPRODEVICE_H_ ola-0.10.5.nojsmin/plugins/usbpro/EnttecUsbProWidget.h0000644000175000017500000001026213023355232022344 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * EnttecUsbProWidget.h * The Enttec USB Pro Widget * Copyright (C) 2010 Simon Newton */ #ifndef PLUGINS_USBPRO_ENTTECUSBPROWIDGET_H_ #define PLUGINS_USBPRO_ENTTECUSBPROWIDGET_H_ #include #include #include #include "ola/Callback.h" #include "ola/DmxBuffer.h" #include "ola/thread/SchedulerInterface.h" #include "ola/rdm/DiscoveryAgent.h" #include "ola/rdm/QueueingRDMController.h" #include "ola/rdm/RDMControllerInterface.h" #include "ola/rdm/UIDSet.h" #include "plugins/usbpro/GenericUsbProWidget.h" class EnttecUsbProWidgetTest; namespace ola { namespace plugin { namespace usbpro { class EnttecPortImpl; /** * A port represents a universe of DMX. It can be used to either send or * receive DMX. */ class EnttecPort : public ola::rdm::DiscoverableRDMControllerInterface { public: // Ownership not transferred. EnttecPort(EnttecPortImpl *impl, unsigned int queue_size, bool enable_rdm); bool SendDMX(const DmxBuffer &buffer); const DmxBuffer &FetchDMX() const; void SetDMXCallback(ola::Callback0 *callback); bool ChangeToReceiveMode(bool change_only); void GetParameters(usb_pro_params_callback *callback); bool SetParameters(uint8_t break_time, uint8_t mab_time, uint8_t rate); bool SupportsRDM() const { return m_enable_rdm; } // the following are from DiscoverableRDMControllerInterface void SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *on_complete); void RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback); void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback); // the tests access the implementation directly. friend class ::EnttecUsbProWidgetTest; private: EnttecPortImpl *m_impl; const bool m_enable_rdm; std::auto_ptr m_controller; }; /* * An Enttec Usb Pro Widget */ class EnttecUsbProWidget: public SerialWidgetInterface { public: /* * The callback to run when we receive a port assignment response * @param true if this command completed ok * @param DMX port 1 assignment * @param DMX port 2 assignment */ typedef ola::SingleUseCallback3 EnttecUsbProPortAssignmentCallback; struct EnttecUsbProWidgetOptions { uint16_t esta_id; uint32_t serial; bool dual_ports; unsigned int queue_size; bool enable_rdm; EnttecUsbProWidgetOptions() : esta_id(0), serial(0), dual_ports(false), queue_size(20), enable_rdm(false) { } EnttecUsbProWidgetOptions(uint16_t esta_id, uint32_t serial) : esta_id(esta_id), serial(serial), dual_ports(false), queue_size(20), enable_rdm(false) { } }; EnttecUsbProWidget(ola::thread::SchedulerInterface *ss, ola::io::ConnectedDescriptor *descriptor, const EnttecUsbProWidgetOptions &options); ~EnttecUsbProWidget(); void GetPortAssignments(EnttecUsbProPortAssignmentCallback *callback); void Stop(); unsigned int PortCount() const; EnttecPort *GetPort(unsigned int i); ola::io::ConnectedDescriptor *GetDescriptor() const; static const uint16_t ENTTEC_ESTA_ID; private: class EnttecUsbProWidgetImpl *m_impl; }; } // namespace usbpro } // namespace plugin } // namespace ola #endif // PLUGINS_USBPRO_ENTTECUSBPROWIDGET_H_ ola-0.10.5.nojsmin/plugins/usbpro/UsbSerialPlugin.cpp0000644000175000017500000002504613023355232022234 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * UsbSerialPlugin.cpp * The UsbPro plugin for ola * Copyright (C) 2006 Simon Newton */ #include #include #include #include #include #include "ola/Callback.h" #include "ola/Logging.h" #include "ola/StringUtils.h" #include "olad/PluginAdaptor.h" #include "olad/Preferences.h" #include "plugins/usbpro/ArduinoRGBDevice.h" #include "plugins/usbpro/DmxTriDevice.h" #include "plugins/usbpro/DmxTriWidget.h" #include "plugins/usbpro/DmxterDevice.h" #include "plugins/usbpro/RobeDevice.h" #include "plugins/usbpro/RobeWidgetDetector.h" #include "plugins/usbpro/UltraDMXProDevice.h" #include "plugins/usbpro/UltraDMXProWidget.h" #include "plugins/usbpro/UsbProDevice.h" #include "plugins/usbpro/UsbSerialPlugin.h" namespace ola { namespace plugin { namespace usbpro { using std::auto_ptr; using std::string; using std::vector; const char UsbSerialPlugin::DEFAULT_DEVICE_DIR[] = "/dev"; const char UsbSerialPlugin::DEVICE_DIR_KEY[] = "device_dir"; const char UsbSerialPlugin::DEVICE_PREFIX_KEY[] = "device_prefix"; const char UsbSerialPlugin::IGNORED_DEVICES_KEY[] = "ignore_device"; const char UsbSerialPlugin::LINUX_DEVICE_PREFIX[] = "ttyUSB"; const char UsbSerialPlugin::BSD_DEVICE_PREFIX[] = "ttyU"; const char UsbSerialPlugin::MAC_DEVICE_PREFIX[] = "cu.usbserial-"; const char UsbSerialPlugin::PLUGIN_NAME[] = "Serial USB"; const char UsbSerialPlugin::PLUGIN_PREFIX[] = "usbserial"; const char UsbSerialPlugin::ROBE_DEVICE_NAME[] = "Robe Universal Interface"; const char UsbSerialPlugin::TRI_USE_RAW_RDM_KEY[] = "tri_use_raw_rdm"; const char UsbSerialPlugin::USBPRO_DEVICE_NAME[] = "Enttec Usb Pro Device"; const char UsbSerialPlugin::USB_PRO_FPS_LIMIT_KEY[] = "pro_fps_limit"; const char UsbSerialPlugin::ULTRA_FPS_LIMIT_KEY[] = "ultra_fps_limit"; UsbSerialPlugin::UsbSerialPlugin(PluginAdaptor *plugin_adaptor) : Plugin(plugin_adaptor), m_detector_thread(this, plugin_adaptor) { } /* * Return the description for this plugin */ string UsbSerialPlugin::Description() const { return "Serial USB Plugin\n" "----------------------------\n" "\n" "This plugin supports DMX USB devices that emulate a serial port. This \n" "includes:\n" " - Arduino RGB Mixer\n" " - DMX-TRI & RDM-TRI\n" " - DMXking USB DMX512-A, Ultra DMX, Ultra DMX Pro\n" " - DMXter4, DMXter4A & mini DMXter\n" " - Enttec DMX USB Pro & USB Pro Mk II\n" " - Robe Universe Interface\n" "\n" "See https://wiki.openlighting.org/index.php/USB_Protocol_Extensions for \n" "more info.\n" "\n" "--- Config file : ola-usbserial.conf ---\n" "\n" "device_dir = /dev\n" "The directory to look for devices in.\n" "\n" "device_prefix = ttyUSB\n" "The prefix of filenames to consider as devices. Multiple keys are allowed.\n" "\n" "ignore_device = /dev/ttyUSB\n" "Ignore the device matching this string. Multiple keys are allowed.\n" "\n" "pro_fps_limit = 190\n" "The max frames per second to send to a Usb Pro or DMXKing device.\n" "\n" "tri_use_raw_rdm = [true|false]\n" "Bypass RDM handling in the {DMX,RDM}-TRI widgets.\n" "\n" "ultra_fps_limit = 40\n" "The max frames per second to send to a Ultra DMX Pro device.\n" "\n"; } /* * Called when a device is removed */ void UsbSerialPlugin::DeviceRemoved(UsbSerialDevice *device) { vector::iterator iter; for (iter = m_devices.begin(); iter != m_devices.end(); ++iter) { if (*iter == device) { break; } } if (iter == m_devices.end()) { OLA_WARN << "Couldn't find the device that was removed"; return; } DeleteDevice(device); m_devices.erase(iter); } /** * Handle a new ArduinoWidget. */ void UsbSerialPlugin::NewWidget( ArduinoWidget *widget, const UsbProWidgetInformation &information) { AddDevice(new ArduinoRGBDevice( m_plugin_adaptor, this, GetDeviceName(information), widget, information.esta_id, information.device_id, information.serial)); } /** * Handle a new Enttec Usb Pro Widget. */ void UsbSerialPlugin::NewWidget( EnttecUsbProWidget *widget, const UsbProWidgetInformation &information) { string device_name = GetDeviceName(information); if (device_name.empty()) { device_name = USBPRO_DEVICE_NAME; } AddDevice(new UsbProDevice(m_plugin_adaptor, this, device_name, widget, information.serial, information.firmware_version, GetProFrameLimit())); } /** * Handle a new Dmx-Tri Widget. */ void UsbSerialPlugin::NewWidget( DmxTriWidget *widget, const UsbProWidgetInformation &information) { widget->UseRawRDM( m_preferences->GetValueAsBool(TRI_USE_RAW_RDM_KEY)); AddDevice(new DmxTriDevice( this, GetDeviceName(information), widget, information.esta_id, information.device_id, information.serial, information.firmware_version)); } /** * Handle a new Dmxter. */ void UsbSerialPlugin::NewWidget( DmxterWidget *widget, const UsbProWidgetInformation &information) { AddDevice(new DmxterDevice( this, GetDeviceName(information), widget, information.esta_id, information.device_id, information.serial)); } /** * New Robe Universal Interface. */ void UsbSerialPlugin::NewWidget( RobeWidget *widget, const RobeWidgetInformation&) { AddDevice(new RobeDevice(m_plugin_adaptor, this, ROBE_DEVICE_NAME, widget)); } /** * A New Ultra DMX Pro Widget */ void UsbSerialPlugin::NewWidget(UltraDMXProWidget *widget, const UsbProWidgetInformation &information) { AddDevice(new UltraDMXProDevice( m_plugin_adaptor, this, GetDeviceName(information), widget, information.esta_id, information.device_id, information.serial, information.firmware_version, GetUltraDMXProFrameLimit())); } /* * Add a new device to the list * @param device the new UsbSerialDevice */ void UsbSerialPlugin::AddDevice(UsbSerialDevice *device) { if (!device->Start()) { delete device; return; } device->SetOnRemove(NewSingleCallback(this, &UsbSerialPlugin::DeviceRemoved, device)); m_devices.push_back(device); m_plugin_adaptor->RegisterDevice(device); } /* * Start the plugin */ bool UsbSerialPlugin::StartHook() { const vector ignored_devices = m_preferences->GetMultipleValue(IGNORED_DEVICES_KEY); m_detector_thread.SetIgnoredDevices(ignored_devices); m_detector_thread.SetDeviceDirectory( m_preferences->GetValue(DEVICE_DIR_KEY)); m_detector_thread.SetDevicePrefixes( m_preferences->GetMultipleValue(DEVICE_PREFIX_KEY)); if (!m_detector_thread.Start()) { OLA_FATAL << "Failed to start the widget discovery thread"; return false; } m_detector_thread.WaitUntilRunning(); return true; } /* * Stop the plugin * @return true on sucess, false on failure */ bool UsbSerialPlugin::StopHook() { vector::iterator iter; for (iter = m_devices.begin(); iter != m_devices.end(); ++iter) { DeleteDevice(*iter); } m_detector_thread.Join(NULL); m_devices.clear(); return true; } /* * Default to sensible values */ bool UsbSerialPlugin::SetDefaultPreferences() { if (!m_preferences) { return false; } bool save = false; vector device_prefixes = m_preferences->GetMultipleValue(DEVICE_PREFIX_KEY); if (device_prefixes.empty()) { m_preferences->SetMultipleValue(DEVICE_PREFIX_KEY, LINUX_DEVICE_PREFIX); m_preferences->SetMultipleValue(DEVICE_PREFIX_KEY, MAC_DEVICE_PREFIX); m_preferences->SetMultipleValue(DEVICE_PREFIX_KEY, BSD_DEVICE_PREFIX); save = true; } save |= m_preferences->SetDefaultValue(DEVICE_DIR_KEY, StringValidator(), DEFAULT_DEVICE_DIR); save |= m_preferences->SetDefaultValue(USB_PRO_FPS_LIMIT_KEY, UIntValidator(0, MAX_PRO_FPS_LIMIT), DEFAULT_PRO_FPS_LIMIT); save |= m_preferences->SetDefaultValue(ULTRA_FPS_LIMIT_KEY, UIntValidator(0, MAX_ULTRA_FPS_LIMIT), DEFAULT_ULTRA_FPS_LIMIT); save |= m_preferences->SetDefaultValue(TRI_USE_RAW_RDM_KEY, BoolValidator(), false); if (save) { m_preferences->Save(); } device_prefixes = m_preferences->GetMultipleValue(DEVICE_PREFIX_KEY); if (device_prefixes.empty()) { return false; } return true; } void UsbSerialPlugin::DeleteDevice(UsbSerialDevice *device) { SerialWidgetInterface *widget = device->GetWidget(); m_plugin_adaptor->UnregisterDevice(device); device->Stop(); delete device; m_detector_thread.FreeWidget(widget); } /** * Get a nicely formatted device name from the widget information. */ string UsbSerialPlugin::GetDeviceName( const UsbProWidgetInformation &information) { string device_name = information.manufacturer; if (!(information.manufacturer.empty() || information.device.empty())) { device_name += " - "; } device_name += information.device; return device_name; } /* * Get the Frames per second limit for a pro device */ unsigned int UsbSerialPlugin::GetProFrameLimit() { unsigned int fps_limit; if (!StringToInt(m_preferences->GetValue(USB_PRO_FPS_LIMIT_KEY) , &fps_limit)) { return DEFAULT_PRO_FPS_LIMIT; } return fps_limit; } /* * Get the Frames per second limit for a Ultra DMX Pro Device */ unsigned int UsbSerialPlugin::GetUltraDMXProFrameLimit() { unsigned int fps_limit; if (!StringToInt(m_preferences->GetValue(ULTRA_FPS_LIMIT_KEY) , &fps_limit)) { return DEFAULT_ULTRA_FPS_LIMIT; } return fps_limit; } } // namespace usbpro } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/sandnet/0000755000175000017500000000000013155164170016600 5ustar wouterwouterola-0.10.5.nojsmin/plugins/sandnet/SandNetDevice.h0000644000175000017500000000411613023355232021422 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SandNetDevice.h * Interface for the sandnet device * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_SANDNET_SANDNETDEVICE_H_ #define PLUGINS_SANDNET_SANDNETDEVICE_H_ #include #include "olad/Device.h" #include "olad/Plugin.h" #include "olad/PluginAdaptor.h" #include "plugins/sandnet/SandNetCommon.h" #include "plugins/sandnet/SandNetNode.h" namespace ola { namespace plugin { namespace sandnet { class SandNetDevice: public ola::Device { public: SandNetDevice(class SandNetPlugin *owner, class Preferences *prefs, class PluginAdaptor *plugin_adaptor); std::string DeviceId() const { return "1"; } SandNetNode *GetNode() { return m_node; } bool SendAdvertisement(); static const char IP_KEY[]; static const char NAME_KEY[]; protected: bool StartHook(); void PrePortStop(); void PostPortStop(); private: class Preferences *m_preferences; class PluginAdaptor *m_plugin_adaptor; SandNetNode *m_node; ola::thread::timeout_id m_timeout_id; static const char SANDNET_DEVICE_NAME[]; // the number of input ports to create static const unsigned int INPUT_PORTS = 8; // send an advertistment every 2s. static const int ADVERTISTMENT_PERIOD_MS = 2000; }; } // namespace sandnet } // namespace plugin } // namespace ola #endif // PLUGINS_SANDNET_SANDNETDEVICE_H_ ola-0.10.5.nojsmin/plugins/sandnet/Makefile.mk0000644000175000017500000000125413023355232020643 0ustar wouterwouter# LIBRARIES ################################################## if USE_SANDNET lib_LTLIBRARIES += plugins/sandnet/libolasandnet.la plugins_sandnet_libolasandnet_la_SOURCES = \ plugins/sandnet/SandNetCommon.h \ plugins/sandnet/SandNetDevice.cpp \ plugins/sandnet/SandNetDevice.h \ plugins/sandnet/SandNetNode.cpp \ plugins/sandnet/SandNetNode.h \ plugins/sandnet/SandNetPackets.h \ plugins/sandnet/SandNetPlugin.cpp \ plugins/sandnet/SandNetPlugin.h \ plugins/sandnet/SandNetPort.cpp \ plugins/sandnet/SandNetPort.h plugins_sandnet_libolasandnet_la_LIBADD = \ common/libolacommon.la \ olad/plugin_api/libolaserverplugininterface.la endif ola-0.10.5.nojsmin/plugins/sandnet/SandNetDevice.cpp0000644000175000017500000001016013023355232021751 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SandNetDevice.cpp * SandNet device * Copyright (C) 2005 Simon Newton */ #include #include #include #include "ola/Logging.h" #include "ola/network/NetworkUtils.h" #include "olad/Plugin.h" #include "olad/PluginAdaptor.h" #include "olad/Preferences.h" #include "plugins/sandnet/SandNetDevice.h" #include "plugins/sandnet/SandNetPlugin.h" #include "plugins/sandnet/SandNetPort.h" namespace ola { namespace plugin { namespace sandnet { using std::ostringstream; using std::string; using std::vector; const char SandNetDevice::IP_KEY[] = "ip"; const char SandNetDevice::NAME_KEY[] = "name"; const char SandNetDevice::SANDNET_DEVICE_NAME[] = "SandNet"; /* * Create a new device */ SandNetDevice::SandNetDevice(SandNetPlugin *owner, Preferences *prefs, PluginAdaptor *plugin_adaptor): Device(owner, SANDNET_DEVICE_NAME), m_preferences(prefs), m_plugin_adaptor(plugin_adaptor), m_node(NULL), m_timeout_id(ola::thread::INVALID_TIMEOUT) { } /* * Start this device */ bool SandNetDevice::StartHook() { vector sockets; vector::iterator iter; m_node = new SandNetNode(m_preferences->GetValue(IP_KEY)); m_node->SetName(m_preferences->GetValue(NAME_KEY)); // setup the output ports (ie INTO sandnet) for (int i = 0; i < SANDNET_MAX_PORTS; i++) { bool ret = m_node->SetPortParameters(i, SandNetNode::SANDNET_PORT_MODE_IN, 0, i); if (!ret) { OLA_WARN << "SetPortParameters failed"; DeleteAllPorts(); delete m_node; return false; } } if (!m_node->Start()) { DeleteAllPorts(); delete m_node; return false; } ostringstream str; str << SANDNET_DEVICE_NAME << " [" << m_node->GetInterface().ip_address << "]"; SetName(str.str()); for (unsigned int i = 0; i < INPUT_PORTS; i++) { SandNetInputPort *port = new SandNetInputPort( this, i, m_plugin_adaptor, m_node); AddPort(port); } for (unsigned int i = 0; i < SANDNET_MAX_PORTS ; i++) { SandNetOutputPort *port = new SandNetOutputPort(this, i, m_node); AddPort(port); } sockets = m_node->GetSockets(); for (iter = sockets.begin(); iter != sockets.end(); ++iter) m_plugin_adaptor->AddReadDescriptor(*iter); m_timeout_id = m_plugin_adaptor->RegisterRepeatingTimeout( ADVERTISTMENT_PERIOD_MS, NewCallback(this, &SandNetDevice::SendAdvertisement)); return true; } /* * Stop this device */ void SandNetDevice::PrePortStop() { vector sockets = m_node->GetSockets(); vector::iterator iter; for (iter = sockets.begin(); iter != sockets.end(); ++iter) m_plugin_adaptor->RemoveReadDescriptor(*iter); if (m_timeout_id != ola::thread::INVALID_TIMEOUT) { m_plugin_adaptor->RemoveTimeout(m_timeout_id); m_timeout_id = ola::thread::INVALID_TIMEOUT; } } /* * Stop this device */ void SandNetDevice::PostPortStop() { m_node->Stop(); delete m_node; m_node = NULL; } /* * Called periodically to send advertisements. */ bool SandNetDevice::SendAdvertisement() { OLA_DEBUG << "Sending Sandnet advertisement"; m_node->SendAdvertisement(); return true; } } // namespace sandnet } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/sandnet/SandNetNode.cpp0000644000175000017500000003075713023355232021455 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SandNetNode.cpp * A SandNet node * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include #include "ola/Logging.h" #include "ola/network/IPV4Address.h" #include "ola/network/MACAddress.h" #include "ola/network/NetworkUtils.h" #include "plugins/sandnet/SandNetNode.h" namespace ola { namespace plugin { namespace sandnet { using std::string; using std::map; using std::vector; using ola::network::HostToNetwork; using ola::network::IPV4Address; using ola::network::IPV4SocketAddress; using ola::network::MACAddress; using ola::network::NetworkToHost; using ola::network::UDPSocket; using ola::Callback0; const uint16_t SandNetNode::CONTROL_PORT = 37895; const uint16_t SandNetNode::DATA_PORT = 37900; const char SandNetNode::CONTROL_ADDRESS[] = "237.1.1.1"; const char SandNetNode::DATA_ADDRESS[] = "237.1.2.1"; const char SandNetNode::DEFAULT_NODE_NAME[] = "ola-SandNet"; /* * Create a new node * @param ip_address the IP address to prefer to listen on, if NULL we choose * one. */ SandNetNode::SandNetNode(const string &ip_address) : m_running(false), m_node_name(DEFAULT_NODE_NAME), m_preferred_ip(ip_address) { for (unsigned int i = 0; i < SANDNET_MAX_PORTS; i++) { m_ports[i].group = 0; m_ports[i].universe = i; } } /* * Cleanup */ SandNetNode::~SandNetNode() { Stop(); universe_handlers::iterator iter; for (iter = m_handlers.begin(); iter != m_handlers.end(); ++iter) { delete iter->second.closure; } m_handlers.clear(); } /* * Start this node */ bool SandNetNode::Start() { if (m_running) return false; ola::network::InterfacePicker *picker = ola::network::InterfacePicker::NewPicker(); if (!picker->ChooseInterface(&m_interface, m_preferred_ip)) { delete picker; OLA_INFO << "Failed to find an interface"; return false; } delete picker; IPV4Address ip; if (!IPV4Address::FromString(CONTROL_ADDRESS, &ip)) { OLA_WARN << "Could not convert " << CONTROL_ADDRESS; return false; } m_control_addr = IPV4SocketAddress(ip, CONTROL_PORT); if (!IPV4Address::FromString(DATA_ADDRESS, &ip)) { OLA_WARN << "Could not convert " << DATA_ADDRESS; return false; } m_data_addr = IPV4SocketAddress(ip, DATA_PORT); if (!InitNetwork()) return false; m_running = true; return true; } /* * Stop this node */ bool SandNetNode::Stop() { if (!m_running) return false; m_data_socket.Close(); m_control_socket.Close(); m_running = false; return true; } /* * Return a list of sockets in use */ vector SandNetNode::GetSockets() { vector sockets; sockets.push_back(&m_data_socket); sockets.push_back(&m_control_socket); return sockets; } /* * Called when there is data on this socket */ void SandNetNode::SocketReady(UDPSocket *socket) { sandnet_packet packet; ssize_t packet_size = sizeof(packet); IPV4SocketAddress source; if (!socket->RecvFrom(reinterpret_cast(&packet), &packet_size, &source)) return; // skip packets sent by us if (source.Host() == m_interface.ip_address) return; if (packet_size < static_cast(sizeof(packet.opcode))) { OLA_WARN << "Small sandnet packet received, discarding"; return; } switch (NetworkToHost(packet.opcode)) { case SANDNET_DMX: HandleDMX(packet.contents.dmx, packet_size - sizeof(packet.opcode)); break; case SANDNET_COMPRESSED_DMX: HandleCompressedDMX(packet.contents.compressed_dmx, packet_size - sizeof(packet.opcode)); break; case SANDNET_ADVERTISEMENT: break; default: OLA_INFO << "Skipping sandnet packet with unknown code: 0x" << std::hex << NetworkToHost(packet.opcode); } } /* * Set the closure to be called when we receive data for this universe. * @param universe the universe to register the handler for * @param handler the Callback0 to call when there is data for this universe. * Ownership of the closure is transferred to the node. */ bool SandNetNode::SetHandler(uint8_t group, uint8_t universe, DmxBuffer *buffer, Callback0 *closure) { if (!closure) return false; group_universe_pair key(group, universe); universe_handlers::iterator iter = m_handlers.find(key); if (iter == m_handlers.end()) { universe_handler handler; handler.buffer = buffer; handler.closure = closure; m_handlers[key] = handler; } else { Callback0 *old_closure = iter->second.closure; iter->second.closure = closure; delete old_closure; } return true; } /* * Remove the handler for this universe * @param universe the universe handler to remove * @param true if removed, false if it didn't exist */ bool SandNetNode::RemoveHandler(uint8_t group, uint8_t universe) { group_universe_pair key(group, universe); universe_handlers::iterator iter = m_handlers.find(key); if (iter != m_handlers.end()) { Callback0 *old_closure = iter->second.closure; m_handlers.erase(iter); delete old_closure; return true; } return false; } /* * Set the parameters for a port */ bool SandNetNode::SetPortParameters(uint8_t port_id, sandnet_port_type type, uint8_t group, uint8_t universe) { if (port_id >= SANDNET_MAX_PORTS) return false; m_ports[port_id].group = group; m_ports[port_id].universe = universe; m_ports[port_id].type = type; return true; } /* * Send a Sandnet Advertisement. */ bool SandNetNode::SendAdvertisement() { if (!m_running) return false; sandnet_packet packet; sandnet_advertisement *advertisement = &packet.contents.advertisement; memset(&packet, 0, sizeof(packet)); packet.opcode = HostToNetwork(static_cast(SANDNET_ADVERTISEMENT)); m_interface.hw_address.Get(advertisement->mac); advertisement->firmware = HostToNetwork(FIRMWARE_VERSION); for (unsigned int i = 0; i < SANDNET_MAX_PORTS; i++) { advertisement->ports[i].mode = m_ports[i].type; advertisement->ports[i].protocol = SANDNET_SANDNET; advertisement->ports[i].group = m_ports[i].group; advertisement->ports[i].universe = m_ports[i].universe; } advertisement->nlen = std::min(m_node_name.size(), static_cast(SANDNET_NAME_LENGTH)); strncpy(advertisement->name, m_node_name.data(), advertisement->nlen); advertisement->magic3[0] = 0xc0; advertisement->magic3[1] = 0xa8; advertisement->magic3[2] = 0x01; advertisement->magic3[3] = 0xa0; advertisement->magic3[4] = 0x00; advertisement->magic3[5] = 0xff; advertisement->magic3[6] = 0xff; advertisement->magic3[7] = 0xff; advertisement->magic3[8] = 0x00; advertisement->magic4 = 0x01; return SendPacket(packet, sizeof(packet.opcode) + sizeof(sandnet_advertisement), true); } /* * Send some DMX data * @param buffer the DMX data * @return true if it was send successfully, false otherwise */ bool SandNetNode::SendDMX(uint8_t port_id, const DmxBuffer &buffer) { if (!m_running || port_id >= SANDNET_MAX_PORTS) return false; // Sandnet doesn't seem to understand compressed DMX return SendUncompressedDMX(port_id, buffer); } /* * Setup the networking compoents. */ bool SandNetNode::InitNetwork() { if (!m_control_socket.Init()) { OLA_WARN << "Socket init failed"; return false; } if (!m_data_socket.Init()) { OLA_WARN << "Socket init failed"; m_control_socket.Close(); return false; } if (!m_control_socket.Bind(IPV4SocketAddress(IPV4Address::WildCard(), CONTROL_PORT))) { m_data_socket.Close(); m_control_socket.Close(); return false; } if (!m_data_socket.Bind(IPV4SocketAddress(IPV4Address::WildCard(), DATA_PORT))) { m_data_socket.Close(); m_control_socket.Close(); return false; } if (!m_control_socket.SetMulticastInterface(m_interface.ip_address)) { m_data_socket.Close(); m_control_socket.Close(); return false; } if (!m_data_socket.SetMulticastInterface(m_interface.ip_address)) { m_data_socket.Close(); m_control_socket.Close(); return false; } if (!m_control_socket.JoinMulticast(m_interface.ip_address, m_control_addr.Host())) { OLA_WARN << "Failed to join multicast to: " << m_control_addr; m_data_socket.Close(); m_control_socket.Close(); return false; } if (!m_data_socket.JoinMulticast(m_interface.ip_address, m_data_addr.Host())) { OLA_WARN << "Failed to join multicast to: " << m_data_addr; m_data_socket.Close(); m_control_socket.Close(); return false; } m_control_socket.SetOnData( NewCallback(this, &SandNetNode::SocketReady, &m_control_socket)); m_data_socket.SetOnData( NewCallback(this, &SandNetNode::SocketReady, &m_data_socket)); return true; } /* * Handle a compressed DMX packet */ bool SandNetNode::HandleCompressedDMX(const sandnet_compressed_dmx &dmx_packet, unsigned int size) { unsigned int header_size = sizeof(dmx_packet) - sizeof(dmx_packet.dmx); if (size <= header_size) { OLA_WARN << "Sandnet data size too small, expected at least " << header_size << ", got " << size; return false; } group_universe_pair key(dmx_packet.group, dmx_packet.universe); universe_handlers::iterator iter = m_handlers.find(key); if (iter == m_handlers.end()) return false; unsigned int data_size = size - header_size; bool r = m_encoder.Decode(0, dmx_packet.dmx, data_size, iter->second.buffer); if (!r) { OLA_WARN << "Failed to decode Sandnet Data"; return false; } iter->second.closure->Run(); return true; } /* * Handle an uncompressed DMX packet */ bool SandNetNode::HandleDMX(const sandnet_dmx &dmx_packet, unsigned int size) { unsigned int header_size = sizeof(dmx_packet) - sizeof(dmx_packet.dmx); if (size <= header_size) { OLA_WARN << "Sandnet data size too small, expected at least " << header_size << ", got " << size; return false; } group_universe_pair key(dmx_packet.group, dmx_packet.universe); universe_handlers::iterator iter = m_handlers.find(key); if (iter == m_handlers.end()) return false; unsigned int data_size = size - header_size; iter->second.buffer->Set(dmx_packet.dmx, data_size); iter->second.closure->Run(); return true; } /* * Send an uncompressed DMX packet */ bool SandNetNode::SendUncompressedDMX(uint8_t port_id, const DmxBuffer &buffer) { sandnet_packet packet; sandnet_dmx *dmx_packet = &packet.contents.dmx; packet.opcode = HostToNetwork(static_cast(SANDNET_DMX)); dmx_packet->group = m_ports[port_id].group; dmx_packet->universe = m_ports[port_id].universe; dmx_packet->port = port_id; unsigned int length = DMX_UNIVERSE_SIZE; buffer.Get(dmx_packet->dmx, &length); unsigned int header_size = sizeof(sandnet_dmx) - sizeof(dmx_packet->dmx); return SendPacket(packet, sizeof(packet.opcode) + header_size + length); } /* * Send a packet */ bool SandNetNode::SendPacket(const sandnet_packet &packet, unsigned int size, bool is_control) { UDPSocket *socket; if (is_control) socket = &m_control_socket; else socket = &m_data_socket; ssize_t bytes_sent = socket->SendTo( reinterpret_cast(&packet), size, is_control ? m_control_addr : m_data_addr); if (bytes_sent != static_cast(size)) { OLA_INFO << "Only sent " << bytes_sent << " of " << size; return false; } return true; } } // namespace sandnet } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/sandnet/SandNetPlugin.cpp0000644000175000017500000000607013023355232022015 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SandNetPlugin.cpp * The SandNet plugin for ola * Copyright (C) 2005 Simon Newton */ #include #include "olad/Preferences.h" #include "plugins/sandnet/SandNetDevice.h" #include "plugins/sandnet/SandNetPlugin.h" namespace ola { namespace plugin { namespace sandnet { using std::string; const char SandNetPlugin::SANDNET_NODE_NAME[] = "ola-SandNet"; const char SandNetPlugin::PLUGIN_NAME[] = "SandNet"; const char SandNetPlugin::PLUGIN_PREFIX[] = "sandnet"; /* * Start the plugin */ bool SandNetPlugin::StartHook() { m_device = new SandNetDevice(this, m_preferences, m_plugin_adaptor); if (!m_device) { return false; } if (!m_device->Start()) { delete m_device; return false; } m_plugin_adaptor->RegisterDevice(m_device); return true; } /* * Stop the plugin * @return true on success, false on failure */ bool SandNetPlugin::StopHook() { if (m_device) { m_plugin_adaptor->UnregisterDevice(m_device); bool ret = m_device->Stop(); delete m_device; return ret; } return true; } /* * Return the description for this plugin */ string SandNetPlugin::Description() const { return "SandNet Plugin\n" "----------------------------\n" "\n" "This plugin creates a single device with 2 output and 8 input ports.\n" "\n" "The universe bindings are offset by one from those displayed in sandnet.\n" "For example, SandNet universe 1 is OLA universe 0.\n" "\n" "--- Config file : ola-sandnet.conf ---\n" "\n" "ip = [a.b.c.d|]\n" "The ip address or interface name to bind to. If not specified it will\n" "use the first non-loopback interface.\n" "\n" "name = ola-SandNet\n" "The name of the node.\n" "\n"; } /* * Assign default values */ bool SandNetPlugin::SetDefaultPreferences() { if (!m_preferences) { return false; } bool save = false; save |= m_preferences->SetDefaultValue(SandNetDevice::IP_KEY, StringValidator(true), ""); save |= m_preferences->SetDefaultValue(SandNetDevice::NAME_KEY, StringValidator(), SANDNET_NODE_NAME); if (save) { m_preferences->Save(); } if (m_preferences->GetValue(SandNetDevice::NAME_KEY).empty()) { return false; } return true; } } // namespace sandnet } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/sandnet/SandNetPort.h0000644000175000017500000000644713023355232021160 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SandNetPort.h * The SandNet plugin for ola * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_SANDNET_SANDNETPORT_H_ #define PLUGINS_SANDNET_SANDNETPORT_H_ #include #include "ola/DmxBuffer.h" #include "olad/Port.h" #include "plugins/sandnet/SandNetDevice.h" namespace ola { namespace plugin { namespace sandnet { class SandNetPortHelper { public: SandNetPortHelper() {} bool PreSetUniverse(Universe *old_universe, Universe *new_universe); std::string Description(const Universe *universe) const; /** * @brief Return the SandNet group that corresponds to a OLA Universe. * @param universe the OLA universe * @return the SandNet group number */ uint8_t SandnetGroup(const Universe* universe) const; /** * @brief Return the SandNet universe that corresponds to a OLA Universe. * * Sandnet universes range from 0 to 255 (represented as 1 to 256 in the packets). * @param universe the OLA universe * @return the sandnet universe number */ uint8_t SandnetUniverse(const Universe *universe) const; }; class SandNetInputPort: public BasicInputPort { public: SandNetInputPort(SandNetDevice *parent, unsigned int id, class PluginAdaptor *plugin_adaptor, SandNetNode *node) : BasicInputPort(parent, id, plugin_adaptor), m_node(node) {} ~SandNetInputPort() {} std::string Description() const { return m_helper.Description(GetUniverse()); } const DmxBuffer &ReadDMX() const { return m_buffer; } bool PreSetUniverse(Universe *old_universe, Universe *new_universe) { return m_helper.PreSetUniverse(old_universe, new_universe); } void PostSetUniverse(Universe *old_universe, Universe *new_universe); private: SandNetPortHelper m_helper; SandNetNode *m_node; DmxBuffer m_buffer; }; class SandNetOutputPort: public BasicOutputPort { public: SandNetOutputPort(SandNetDevice *parent, unsigned int id, SandNetNode *node) : BasicOutputPort(parent, id), m_node(node) {} ~SandNetOutputPort() {} std::string Description() const { return m_helper.Description(GetUniverse()); } bool WriteDMX(const DmxBuffer &buffer, uint8_t priority); bool PreSetUniverse(Universe *old_universe, Universe *new_universe) { return m_helper.PreSetUniverse(old_universe, new_universe); } void PostSetUniverse(Universe *old_universe, Universe *new_universe); private: SandNetPortHelper m_helper; SandNetNode *m_node; }; } // namespace sandnet } // namespace plugin } // namespace ola #endif // PLUGINS_SANDNET_SANDNETPORT_H_ ola-0.10.5.nojsmin/plugins/sandnet/SandNetCommon.h0000644000175000017500000000173013023355232021452 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SandNetCommon.h * Constants for the sandnet plugin * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_SANDNET_SANDNETCOMMON_H_ #define PLUGINS_SANDNET_SANDNETCOMMON_H_ enum {SANDNET_MAX_PORTS = 2}; #endif // PLUGINS_SANDNET_SANDNETCOMMON_H_ ola-0.10.5.nojsmin/plugins/sandnet/SandNetPlugin.h0000644000175000017500000000346713023355232021471 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SandNetPlugin.h * Interface for the sandnet plugin class * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_SANDNET_SANDNETPLUGIN_H_ #define PLUGINS_SANDNET_SANDNETPLUGIN_H_ #include #include "ola/plugin_id.h" #include "olad/Plugin.h" #include "olad/PluginAdaptor.h" namespace ola { namespace plugin { namespace sandnet { class SandNetPlugin: public ola::Plugin { public: explicit SandNetPlugin(ola::PluginAdaptor *plugin_adaptor) : Plugin(plugin_adaptor), m_device(NULL) {} std::string Name() const { return PLUGIN_NAME; } std::string Description() const; ola_plugin_id Id() const { return OLA_PLUGIN_SANDNET; } std::string PluginPrefix() const { return PLUGIN_PREFIX; } private: class SandNetDevice *m_device; // only have one device bool StartHook(); bool StopHook(); bool SetDefaultPreferences(); static const char SANDNET_NODE_NAME[]; static const char PLUGIN_NAME[]; static const char PLUGIN_PREFIX[]; }; } // namespace sandnet } // namespace plugin } // namespace ola #endif // PLUGINS_SANDNET_SANDNETPLUGIN_H_ ola-0.10.5.nojsmin/plugins/sandnet/SandNetPort.cpp0000644000175000017500000000654313023355232021510 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SandNetPort.cpp * The SandNet plugin for ola * Copyright (C) 2005 Simon Newton */ #include #include #include #include "ola/Callback.h" #include "ola/Logging.h" #include "olad/Universe.h" #include "plugins/sandnet/SandNetPort.h" #include "plugins/sandnet/SandNetDevice.h" #include "plugins/sandnet/SandNetCommon.h" namespace ola { namespace plugin { namespace sandnet { using std::string; // We override the set universe method to update the universe -> port hash bool SandNetPortHelper::PreSetUniverse(Universe *old_universe, Universe *new_universe) { if (new_universe && !new_universe->UniverseId()) { OLA_WARN << "Can't use universe 0 with Sandnet!"; return false; } (void) old_universe; return true; } string SandNetPortHelper::Description(const Universe *universe) const { std::ostringstream str; if (universe) { str << "Sandnet group " << static_cast(SandnetGroup(universe)) << ", universe " << 1 + SandnetUniverse(universe); } return str.str(); } uint8_t SandNetPortHelper::SandnetGroup(const Universe *universe) const { if (universe) return (uint8_t) ((universe->UniverseId() - 1) >> 8); return 0; } uint8_t SandNetPortHelper::SandnetUniverse(const Universe *universe) const { if (universe) return universe->UniverseId() - 1; return 0; } void SandNetInputPort::PostSetUniverse(Universe *old_universe, Universe *new_universe) { if (old_universe) m_node->RemoveHandler(m_helper.SandnetGroup(old_universe), m_helper.SandnetUniverse(old_universe)); if (new_universe) { m_node->SetHandler( m_helper.SandnetGroup(new_universe), m_helper.SandnetUniverse(new_universe), &m_buffer, NewCallback(this, &SandNetInputPort::DmxChanged)); } } bool SandNetOutputPort::WriteDMX(const DmxBuffer &buffer, uint8_t priority) { (void) priority; if (!GetUniverse()) return false; if (!m_node->SendDMX(PortId(), buffer)) return false; return true; } void SandNetOutputPort::PostSetUniverse(Universe *old_universe, Universe *new_universe) { if (new_universe) m_node->SetPortParameters(PortId(), SandNetNode::SANDNET_PORT_MODE_IN, m_helper.SandnetGroup(new_universe), m_helper.SandnetUniverse(new_universe)); (void) old_universe; } } // namespace sandnet } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/sandnet/SandNetPackets.h0000644000175000017500000001331413023355232021615 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SandNetPackets.h * Datagram definitions for SandNet * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_SANDNET_SANDNETPACKETS_H_ #define PLUGINS_SANDNET_SANDNETPACKETS_H_ #include #include #ifndef _WIN32 #include #endif // _WIN32 #include #include "ola/network/IPV4Address.h" #include "ola/network/MACAddress.h" #include "plugins/sandnet/SandNetCommon.h" namespace ola { namespace plugin { namespace sandnet { enum { SANDNET_NAME_LENGTH = 31}; /* * SandNet opcodes. * These are transmitted as little-endian which is why they appear strange. */ // We can't use the PACK macro for enums #ifdef _WIN32 #pragma pack(push, 1) #endif // _WIN32 enum packet_type_e { SANDNET_ADVERTISEMENT = 0x0100, SANDNET_CONTROL = 0x0200, SANDNET_DMX = 0x0300, SANDNET_NAME = 0x0400, SANDNET_IDENTIFY = 0x0500, SANDNET_PROG = 0x0600, SANDNET_LED = 0x0700, SANDNET_COMPRESSED_DMX = 0x0a00, #ifdef _WIN32 }; #pragma pack(pop) #else } __attribute__((packed)); #endif // _WIN32 typedef enum packet_type_e packet_type_t; // We can't use the PACK macro for enums #ifdef _WIN32 #pragma pack(push, 1) #endif // _WIN32 enum protocol_id_e { SANDNET_SANDNET = 0x02, SANDNET_ARTNET = 0x04, SANDNET_COMPULIGHT = 0x06, SANDNET_SHOWNET = 0x09, SANDNET_IPX = 0x0d, SANDNET_ACN = 0x0e, #ifdef _WIN32 }; #pragma pack(pop) #else } __attribute__((packed)); #endif // _WIN32 typedef enum protocol_id_e protocol_id_t; PACK( struct sandnet_packet_advertisement_port_s { protocol_id_t protocol; // protocol uint8_t mode; // mode uint8_t term; // terminate uint8_t b; // ?? uint8_t group; // group uint8_t universe; // universe uint8_t crap[53]; // ?? }); /* * A Sandnet Advertisement */ PACK( struct sandnet_advertisement_s { uint8_t mac[ola::network::MACAddress::LENGTH]; // mac address uint32_t firmware; // firmware version struct sandnet_packet_advertisement_port_s ports[SANDNET_MAX_PORTS]; // ports uint8_t nlen; // length of the name field char name[SANDNET_NAME_LENGTH]; // name field (null terminated) uint8_t magic3[9]; // magic numbers uint8_t led; // flash the led uint8_t magic4; // ?? uint8_t zero4[64]; // null }); typedef struct sandnet_advertisement_s sandnet_advertisement; /* * The first of the DMX packets */ PACK( struct sandnet_dmx_s { uint8_t group; // group uint8_t universe; // universe uint8_t port; // physical port number uint8_t dmx[DMX_UNIVERSE_SIZE]; // dmx buffer }); typedef struct sandnet_dmx_s sandnet_dmx; /* * Changes the port attributes */ PACK( struct sandnet_port_control_s { uint8_t mac[ola::network::MACAddress::LENGTH]; // mac address uint8_t magic[4]; // ?? seems to change struct sandnet_packet_advertisement_port_s ports[SANDNET_MAX_PORTS]; // ports }); typedef struct sandnet_port_control_s sandnet_port_control; /* * Sets the name of the sandnet node */ PACK( struct sandnet_name_s { uint8_t mac[ola::network::MACAddress::LENGTH]; // mac address uint8_t name_length; // length of the name field uint8_t name[SANDNET_NAME_LENGTH]; // name field }); typedef struct sandnet_name_s sandnet_name; /* * identify packet * (presumably this flashes the leds or something) */ PACK( struct sandnet_identify_s { uint8_t mac[ola::network::MACAddress::LENGTH]; // mac address }); typedef struct sandnet_identify_s sandnet_identify; /* * ip program packet * sets the node's networking parameters */ PACK( struct sandnet_program_s { uint8_t mac[ola::network::MACAddress::LENGTH]; // mac address uint8_t ip[ola::network::IPV4Address::LENGTH]; uint8_t dhcp; uint8_t netmask[ola::network::IPV4Address::LENGTH]; }); typedef struct sandnet_program_s sandnet_program; /* * Turns the led on and off */ PACK( struct sandnet_led_s { uint8_t mac[ola::network::MACAddress::LENGTH]; // mac address uint8_t led; // 0x00 off, 0xff on }); typedef struct sandnet_led_s sandnet_led; /* * DMX data */ PACK( struct sandnet_compressed_dmx_s { uint8_t group; // group uint8_t universe; // universe uint8_t port; // physical port number uint8_t zero1[4]; // could be the offset uint8_t two; // 0x02 uint16_t length; // length of data uint8_t dmx[DMX_UNIVERSE_SIZE]; }); typedef struct sandnet_compressed_dmx_s sandnet_compressed_dmx; // A generic Sandnet packet containing the union of all possible packets PACK( struct sandnet_packet { uint16_t opcode; union { sandnet_advertisement advertisement; sandnet_port_control port_control; sandnet_dmx dmx; sandnet_name name; sandnet_identify id; sandnet_program program; sandnet_led led; sandnet_compressed_dmx compressed_dmx; } contents; }); } // namespace sandnet } // namespace plugin } // namespace ola #endif // PLUGINS_SANDNET_SANDNETPACKETS_H_ ola-0.10.5.nojsmin/plugins/sandnet/SandNetNode.h0000644000175000017500000000756013023355232021116 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SandNetNode.h * Header file for the SandNetNode class * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_SANDNET_SANDNETNODE_H_ #define PLUGINS_SANDNET_SANDNETNODE_H_ #include #include #include #include #include "ola/Callback.h" #include "ola/DmxBuffer.h" #include "ola/network/IPV4Address.h" #include "ola/network/InterfacePicker.h" #include "ola/network/Socket.h" #include "ola/dmx/RunLengthEncoder.h" #include "plugins/sandnet/SandNetPackets.h" namespace ola { namespace plugin { namespace sandnet { class SandNetNode { public: typedef enum { SANDNET_PORT_MODE_DISABLED, SANDNET_PORT_MODE_OUT, SANDNET_PORT_MODE_IN, SANDNET_PORT_MODE_MOUT, SANDNET_PORT_MODE_MIN } sandnet_port_type; explicit SandNetNode(const std::string &preferred_ip); ~SandNetNode(); const ola::network::Interface &GetInterface() const { return m_interface; } void SetName(const std::string &name) { m_node_name = name; } bool Start(); bool Stop(); std::vector GetSockets(); void SocketReady(ola::network::UDPSocket *socket); bool SetHandler(uint8_t group, uint8_t universe, DmxBuffer *buffer, Callback0 *closure); bool RemoveHandler(uint8_t group, uint8_t universe); bool SetPortParameters(uint8_t port_id, sandnet_port_type type, uint8_t group, uint8_t universe); bool SendAdvertisement(); bool SendDMX(uint8_t port_id, const DmxBuffer &buffer); private: typedef struct { uint8_t group; uint8_t universe; sandnet_port_type type; } sandnet_port; typedef struct { DmxBuffer *buffer; Callback0 *closure; } universe_handler; typedef std::pair group_universe_pair; typedef std::map universe_handlers; bool InitNetwork(); bool HandleCompressedDMX(const sandnet_compressed_dmx &dmx_packet, unsigned int size); bool HandleDMX(const sandnet_dmx &dmx_packet, unsigned int size); bool SendUncompressedDMX(uint8_t port_id, const DmxBuffer &buffer); bool SendPacket(const sandnet_packet &packet, unsigned int size, bool is_control = false); bool m_running; std::string m_node_name; std::string m_preferred_ip; sandnet_port m_ports[SANDNET_MAX_PORTS]; universe_handlers m_handlers; ola::network::Interface m_interface; ola::network::UDPSocket m_control_socket; ola::network::UDPSocket m_data_socket; ola::dmx::RunLengthEncoder m_encoder; ola::network::IPV4SocketAddress m_control_addr; ola::network::IPV4SocketAddress m_data_addr; static const uint16_t CONTROL_PORT; static const uint16_t DATA_PORT; static const char CONTROL_ADDRESS[]; static const char DATA_ADDRESS[]; static const char DEFAULT_NODE_NAME[]; static const uint32_t FIRMWARE_VERSION = 0x00050501; }; } // namespace sandnet } // namespace plugin } // namespace ola #endif // PLUGINS_SANDNET_SANDNETNODE_H_ ola-0.10.5.nojsmin/plugins/opendmx/0000755000175000017500000000000013155164170016616 5ustar wouterwouterola-0.10.5.nojsmin/plugins/opendmx/Makefile.mk0000644000175000017500000000107513023355232020662 0ustar wouterwouter# LIBRARIES ################################################## if USE_OPENDMX lib_LTLIBRARIES += plugins/opendmx/libolaopendmx.la plugins_opendmx_libolaopendmx_la_SOURCES = \ plugins/opendmx/OpenDmxDevice.cpp \ plugins/opendmx/OpenDmxDevice.h \ plugins/opendmx/OpenDmxPlugin.cpp \ plugins/opendmx/OpenDmxPlugin.h \ plugins/opendmx/OpenDmxPort.h \ plugins/opendmx/OpenDmxThread.cpp \ plugins/opendmx/OpenDmxThread.h plugins_opendmx_libolaopendmx_la_LIBADD = \ common/libolacommon.la \ olad/plugin_api/libolaserverplugininterface.la endif ola-0.10.5.nojsmin/plugins/opendmx/OpenDmxPlugin.h0000644000175000017500000000360213023355232021514 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OpenDmxPlugin.h * Interface for the opendmx plugin class * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_OPENDMX_OPENDMXPLUGIN_H_ #define PLUGINS_OPENDMX_OPENDMXPLUGIN_H_ #include #include #include "olad/Plugin.h" #include "ola/plugin_id.h" namespace ola { namespace plugin { namespace opendmx { class OpenDmxDevice; class OpenDmxPlugin: public Plugin { public: explicit OpenDmxPlugin(PluginAdaptor *plugin_adaptor): Plugin(plugin_adaptor) { } std::string Name() const { return PLUGIN_NAME; } std::string Description() const; ola_plugin_id Id() const { return OLA_PLUGIN_OPENDMX; } std::string PluginPrefix() const { return PLUGIN_PREFIX; } private: bool StartHook(); bool StopHook(); bool SetDefaultPreferences(); typedef std::vector DeviceList; DeviceList m_devices; static const char PLUGIN_NAME[]; static const char PLUGIN_PREFIX[]; static const char OPENDMX_DEVICE_PATH[]; static const char OPENDMX_DEVICE_NAME[]; static const char DEVICE_KEY[]; }; } // namespace opendmx } // namespace plugin } // namespace ola #endif // PLUGINS_OPENDMX_OPENDMXPLUGIN_H_ ola-0.10.5.nojsmin/plugins/opendmx/OpenDmxDevice.h0000644000175000017500000000301513023355232021453 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OpenDmxDevice.h * Interface for the Open DMX device * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_OPENDMX_OPENDMXDEVICE_H_ #define PLUGINS_OPENDMX_OPENDMXDEVICE_H_ #include #include "olad/Device.h" namespace ola { namespace plugin { namespace opendmx { class OpenDmxDevice: public ola::Device { public: OpenDmxDevice(ola::AbstractPlugin *owner, const std::string &name, const std::string &path, unsigned int device_id); // we only support one widget for now std::string DeviceId() const { return m_device_id; } protected: bool StartHook(); private: std::string m_path; std::string m_device_id; }; } // namespace opendmx } // namespace plugin } // namespace ola #endif // PLUGINS_OPENDMX_OPENDMXDEVICE_H_ ola-0.10.5.nojsmin/plugins/opendmx/OpenDmxThread.cpp0000644000175000017500000000616013023355232022022 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OpenDmxThread.cpp * Thread for the Open DMX device * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include #include #include #include #include #include #include #include #include "ola/Clock.h" #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/io/IOUtils.h" #include "plugins/opendmx/OpenDmxThread.h" namespace ola { namespace plugin { namespace opendmx { using std::string; using ola::thread::Mutex; using ola::thread::MutexLocker; /* * Create a new OpenDmxThread object */ OpenDmxThread::OpenDmxThread(const string &path) : ola::thread::Thread(), m_fd(INVALID_FD), m_path(path), m_term(false) { } /* * Run this thread */ void *OpenDmxThread::Run() { uint8_t buffer[DMX_UNIVERSE_SIZE+1]; unsigned int length = DMX_UNIVERSE_SIZE; Clock clock; // should close other fd here // start code buffer[0] = 0x00; ola::io::Open(m_path, O_WRONLY, &m_fd); while (true) { { MutexLocker lock(&m_term_mutex); if (m_term) break; } if (m_fd == INVALID_FD) { TimeStamp wake_up; clock.CurrentTime(&wake_up); wake_up += TimeInterval(1, 0); // wait for either a signal that we should terminate, or ts seconds m_term_mutex.Lock(); if (m_term) break; m_term_cond.TimedWait(&m_term_mutex, wake_up); m_term_mutex.Unlock(); ola::io::Open(m_path, O_WRONLY, &m_fd); } else { length = DMX_UNIVERSE_SIZE; { MutexLocker locker(&m_mutex); m_buffer.Get(buffer + 1, &length); } if (write(m_fd, buffer, length + 1) < 0) { // if you unplug the dongle OLA_WARN << "Error writing to device: " << strerror(errno); if (close(m_fd) < 0) OLA_WARN << "Close failed " << strerror(errno); m_fd = INVALID_FD; } } } return NULL; } /* * Stop the thread */ bool OpenDmxThread::Stop() { { MutexLocker locker(&m_mutex); m_term = true; } m_term_cond.Signal(); return Join(); } /* * Store the data in the shared buffer * */ bool OpenDmxThread::WriteDmx(const DmxBuffer &buffer) { MutexLocker locker(&m_mutex); // avoid the reference counting m_buffer.Set(buffer); return true; } } // namespace opendmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/opendmx/OpenDmxThread.h0000644000175000017500000000311713023355232021466 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OpenDmxThread.h * Thread for the Open DMX device * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_OPENDMX_OPENDMXTHREAD_H_ #define PLUGINS_OPENDMX_OPENDMXTHREAD_H_ #include #include "ola/DmxBuffer.h" #include "ola/thread/Thread.h" namespace ola { namespace plugin { namespace opendmx { class OpenDmxThread: public ola::thread::Thread { public: explicit OpenDmxThread(const std::string &path); ~OpenDmxThread() {} bool Stop(); bool WriteDmx(const DmxBuffer &buffer); void *Run(); private: int m_fd; std::string m_path; DmxBuffer m_buffer; bool m_term; ola::thread::Mutex m_mutex; ola::thread::Mutex m_term_mutex; ola::thread::ConditionVariable m_term_cond; static const int INVALID_FD = -1; }; } // namespace opendmx } // namespace plugin } // namespace ola #endif // PLUGINS_OPENDMX_OPENDMXTHREAD_H_ ola-0.10.5.nojsmin/plugins/opendmx/OpenDmxPlugin.cpp0000644000175000017500000000734113023355232022053 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OpenDmxPlugin.cpp * The Open DMX plugin for ola * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include #include #include #include "ola/Logging.h" #include "ola/io/IOUtils.h" #include "olad/PluginAdaptor.h" #include "olad/Preferences.h" #include "plugins/opendmx/OpenDmxDevice.h" #include "plugins/opendmx/OpenDmxPlugin.h" namespace ola { namespace plugin { namespace opendmx { using ola::PluginAdaptor; using std::string; using std::vector; const char OpenDmxPlugin::OPENDMX_DEVICE_PATH[] = "/dev/dmx0"; const char OpenDmxPlugin::OPENDMX_DEVICE_NAME[] = "OpenDmx USB Device"; const char OpenDmxPlugin::PLUGIN_NAME[] = "Enttec Open DMX"; const char OpenDmxPlugin::PLUGIN_PREFIX[] = "opendmx"; const char OpenDmxPlugin::DEVICE_KEY[] = "device"; /* * Start the plugin * TODO: scan /dev for devices? */ bool OpenDmxPlugin::StartHook() { vector devices = m_preferences->GetMultipleValue(DEVICE_KEY); vector::const_iterator iter = devices.begin(); // start counting device ids from 0 unsigned int device_id = 0; for (; iter != devices.end(); ++iter) { // first check if it's there int fd; if (ola::io::Open(*iter, O_WRONLY, &fd)) { close(fd); OpenDmxDevice *device = new OpenDmxDevice( this, OPENDMX_DEVICE_NAME, *iter, device_id++); if (device->Start()) { m_devices.push_back(device); m_plugin_adaptor->RegisterDevice(device); } else { OLA_WARN << "Failed to start OpenDmxDevice for " << *iter; delete device; } } else { OLA_WARN << "Could not open " << *iter << " " << strerror(errno); } } return true; } /* * Stop the plugin * @return true on success, false on failure */ bool OpenDmxPlugin::StopHook() { bool ret = true; DeviceList::iterator iter = m_devices.begin(); for (; iter != m_devices.end(); ++iter) { m_plugin_adaptor->UnregisterDevice(*iter); ret &= (*iter)->Stop(); delete *iter; } m_devices.clear(); return ret; } /* * Return the description for this plugin */ string OpenDmxPlugin::Description() const { return "Enttec Open DMX Plugin\n" "----------------------------\n" "\n" "The plugin creates a single device with one output port using the Enttec\n" "Open DMX USB widget.\n" "\n" "--- Config file : ola-opendmx.conf ---\n" "\n" "device = /dev/dmx0\n" "The path to the Open DMX USB device. Multiple entries are supported.\n" "\n"; } /* * Set default preferences. */ bool OpenDmxPlugin::SetDefaultPreferences() { if (!m_preferences) { return false; } if (m_preferences->SetDefaultValue(DEVICE_KEY, StringValidator(), OPENDMX_DEVICE_PATH)) { m_preferences->Save(); } // check if this save correctly // we don't want to use it if null if (m_preferences->GetValue(DEVICE_KEY).empty()) { return false; } return true; } } // namespace opendmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/opendmx/OpenDmxDevice.cpp0000644000175000017500000000325213023355232022011 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OpenDmxDevice.cpp * The Open DMX device * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include #include "plugins/opendmx/OpenDmxDevice.h" #include "plugins/opendmx/OpenDmxPort.h" namespace ola { namespace plugin { namespace opendmx { using ola::Device; using std::string; /* * Create a new device * @param owner * @param name * @param path to device */ OpenDmxDevice::OpenDmxDevice(AbstractPlugin *owner, const string &name, const string &path, unsigned int device_id) : Device(owner, name), m_path(path) { std::ostringstream str; str << device_id; m_device_id = str.str(); } /* * Start this device */ bool OpenDmxDevice::StartHook() { AddPort(new OpenDmxOutputPort(this, 0, m_path)); return true; } } // namespace opendmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/opendmx/OpenDmxPort.h0000644000175000017500000000342313023355232021203 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OpenDmxPort.h * The Open DMX plugin for ola * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_OPENDMX_OPENDMXPORT_H_ #define PLUGINS_OPENDMX_OPENDMXPORT_H_ #include #include "ola/DmxBuffer.h" #include "olad/Port.h" #include "plugins/opendmx/OpenDmxDevice.h" #include "plugins/opendmx/OpenDmxThread.h" namespace ola { namespace plugin { namespace opendmx { class OpenDmxOutputPort: public BasicOutputPort { public: OpenDmxOutputPort(OpenDmxDevice *parent, unsigned int id, const std::string &path) : BasicOutputPort(parent, id), m_thread(path), m_path(path) { m_thread.Start(); } ~OpenDmxOutputPort() { m_thread.Stop(); } std::string Description() const { return "Open DMX at " + m_path; } bool WriteDMX(const DmxBuffer &buffer, OLA_UNUSED uint8_t priority) { return m_thread.WriteDmx(buffer); } private: OpenDmxThread m_thread; std::string m_path; }; } // namespace opendmx } // namespace plugin } // namespace ola #endif // PLUGINS_OPENDMX_OPENDMXPORT_H_ ola-0.10.5.nojsmin/plugins/uartdmx/0000755000175000017500000000000013155164170016630 5ustar wouterwouterola-0.10.5.nojsmin/plugins/uartdmx/UartDmxPlugin.cpp0000644000175000017500000001201713023355232022073 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * UartDmxPlugin.cpp * The DMX through a UART plugin for ola * Copyright (C) 2011 Rui Barreiros * Copyright (C) 2014 Richard Ash */ #include #include #include #include #include #include "ola/StringUtils.h" #include "ola/io/IOUtils.h" #include "olad/Preferences.h" #include "olad/PluginAdaptor.h" #include "plugins/uartdmx/UartDmxPlugin.h" #include "plugins/uartdmx/UartDmxDevice.h" #include "plugins/uartdmx/UartWidget.h" namespace ola { namespace plugin { namespace uartdmx { using std::string; using std::vector; const char UartDmxPlugin::PLUGIN_NAME[] = "UART native DMX"; const char UartDmxPlugin::PLUGIN_PREFIX[] = "uartdmx"; const char UartDmxPlugin::K_DEVICE[] = "device"; const char UartDmxPlugin::DEFAULT_DEVICE[] = "/dev/ttyACM0"; /* * Start the plug-in, using only the configured device(s) (we cannot sensibly * scan for UARTs!). Stolen from the opendmx plugin. */ bool UartDmxPlugin::StartHook() { vector devices = m_preferences->GetMultipleValue(K_DEVICE); vector::const_iterator iter; // iterate over devices // start counting device ids from 0 for (iter = devices.begin(); iter != devices.end(); ++iter) { // first check if device configured if (iter->empty()) { OLA_DEBUG << "No path configured for device, please set one in " << "ola-uartdmx.conf"; continue; } OLA_DEBUG << "Trying to open UART device " << *iter; int fd; if (!ola::io::Open(*iter, O_WRONLY, &fd)) { OLA_WARN << "Could not open " << *iter << " " << strerror(errno); continue; } // can open device, so shut the temporary file descriptor close(fd); std::auto_ptr device(new UartDmxDevice( this, m_preferences, PLUGIN_NAME, *iter)); // got a device, now lets see if we can configure it before we announce // it to the world if (!device->GetWidget()->SetupOutput()) { OLA_WARN << "Unable to setup device for output, device ignored " << device->DeviceId(); continue; } // OK, device is good to go if (!device->Start()) { OLA_WARN << "Failed to start UartDmxDevice for " << *iter; continue; } OLA_DEBUG << "Started UartDmxDevice " << *iter; m_plugin_adaptor->RegisterDevice(device.get()); m_devices.push_back(device.release()); } return true; } /** * Stop all the devices. */ bool UartDmxPlugin::StopHook() { UartDeviceVector::iterator iter; for (iter = m_devices.begin(); iter != m_devices.end(); ++iter) { m_plugin_adaptor->UnregisterDevice(*iter); (*iter)->Stop(); delete *iter; } m_devices.clear(); return true; } /** * Return a description for this plugin. */ string UartDmxPlugin::Description() const { return "Native UART DMX Plugin\n" "----------------------\n" "\n" "This plugin drives a supported POSIX UART (plus extensions)\n" "to produce a direct DMX output stream. The host needs to\n" "create the DMX stream itself as there is no external microcontroller.\n" "This is tested with the on-board UART of the Raspberry Pi.\n" "See here for a possible schematic:\n" "http://eastertrail.blogspot.co.uk/2014/04/command-and-control-ii.html\n" "\n" "--- Config file : ola-uartdmx.conf ---\n" "\n" "enabled = true\n" "Enable this plugin (DISABLED by default).\n" "device = /dev/ttyACM0\n" "The device to use for DMX output (optional). Multiple devices are supported " "if the hardware exists. Using USB-serial adapters is not supported (try the " "ftdidmx plugin instead).\n" "--- Per Device Settings (using above device name) ---\n" "-break = 100\n" "The DMX break time in microseconds for this device (optional).\n" "-malf = 100\n" "The Mark After Last Frame time in microseconds for this device (optional).\n" "\n"; } /** * Set the default preferences */ bool UartDmxPlugin::SetDefaultPreferences() { if (!m_preferences) { return false; } // only insert default device name, no others at this stage bool save = m_preferences->SetDefaultValue(K_DEVICE, StringValidator(), DEFAULT_DEVICE); if (save) { m_preferences->Save(); } // Just check key exists, as we've set it to "" if (!m_preferences->HasKey(K_DEVICE)) { return false; } return true; } } // namespace uartdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/uartdmx/Makefile.mk0000644000175000017500000000120313023355232020665 0ustar wouterwouter# LIBRARIES ################################################## if USE_UART lib_LTLIBRARIES += plugins/uartdmx/libolauartdmx.la plugins_uartdmx_libolauartdmx_la_SOURCES = \ plugins/uartdmx/UartDmxDevice.cpp \ plugins/uartdmx/UartDmxDevice.h \ plugins/uartdmx/UartDmxPlugin.cpp \ plugins/uartdmx/UartDmxPlugin.h \ plugins/uartdmx/UartDmxPort.h \ plugins/uartdmx/UartDmxThread.cpp \ plugins/uartdmx/UartDmxThread.h \ plugins/uartdmx/UartWidget.cpp \ plugins/uartdmx/UartWidget.h plugins_uartdmx_libolauartdmx_la_LIBADD = \ common/libolacommon.la \ olad/plugin_api/libolaserverplugininterface.la endif ola-0.10.5.nojsmin/plugins/uartdmx/UartDmxThread.cpp0000644000175000017500000000623313023355232022047 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * UartDmxThread.cpp * The DMX through a UART plugin for ola * Copyright (C) 2011 Rui Barreiros * Copyright (C) 2014 Richard Ash */ #include #include #include #include "ola/Clock.h" #include "ola/Logging.h" #include "ola/StringUtils.h" #include "plugins/uartdmx/UartWidget.h" #include "plugins/uartdmx/UartDmxThread.h" namespace ola { namespace plugin { namespace uartdmx { UartDmxThread::UartDmxThread(UartWidget *widget, unsigned int breakt, unsigned int malft) : m_granularity(UNKNOWN), m_widget(widget), m_term(false), m_breakt(breakt), m_malft(malft) { } UartDmxThread::~UartDmxThread() { Stop(); } /** * Stop this thread */ bool UartDmxThread::Stop() { { ola::thread::MutexLocker locker(&m_term_mutex); m_term = true; } return Join(); } /** * Copy a DMXBuffer to the output thread */ bool UartDmxThread::WriteDMX(const DmxBuffer &buffer) { ola::thread::MutexLocker locker(&m_buffer_mutex); m_buffer.Set(buffer); return true; } /** * The method called by the thread */ void *UartDmxThread::Run() { TimeStamp ts1, ts2; Clock clock; CheckTimeGranularity(); DmxBuffer buffer; // Setup the widget if (!m_widget->IsOpen()) m_widget->SetupOutput(); while (1) { { ola::thread::MutexLocker locker(&m_term_mutex); if (m_term) break; } { ola::thread::MutexLocker locker(&m_buffer_mutex); buffer.Set(m_buffer); } if (!m_widget->SetBreak(true)) goto framesleep; if (m_granularity == GOOD) usleep(m_breakt); if (!m_widget->SetBreak(false)) goto framesleep; if (m_granularity == GOOD) usleep(DMX_MAB); if (!m_widget->Write(buffer)) goto framesleep; framesleep: // Sleep for the remainder of the DMX frame time usleep(m_malft); } return NULL; } /** * Check the granularity of usleep. */ void UartDmxThread::CheckTimeGranularity() { TimeStamp ts1, ts2; Clock clock; /** If sleeping for 1ms takes longer than this, don't trust * usleep for this session */ const int threshold = 3; clock.CurrentTime(&ts1); usleep(1000); clock.CurrentTime(&ts2); TimeInterval interval = ts2 - ts1; m_granularity = interval.InMilliSeconds() > threshold ? BAD : GOOD; OLA_INFO << "Granularity for UART thread is " << (m_granularity == GOOD ? "GOOD" : "BAD"); } } // namespace uartdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/uartdmx/UartDmxPort.h0000644000175000017500000000401213023355232021222 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * UartDmxPort.h * The DMX through a UART plugin for ola * Copyright (C) 2011 Rui Barreiros * Copyright (C) 2014 Richard Ash */ #ifndef PLUGINS_UARTDMX_UARTDMXPORT_H_ #define PLUGINS_UARTDMX_UARTDMXPORT_H_ #include #include "ola/DmxBuffer.h" #include "olad/Port.h" #include "olad/Preferences.h" #include "plugins/uartdmx/UartDmxDevice.h" #include "plugins/uartdmx/UartWidget.h" #include "plugins/uartdmx/UartDmxThread.h" namespace ola { namespace plugin { namespace uartdmx { class UartDmxOutputPort : public ola::BasicOutputPort { public: UartDmxOutputPort(UartDmxDevice *parent, unsigned int id, UartWidget *widget, unsigned int breakt, unsigned int malft) : BasicOutputPort(parent, id), m_widget(widget), m_thread(widget, breakt, malft) { m_thread.Start(); } ~UartDmxOutputPort() { m_thread.Stop(); } bool WriteDMX(const ola::DmxBuffer &buffer, uint8_t) { return m_thread.WriteDMX(buffer); } std::string Description() const { return m_widget->Description(); } private: UartWidget *m_widget; UartDmxThread m_thread; DISALLOW_COPY_AND_ASSIGN(UartDmxOutputPort); }; } // namespace uartdmx } // namespace plugin } // namespace ola #endif // PLUGINS_UARTDMX_UARTDMXPORT_H_ ola-0.10.5.nojsmin/plugins/uartdmx/UartDmxDevice.h0000644000175000017500000000417613023355232021510 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * UartDmxDevice.h * The DMX through a UART plugin for ola * Copyright (C) 2011 Rui Barreiros * Copyright (C) 2014 Richard Ash */ #ifndef PLUGINS_UARTDMX_UARTDMXDEVICE_H_ #define PLUGINS_UARTDMX_UARTDMXDEVICE_H_ #include #include #include #include "ola/DmxBuffer.h" #include "olad/Device.h" #include "olad/Preferences.h" #include "plugins/uartdmx/UartWidget.h" namespace ola { namespace plugin { namespace uartdmx { class UartDmxDevice : public Device { public: UartDmxDevice(AbstractPlugin *owner, class Preferences *preferences, const std::string &name, const std::string &path); ~UartDmxDevice(); std::string DeviceId() const { return m_path; } UartWidget* GetWidget() { return m_widget.get(); } protected: bool StartHook(); private: // Per device options std::string DeviceBreakKey() const; std::string DeviceMalfKey() const; void SetDefaults(); std::auto_ptr m_widget; class Preferences *m_preferences; const std::string m_name; const std::string m_path; unsigned int m_breakt; unsigned int m_malft; static const unsigned int DEFAULT_MALF; static const char K_MALF[]; static const unsigned int DEFAULT_BREAK; static const char K_BREAK[]; DISALLOW_COPY_AND_ASSIGN(UartDmxDevice); }; } // namespace uartdmx } // namespace plugin } // namespace ola #endif // PLUGINS_UARTDMX_UARTDMXDEVICE_H_ ola-0.10.5.nojsmin/plugins/uartdmx/UartWidget.h0000644000175000017500000000532313023355232021056 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * UartWidget.h * This class is based on QLCFTDI class from * * Q Light Controller * qlcftdi.h * * Copyright (C) Heikki Junnila * * Only standard CPP conversion was changed and function name changed * to follow OLA coding standards. * * by Rui Barreiros * Copyright (C) 2014 Richard Ash */ #ifndef PLUGINS_UARTDMX_UARTWIDGET_H_ #define PLUGINS_UARTDMX_UARTWIDGET_H_ #include #include #include "ola/base/Macro.h" #include "ola/DmxBuffer.h" namespace ola { namespace plugin { namespace uartdmx { /** * An UART widget (i.e. a serial port with suitable hardware attached) */ class UartWidget { public: /** * Construct a new UartWidget instance for one widget. * @param path The device file path of the serial port */ explicit UartWidget(const std::string &path); /** Destructor */ virtual ~UartWidget(); /** Get the widget's device name */ std::string Name() const { return m_path; } std::string Description() const { return m_path; } /** Open the widget */ bool Open(); /** Close the widget */ bool Close(); /** Check if the widget is open */ bool IsOpen() const; /** Toggle communications line BREAK condition on/off */ bool SetBreak(bool on); /** Write data to a previously-opened line */ bool Write(const ola::DmxBuffer &data); /** Read data from a previously-opened line */ bool Read(unsigned char* buff, int size); /** Setup device for DMX Output **/ bool SetupOutput(); private: const std::string m_path; /** * variable to hold the Unix file descriptor used to open and manipulate * the port. Set to -2 when port is not open. */ int m_fd; /** * Constant value for file is not open */ static const int NOT_OPEN = -2; /** * Constant value for failed to open file */ static const int FAILED_OPEN = -1; DISALLOW_COPY_AND_ASSIGN(UartWidget); }; } // namespace uartdmx } // namespace plugin } // namespace ola #endif // PLUGINS_UARTDMX_UARTWIDGET_H_ ola-0.10.5.nojsmin/plugins/uartdmx/UartDmxPlugin.h0000644000175000017500000000420513023355232021540 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * UartDmxPlugin.h * The DMX through a UART plugin for ola * Copyright (C) 2011 Rui Barreiros * Copyright (C) 2014 Richard Ash */ #ifndef PLUGINS_UARTDMX_UARTDMXPLUGIN_H_ #define PLUGINS_UARTDMX_UARTDMXPLUGIN_H_ #include #include #include #include "olad/Plugin.h" #include "ola/plugin_id.h" #include "plugins/uartdmx/UartDmxDevice.h" namespace ola { namespace plugin { namespace uartdmx { class UartDmxPlugin : public Plugin { public: explicit UartDmxPlugin(ola::PluginAdaptor *plugin_adaptor) : Plugin(plugin_adaptor) { } ola_plugin_id Id() const { return OLA_PLUGIN_UARTDMX; } std::string Name() const { return PLUGIN_NAME; } std::string PluginPrefix() const { return PLUGIN_PREFIX; } // This plugin is disabled unless explicitly enabled by a user. bool DefaultMode() const { return false; } std::string Description() const; private: typedef std::vector UartDeviceVector; UartDeviceVector m_devices; void AddDevice(UartDmxDevice *device); bool StartHook(); bool StopHook(); bool SetDefaultPreferences(); unsigned int GetBreak(); unsigned int GetMalf(); static const char PLUGIN_NAME[]; static const char PLUGIN_PREFIX[]; static const char K_DEVICE[]; static const char DEFAULT_DEVICE[]; DISALLOW_COPY_AND_ASSIGN(UartDmxPlugin); }; } // namespace uartdmx } // namespace plugin } // namespace ola #endif // PLUGINS_UARTDMX_UARTDMXPLUGIN_H_ ola-0.10.5.nojsmin/plugins/uartdmx/UartWidget.cpp0000644000175000017500000001105713023355232021412 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * UartWidget.cpp * This class is based on QLCFTDI class from * * Q Light Controller * qlcftdi-libftdi.cpp * * Copyright (C) Heikki Junnila * * Only standard CPP conversion was changed and function name changed * to follow OLA coding standards. * * by Rui Barreiros * Copyright (C) 2014 Richard Ash */ #include #include #include #include #include #include #include #include #include #include #include #include "ola/Constants.h" #include "ola/io/ExtendedSerial.h" #include "ola/io/IOUtils.h" #include "ola/Logging.h" #include "plugins/uartdmx/UartWidget.h" namespace ola { namespace plugin { namespace uartdmx { using std::string; using std::vector; UartWidget::UartWidget(const string& path) : m_path(path), m_fd(NOT_OPEN) { } UartWidget::~UartWidget() { if (IsOpen()) { Close(); } } bool UartWidget::Open() { OLA_DEBUG << "Opening serial port " << Name(); if (!ola::io::Open(m_path, O_WRONLY, &m_fd)) { m_fd = FAILED_OPEN; OLA_WARN << Name() << " failed to open"; return false; } else { OLA_DEBUG << "Opened serial port " << Name(); return true; } } bool UartWidget::Close() { if (!IsOpen()) { return true; } if (close(m_fd) > 0) { OLA_WARN << Name() << " error closing"; m_fd = NOT_OPEN; return false; } else { m_fd = NOT_OPEN; return true; } } bool UartWidget::IsOpen() const { return m_fd >= 0; } bool UartWidget::SetBreak(bool on) { unsigned long request; /* NOLINT(runtime/int) */ /* this is passed to ioctl, which is declared to take * unsigned long as it's second argument */ if (on == true) { request = TIOCSBRK; } else { request = TIOCCBRK; } if (ioctl(m_fd, request, NULL) < 0) { OLA_WARN << Name() << " ioctl() failed"; return false; } else { return true; } } bool UartWidget::Write(const ola::DmxBuffer& data) { unsigned char buffer[DMX_UNIVERSE_SIZE + 1]; unsigned int length = DMX_UNIVERSE_SIZE; buffer[0] = DMX512_START_CODE; data.Get(buffer + 1, &length); if (write(m_fd, buffer, length + 1) <= 0) { // TODO(richardash1981): handle errors better as per the test code, // especially if we alter the scheduling! OLA_WARN << Name() << " Short or failed write!"; return false; } else { return true; } } bool UartWidget::Read(unsigned char *buff, int size) { int readb = read(m_fd, buff, size); if (readb <= 0) { OLA_WARN << Name() << " read error"; return false; } else { return true; } } /** * Setup our device for DMX send * Also used to test if device is working correctly * before AddDevice() */ bool UartWidget::SetupOutput() { struct termios my_tios; // Setup the Uart for DMX if (Open() == false) { OLA_WARN << "Error Opening widget"; return false; } /* do the port settings */ if (tcgetattr(m_fd, &my_tios) < 0) { // get current settings OLA_WARN << "Failed to get POSIX port settings"; return false; } cfmakeraw(&my_tios); // make it a binary data port my_tios.c_cflag |= CLOCAL; // port is local, no flow control my_tios.c_cflag &= ~CSIZE; my_tios.c_cflag |= CS8; // 8 bit chars my_tios.c_cflag &= ~PARENB; // no parity my_tios.c_cflag |= CSTOPB; // 2 stop bit for DMX my_tios.c_cflag &= ~CRTSCTS; // no CTS/RTS flow control if (tcsetattr(m_fd, TCSANOW, &my_tios) < 0) { // apply settings OLA_WARN << "Failed to get POSIX port settings"; return false; } /* Do the platform-specific initialisation of the UART to 250kbaud */ if (!ola::io::LinuxHelper::SetDmxBaud(m_fd)) { OLA_WARN << "Failed to set baud rate to 250k"; return false; } /* everything must have worked to get here */ return true; } } // namespace uartdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/uartdmx/UartDmxDevice.cpp0000644000175000017500000000604413023355232022037 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * UartDmxDevice.cpp * The DMX through a UART plugin for ola * Copyright (C) 2011 Rui Barreiros * Copyright (C) 2014 Richard Ash */ #include #include #include "ola/Logging.h" #include "ola/StringUtils.h" #include "plugins/uartdmx/UartDmxDevice.h" #include "plugins/uartdmx/UartDmxPort.h" namespace ola { namespace plugin { namespace uartdmx { using std::string; const char UartDmxDevice::K_MALF[] = "-malf"; const char UartDmxDevice::K_BREAK[] = "-break"; const unsigned int UartDmxDevice::DEFAULT_BREAK = 100; const unsigned int UartDmxDevice::DEFAULT_MALF = 100; UartDmxDevice::UartDmxDevice(AbstractPlugin *owner, class Preferences *preferences, const string &name, const string &path) : Device(owner, name), m_preferences(preferences), m_name(name), m_path(path) { // set up some per-device default configuration if not already set SetDefaults(); // now read per-device configuration // Break time in microseconds if (!StringToInt(m_preferences->GetValue(DeviceBreakKey()), &m_breakt)) { m_breakt = DEFAULT_BREAK; } // Mark After Last Frame in microseconds if (!StringToInt(m_preferences->GetValue(DeviceMalfKey()), &m_malft)) { m_malft = DEFAULT_MALF; } m_widget.reset(new UartWidget(path)); } UartDmxDevice::~UartDmxDevice() { if (m_widget->IsOpen()) { m_widget->Close(); } } bool UartDmxDevice::StartHook() { AddPort(new UartDmxOutputPort(this, 0, m_widget.get(), m_breakt, m_malft)); return true; } string UartDmxDevice::DeviceMalfKey() const { return m_path + K_MALF; } string UartDmxDevice::DeviceBreakKey() const { return m_path + K_BREAK; } /** * Set the default preferences for this one Device */ void UartDmxDevice::SetDefaults() { if (!m_preferences) { return; } bool save = false; save |= m_preferences->SetDefaultValue(DeviceBreakKey(), UIntValidator(88, 1000000), DEFAULT_BREAK); save |= m_preferences->SetDefaultValue(DeviceMalfKey(), UIntValidator(8, 1000000), DEFAULT_MALF); if (save) { m_preferences->Save(); } } } // namespace uartdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/uartdmx/UartDmxThread.h0000644000175000017500000000341013023355232021506 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * UartDmxThread.h * The DMX through a UART plugin for ola * Copyright (C) 2011 Rui Barreiros * Copyright (C) 2014 Richard Ash */ #ifndef PLUGINS_UARTDMX_UARTDMXTHREAD_H_ #define PLUGINS_UARTDMX_UARTDMXTHREAD_H_ #include "ola/DmxBuffer.h" #include "ola/thread/Thread.h" namespace ola { namespace plugin { namespace uartdmx { class UartDmxThread : public ola::thread::Thread { public: UartDmxThread(UartWidget *widget, unsigned int breakt, unsigned int malft); ~UartDmxThread(); bool Stop(); void *Run(); bool WriteDMX(const DmxBuffer &buffer); private: enum TimerGranularity { UNKNOWN, GOOD, BAD }; TimerGranularity m_granularity; UartWidget *m_widget; bool m_term; unsigned int m_breakt; unsigned int m_malft; DmxBuffer m_buffer; ola::thread::Mutex m_term_mutex; ola::thread::Mutex m_buffer_mutex; void CheckTimeGranularity(); static const uint32_t DMX_MAB = 16; DISALLOW_COPY_AND_ASSIGN(UartDmxThread); }; } // namespace uartdmx } // namespace plugin } // namespace ola #endif // PLUGINS_UARTDMX_UARTDMXTHREAD_H_ ola-0.10.5.nojsmin/plugins/karate/0000755000175000017500000000000013155164170016413 5ustar wouterwouterola-0.10.5.nojsmin/plugins/karate/Makefile.mk0000644000175000017500000000123613023355232020456 0ustar wouterwouter# LIBRARIES ################################################## if USE_KARATE lib_LTLIBRARIES += plugins/karate/libolakarate.la plugins_karate_libolakarate_la_SOURCES = \ plugins/karate/KaratePlugin.cpp \ plugins/karate/KarateDevice.cpp \ plugins/karate/KarateThread.cpp \ plugins/karate/KarateLight.cpp \ plugins/karate/KaratePlugin.h \ plugins/karate/KarateDevice.h \ plugins/karate/KaratePort.h \ plugins/karate/KarateThread.h \ plugins/karate/KarateLight.h plugins_karate_libolakarate_la_LIBADD = \ common/libolacommon.la \ olad/plugin_api/libolaserverplugininterface.la endif EXTRA_DIST += plugins/karate/README.protocol ola-0.10.5.nojsmin/plugins/karate/KaratePort.h0000644000175000017500000000340513023355232020635 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * KaratePort.h * The karate plugin for ola * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_KARATE_KARATEPORT_H_ #define PLUGINS_KARATE_KARATEPORT_H_ #include #include "ola/DmxBuffer.h" #include "olad/Port.h" #include "plugins/karate/KarateDevice.h" #include "plugins/karate/KarateThread.h" namespace ola { namespace plugin { namespace karate { class KarateOutputPort: public BasicOutputPort { public: KarateOutputPort(KarateDevice *parent, unsigned int id, const std::string &path) : BasicOutputPort(parent, id), m_thread(path), m_path(path) { m_thread.Start(); } ~KarateOutputPort() { m_thread.Stop(); } std::string Description() const { return "KarateLight at " + m_path; } bool WriteDMX(const ola::DmxBuffer &buffer, OLA_UNUSED uint8_t priority) { return m_thread.WriteDmx(buffer); } private: KarateThread m_thread; std::string m_path; }; } // namespace karate } // namespace plugin } // namespace ola #endif // PLUGINS_KARATE_KARATEPORT_H_ ola-0.10.5.nojsmin/plugins/karate/KarateLight.cpp0000644000175000017500000002774013023355232021323 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * KarateLight.cpp * The KarateLight communication class * Copyright (C) 2013 Carsten Presser */ #include #include #include #include #include #include #include #include #include #include #include #include "ola/Constants.h" #include "ola/DmxBuffer.h" #include "ola/Logging.h" #include "ola/io/IOUtils.h" #include "ola/strings/Format.h" #include "plugins/karate/KarateLight.h" namespace ola { namespace plugin { namespace karate { using std::string; /** * @brief Default constructor * @param dev the filename of the device to use */ KarateLight::KarateLight(const string &dev) : m_devname(dev), m_fd(-1), m_fw_version(0), m_hw_version(0), m_nChannels(0), m_dmx_offset(0), m_use_memcmp(1), m_active(false) { } /** * @brief Default destructor * * Closes the device and does release the file-lock */ KarateLight::~KarateLight() { KarateLight::Close(); } void KarateLight::Close() { // remove lock and close file if (m_fd >= 0) { flock(m_fd, LOCK_UN); tcflush(m_fd, TCIOFLUSH); close(m_fd); } m_active = false; } /** * @brief Initialize the device * * 1. Open the device file and get a file lock * 2. Read defaults (firmware, hardware, channels count) * 3. Set all channels to black */ bool KarateLight::Init() { uint8_t rd_buffer[CMD_MAX_LENGTH]; struct termios options; if (m_active) return false; if (!ola::io::Open(m_devname, O_RDWR | O_NOCTTY, &m_fd)) { return false; } /* Clear the line */ tcflush(m_fd, TCOFLUSH); memset(&options, 0, sizeof(options)); cfsetispeed(&options, B115200); cfsetospeed(&options, B115200); options.c_cflag = CS8 | CLOCAL | CREAD; // If MIN = 0 and TIME > 0, TIME serves as a timeout value. The read // will be satisfied if a single character is read, or TIME is // exceeded (t = TIME *0.1 s). If TIME is exceeded, no character will // be returned. options.c_cc[VTIME] = 1; options.c_cc[VMIN] = 0; // always require at least one byte returned // Update the options and do it NOW if (tcsetattr(m_fd, TCSANOW, &options) != 0) { OLA_WARN << "tcsetattr failed on " << m_devname; return false; } // Try to get a lock on the device, making access exclusive if (flock(m_fd, LOCK_EX | LOCK_NB) != 0) { OLA_WARN << "Error getting a lock on " << m_devname << "Maybe a other programm is accessing the device." << "Errorcode: " << strerror(errno); return false; } // clear possible junk data still in the systems fifo int bytes_read = 1; while (bytes_read > 0) { bytes_read = read(m_fd, rd_buffer, CMD_MAX_LENGTH); } // read firmware version if (SendCommand(CMD_GET_VERSION, NULL, 0, rd_buffer, 1)) { m_fw_version = rd_buffer[0]; } else { OLA_WARN << "failed to read the firmware-version."; return false; } // if an older Firware-Version is used. quit. the communication wont work if (m_fw_version < 0x33) { OLA_WARN << "Firmware 0x" << static_cast(m_fw_version) \ << "is to old!"; return false; } // read HW version if (SendCommand(CMD_GET_HARDWARE, NULL, 0, rd_buffer, 1)) { m_hw_version = rd_buffer[0]; } else { OLA_WARN << "failed to read the hardware-revision."; return false; } // read number of channels if (SendCommand(CMD_GET_N_CHANNELS, NULL, 0, rd_buffer, 2)) { m_nChannels = (rd_buffer[1] << 8) + rd_buffer[0]; } else { return false; } m_active = true; // stuff specific for the KarateLight8/16 if (m_hw_version == HW_ID_KARATE) { // disable memcmp for the classic KarateLight Hardware m_use_memcmp = 0; // read the dmx_offset from eeprom uint8_t upper, lower; if (ReadByteFromEeprom(3, &upper) && ReadByteFromEeprom(2, &lower)) { m_dmx_offset = (upper << 8) + lower; } else { OLA_WARN << "Error Reading EEPROM"; m_active = false; return false; } if (m_dmx_offset > 511) { OLA_WARN << "DMX Offset to large" << std::dec << m_dmx_offset << ". Setting it to 0"; m_dmx_offset = 0; } } else { // KL-DMX-Device m_dmx_offset = 0; } OLA_INFO << "successfully initalized device " << m_devname << " with firmware version 0x" << strings::ToHex(m_fw_version) << ", hardware-revision = 0x" << strings::ToHex(m_hw_version) << ", channel_count = " << m_nChannels << ", dmx_offset = " << m_dmx_offset; // set channels to black return KarateLight::Blank(); } /** * @brief Sets all Channels to black and sends data to the device * @returns true on success */ bool KarateLight::Blank() { memset(m_color_buffer, 0, DMX_UNIVERSE_SIZE); memset(m_color_buffer_old, 1, DMX_UNIVERSE_SIZE); return KarateLight::UpdateColors(); } /** * @brief Copy contents of the DmxBuffer into my local scope * @returns true on success */ bool KarateLight::SetColors(const DmxBuffer &da) { // make sure not to request data beyond the bounds of the universe unsigned int length = std::min(static_cast(da.Size()), DMX_UNIVERSE_SIZE - m_dmx_offset); da.GetRange(m_dmx_offset, m_color_buffer, &length); return KarateLight::UpdateColors(); } /* PRIVATE FUNCTIONS */ /** * @brief Tries to read an answer from the device * @param rd_data buffer for the received data (excluding the header) * @param rd_len number of bytes to read (excluding the header), will be * overwritten with the number of bytes received in the case * of a mismatch * @return true on success */ bool KarateLight::ReadBack(uint8_t *rd_data, uint8_t *rd_len) { uint8_t rd_buffer[CMD_MAX_LENGTH]; // read header (4 bytes) int bytes_read = read(m_fd, rd_buffer, CMD_DATA_START); if (bytes_read != CMD_DATA_START) { if (errno != EINTR) { // this is also true for EAGAIN OLA_WARN << "Could not read 4 bytes (header) from " << m_devname << " ErrorCode: " << strerror(errno); KarateLight::Close(); return false; } } bytes_read = 0; // read payload-data (if there is any) uint8_t payload_size = rd_buffer[CMD_HD_LEN]; if (payload_size > CMD_MAX_LENGTH - CMD_DATA_START) { OLA_WARN << "KarateLight returned " << static_cast(payload_size) << " bytes of data, this exceeds our buffer size"; return false; } if (payload_size > 0u) { // we won't enter this loop if there are no bytes to receive bytes_read = read(m_fd, &rd_buffer[CMD_DATA_START], payload_size); if (bytes_read != payload_size) { if (errno != EINTR) { // this is also true for EAGAIN (timeout) OLA_WARN << "Reading > " << static_cast(payload_size) << " < bytes payload from " << m_devname << " ErrorCode: " << strerror(errno); KarateLight::Close(); return false; } } } // verify data-length if (*rd_len != payload_size) { OLA_WARN << "Number of bytes read > " << bytes_read << " < does not match number of bytes expected > " << static_cast(payload_size) << " <"; KarateLight::Close(); return false; } // verify checksum int checksum = 0; for (int i = 0; i < bytes_read + CMD_DATA_START; i++) { if (i != CMD_HD_CHECK) { checksum ^= rd_buffer[i]; } } if (checksum != rd_buffer[CMD_HD_CHECK]) { OLA_WARN << "Checkum verification of incoming data failed. " << "Data-checkum is: " << strings::ToHex(checksum) << " but the device said it would be 0x" << static_cast(rd_buffer[CMD_HD_CHECK]); KarateLight::Close(); return false; } // prepare data *rd_len = static_cast(bytes_read); memcpy(rd_data, &rd_buffer[CMD_DATA_START], *rd_len); return true; } // end of KarateLight::ReadBack /** * @brief Reads the a single byte from the eeprom * @param addr the eeprom address to read from (0..255) * @param data location to store the received byte to * @return true on success */ bool KarateLight::ReadByteFromEeprom(uint8_t addr , uint8_t *data) { uint8_t rd_buffer[CMD_MAX_LENGTH]; if (!m_active) return false; if (!SendCommand(CMD_READ_EEPROM, &addr, 1, rd_buffer, 1)) { return false; } *data = rd_buffer[0]; return true; } /** * @brief Creates and Command, sends it, reads the reply * * Will return false in case the number of bytes received does not match * the number of bytes expected. * * @param cmd the commandcode to be used * @param output_buffer buffer containing payload-data to be send * @param n_bytes_to_write number of bytes to be written * @param input_buffer returned payload data will be stored here * @param n_bytes_expected number of bytes expected (excluding the header) * @returns true on success */ bool KarateLight::SendCommand(uint8_t cmd, const uint8_t *output_buffer, int n_bytes_to_write, uint8_t *input_buffer, int n_bytes_expected) { uint8_t wr_buffer[CMD_MAX_LENGTH]; uint8_t n_bytes_read; // maximum command length uint8_t cmd_length = n_bytes_to_write + CMD_DATA_START; if (cmd_length > CMD_MAX_LENGTH) { OLA_WARN << "Error: Command is to long (" << std::dec << n_bytes_to_write << " > " << (CMD_MAX_LENGTH - CMD_DATA_START); return false; } // build header wr_buffer[CMD_HD_SYNC] = CMD_SYNC_SEND; wr_buffer[CMD_HD_COMMAND] = cmd; wr_buffer[CMD_HD_LEN] = n_bytes_to_write; // copy data to our local buffer memcpy(&wr_buffer[CMD_DATA_START], output_buffer, n_bytes_to_write); // calc checksum wr_buffer[CMD_HD_CHECK] = 0; // clear byte 2 for (int i = 0; i < cmd_length; i++) { if (i != CMD_HD_CHECK) { wr_buffer[CMD_HD_CHECK] ^= wr_buffer[i]; } } // now write to the serial port if (write(m_fd, wr_buffer, cmd_length) != cmd_length) { OLA_WARN << "Failed to write data to " << m_devname; KarateLight::Close(); return false; } // read the answer, check if we got the number of bytes we expected n_bytes_read = n_bytes_expected; if (!ReadBack(input_buffer, &n_bytes_read) || (n_bytes_read != n_bytes_expected)) { KarateLight::Close(); return false; } return true; } /** * @brief Sends color values currently stored in the local buffer * to the hardware. * @returns true on success */ bool KarateLight::UpdateColors() { int block; int n_chunks; if (!m_active) return false; n_chunks = (m_nChannels + CHUNK_SIZE - 1) / CHUNK_SIZE; // write colors for (block = 0; block < n_chunks; block++) { if ((memcmp(&m_color_buffer[block * CHUNK_SIZE], &m_color_buffer_old[block * CHUNK_SIZE], CHUNK_SIZE) == 0) && (m_use_memcmp == 1)) { continue; } if (!SendCommand(CMD_SET_DATA_00 + block, // cmd-code &m_color_buffer[block * CHUNK_SIZE], // data to write CHUNK_SIZE, // len of data NULL, // buffer for incoming data 0)) { // number of data-bytes expected KarateLight::Close(); return false; } } // update old_values memcpy(m_color_buffer_old, m_color_buffer, DMX_UNIVERSE_SIZE); return true; } // end of UpdateColors() } // namespace karate } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/karate/README.protocol0000644000175000017500000000476013023355232021135 0ustar wouterwouterThe KarateLight uses a very simple protocol to transfer data. Each command consists of a 4-byte header and up to 60 bytes payload data. For larger transfers data has to be send in multiple packets. This limitation is due to the fact that the USB-Endpoint-Buffers on the Pic-Microcontroller are only 64 bytes large. After each command send, the controller responds with an ACK-Message using the same format convention as for data send to the contoller. Structure of the 4-Byte-Header: Pos Value 0 Sync-Byte, always 0xAA for the host, 0x55 for the controller 1 Command/Staus-Byte. See the command or status list 2 Checksum-Byte. Contains a simple XOR-Checksum over all bytes, except itself 3 Lenght-Byte. Number of Payload bytes Transmitted after the header. Status-List: (Send by the controller to the host) CMD_SYS_ACK = 0x01 The command has ben successfully processed CMD_SYS_NACK = 0x02 Error: while processing the command CMD_SYS_NACK_LENGTH = 0x03 Error: payload-lenght mismatch CMD_SYS_NACK_CHECK = 0x03 Error: Checksum mismatch CMD_SYS_NIMP = 0xFF Error: Command not implemented CMD_SYS_IR = 0x10 (not used) CMD_SYS_DATA = 0x20 Same as ACK, but with payload-data Command-List: (Send by the host to the controller) ID-Code Payload Description CMD_GET_VERSION = 0x01 0 Read the Firmware Version CMD_GET_HARDWARE = 0x02 0 Read the Hardware Version CMD_GET_TLC_PWM_VALUE = 0x14 0 Read the PWM-Callibration Value. CMD_SET_TLC_PWM_VALUE = 0x15 2 Set PWM-Callibration Value (only for debugging) CMD_SET_DATA_00 = 0x20 32 Send a batch of 32 data bytes (1st. slot) ... 32 ... CMD_SET_DATA_0F = 0x2F 32 Send a batch of 32 data bytes (16th. slot) CMD_GET_N_CHANNELS = 0x30 0 Read the number of Channels CMD_READ_ADC0 = 0x40 0 Read the value of A/D-Channel 0 (may be used for ambient light compensation) CMD_READ_EEPROM = 0x50 1 Read a single byte from the eeprom CMD_WRITE_EEPROM = 0x51 2 Write a single byte to the eeprom CMD_BOOT_REQUEST = 0x80 0 Start bootload-sequence CMD_BOOT_START = 0x81 2 Enter bootload-sequence Example: Host Sends "0xAA 0x01 0xAB 0x00" (Read Firmware Version) Controller Replies "0x55 0x20 0x44 0x01 0x30" (Send Data, Value = 0x30) For more information please take a look at the firmware. The protocol handler is in the file comm.c. ola-0.10.5.nojsmin/plugins/karate/KarateDevice.h0000644000175000017500000000277513023355232021121 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * KarateDevice.h * Interface for the karate device * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_KARATE_KARATEDEVICE_H_ #define PLUGINS_KARATE_KARATEDEVICE_H_ #include #include "olad/Device.h" namespace ola { namespace plugin { namespace karate { class KarateDevice: public ola::Device { public: KarateDevice(ola::AbstractPlugin *owner, const std::string &name, const std::string &path, unsigned int device_id); // we only support one widget for now std::string DeviceId() const { return m_device_id; } protected: bool StartHook(); private: std::string m_path; std::string m_device_id; }; } // namespace karate } // namespace plugin } // namespace ola #endif // PLUGINS_KARATE_KARATEDEVICE_H_ ola-0.10.5.nojsmin/plugins/karate/KaratePlugin.cpp0000644000175000017500000000753113023355232021506 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * KaratePlugin.cpp * The karate plugin for ola * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include #include #include #include #include "ola/Logging.h" #include "ola/io/IOUtils.h" #include "olad/PluginAdaptor.h" #include "olad/Preferences.h" #include "plugins/karate/KarateDevice.h" #include "plugins/karate/KaratePlugin.h" namespace ola { namespace plugin { namespace karate { using ola::PluginAdaptor; using std::string; using std::vector; const char KaratePlugin::KARATE_DEVICE_PATH[] = "/dev/kldmx0"; const char KaratePlugin::KARATE_DEVICE_NAME[] = "KarateLight Device"; const char KaratePlugin::PLUGIN_NAME[] = "KarateLight"; const char KaratePlugin::PLUGIN_PREFIX[] = "karate"; const char KaratePlugin::DEVICE_KEY[] = "device"; /** * @brief Start the plugin */ bool KaratePlugin::StartHook() { vector devices = m_preferences->GetMultipleValue(DEVICE_KEY); vector::const_iterator iter = devices.begin(); // start counting device ids from 0 unsigned int device_id = 0; for (; iter != devices.end(); ++iter) { // first check if it's there int fd; if (ola::io::Open(*iter, O_WRONLY, &fd)) { close(fd); KarateDevice *device = new KarateDevice( this, KARATE_DEVICE_NAME, *iter, device_id++); if (device->Start()) { m_devices.push_back(device); m_plugin_adaptor->RegisterDevice(device); } else { OLA_WARN << "Failed to start KarateLight for " << *iter; delete device; } } else { OLA_WARN << "Could not open " << *iter << " " << strerror(errno); } } return true; } /** * @brief Stop the plugin * @return true on success, false on failure */ bool KaratePlugin::StopHook() { bool ret = true; DeviceList::iterator iter = m_devices.begin(); for (; iter != m_devices.end(); ++iter) { m_plugin_adaptor->UnregisterDevice(*iter); ret &= (*iter)->Stop(); delete *iter; } m_devices.clear(); return ret; } /** * @brief Return the description for this plugin */ string KaratePlugin::Description() const { return "KarateLight - Version 0.1\n" "----------------------------\n" "\n" "The plugin creates devices with a single output port.\n" "Info on the KarateLight Hardware can be found at http://karatelight.de\n" "Unfortunately the site is in German only, but the maintainer will respond " "to emails in English.\n\n" "--- Config file : ola-karate.conf ---\n" "\n" "device = /dev/kldmx0\n" "The path to the KarateLight device. Multiple entries are supported.\n"; } /** * @brief Set default preferences. */ bool KaratePlugin::SetDefaultPreferences() { if (!m_preferences) { return false; } if (m_preferences->SetDefaultValue(DEVICE_KEY, StringValidator(), KARATE_DEVICE_PATH)) { m_preferences->Save(); } // check if this saved correctly // we don't want to use it if null if (m_preferences->GetValue(DEVICE_KEY).empty()) { return false; } return true; } } // namespace karate } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/karate/KarateThread.cpp0000644000175000017500000000565013023355232021457 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * KarateThread.cpp * Thread for the karate device * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ola/Clock.h" #include "ola/Constants.h" #include "ola/Logging.h" #include "plugins/karate/KarateLight.h" #include "plugins/karate/KarateThread.h" namespace ola { namespace plugin { namespace karate { using ola::thread::Mutex; using ola::thread::MutexLocker; using std::string; /** * @brief Create a new KarateThread object */ KarateThread::KarateThread(const string &path) : ola::thread::Thread(), m_path(path), m_term(false) { } /** * @brief Run this thread */ void *KarateThread::Run() { bool write_success; Clock clock; KarateLight k(m_path); k.Init(); while (true) { { MutexLocker lock(&m_term_mutex); if (m_term) break; } if (!k.IsActive()) { // try to reopen the device... TimeStamp wake_up; clock.CurrentTime(&wake_up); wake_up += TimeInterval(2, 0); // wait for either a signal that we should terminate, or ts seconds m_term_mutex.Lock(); if (m_term) break; m_term_cond.TimedWait(&m_term_mutex, wake_up); m_term_mutex.Unlock(); OLA_WARN << "Re-Initialising device " << m_path; k.Init(); } else { { MutexLocker locker(&m_mutex); write_success = k.SetColors(m_buffer); } if (!write_success) { OLA_WARN << "Failed to write color data"; } else { usleep(20000); // 50Hz } } // port is okay } return NULL; } /** * @brief Stop the thread */ bool KarateThread::Stop() { { MutexLocker locker(&m_mutex); m_term = true; } m_term_cond.Signal(); return Join(); } /** * @brief Store the data in the shared buffer. */ bool KarateThread::WriteDmx(const DmxBuffer &buffer) { MutexLocker locker(&m_mutex); // avoid the reference counting m_buffer.Set(buffer); return true; } } // namespace karate } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/karate/KarateThread.h0000644000175000017500000000277113023355232021125 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * KarateThread.h * Thread for the karate dmx device * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_KARATE_KARATETHREAD_H_ #define PLUGINS_KARATE_KARATETHREAD_H_ #include #include "ola/DmxBuffer.h" #include "ola/thread/Thread.h" namespace ola { namespace plugin { namespace karate { class KarateThread: public ola::thread::Thread { public: explicit KarateThread(const std::string &path); bool Stop(); bool WriteDmx(const DmxBuffer &buffer); void *Run(); private: std::string m_path; DmxBuffer m_buffer; bool m_term; ola::thread::Mutex m_mutex; ola::thread::Mutex m_term_mutex; ola::thread::ConditionVariable m_term_cond; }; } // namespace karate } // namespace plugin } // namespace ola #endif // PLUGINS_KARATE_KARATETHREAD_H_ ola-0.10.5.nojsmin/plugins/karate/KarateLight.h0000644000175000017500000001033413023355232020757 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * KarateLight.h * The KarateLight communication class * Copyright (C) 2013 Carsten Presser */ #ifndef PLUGINS_KARATE_KARATELIGHT_H_ #define PLUGINS_KARATE_KARATELIGHT_H_ #include #include #include "ola/Constants.h" #include "ola/DmxBuffer.h" namespace ola { namespace plugin { namespace karate { class KarateLight { public: explicit KarateLight(const std::string &dev); ~KarateLight(); bool Init(); void Close(); bool Blank(); bool SetColors(const DmxBuffer &da); uint16_t GetnChannels() const { return m_nChannels; } uint8_t GetFWVersion() const { return m_fw_version; } uint8_t GetHWVersion() const { return m_hw_version; } uint16_t GetDMXOffset() const { return m_dmx_offset; } bool IsActive() const { return m_active; } private: bool ReadBack(uint8_t *rd_data, uint8_t *rd_len); bool ReadByteFromEeprom(uint8_t addr, uint8_t *data); bool SendCommand(uint8_t cmd, const uint8_t *output_buffer, int n_bytes_to_write, uint8_t *input_buffer, int n_bytes_expected); bool UpdateColors(); const std::string m_devname; int m_fd; static const uint16_t CMD_MAX_LENGTH = 64; static const uint16_t CHUNK_SIZE = 32; uint8_t m_fw_version; uint8_t m_hw_version; uint16_t m_nChannels; uint16_t m_dmx_offset; uint8_t m_color_buffer[DMX_UNIVERSE_SIZE]; uint8_t m_color_buffer_old[DMX_UNIVERSE_SIZE]; uint8_t m_use_memcmp; bool m_active; // address static const uint8_t CMD_HD_SYNC = 0x00; static const uint8_t CMD_HD_COMMAND = 0x01; static const uint8_t CMD_HD_CHECK = 0x02; static const uint8_t CMD_HD_LEN = 0x03; static const uint8_t CMD_DATA_START = 0x04; // sync words static const uint8_t CMD_SYNC_SEND = 0xAA; static const uint8_t CMD_SYNC_RECV = 0x55; // status static const uint8_t CMD_SYS_ACK = 0x01; static const uint8_t CMD_SYS_NACK = 0x02; static const uint8_t CMD_SYS_NIMP = 0xFF; static const uint8_t CMD_SYS_IR = 0x10; static const uint8_t CMD_SYS_DATA = 0x20; static const uint8_t CMD_SYS_NACK_LENGTH = 0x03; static const uint8_t CMD_SYS_NACK_CHECK = 0x04; // commands static const uint8_t CMD_GET_VERSION = 0x01; static const uint8_t CMD_GET_HARDWARE = 0x02; static const uint8_t CMD_GET_TLC_PWM_VALUE = 0x14; static const uint8_t CMD_SET_TLC_PWM_VALUE = 0x15; static const uint8_t CMD_SET_DATA_00 = 0x20; static const uint8_t CMD_SET_DATA_01 = 0x21; static const uint8_t CMD_SET_DATA_02 = 0x22; static const uint8_t CMD_SET_DATA_03 = 0x23; static const uint8_t CMD_SET_DATA_04 = 0x24; static const uint8_t CMD_SET_DATA_05 = 0x25; static const uint8_t CMD_SET_DATA_06 = 0x26; static const uint8_t CMD_SET_DATA_07 = 0x27; static const uint8_t CMD_SET_DATA_08 = 0x28; static const uint8_t CMD_SET_DATA_09 = 0x29; static const uint8_t CMD_SET_DATA_0A = 0x2A; static const uint8_t CMD_SET_DATA_0B = 0x2B; static const uint8_t CMD_SET_DATA_0C = 0x2C; static const uint8_t CMD_SET_DATA_0D = 0x2D; static const uint8_t CMD_SET_DATA_0E = 0x2E; static const uint8_t CMD_SET_DATA_0F = 0x2F; static const uint8_t CMD_GET_N_CHANNELS = 0x30; static const uint8_t CMD_READ_ADC0 = 0x40; static const uint8_t CMD_READ_EEPROM = 0x50; static const uint8_t CMD_WRITE_EEPROM = 0x51; static const uint8_t CMD_BOOT_REQUEST = 0x80; static const uint8_t CMD_BOOT_START = 0x81; static const uint8_t HW_ID_KARATE = 0x01; static const uint8_t HW_ID_USB2DMX = 0x02; }; } // namespace karate } // namespace plugin } // namespace ola #endif // PLUGINS_KARATE_KARATELIGHT_H_ ola-0.10.5.nojsmin/plugins/karate/KaratePlugin.h0000644000175000017500000000356513023355232021156 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * KaratePlugin.h * Interface for the karate plugin class * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_KARATE_KARATEPLUGIN_H_ #define PLUGINS_KARATE_KARATEPLUGIN_H_ #include #include #include "olad/Plugin.h" #include "ola/plugin_id.h" namespace ola { namespace plugin { namespace karate { class KarateDevice; class KaratePlugin: public Plugin { public: explicit KaratePlugin(PluginAdaptor *plugin_adaptor) : Plugin(plugin_adaptor) { } std::string Name() const { return PLUGIN_NAME; } std::string Description() const; ola_plugin_id Id() const { return OLA_PLUGIN_KARATE; } std::string PluginPrefix() const { return PLUGIN_PREFIX; } private: bool StartHook(); bool StopHook(); bool SetDefaultPreferences(); typedef std::vector DeviceList; DeviceList m_devices; static const char PLUGIN_NAME[]; static const char PLUGIN_PREFIX[]; static const char KARATE_DEVICE_PATH[]; static const char KARATE_DEVICE_NAME[]; static const char DEVICE_KEY[]; }; } // namespace karate } // namespace plugin } // namespace ola #endif // PLUGINS_KARATE_KARATEPLUGIN_H_ ola-0.10.5.nojsmin/plugins/karate/KarateDevice.cpp0000644000175000017500000000306513023355232021445 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * KarateDevice.cpp * The KarateLight device * Copyright (C) 2005 Simon Newton */ #include #include #include "plugins/karate/KarateDevice.h" #include "plugins/karate/KaratePort.h" namespace ola { namespace plugin { namespace karate { using ola::Device; using std::string; /** * @brief Create a new device */ KarateDevice::KarateDevice(AbstractPlugin *owner, const string &name, const string &path, unsigned int device_id) : Device(owner, name), m_path(path) { std::ostringstream str; str << device_id; m_device_id = str.str(); } /** * @brief Start this device */ bool KarateDevice::StartHook() { AddPort(new KarateOutputPort(this, 0, m_path)); return true; } } // namespace karate } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/espnet/0000755000175000017500000000000013155164170016442 5ustar wouterwouterola-0.10.5.nojsmin/plugins/espnet/EspNetPort.h0000644000175000017500000000462013023355232020653 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * EspNetPort.h * The ESPNet plugin for ola * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_ESPNET_ESPNETPORT_H_ #define PLUGINS_ESPNET_ESPNETPORT_H_ #include #include "ola/DmxBuffer.h" #include "olad/Port.h" #include "plugins/espnet/EspNetDevice.h" namespace ola { namespace plugin { namespace espnet { class EspNetPortHelper { public: std::string Description(Universe *universe) const; uint8_t EspNetUniverseId(Universe *universe) const; }; class EspNetInputPort: public BasicInputPort { public: EspNetInputPort(EspNetDevice *parent, unsigned int id, class PluginAdaptor *plugin_adaptor, EspNetNode *node) : BasicInputPort(parent, id, plugin_adaptor), m_helper(), m_node(node) {} ~EspNetInputPort() {} std::string Description() const { return m_helper.Description(GetUniverse()); } void PostSetUniverse(Universe *old_universe, Universe *new_universe); const DmxBuffer &ReadDMX() const { return m_buffer; } private: EspNetPortHelper m_helper; EspNetNode *m_node; DmxBuffer m_buffer; }; class EspNetOutputPort: public BasicOutputPort { public: EspNetOutputPort(EspNetDevice *parent, unsigned int id, EspNetNode *node) : BasicOutputPort(parent, id), m_helper(), m_node(node) {} ~EspNetOutputPort() {} std::string Description() const { return m_helper.Description(GetUniverse()); } bool WriteDMX(const DmxBuffer &buffer, uint8_t priority); private: EspNetPortHelper m_helper; EspNetNode *m_node; }; } // namespace espnet } // namespace plugin } // namespace ola #endif // PLUGINS_ESPNET_ESPNETPORT_H_ ola-0.10.5.nojsmin/plugins/espnet/Makefile.mk0000644000175000017500000000221013023355232020476 0ustar wouterwouter# LIBRARIES ################################################## if USE_ESPNET lib_LTLIBRARIES += plugins/espnet/libolaespnet.la plugins_espnet_libolaespnet_la_SOURCES = \ plugins/espnet/EspNetDevice.cpp \ plugins/espnet/EspNetDevice.h \ plugins/espnet/EspNetNode.cpp \ plugins/espnet/EspNetNode.h \ plugins/espnet/EspNetPackets.h \ plugins/espnet/EspNetPlugin.cpp \ plugins/espnet/EspNetPlugin.h \ plugins/espnet/EspNetPluginCommon.h \ plugins/espnet/EspNetPort.cpp \ plugins/espnet/EspNetPort.h \ plugins/espnet/RunLengthDecoder.cpp \ plugins/espnet/RunLengthDecoder.h plugins_espnet_libolaespnet_la_LIBADD = \ common/libolacommon.la \ olad/plugin_api/libolaserverplugininterface.la # TESTS ################################################## test_programs += plugins/espnet/EspNetTester plugins_espnet_EspNetTester_SOURCES = \ plugins/espnet/RunLengthDecoderTest.cpp \ plugins/espnet/RunLengthDecoder.cpp plugins_espnet_EspNetTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) plugins_espnet_EspNetTester_LDADD = $(COMMON_TESTING_LIBS) \ common/libolacommon.la endif ola-0.10.5.nojsmin/plugins/espnet/EspNetNode.cpp0000644000175000017500000002600713023355232021152 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * EspNetNode.cpp * A EspNet node * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include "ola/Logging.h" #include "ola/network/InterfacePicker.h" #include "ola/network/IPV4Address.h" #include "ola/network/MACAddress.h" #include "ola/network/NetworkUtils.h" #include "plugins/espnet/EspNetNode.h" namespace ola { namespace plugin { namespace espnet { using ola::network::HostToNetwork; using ola::network::IPV4Address; using ola::network::IPV4SocketAddress; using ola::network::NetworkToHost; using ola::network::UDPSocket; using ola::Callback0; using std::map; using std::string; const char EspNetNode::NODE_NAME[] = "OLA Node"; /* * Create a new node * @param ip_address the IP address to prefer to listen on, if NULL we choose * one. */ EspNetNode::EspNetNode(const string &ip_address) : m_running(false), m_options(DEFAULT_OPTIONS), m_tos(DEFAULT_TOS), m_ttl(DEFAULT_TTL), m_universe(0), m_type(ESPNET_NODE_TYPE_IO), m_node_name(NODE_NAME), m_preferred_ip(ip_address) { } /* * Cleanup */ EspNetNode::~EspNetNode() { Stop(); std::map::iterator iter; for (iter = m_handlers.begin(); iter != m_handlers.end(); ++iter) { delete iter->second.closure; } m_handlers.clear(); } /* * Start this node */ bool EspNetNode::Start() { if (m_running) return false; ola::network::InterfacePicker *picker = ola::network::InterfacePicker::NewPicker(); if (!picker->ChooseInterface(&m_interface, m_preferred_ip)) { OLA_INFO << "Failed to find an interface"; delete picker; return false; } delete picker; if (!InitNetwork()) return false; m_running = true; return true; } /* * Stop this node */ bool EspNetNode::Stop() { if (!m_running) return false; m_running = false; return true; } /* * Called when there is data on this socket */ void EspNetNode::SocketReady() { espnet_packet_union_t packet; memset(&packet, 0, sizeof(packet)); ola::network::IPV4SocketAddress source; ssize_t packet_size = sizeof(packet); if (!m_socket.RecvFrom(reinterpret_cast(&packet), &packet_size, &source)) return; if (packet_size < (ssize_t) sizeof(packet.poll.head)) { OLA_WARN << "Small espnet packet received, discarding"; return; } // skip packets sent by us if (source.Host() == m_interface.ip_address) { return; } switch (NetworkToHost(packet.poll.head)) { case ESPNET_POLL: HandlePoll(packet.poll, packet_size, source.Host()); break; case ESPNET_REPLY: HandleReply(packet.reply, packet_size, source.Host()); break; case ESPNET_DMX: HandleData(packet.dmx, packet_size, source.Host()); break; case ESPNET_ACK: HandleAck(packet.ack, packet_size, source.Host()); break; default: OLA_INFO << "Skipping a packet with invalid header" << packet.poll.head; } } /* * Set the closure to be called when we receive data for this universe. * @param universe the universe to register the handler for * @param handler the Callback0 to call when there is data for this universe. * Ownership of the closure is transferred to the node. */ bool EspNetNode::SetHandler(uint8_t universe, DmxBuffer *buffer, Callback0 *closure) { if (!closure) return false; map::iterator iter = m_handlers.find(universe); if (iter == m_handlers.end()) { universe_handler handler; handler.buffer = buffer; handler.closure = closure; m_handlers[universe] = handler; } else { Callback0 *old_closure = iter->second.closure; iter->second.closure = closure; delete old_closure; } return true; } /* * Remove the handler for this universe * @param universe the universe handler to remove * @param true if removed, false if it didn't exist */ bool EspNetNode::RemoveHandler(uint8_t universe) { map::iterator iter = m_handlers.find(universe); if (iter != m_handlers.end()) { Callback0 *old_closure = iter->second.closure; m_handlers.erase(iter); delete old_closure; return true; } return false; } /* * Send an Esp Poll * @param full_poll */ bool EspNetNode::SendPoll(bool full_poll) { if (!m_running) return false; return SendEspPoll(m_interface.bcast_address, full_poll); } /* * Send some DMX data * @param universe the id of the universe to send * @param buffer the DMX data * @return true if it was send successfully, false otherwise */ bool EspNetNode::SendDMX(uint8_t universe, const ola::DmxBuffer &buffer) { if (!m_running) return false; return SendEspData(m_interface.bcast_address, universe, buffer); } /* * Setup the networking compoents. */ bool EspNetNode::InitNetwork() { if (!m_socket.Init()) { OLA_WARN << "Socket init failed"; return false; } if (!m_socket.Bind(IPV4SocketAddress(IPV4Address::WildCard(), ESPNET_PORT))) return false; if (!m_socket.EnableBroadcast()) { OLA_WARN << "Failed to enable broadcasting"; return false; } m_socket.SetOnData(NewCallback(this, &EspNetNode::SocketReady)); return true; } /* * Handle an Esp Poll packet */ void EspNetNode::HandlePoll(const espnet_poll_t &poll, ssize_t length, const IPV4Address &source) { OLA_DEBUG << "Got ESP Poll " << poll.type; if (length < (ssize_t) sizeof(espnet_poll_t)) { OLA_DEBUG << "Poll size too small " << length << " < " << sizeof(espnet_poll_t); return; } if (poll.type) SendEspPollReply(source); else SendEspAck(source, 0, 0); } /* * Handle an Esp reply packet. This does nothing at the moment. */ void EspNetNode::HandleReply(const espnet_poll_reply_t &reply, ssize_t length, const IPV4Address &source) { if (length < (ssize_t) sizeof(espnet_poll_reply_t)) { OLA_DEBUG << "Poll reply size too small " << length << " < " << sizeof(espnet_poll_reply_t); return; } (void) reply; (void) source; } /* * Handle a Esp Ack packet */ void EspNetNode::HandleAck(const espnet_ack_t &ack, ssize_t length, const IPV4Address &source) { if (length < (ssize_t) sizeof(espnet_ack_t)) { OLA_DEBUG << "Ack size too small " << length << " < " << sizeof(espnet_ack_t); return; } (void) ack; (void) source; } /* * Handle an Esp data packet */ void EspNetNode::HandleData(const espnet_data_t &data, ssize_t length, const IPV4Address &source) { static const ssize_t header_size = sizeof(espnet_data_t) - DMX_UNIVERSE_SIZE; if (length < header_size) { OLA_DEBUG << "Data size too small " << length << " < " << header_size; return; } map::iterator iter = m_handlers.find(data.universe); if (iter == m_handlers.end()) { OLA_DEBUG << "Not interested in universe " << static_cast(data.universe) << ", skipping "; return; } ssize_t data_size = std::min(length - header_size, (ssize_t) NetworkToHost(data.size)); // we ignore the start code switch (data.type) { case DATA_RAW: iter->second.buffer->Set(data.data, data_size); break; case DATA_PAIRS: OLA_WARN << "espnet data pairs aren't supported"; return; case DATA_RLE: m_decoder.Decode(iter->second.buffer, data.data, data_size); break; default: OLA_WARN << "unknown espnet data type " << data.type; return; } iter->second.closure->Run(); (void) source; } /* * Send an EspNet poll */ bool EspNetNode::SendEspPoll(const IPV4Address &dst, bool full) { espnet_packet_union_t packet; packet.poll.head = HostToNetwork((uint32_t) ESPNET_POLL); packet.poll.type = full; return SendPacket(dst, packet, sizeof(packet.poll)); } /* * Send an EspNet Ack */ bool EspNetNode::SendEspAck(const IPV4Address &dst, uint8_t status, uint8_t crc) { espnet_packet_union_t packet; packet.ack.head = HostToNetwork((uint32_t) ESPNET_ACK); packet.ack.status = status; packet.ack.crc = crc; return SendPacket(dst, packet, sizeof(packet.ack)); } /* * Send an EspNet Poll Reply */ bool EspNetNode::SendEspPollReply(const IPV4Address &dst) { espnet_packet_union_t packet; packet.reply.head = HostToNetwork((uint32_t) ESPNET_REPLY); m_interface.hw_address.Get(packet.reply.mac); packet.reply.type = HostToNetwork((uint32_t) m_type); packet.reply.version = FIRMWARE_VERSION; packet.reply.sw = SWITCH_SETTINGS; memcpy(packet.reply.name, m_node_name.data(), ESPNET_NAME_LENGTH); packet.reply.name[ESPNET_NAME_LENGTH - 1] = 0; packet.reply.option = m_options; packet.reply.option |= 0x01; // We're always configured packet.reply.tos = m_tos; packet.reply.ttl = m_ttl; packet.reply.config.listen = 0x04; m_interface.ip_address.Get(packet.reply.config.ip); packet.reply.config.universe = m_universe; return SendPacket(dst, packet, sizeof(packet.reply)); } /* * Send an EspNet data packet */ bool EspNetNode::SendEspData(const IPV4Address &dst, uint8_t universe, const DmxBuffer &buffer) { espnet_packet_union_t packet; memset(&packet.dmx, 0, sizeof(packet.dmx)); packet.dmx.head = HostToNetwork((uint32_t) ESPNET_DMX); packet.dmx.universe = universe; packet.dmx.start = START_CODE; packet.dmx.type = DATA_RAW; unsigned int size = DMX_UNIVERSE_SIZE; buffer.Get(packet.dmx.data, &size); packet.dmx.size = HostToNetwork((uint16_t) size); return SendPacket(dst, packet, sizeof(packet.dmx)); } /* * Send an EspNet packet */ bool EspNetNode::SendPacket(const IPV4Address &dst, const espnet_packet_union_t &packet, unsigned int size) { ssize_t bytes_sent = m_socket.SendTo( reinterpret_cast(&packet), size, IPV4SocketAddress(dst, ESPNET_PORT)); if (bytes_sent != (ssize_t) size) { OLA_WARN << "Only sent " << bytes_sent << " of " << size; return false; } return true; } } // namespace espnet } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/espnet/EspNetDevice.h0000644000175000017500000000322613023355232021127 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * EspNetDevice.h * Interface for the EspNet device * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_ESPNET_ESPNETDEVICE_H_ #define PLUGINS_ESPNET_ESPNETDEVICE_H_ #include #include "olad/Device.h" #include "olad/Plugin.h" namespace ola { namespace plugin { namespace espnet { class EspNetDevice: public Device { public: EspNetDevice(Plugin *owner, class Preferences *prefs, class PluginAdaptor *plugin_adaptor); std::string DeviceId() const { return "1"; } static const char IP_KEY[]; static const char NODE_NAME_KEY[]; protected: bool StartHook(); void PrePortStop(); void PostPortStop(); private: class Preferences *m_preferences; class PluginAdaptor *m_plugin_adaptor; class EspNetNode *m_node; static const char ESPNET_DEVICE_NAME[]; }; } // namespace espnet } // namespace plugin } // namespace ola #endif // PLUGINS_ESPNET_ESPNETDEVICE_H_ ola-0.10.5.nojsmin/plugins/espnet/RunLengthDecoderTest.cpp0000644000175000017500000000357413023355232023206 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RunLengthDecoderTest.cpp * Test fixture for the RunLengthDecoder class * Copyright (C) 2005 Simon Newton */ #include #include #include "ola/testing/TestUtils.h" #include "plugins/espnet/RunLengthDecoder.h" class RunLengthDecoderTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(RunLengthDecoderTest); CPPUNIT_TEST(testDecode); CPPUNIT_TEST_SUITE_END(); public: void testDecode(); private: }; CPPUNIT_TEST_SUITE_REGISTRATION(RunLengthDecoderTest); /* * Check that we can decode DMX data */ void RunLengthDecoderTest::testDecode() { ola::plugin::espnet::RunLengthDecoder decoder; uint8_t data[] = {0x78, 0x56, 0x74, 0xFE, 0x5, 0x10, 0x41, 0x78, 0xFD, 0xFE, 0x36, 0xFD, 0xFD}; uint8_t expected_data[] = {0x78, 0x56, 0x74, 0x10, 0x10, 0x10, 0x10, 0x10, 0x41, 0x78, 0xFE, 0x36, 0xFD}; ola::DmxBuffer buffer; ola::DmxBuffer expected(expected_data, sizeof(expected_data)); buffer.Blackout(); buffer.Reset(); OLA_ASSERT_EQ((unsigned int) 0, buffer.Size()); decoder.Decode(&buffer, data, sizeof(data)); OLA_ASSERT(buffer == expected); } ola-0.10.5.nojsmin/plugins/espnet/RunLengthDecoder.cpp0000644000175000017500000000354213134123277022346 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RunLengthDecoder.cpp * The Run Length Decoder * Copyright (C) 2005 Simon Newton */ #include #include #include "plugins/espnet/RunLengthDecoder.h" namespace ola { namespace plugin { namespace espnet { /* * Decode the RLE'ed data into a DmxBuffer. * @param dst the DmxBuffer to store the result * @param src_data the data to decode * @param length the length of the data to decode */ void RunLengthDecoder::Decode(DmxBuffer *dst, const uint8_t *src_data, unsigned int length) { dst->Reset(); unsigned int i = 0; const uint8_t *value = src_data; uint8_t count; while (i < DMX_UNIVERSE_SIZE && value < src_data + length) { switch (*value) { case REPEAT_VALUE: value++; count = *(value++); dst->SetRangeToValue(i, *value, count); i+= count; break; case ESCAPE_VALUE: value++; // fall through OLA_FALLTHROUGH default: dst->SetChannel(i, *value); i++; } value++; } } } // namespace espnet } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/espnet/EspNetPlugin.h0000644000175000017500000000342713023355232021171 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * EspNetPlugin.h * Interface for the espnet plugin class * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_ESPNET_ESPNETPLUGIN_H_ #define PLUGINS_ESPNET_ESPNETPLUGIN_H_ #include #include "olad/Plugin.h" #include "olad/PluginAdaptor.h" #include "ola/plugin_id.h" namespace ola { namespace plugin { namespace espnet { class EspNetDevice; class EspNetPlugin: public ola::Plugin { public: explicit EspNetPlugin(ola::PluginAdaptor *plugin_adaptor): Plugin(plugin_adaptor), m_device(NULL) {} std::string Name() const { return PLUGIN_NAME; } std::string Description() const; ola_plugin_id Id() const { return OLA_PLUGIN_ESPNET; } std::string PluginPrefix() const { return PLUGIN_PREFIX; } private: bool StartHook(); bool StopHook(); bool SetDefaultPreferences(); EspNetDevice *m_device; static const char ESPNET_NODE_NAME[]; static const char PLUGIN_NAME[]; static const char PLUGIN_PREFIX[]; }; } // namespace espnet } // namespace plugin } // namespace ola #endif // PLUGINS_ESPNET_ESPNETPLUGIN_H_ ola-0.10.5.nojsmin/plugins/espnet/EspNetPackets.h0000644000175000017500000000610513023355232021321 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * EspNetPackets.h * Datagram definitions for EspNet * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_ESPNET_ESPNETPACKETS_H_ #define PLUGINS_ESPNET_ESPNETPACKETS_H_ #include #include #ifndef _WIN32 #include #endif // _WIN32 #include "ola/network/MACAddress.h" #include "ola/Constants.h" namespace ola { namespace plugin { namespace espnet { enum { ESPNET_NAME_LENGTH = 10 }; enum { ESPNET_DATA_LENGTH = 200 }; // We can't use the PACK macro for enums #ifdef _WIN32 #pragma pack(push, 1) #endif // _WIN32 enum espnet_packet_type_e { ESPNET_POLL = 'E' << 24 | 'S' << 16 | 'P' << 8 | 'P', ESPNET_REPLY = 'E' << 24 | 'S' << 16 | 'P' << 8 | 'R', ESPNET_DMX = 'E' << 24 | 'S' << 16 | 'D' << 8 | 'D', ESPNET_ACK = 'E' << 24 | 'S' << 16 | 'A' << 8 | 'P' #ifdef _WIN32 }; #pragma pack(pop) #else } __attribute__((packed)); #endif // _WIN32 typedef enum espnet_packet_type_e espnet_packet_type_t; /* * poll datagram */ PACK( struct espnet_poll_s { uint32_t head; uint8_t type; }); typedef struct espnet_poll_s espnet_poll_t; /* * This is used in the poll reply and config */ struct espnet_node_config_s { uint8_t listen; uint8_t ip[4]; uint8_t universe; // bit bizzare that nodes only listen to one universe?? }; typedef struct espnet_node_config_s espnet_node_config_t; /* * poll reply */ PACK( struct espnet_poll_reply_s { uint32_t head; uint8_t mac[ola::network::MACAddress::LENGTH]; uint16_t type; uint8_t version; uint8_t sw; uint8_t name[ESPNET_NAME_LENGTH]; uint8_t option; uint8_t tos; uint8_t ttl; espnet_node_config_t config; }); typedef struct espnet_poll_reply_s espnet_poll_reply_t; /* * ack datagram */ PACK( struct espnet_ack_s { uint32_t head; uint8_t status; uint8_t crc; }); typedef struct espnet_ack_s espnet_ack_t; /* * dmx datagram */ PACK( struct espnet_data_s { uint32_t head; uint8_t universe; uint8_t start; uint8_t type; uint16_t size; uint8_t data[DMX_UNIVERSE_SIZE]; }); typedef struct espnet_data_s espnet_data_t; // we need to add the TCP config crap here /* * union of all espnet packets */ typedef union { espnet_poll_t poll; espnet_poll_reply_t reply; espnet_ack_t ack; espnet_data_t dmx; } espnet_packet_union_t; } // namespace espnet } // namespace plugin } // namespace ola #endif // PLUGINS_ESPNET_ESPNETPACKETS_H_ ola-0.10.5.nojsmin/plugins/espnet/EspNetNode.h0000644000175000017500000001106513023355232020615 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * EspNetNode.h * Header file for the EspNetNode class * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_ESPNET_ESPNETNODE_H_ #define PLUGINS_ESPNET_ESPNETNODE_H_ #include #include #include "ola/Callback.h" #include "ola/DmxBuffer.h" #include "ola/network/IPV4Address.h" #include "ola/network/Interface.h" #include "ola/network/Socket.h" #include "plugins/espnet/EspNetPackets.h" #include "plugins/espnet/RunLengthDecoder.h" namespace ola { namespace plugin { namespace espnet { // the node types typedef enum { ESPNET_NODE_TYPE_SINGLE_OUT = 0x0001, // ip to dmx ESPNET_NODE_TYPE_SINGLE_IN = 0x0002, // dmx to ip ESPNET_NODE_TYPE_RS232 = 0x0060, ESPNET_NODE_TYPE_IO = 0x0061, // multi universe ESPNET_NODE_TYPE_LONWORKS = 0x0100, } espnet_node_type; enum { ESPNET_MAX_UNIVERSES = 512 }; class EspNetNode { public: explicit EspNetNode(const std::string &ip_address); virtual ~EspNetNode(); bool Start(); bool Stop(); const ola::network::Interface &GetInterface() const { return m_interface; } void SetName(const std::string &name) { m_node_name = name; } void SetType(espnet_node_type type) { m_type = type; } void SetUniverse(uint8_t universe) { m_universe = universe; } // IO methods ola::network::UDPSocket* GetSocket() { return &m_socket; } void SocketReady(); // DMX Receiving methods bool SetHandler(uint8_t universe, DmxBuffer *buffer, ola::Callback0 *handler); bool RemoveHandler(uint8_t universe); // Sending methods bool SendPoll(bool full_poll = false); bool SendDMX(uint8_t universe, const ola::DmxBuffer &buffer); private: typedef struct { DmxBuffer *buffer; Callback0 *closure; } universe_handler; EspNetNode(const EspNetNode&); EspNetNode& operator=(const EspNetNode&); bool InitNetwork(); void HandlePoll(const espnet_poll_t &poll, ssize_t length, const ola::network::IPV4Address &source); void HandleReply(const espnet_poll_reply_t &reply, ssize_t length, const ola::network::IPV4Address &source); void HandleAck(const espnet_ack_t &ack, ssize_t length, const ola::network::IPV4Address &source); void HandleData(const espnet_data_t &data, ssize_t length, const ola::network::IPV4Address &source); bool SendEspPoll(const ola::network::IPV4Address &dst, bool full); bool SendEspAck(const ola::network::IPV4Address &dst, uint8_t status, uint8_t crc); bool SendEspPollReply(const ola::network::IPV4Address &dst); bool SendEspData(const ola::network::IPV4Address &dst, uint8_t universe, const DmxBuffer &buffer); bool SendPacket(const ola::network::IPV4Address &dst, const espnet_packet_union_t &packet, unsigned int size); bool m_running; uint8_t m_options; uint8_t m_tos; uint8_t m_ttl; uint8_t m_universe; espnet_node_type m_type; std::string m_node_name; std::string m_preferred_ip; std::map m_handlers; ola::network::Interface m_interface; ola::network::UDPSocket m_socket; RunLengthDecoder m_decoder; static const char NODE_NAME[]; static const uint8_t DEFAULT_OPTIONS = 0; static const uint8_t DEFAULT_TOS = 0; static const uint8_t DEFAULT_TTL = 4; static const uint8_t FIRMWARE_VERSION = 1; static const uint8_t SWITCH_SETTINGS = 0; static const uint16_t ESPNET_PORT = 3333; static const uint8_t DATA_RAW = 1; static const uint8_t DATA_PAIRS = 2; static const uint8_t DATA_RLE = 4; static const uint8_t START_CODE = 0; }; } // namespace espnet } // namespace plugin } // namespace ola #endif // PLUGINS_ESPNET_ESPNETNODE_H_ ola-0.10.5.nojsmin/plugins/espnet/EspNetPort.cpp0000644000175000017500000000472613023355232021215 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * EspNetPort.cpp * The EspNet plugin for ola * Copyright (C) 2005 Simon Newton */ #include #include #include #include "ola/Logging.h" #include "olad/Universe.h" #include "plugins/espnet/EspNetPort.h" #include "plugins/espnet/EspNetDevice.h" #include "plugins/espnet/EspNetNode.h" namespace ola { namespace plugin { namespace espnet { using std::string; string EspNetPortHelper::Description(Universe *universe) const { std::ostringstream str; if (universe) str << "EspNet universe " << (unsigned int) EspNetUniverseId(universe); return str.str(); } /* * Return the EspNet universe ID for this port. In case we don't have a * universe, 0 is returned. Note that universe 0 is valid. */ uint8_t EspNetPortHelper::EspNetUniverseId(Universe *universe) const { if (universe) return universe->UniverseId() % ESPNET_MAX_UNIVERSES; else return 0; } /* * Set the universe for an InputPort. */ void EspNetInputPort::PostSetUniverse(Universe *old_universe, Universe *new_universe) { if (old_universe) m_node->RemoveHandler(m_helper.EspNetUniverseId(old_universe)); if (new_universe) m_node->SetHandler( m_helper.EspNetUniverseId(new_universe), &m_buffer, ola::NewCallback(this, &EspNetInputPort::DmxChanged)); } /* * Write data to this port. */ bool EspNetOutputPort::WriteDMX(const DmxBuffer &buffer, OLA_UNUSED uint8_t priority) { if (!GetUniverse()) return false; if (!m_node->SendDMX(m_helper.EspNetUniverseId(GetUniverse()), buffer)) return false; return true; } } // namespace espnet } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/espnet/RunLengthDecoder.h0000644000175000017500000000257713023355232022015 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RunLengthDecoder.h * Header file for the RunLengthDecoder class * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_ESPNET_RUNLENGTHDECODER_H_ #define PLUGINS_ESPNET_RUNLENGTHDECODER_H_ #include namespace ola { namespace plugin { namespace espnet { class RunLengthDecoder { public: RunLengthDecoder() {} ~RunLengthDecoder() {} void Decode(DmxBuffer *dst, const uint8_t *data, unsigned int length); private: static const uint8_t ESCAPE_VALUE = 0xFD; static const uint8_t REPEAT_VALUE = 0xFE; }; } // namespace espnet } // namespace plugin } // namespace ola #endif // PLUGINS_ESPNET_RUNLENGTHDECODER_H_ ola-0.10.5.nojsmin/plugins/espnet/EspNetPluginCommon.h0000644000175000017500000000223313023355232022334 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * EspNetPluginCommon.h * Constants for the ESP plugin * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_ESPNET_ESPNETPLUGINCOMMON_H_ #define PLUGINS_ESPNET_ESPNETPLUGINCOMMON_H_ namespace ola { namespace plugin { namespace espnet { // modify this to increase the number of ports in the plugin enum { PORTS_PER_DEVICE = 5 }; } // namespace espnet } // namespace plugin } // namespace ola #endif // PLUGINS_ESPNET_ESPNETPLUGINCOMMON_H_ ola-0.10.5.nojsmin/plugins/espnet/EspNetPlugin.cpp0000644000175000017500000000643313023355232021524 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * EspNetPlugin.cpp * The EspNet plugin for ola * Copyright (C) 2005 Simon Newton */ #include #include "olad/Preferences.h" #include "plugins/espnet/EspNetPlugin.h" #include "plugins/espnet/EspNetDevice.h" namespace ola { namespace plugin { namespace espnet { using std::string; const char EspNetPlugin::ESPNET_NODE_NAME[] = "ola-EspNet"; const char EspNetPlugin::PLUGIN_NAME[] = "ESP Net"; const char EspNetPlugin::PLUGIN_PREFIX[] = "espnet"; /* * Start the plugin * For now we just have one device. */ bool EspNetPlugin::StartHook() { m_device = new EspNetDevice(this, m_preferences, m_plugin_adaptor); if (!m_device) { return false; } if (!m_device->Start()) { delete m_device; return false; } m_plugin_adaptor->RegisterDevice(m_device); return true; } /* * Stop the plugin * @return true on success, false on failure */ bool EspNetPlugin::StopHook() { if (m_device) { bool ret = m_plugin_adaptor->UnregisterDevice(m_device); m_device->Stop(); delete m_device; return ret; } return true; } /* * Return the description for this plugin */ string EspNetPlugin::Description() const { return "Enttec ESP Net Plugin\n" "----------------------------\n" "\n" "This plugin creates a single device with five input and five output ports.\n" "\n" "ESP supports up to 255 universes. As ESP has no notion of ports, we provide\n" "a fixed number of ports which can be patched to any universe. When sending\n" "data from a port, the data is addressed to the universe the port is patched\n" "to. For example if port 0 is patched to universe 10, the data will be\n" "sent to ESP universe 10.\n" "\n" "--- Config file : ola-espnet.conf ---\n" "\n" "ip = [a.b.c.d|]\n" "The ip address or interface name to bind to. If not specified it will\n" "use the first non-loopback interface.\n" "\n" "name = ola-EspNet\n" "The name of the node.\n" "\n"; } /* * Set the default preferences. */ bool EspNetPlugin::SetDefaultPreferences() { if (!m_preferences) { return false; } bool save = false; save |= m_preferences->SetDefaultValue(EspNetDevice::IP_KEY, StringValidator(true), ""); save |= m_preferences->SetDefaultValue(EspNetDevice::NODE_NAME_KEY, StringValidator(), ESPNET_NODE_NAME); if (save) { m_preferences->Save(); } if (m_preferences->GetValue("name").empty()) { return false; } return true; } } // namespace espnet } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/espnet/EspNetDevice.cpp0000644000175000017500000000542613023355232021466 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * EspNetDevice.cpp * Esp-Net device * Copyright (C) 2005 Simon Newton * * */ #include #include #include "ola/Logging.h" #include "ola/network/NetworkUtils.h" #include "olad/Plugin.h" #include "olad/PluginAdaptor.h" #include "olad/Preferences.h" #include "plugins/espnet/EspNetDevice.h" #include "plugins/espnet/EspNetNode.h" #include "plugins/espnet/EspNetPluginCommon.h" #include "plugins/espnet/EspNetPort.h" namespace ola { namespace plugin { namespace espnet { using std::ostringstream; const char EspNetDevice::ESPNET_DEVICE_NAME[] = "ESP Net"; const char EspNetDevice::IP_KEY[] = "ip"; const char EspNetDevice::NODE_NAME_KEY[] = "name"; /* * Create a new device */ EspNetDevice::EspNetDevice(Plugin *owner, Preferences *prefs, PluginAdaptor *plugin_adaptor): Device(owner, ESPNET_DEVICE_NAME), m_preferences(prefs), m_plugin_adaptor(plugin_adaptor), m_node(NULL) { } /* * Start this device */ bool EspNetDevice::StartHook() { m_node = new EspNetNode(m_preferences->GetValue(IP_KEY)); m_node->SetName(m_preferences->GetValue(NODE_NAME_KEY)); m_node->SetType(ESPNET_NODE_TYPE_IO); if (!m_node->Start()) { delete m_node; m_node = NULL; return false; } ostringstream str; str << ESPNET_DEVICE_NAME << " [" << m_node->GetInterface().ip_address << "]"; SetName(str.str()); for (unsigned int i = 0; i < PORTS_PER_DEVICE; i++) { EspNetInputPort *input_port = new EspNetInputPort( this, i, m_plugin_adaptor, m_node); AddPort(input_port); EspNetOutputPort *output_port = new EspNetOutputPort(this, i, m_node); AddPort(output_port); } m_plugin_adaptor->AddReadDescriptor(m_node->GetSocket()); return true; } /* * Stop this device */ void EspNetDevice::PrePortStop() { m_plugin_adaptor->RemoveReadDescriptor(m_node->GetSocket()); } /* * Stop this device */ void EspNetDevice::PostPortStop() { m_node->Stop(); delete m_node; m_node = NULL; } } // namespace espnet } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/ftdidmx/0000755000175000017500000000000013155164170016603 5ustar wouterwouterola-0.10.5.nojsmin/plugins/ftdidmx/FtdiDmxPlugin.h0000644000175000017500000000430013023355232021462 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * FtdiDmxPlugin.h * The FTDI usb chipset DMX plugin for ola * Copyright (C) 2011 Rui Barreiros */ #ifndef PLUGINS_FTDIDMX_FTDIDMXPLUGIN_H_ #define PLUGINS_FTDIDMX_FTDIDMXPLUGIN_H_ #include #include #include #include "olad/Plugin.h" #include "ola/plugin_id.h" #include "plugins/ftdidmx/FtdiDmxDevice.h" namespace ola { namespace plugin { namespace ftdidmx { class FtdiDmxPlugin : public Plugin { public: explicit FtdiDmxPlugin(ola::PluginAdaptor *plugin_adaptor) : Plugin(plugin_adaptor) { } ola_plugin_id Id() const { return OLA_PLUGIN_FTDIDMX; } std::string Name() const { return PLUGIN_NAME; } std::string PluginPrefix() const { return PLUGIN_PREFIX; } // This plugin is disabled unless explicitly enabled by a user. bool DefaultMode() const { return false; } void ConflictsWith(std::set *conflict_set) const { conflict_set->insert(ola::OLA_PLUGIN_USBPRO); conflict_set->insert(ola::OLA_PLUGIN_OPENDMX); } std::string Description() const; private: typedef std::vector FtdiDeviceVector; FtdiDeviceVector m_devices; void AddDevice(FtdiDmxDevice *device); bool StartHook(); bool StopHook(); bool SetDefaultPreferences(); static const uint8_t DEFAULT_FREQUENCY = 30; static const char K_FREQUENCY[]; static const char PLUGIN_NAME[]; static const char PLUGIN_PREFIX[]; }; } // namespace ftdidmx } // namespace plugin } // namespace ola #endif // PLUGINS_FTDIDMX_FTDIDMXPLUGIN_H_ ola-0.10.5.nojsmin/plugins/ftdidmx/FtdiWidget.cpp0000644000175000017500000002632113023355232021340 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * FtdiWidget.cpp * This class is based on QLCFTDI class from * * Q Light Controller * qlcftdi-libftdi.cpp * * Copyright (C) Heikki Junnila * * Only standard CPP conversion was changed and function name changed * to follow OLA coding standards. * * by Rui Barreiros * * Additional modifications to enable support for multiple outputs and * additional device ids did change the original structure. * * by E.S. Rosenberg a.k.a. Keeper of the Keys 5774/2014 */ #include #include #include #include #include #include #include "ola/Logging.h" #include "ola/BaseTypes.h" #include "ola/StringUtils.h" #include "ola/Constants.h" #include "plugins/ftdidmx/FtdiWidget.h" namespace ola { namespace plugin { namespace ftdidmx { using std::string; using std::vector; const uint16_t FtdiWidgetInfo::FTDI_VID = 0x0403; const uint16_t FtdiWidgetInfo::FT232_PID = 0x6001; const uint16_t FtdiWidgetInfo::FT4232_PID = 0x6011; FtdiWidget::FtdiWidget(const string& serial, const string& name, uint32_t id, const uint16_t vid, const uint16_t pid) : m_serial(serial), m_name(name), m_id(id), m_vid(vid), m_pid(pid) {} FtdiWidget::~FtdiWidget() {} /** * @brief Get the number of physical interfaces our widget has to offer. * * This does not deal with product names being named in a different way. * * Originally I had hoped to use ftdi_context::type however, it only gets set * properly after the device has been opened. */ int FtdiWidget::GetInterfaceCount() { std::string tmp = m_name; ToLower(&tmp); if (std::string::npos != tmp.find("plus4")) { return 4; } else if (std::string::npos != tmp.find("plus2")) { return 2; } else { return 1; } } bool FtdiWidget::m_missing_serial = false; /** * @brief Build a list of all attached ftdi devices */ void FtdiWidget::Widgets(vector *widgets) { int i = -1; widgets->clear(); struct ftdi_context *ftdi = ftdi_new(); if (!ftdi) { OLA_WARN << "Failed to allocate FTDI context"; return; } vector pids; pids.push_back(FtdiWidgetInfo::FT232_PID); pids.push_back(FtdiWidgetInfo::FT4232_PID); const uint16_t vid = FtdiWidgetInfo::FTDI_VID; for (vector::iterator current_pid = pids.begin(); current_pid != pids.end(); ++current_pid) { struct ftdi_device_list* list = NULL; int devices_found = ftdi_usb_find_all(ftdi, &list, vid, *current_pid); if (devices_found < 0) { OLA_WARN << "Failed to get FTDI devices: " << ftdi_get_error_string(ftdi) << " with PID: " << *current_pid; } else { OLA_INFO << "Found " << devices_found << " FTDI devices with PID: " << *current_pid << "."; ftdi_device_list* current_device = list; while (current_device != NULL) { struct usb_device *dev = current_device->dev; current_device = current_device->next; i++; if (!dev) { OLA_WARN << "Device returned from ftdi_usb_find_all was NULL"; continue; } char serial[256]; char name[256]; char vendor[256]; int r = ftdi_usb_get_strings(ftdi, dev, vendor, sizeof(vendor), name, sizeof(name), serial, sizeof(serial)); if (r < 0 && r != FtdiWidget::libftdi_ftdi_usb_get_strings_get_serial_failed) { OLA_WARN << "Unable to fetch string information from USB device: " << ftdi_get_error_string(ftdi); continue; } string v = string(vendor); string sname = string(name); string sserial = string(serial); if (sserial == "?" || r == FtdiWidget::libftdi_ftdi_usb_get_strings_get_serial_failed) { // This means there wasn't a serial number sserial.clear(); } if (r == FtdiWidget::libftdi_ftdi_usb_get_strings_get_serial_failed) { if (FtdiWidget::m_missing_serial) { OLA_WARN << "Failed to read serial number or serial number empty. " << "We can only support one device without a serial " << "number."; continue; } else { OLA_WARN << "Failed to read serial number for " << sname; FtdiWidget::m_missing_serial = true; } } OLA_INFO << "Found FTDI device. Vendor: '" << v << "', Name: '" << sname << "', Serial: '" << sserial << "'"; ToUpper(&v); if (std::string::npos != v.find("FTDI") || std::string::npos != v.find("KMTRONIC") || std::string::npos != v.find("KWMATIK") || std::string::npos != v.find("WWW.SOH.CZ")) { widgets->push_back(FtdiWidgetInfo(sname, sserial, i, vid, *current_pid)); } else { OLA_INFO << "Unknown FTDI device with vendor string: '" << v << "'"; } } // while (list != NULL) OLA_DEBUG << "Freeing list"; ftdi_list_free(&list); } } ftdi_free(ftdi); } FtdiInterface::FtdiInterface(const FtdiWidget * parent, const ftdi_interface interface) : m_parent(parent), m_interface(interface) { memset(&m_handle, '\0', sizeof(struct ftdi_context)); ftdi_init(&m_handle); } FtdiInterface::~FtdiInterface() { if (IsOpen()) { Close(); } ftdi_deinit(&m_handle); } bool FtdiInterface::SetInterface() { OLA_INFO << "Setting interface to: " << m_interface; if (ftdi_set_interface(&m_handle, m_interface) < 0) { OLA_WARN << m_parent->Description() << " " << ftdi_get_error_string(&m_handle); return false; } else { return true; } } bool FtdiInterface::Open() { if (m_parent->Serial().empty()) { OLA_WARN << m_parent->Name() << " has no serial number, which might cause " << "issues with multiple devices"; if (ftdi_usb_open(&m_handle, m_parent->Vid(), m_parent->Pid()) < 0) { OLA_WARN << m_parent->Description() << " " << ftdi_get_error_string(&m_handle); return false; } else { return true; } } else { OLA_DEBUG << "Opening FTDI device " << m_parent->Name() << ", serial: " << m_parent->Serial() << ", interface: " << m_interface; if (ftdi_usb_open_desc(&m_handle, m_parent->Vid(), m_parent->Pid(), m_parent->Name().c_str(), m_parent->Serial().c_str()) < 0) { OLA_WARN << m_parent->Description() << " " << ftdi_get_error_string(&m_handle); return false; } else { return true; } } } bool FtdiInterface::Close() { if (ftdi_usb_close(&m_handle) < 0) { OLA_WARN << m_parent->Description() << " " << ftdi_get_error_string(&m_handle); return false; } else { return true; } } bool FtdiInterface::IsOpen() const { return (m_handle.usb_dev != NULL); } bool FtdiInterface::Reset() { if (ftdi_usb_reset(&m_handle) < 0) { OLA_WARN << m_parent->Description() << " " << ftdi_get_error_string(&m_handle); return false; } else { return true; } } bool FtdiInterface::SetLineProperties() { if ((ftdi_set_line_property(&m_handle, BITS_8, STOP_BIT_2, NONE) < 0)) { OLA_WARN << m_parent->Description() << " " << ftdi_get_error_string(&m_handle); return false; } else { return true; } } bool FtdiInterface::SetBaudRate(int speed) { if (ftdi_set_baudrate(&m_handle, speed) < 0) { OLA_WARN << "Error setting " << m_parent->Description() << " to baud rate " << "of " << speed << " - " << ftdi_get_error_string(&m_handle); return false; } else { return true; } } bool FtdiInterface::SetFlowControl() { if (ftdi_setflowctrl(&m_handle, SIO_DISABLE_FLOW_CTRL) < 0) { OLA_WARN << m_parent->Description() << " " << ftdi_get_error_string(&m_handle); return false; } else { return true; } } bool FtdiInterface::ClearRts() { if (ftdi_setrts(&m_handle, 0) < 0) { OLA_WARN << m_parent->Description() << " " << ftdi_get_error_string(&m_handle); return false; } else { return true; } } bool FtdiInterface::PurgeBuffers() { if (ftdi_usb_purge_buffers(&m_handle) < 0) { OLA_WARN << m_parent->Description() << " " << ftdi_get_error_string(&m_handle); return false; } else { return true; } } bool FtdiInterface::SetBreak(bool on) { if (ftdi_set_line_property2(&m_handle, BITS_8, STOP_BIT_2, NONE, (on ? BREAK_ON : BREAK_OFF)) < 0) { OLA_WARN << m_parent->Description() << " " << ftdi_get_error_string(&m_handle); return false; } else { return true; } } bool FtdiInterface::Write(const ola::DmxBuffer& data) { unsigned char buffer[DMX_UNIVERSE_SIZE + 1]; unsigned int length = DMX_UNIVERSE_SIZE; buffer[0] = DMX512_START_CODE; data.Get(buffer + 1, &length); if (ftdi_write_data(&m_handle, buffer, length + 1) < 0) { OLA_WARN << m_parent->Description() << " " << ftdi_get_error_string(&m_handle); return false; } else { return true; } } bool FtdiInterface::Read(unsigned char *buff, int size) { int read = ftdi_read_data(&m_handle, buff, size); if (read <= 0) { OLA_WARN << m_parent->Description() << " " << ftdi_get_error_string(&m_handle); return false; } else { return true; } } bool FtdiInterface::SetupOutput() { // Setup the widget if (!SetInterface()) { OLA_WARN << "Error setting the device interface."; return false; } if (!Open()) { OLA_WARN << "Error Opening widget"; return false; } if (!Reset()) { OLA_WARN << "Error Resetting widget"; return false; } if (!SetBaudRate()) { OLA_WARN << "Error Setting baudrate"; return false; } if (!SetLineProperties()) { OLA_WARN << "Error setting line properties"; return false; } if (!SetFlowControl()) { OLA_WARN << "Error setting flow control"; return false; } if (!PurgeBuffers()) { OLA_WARN << "Error purging buffers"; return false; } if (!ClearRts()) { OLA_WARN << "Error clearing rts"; return false; } return true; } } // namespace ftdidmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/ftdidmx/Makefile.mk0000644000175000017500000000123013023355232020640 0ustar wouterwouter# LIBRARIES ################################################## if USE_FTDI lib_LTLIBRARIES += plugins/ftdidmx/libolaftdidmx.la plugins_ftdidmx_libolaftdidmx_la_SOURCES = \ plugins/ftdidmx/FtdiDmxDevice.cpp \ plugins/ftdidmx/FtdiDmxDevice.h \ plugins/ftdidmx/FtdiDmxPlugin.cpp \ plugins/ftdidmx/FtdiDmxPlugin.h \ plugins/ftdidmx/FtdiDmxPort.h \ plugins/ftdidmx/FtdiDmxThread.cpp \ plugins/ftdidmx/FtdiDmxThread.h \ plugins/ftdidmx/FtdiWidget.cpp \ plugins/ftdidmx/FtdiWidget.h plugins_ftdidmx_libolaftdidmx_la_LIBADD = \ $(libftdi_LIBS) \ common/libolacommon.la \ olad/plugin_api/libolaserverplugininterface.la endif ola-0.10.5.nojsmin/plugins/ftdidmx/FtdiDmxPlugin.cpp0000644000175000017500000000751513023355232022030 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * FtdiDmxPlugin.cpp * The FTDI usb chipset DMX plugin for ola * Copyright (C) 2011 Rui Barreiros * * Additional modifications to enable support for multiple outputs and * additional device ids did change the original structure. * * by E.S. Rosenberg a.k.a. Keeper of the Keys 5774/2014 */ #include #include #include "ola/StringUtils.h" #include "olad/Preferences.h" #include "olad/PluginAdaptor.h" #include "plugins/ftdidmx/FtdiDmxPlugin.h" #include "plugins/ftdidmx/FtdiDmxDevice.h" #include "plugins/ftdidmx/FtdiWidget.h" namespace ola { namespace plugin { namespace ftdidmx { using std::string; using std::vector; const char FtdiDmxPlugin::K_FREQUENCY[] = "frequency"; const char FtdiDmxPlugin::PLUGIN_NAME[] = "FTDI USB DMX"; const char FtdiDmxPlugin::PLUGIN_PREFIX[] = "ftdidmx"; /** * @brief Attempt to start a device and, if successful, register it * * Ownership of the FtdiDmxDevice is transfered to us here. */ void FtdiDmxPlugin::AddDevice(FtdiDmxDevice *device) { if (device->Start()) { m_devices.push_back(device); m_plugin_adaptor->RegisterDevice(device); } else { OLA_WARN << "Failed to start FTDI device " << device->Description(); delete device; } } /** * @brief Fetch a list of all FTDI widgets and create a new device for each of them. */ bool FtdiDmxPlugin::StartHook() { typedef vector FtdiWidgetInfoVector; FtdiWidgetInfoVector widgets; FtdiWidget::Widgets(&widgets); unsigned int frequency = StringToIntOrDefault( m_preferences->GetValue(K_FREQUENCY), DEFAULT_FREQUENCY); FtdiWidgetInfoVector::const_iterator iter; for (iter = widgets.begin(); iter != widgets.end(); ++iter) { AddDevice(new FtdiDmxDevice(this, *iter, frequency)); } return true; } /** * @brief Stop all the devices. */ bool FtdiDmxPlugin::StopHook() { FtdiDeviceVector::iterator iter; for (iter = m_devices.begin(); iter != m_devices.end(); ++iter) { m_plugin_adaptor->UnregisterDevice(*iter); (*iter)->Stop(); delete (*iter); } m_devices.clear(); return true; } /** * @brief Return a description for this plugin. */ string FtdiDmxPlugin::Description() const { return "FTDI USB Chipset DMX Plugin\n" "----------------------------\n" "\n" "This plugin is compatible with Enttec OpenDmx and other\n" "FTDI chipset based USB to DMX converters where the host\n" "needs to create the DMX stream itself and not the interface\n" "(the interface has no microprocessor to do so).\n" "\n" "--- Config file : ola-ftdidmx.conf ---\n" "\n" "frequency = 30\n" "The DMX stream frequency (30 to 44 Hz max are the usual).\n" "\n"; } /** * @brief Set the default preferences */ bool FtdiDmxPlugin::SetDefaultPreferences() { if (!m_preferences) { return false; } if (m_preferences->SetDefaultValue(FtdiDmxPlugin::K_FREQUENCY, UIntValidator(1, 44), DEFAULT_FREQUENCY)) { m_preferences->Save(); } if (m_preferences->GetValue(FtdiDmxPlugin::K_FREQUENCY).empty()) { return false; } return true; } } // namespace ftdidmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/ftdidmx/FtdiDmxThread.cpp0000644000175000017500000001017713023355232021777 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * FtdiDmxThread.cpp * The FTDI usb chipset DMX plugin for ola * Copyright (C) 2011 Rui Barreiros * * Additional modifications to enable support for multiple outputs and * additional device ids did change the original structure. * * by E.S. Rosenberg a.k.a. Keeper of the Keys 5774/2014 */ #include #include #include #include "ola/Clock.h" #include "ola/Logging.h" #include "ola/StringUtils.h" #include "plugins/ftdidmx/FtdiWidget.h" #include "plugins/ftdidmx/FtdiDmxThread.h" namespace ola { namespace plugin { namespace ftdidmx { FtdiDmxThread::FtdiDmxThread(FtdiInterface *interface, unsigned int frequency) : m_granularity(UNKNOWN), m_interface(interface), m_term(false), m_frequency(frequency) { } FtdiDmxThread::~FtdiDmxThread() { Stop(); } /** * @brief Stop this thread */ bool FtdiDmxThread::Stop() { { ola::thread::MutexLocker locker(&m_term_mutex); m_term = true; } return Join(); } /** * @brief Copy a DMXBuffer to the output thread */ bool FtdiDmxThread::WriteDMX(const DmxBuffer &buffer) { { ola::thread::MutexLocker locker(&m_buffer_mutex); m_buffer.Set(buffer); return true; } } /** * @brief The method called by the thread */ void *FtdiDmxThread::Run() { TimeStamp ts1, ts2, ts3; Clock clock; CheckTimeGranularity(); DmxBuffer buffer; int frameTime = static_cast(floor( (static_cast(1000) / m_frequency) + static_cast(0.5))); // Setup the interface if (!m_interface->IsOpen()) { m_interface->SetupOutput(); } while (1) { { ola::thread::MutexLocker locker(&m_term_mutex); if (m_term) { break; } } { ola::thread::MutexLocker locker(&m_buffer_mutex); buffer.Set(m_buffer); } clock.CurrentTime(&ts1); if (!m_interface->SetBreak(true)) { goto framesleep; } if (m_granularity == GOOD) { usleep(DMX_BREAK); } if (!m_interface->SetBreak(false)) { goto framesleep; } if (m_granularity == GOOD) { usleep(DMX_MAB); } if (!m_interface->Write(buffer)) { goto framesleep; } framesleep: // Sleep for the remainder of the DMX frame time clock.CurrentTime(&ts2); TimeInterval elapsed = ts2 - ts1; if (m_granularity == GOOD) { while (elapsed.InMilliSeconds() < frameTime) { usleep(1000); clock.CurrentTime(&ts2); elapsed = ts2 - ts1; } } else { // See if we can drop out of bad mode. usleep(1000); clock.CurrentTime(&ts3); TimeInterval interval = ts3 - ts2; if (interval.InMilliSeconds() < BAD_GRANULARITY_LIMIT) { m_granularity = GOOD; OLA_INFO << "Switching from BAD to GOOD granularity for ftdi thread"; } elapsed = ts3 - ts1; while (elapsed.InMilliSeconds() < frameTime) { clock.CurrentTime(&ts2); elapsed = ts2 - ts1; } } } return NULL; } /** * @brief Check the granularity of usleep. */ void FtdiDmxThread::CheckTimeGranularity() { TimeStamp ts1, ts2; Clock clock; clock.CurrentTime(&ts1); usleep(1000); clock.CurrentTime(&ts2); TimeInterval interval = ts2 - ts1; m_granularity = (interval.InMilliSeconds() > BAD_GRANULARITY_LIMIT) ? BAD : GOOD; OLA_INFO << "Granularity for FTDI thread is " << ((m_granularity == GOOD) ? "GOOD" : "BAD"); } } // namespace ftdidmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/ftdidmx/FtdiDmxDevice.cpp0000644000175000017500000000542213023355232021764 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * FtdiDmxDevice.cpp * The FTDI usb chipset DMX plugin for ola * Copyright (C) 2011 Rui Barreiros * * Additional modifications to enable support for multiple outputs and * additional device ids did change the original structure. * * by E.S. Rosenberg a.k.a. Keeper of the Keys 5774/2014 */ #include #include #include "ola/Logging.h" #include "plugins/ftdidmx/FtdiDmxDevice.h" #include "plugins/ftdidmx/FtdiDmxPort.h" namespace ola { namespace plugin { namespace ftdidmx { using std::string; FtdiDmxDevice::FtdiDmxDevice(AbstractPlugin *owner, const FtdiWidgetInfo &widget_info, unsigned int frequency) : Device(owner, widget_info.Description()), m_widget_info(widget_info), m_frequency(frequency) { m_widget = new FtdiWidget(widget_info.Serial(), widget_info.Name(), widget_info.Id(), widget_info.Vid(), widget_info.Pid()); } FtdiDmxDevice::~FtdiDmxDevice() { DeleteAllPorts(); delete m_widget; } bool FtdiDmxDevice::StartHook() { unsigned int interface_count = m_widget->GetInterfaceCount(); unsigned int successfully_added = 0; OLA_INFO << "Widget " << m_widget->Name() << " has " << interface_count << " interfaces."; for (unsigned int i = 1; i <= interface_count; i++) { FtdiInterface *port = new FtdiInterface(m_widget, static_cast(i)); if (port->SetupOutput()) { AddPort(new FtdiDmxOutputPort(this, port, i, m_frequency)); successfully_added += 1; } else { OLA_WARN << "Failed to add interface: " << i; delete port; } } if (successfully_added > 0) { OLA_INFO << "Successfully added " << successfully_added << "/" << interface_count << " interfaces."; } else { OLA_INFO << "Removing widget since no ports were added."; return false; } return true; } } // namespace ftdidmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/ftdidmx/FtdiDmxPort.h0000644000175000017500000000424513023355232021160 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * FtdiDmxPort.h * The FTDI usb chipset DMX plugin for ola * Copyright (C) 2011 Rui Barreiros * * Additional modifications to enable support for multiple outputs and * additional device ids did change the original structure. * * by E.S. Rosenberg a.k.a. Keeper of the Keys 5774/2014 */ #ifndef PLUGINS_FTDIDMX_FTDIDMXPORT_H_ #define PLUGINS_FTDIDMX_FTDIDMXPORT_H_ #include #include "ola/DmxBuffer.h" #include "olad/Port.h" #include "olad/Preferences.h" #include "plugins/ftdidmx/FtdiDmxDevice.h" #include "plugins/ftdidmx/FtdiWidget.h" #include "plugins/ftdidmx/FtdiDmxThread.h" namespace ola { namespace plugin { namespace ftdidmx { class FtdiDmxOutputPort : public ola::BasicOutputPort { public: FtdiDmxOutputPort(FtdiDmxDevice *parent, FtdiInterface *interface, unsigned int id, unsigned int freq) : BasicOutputPort(parent, id), m_interface(interface), m_thread(interface, freq) { m_thread.Start(); } ~FtdiDmxOutputPort() { m_thread.Stop(); delete m_interface; } bool WriteDMX(const ola::DmxBuffer &buffer, uint8_t) { return m_thread.WriteDMX(buffer); } std::string Description() const { return m_interface->Description(); } private: FtdiInterface *m_interface; FtdiDmxThread m_thread; }; } // namespace ftdidmx } // namespace plugin } // namespace ola #endif // PLUGINS_FTDIDMX_FTDIDMXPORT_H_ ola-0.10.5.nojsmin/plugins/ftdidmx/FtdiDmxDevice.h0000644000175000017500000000364413023355232021435 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * FtdiDmxDevice.h * The FTDI usb chipset DMX plugin for ola * Copyright (C) 2011 Rui Barreiros * * Additional modifications to enable support for multiple outputs and * additional device ids did change the original structure. * * by E.S. Rosenberg a.k.a. Keeper of the Keys 5774/2014 */ #ifndef PLUGINS_FTDIDMX_FTDIDMXDEVICE_H_ #define PLUGINS_FTDIDMX_FTDIDMXDEVICE_H_ #include #include #include "ola/DmxBuffer.h" #include "olad/Device.h" #include "olad/Preferences.h" #include "plugins/ftdidmx/FtdiWidget.h" namespace ola { namespace plugin { namespace ftdidmx { class FtdiDmxDevice : public Device { public: FtdiDmxDevice(AbstractPlugin *owner, const FtdiWidgetInfo &widget_info, unsigned int frequency); ~FtdiDmxDevice(); std::string DeviceId() const { return m_widget->Serial(); } std::string Description() const { return m_widget_info.Description(); } FtdiWidget* GetDevice() { return m_widget; } protected: bool StartHook(); private: FtdiWidget *m_widget; const FtdiWidgetInfo m_widget_info; unsigned int m_frequency; }; } // namespace ftdidmx } // namespace plugin } // namespace ola #endif // PLUGINS_FTDIDMX_FTDIDMXDEVICE_H_ ola-0.10.5.nojsmin/plugins/ftdidmx/FtdiDmxThread.h0000644000175000017500000000374213023355232021444 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * FtdiDmxThread.h * The FTDI usb chipset DMX plugin for ola * Copyright (C) 2011 Rui Barreiros * * Additional modifications to enable support for multiple outputs and * additional device ids did change the original structure. * * by E.S. Rosenberg a.k.a. Keeper of the Keys 5774/2014 */ #ifndef PLUGINS_FTDIDMX_FTDIDMXTHREAD_H_ #define PLUGINS_FTDIDMX_FTDIDMXTHREAD_H_ #include "ola/DmxBuffer.h" #include "ola/thread/Thread.h" namespace ola { namespace plugin { namespace ftdidmx { class FtdiDmxThread : public ola::thread::Thread { public: FtdiDmxThread(FtdiInterface *interface, unsigned int frequency); ~FtdiDmxThread(); bool Stop(); void *Run(); bool WriteDMX(const DmxBuffer &buffer); private: enum TimerGranularity { UNKNOWN, GOOD, BAD }; TimerGranularity m_granularity; FtdiInterface *m_interface; bool m_term; unsigned int m_frequency; DmxBuffer m_buffer; ola::thread::Mutex m_term_mutex; ola::thread::Mutex m_buffer_mutex; void CheckTimeGranularity(); static const uint32_t DMX_MAB = 16; static const uint32_t DMX_BREAK = 110; static const uint32_t BAD_GRANULARITY_LIMIT = 3; }; } // namespace ftdidmx } // namespace plugin } // namespace ola #endif // PLUGINS_FTDIDMX_FTDIDMXTHREAD_H_ ola-0.10.5.nojsmin/plugins/ftdidmx/FtdiWidget.h0000644000175000017500000001411113023355232020777 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * FtdiWidget.h * This class is based on QLCFTDI class from * * Q Light Controller * qlcftdi.h * * Copyright (C) Heikki Junnila * * Only standard CPP conversion was changed and function name changed * to follow OLA coding standards. * * by Rui Barreiros * * Additional modifications to enable support for multiple outputs and * additional devices ids did change the original structure. * * by E.S. Rosenberg a.k.a. Keeper of the Keys 5774/2014 */ #ifndef PLUGINS_FTDIDMX_FTDIWIDGET_H_ #define PLUGINS_FTDIDMX_FTDIWIDGET_H_ #include #include #include #include #include #include "ola/DmxBuffer.h" namespace ola { namespace plugin { namespace ftdidmx { /** * @brief This class holds information about an attached FTDI chip */ class FtdiWidgetInfo { public: static const uint16_t FTDI_VID; static const uint16_t FT232_PID; static const uint16_t FT4232_PID; FtdiWidgetInfo(const std::string &name, const std::string &serial, unsigned int id, const uint16_t vid = FTDI_VID, const uint16_t pid = FT232_PID) : m_name(name), m_serial(serial), m_id(id), m_vid(vid), m_pid(pid) { } FtdiWidgetInfo(const FtdiWidgetInfo &info) : m_name(info.Name()), m_serial(info.Serial()), m_id(info.Id()), m_vid(info.Vid()), m_pid(info.Pid()) { } ~FtdiWidgetInfo() {} std::string Name() const { return m_name; } std::string Serial() const { return m_serial; } unsigned int Id() const { return m_id; } uint16_t Vid() const { return m_vid; } uint16_t Pid() const { return m_pid; } std::string Description() const { return m_name + " with serial number : " + m_serial + " "; } FtdiWidgetInfo& operator=(const FtdiWidgetInfo &other) { if (this != &other) { m_name = other.Name(); m_serial = other.Serial(); m_id = other.Id(); m_vid = other.Vid(); m_pid = other.Pid(); } return *this; } private: std::string m_name; std::string m_serial; unsigned int m_id; uint16_t m_vid; uint16_t m_pid; }; /** * @brief An FTDI widget */ class FtdiWidget { public: /** * @brief Construct a new FtdiWidget instance for one widget. * @param serial The widget's USB serial number * @param name The widget's USB name (description) * @param id id based on order of adding it seems from the code * @param vid The VendorID of the device, def = FtdiWidgetInfo::ftdi_vid * @param pid The ProductID of the device, def = FtdiWidgetInfo::ft232_pid */ FtdiWidget(const std::string &serial, const std::string &name, uint32_t id = 0, const uint16_t vid = FtdiWidgetInfo::FTDI_VID, const uint16_t pid = FtdiWidgetInfo::FT232_PID); /** @brief Destructor */ virtual ~FtdiWidget(); /** @brief Get the widget's USB serial number */ std::string Serial() const { return m_serial; } /** @brief Get the widget's USB name */ std::string Name() const { return m_name; } uint16_t Vid() const { return m_vid; } uint16_t Pid() const { return m_pid; } /** @brief Get the widget's FTD2XX ID number */ uint32_t Id() const { return m_id; } std::string Description() const { return m_name + " with serial number : " + m_serial +" "; } /** @brief Get Widget available interface count **/ int GetInterfaceCount(); /** * @brief Build a list of available ftdi widgets. * @param widgets a pointer to a vector of FtdiWidgetInfo objects. */ static void Widgets(std::vector *widgets); // From reading libftdi docs it seems they may reuse error codes, which is // why I chose to name this const __. static const int libftdi_ftdi_usb_get_strings_get_serial_failed = -9; static bool m_missing_serial; private: std::string m_serial; std::string m_name; uint32_t m_id; const uint16_t m_vid; const uint16_t m_pid; }; class FtdiInterface { public: FtdiInterface(const FtdiWidget * parent, const ftdi_interface interface); virtual ~FtdiInterface(); std::string Description() const { return m_parent->Description(); } /** @brief Set interface on the widget */ bool SetInterface(); /** @brief Open the widget */ bool Open(); /** @brief Close the widget */ bool Close(); /** @brief Check if the widget is open */ bool IsOpen() const; /** @brief Reset the communications line */ bool Reset(); /** @brief Setup communications line for 8N2 traffic */ bool SetLineProperties(); /** @brief Set 250kbps baud rate */ bool SetBaudRate(int speed = 250000); /** @brief Disable flow control */ bool SetFlowControl(); /** @brief Clear the RTS bit */ bool ClearRts(); /** @brief Purge TX & RX buffers */ bool PurgeBuffers(); /** @brief Toggle communications line BREAK condition on/off */ bool SetBreak(bool on); /** @brief Write data to a previously-opened line */ bool Write(const ola::DmxBuffer &data); /** @brief Read data from a previously-opened line */ bool Read(unsigned char* buff, int size); /** @brief Setup device for DMX Output **/ bool SetupOutput(); private: const FtdiWidget * m_parent; struct ftdi_context m_handle; const ftdi_interface m_interface; }; // FtdiInterface } // namespace ftdidmx } // namespace plugin } // namespace ola #endif // PLUGINS_FTDIDMX_FTDIWIDGET_H_ ola-0.10.5.nojsmin/plugins/usbdmx/0000755000175000017500000000000013155164170016446 5ustar wouterwouterola-0.10.5.nojsmin/plugins/usbdmx/JaRuleDevice.h0000644000175000017500000000356613023355232021126 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * JaRuleDevice.h * A Ja Rule device. * Copyright (C) 2015 Simon Newton */ #ifndef PLUGINS_USBDMX_JARULEDEVICE_H_ #define PLUGINS_USBDMX_JARULEDEVICE_H_ #include #include #include "libs/usb/JaRuleWidget.h" #include "ola/base/Macro.h" #include "olad/Device.h" namespace ola { namespace plugin { namespace usbdmx { /** * @brief A JaRule device, that represents one widget. * * A widget may have multiple input / output ports. */ class JaRuleDevice: public Device { public: /** * @brief Create a new JaRuleDevice. * @param owner The plugin this device belongs to. * @param widget An initalized JaRuleWidget. * @param device_name The name of the device. */ JaRuleDevice(ola::AbstractPlugin *owner, ola::usb::JaRuleWidget *widget, const std::string &device_name); std::string DeviceId() const { return m_device_id; } protected: bool StartHook(); private: ola::usb::JaRuleWidget *m_widget; // not owned const std::string m_device_id; DISALLOW_COPY_AND_ASSIGN(JaRuleDevice); }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_JARULEDEVICE_H_ ola-0.10.5.nojsmin/plugins/usbdmx/UsbDmxPlugin.h0000644000175000017500000000440713023355232021200 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * UsbDmxPlugin.h * A plugin that uses libusb to communicate with USB devices. * Copyright (C) 2010 Simon Newton */ #ifndef PLUGINS_USBDMX_USBDMXPLUGIN_H_ #define PLUGINS_USBDMX_USBDMXPLUGIN_H_ #include #include #include "ola/base/Macro.h" #include "ola/plugin_id.h" #include "olad/Plugin.h" namespace ola { namespace plugin { namespace usbdmx { /** * @brief A plugin that uses libusb to communicate with USB devices. * * This plugin supports a number of USB dongles including * - Anyma uDMX * - Eurolite DMX USB Pro. * - Scanlime's Fadecandy. * - Sunlite. * - Velleman K8062. */ class UsbDmxPlugin: public ola::Plugin { public: /** * @brief Create a new UsbDmxPlugin. * @param plugin_adaptor The PluginAdaptor to use, ownership is not * transferred. */ explicit UsbDmxPlugin(PluginAdaptor *plugin_adaptor); ~UsbDmxPlugin(); std::string Name() const { return PLUGIN_NAME; } std::string Description() const; ola_plugin_id Id() const { return OLA_PLUGIN_USBDMX; } std::string PluginPrefix() const { return PLUGIN_PREFIX; } private: std::auto_ptr m_impl; bool StartHook(); bool StopHook(); bool SetDefaultPreferences(); static const char PLUGIN_NAME[]; static const char PLUGIN_PREFIX[]; static const char LIBUSB_DEBUG_LEVEL_KEY[]; static int LIBUSB_DEFAULT_DEBUG_LEVEL; static int LIBUSB_MAX_DEBUG_LEVEL; DISALLOW_COPY_AND_ASSIGN(UsbDmxPlugin); }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_USBDMXPLUGIN_H_ ola-0.10.5.nojsmin/plugins/usbdmx/SunliteFirmwareLoader.h0000644000175000017500000000347713023355232023074 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SunliteFirmwareLoader.h * Load the firmware onto a USBDMX2 device * Copyright (C) 2010 Simon Newton * * The Soundlite USBDMX2 interfaces require firmware to be loaded when they're * connected, this performs that job. */ #ifndef PLUGINS_USBDMX_SUNLITEFIRMWARELOADER_H_ #define PLUGINS_USBDMX_SUNLITEFIRMWARELOADER_H_ #include #include "ola/base/Macro.h" #include "plugins/usbdmx/FirmwareLoader.h" namespace ola { namespace plugin { namespace usbdmx { class SunliteFirmwareLoader: public FirmwareLoader { public: explicit SunliteFirmwareLoader(libusb_device *usb_device) : m_device(usb_device) {} ~SunliteFirmwareLoader() {} bool LoadFirmware(); private: libusb_device *m_device; static const int INTERFACE_NUMBER = 0; // the device only has 1 interface static const uint8_t UPLOAD_REQUEST_TYPE = 0x40; static const uint8_t UPLOAD_REQUEST = 0xa0; static const unsigned int UPLOAD_TIMEOUT = 300; // ms DISALLOW_COPY_AND_ASSIGN(SunliteFirmwareLoader); }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_SUNLITEFIRMWARELOADER_H_ ola-0.10.5.nojsmin/plugins/usbdmx/SyncronizedWidgetObserver.cpp0000644000175000017500000000357413023355232024341 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SyncronizedWidgetObserver.cpp * Transfers widget add/remove events to another thread. * Copyright (C) 2014 Simon Newton */ #include "plugins/usbdmx/SyncronizedWidgetObserver.h" #include "ola/Callback.h" namespace ola { namespace plugin { namespace usbdmx { using ola::thread::Thread; SyncronizedWidgetObserver::SyncronizedWidgetObserver( WidgetObserver *observer, ola::io::SelectServerInterface *ss) : m_observer(observer), m_ss(ss), m_main_thread_id(Thread::Self()) { } template bool SyncronizedWidgetObserver::DispatchNewWidget(WidgetClass *widget) { if (pthread_equal(Thread::Self(), m_main_thread_id)) { return m_observer->NewWidget(widget); } else { AddFuture f; m_ss->Execute( NewSingleCallback( this, &SyncronizedWidgetObserver::HandleNewWidget, widget, &f)); return f.Get(); } } template void SyncronizedWidgetObserver::HandleNewWidget(WidgetClass*widget, AddFuture *f) { f->Set(m_observer->NewWidget(widget)); } } // namespace usbdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbdmx/Makefile.mk0000644000175000017500000000651213023355232020513 0ustar wouterwouter# LIBRARIES ################################################## if USE_LIBUSB noinst_LTLIBRARIES += plugins/usbdmx/libolausbdmxwidget.la plugins_usbdmx_libolausbdmxwidget_la_SOURCES = \ plugins/usbdmx/AnymauDMX.cpp \ plugins/usbdmx/AnymauDMX.h \ plugins/usbdmx/AnymauDMXFactory.cpp \ plugins/usbdmx/AnymauDMXFactory.h \ plugins/usbdmx/AsyncUsbReceiver.cpp \ plugins/usbdmx/AsyncUsbReceiver.h \ plugins/usbdmx/AsyncUsbSender.cpp \ plugins/usbdmx/AsyncUsbSender.h \ plugins/usbdmx/AsyncUsbTransceiverBase.cpp \ plugins/usbdmx/AsyncUsbTransceiverBase.h \ plugins/usbdmx/DMXCProjectsNodleU1.cpp \ plugins/usbdmx/DMXCProjectsNodleU1.h \ plugins/usbdmx/DMXCProjectsNodleU1Factory.cpp \ plugins/usbdmx/DMXCProjectsNodleU1Factory.h \ plugins/usbdmx/EurolitePro.cpp \ plugins/usbdmx/EurolitePro.h \ plugins/usbdmx/EuroliteProFactory.cpp \ plugins/usbdmx/EuroliteProFactory.h \ plugins/usbdmx/FirmwareLoader.h \ plugins/usbdmx/Flags.cpp \ plugins/usbdmx/JaRuleFactory.cpp \ plugins/usbdmx/JaRuleFactory.h \ plugins/usbdmx/ScanlimeFadecandy.cpp \ plugins/usbdmx/ScanlimeFadecandy.h \ plugins/usbdmx/ScanlimeFadecandyFactory.cpp \ plugins/usbdmx/ScanlimeFadecandyFactory.h \ plugins/usbdmx/Sunlite.cpp \ plugins/usbdmx/Sunlite.h \ plugins/usbdmx/SunliteFactory.cpp \ plugins/usbdmx/SunliteFactory.h \ plugins/usbdmx/SunliteFirmware.h \ plugins/usbdmx/SunliteFirmwareLoader.cpp \ plugins/usbdmx/SunliteFirmwareLoader.h \ plugins/usbdmx/SyncronizedWidgetObserver.cpp \ plugins/usbdmx/SyncronizedWidgetObserver.h \ plugins/usbdmx/ThreadedUsbReceiver.cpp \ plugins/usbdmx/ThreadedUsbReceiver.h \ plugins/usbdmx/ThreadedUsbSender.cpp \ plugins/usbdmx/ThreadedUsbSender.h \ plugins/usbdmx/VellemanK8062.cpp \ plugins/usbdmx/VellemanK8062.h \ plugins/usbdmx/VellemanK8062Factory.cpp \ plugins/usbdmx/VellemanK8062Factory.h \ plugins/usbdmx/Widget.h \ plugins/usbdmx/WidgetFactory.h plugins_usbdmx_libolausbdmxwidget_la_CXXFLAGS = \ $(COMMON_CXXFLAGS) \ $(libusb_CFLAGS) plugins_usbdmx_libolausbdmxwidget_la_LIBADD = \ $(libusb_LIBS) \ common/libolacommon.la \ libs/usb/libolausb.la lib_LTLIBRARIES += plugins/usbdmx/libolausbdmx.la plugins_usbdmx_libolausbdmx_la_SOURCES = \ plugins/usbdmx/AsyncPluginImpl.cpp \ plugins/usbdmx/AsyncPluginImpl.h \ plugins/usbdmx/DMXCProjectsNodleU1Device.cpp \ plugins/usbdmx/DMXCProjectsNodleU1Device.h \ plugins/usbdmx/DMXCProjectsNodleU1Port.cpp \ plugins/usbdmx/DMXCProjectsNodleU1Port.h \ plugins/usbdmx/GenericDevice.cpp \ plugins/usbdmx/GenericDevice.h \ plugins/usbdmx/GenericOutputPort.cpp \ plugins/usbdmx/GenericOutputPort.h \ plugins/usbdmx/JaRuleDevice.cpp \ plugins/usbdmx/JaRuleDevice.h \ plugins/usbdmx/JaRuleOutputPort.cpp \ plugins/usbdmx/JaRuleOutputPort.h \ plugins/usbdmx/PluginImplInterface.h \ plugins/usbdmx/SyncPluginImpl.cpp \ plugins/usbdmx/SyncPluginImpl.h \ plugins/usbdmx/UsbDmxPlugin.cpp \ plugins/usbdmx/UsbDmxPlugin.h plugins_usbdmx_libolausbdmx_la_CXXFLAGS = $(COMMON_CXXFLAGS) $(libusb_CFLAGS) plugins_usbdmx_libolausbdmx_la_LIBADD = \ olad/plugin_api/libolaserverplugininterface.la \ plugins/usbdmx/libolausbdmxwidget.la endif EXTRA_DIST += plugins/usbdmx/README.md ola-0.10.5.nojsmin/plugins/usbdmx/Sunlite.cpp0000644000175000017500000001451613023355232020577 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Sunlite.cpp * The synchronous and asynchronous Sunlite widgets. * Copyright (C) 2014 Simon Newton */ #include "plugins/usbdmx/Sunlite.h" #include #include "libs/usb/LibUsbAdaptor.h" #include "ola/Constants.h" #include "ola/Logging.h" #include "plugins/usbdmx/AsyncUsbSender.h" #include "plugins/usbdmx/ThreadedUsbSender.h" namespace ola { namespace plugin { namespace usbdmx { using ola::usb::LibUsbAdaptor; namespace { static const unsigned int CHUNKS_PER_PACKET = 26; static const unsigned int CHANNELS_PER_CHUNK = 20; static const unsigned int CHUNK_SIZE = 32; static const uint8_t ENDPOINT = 1; static const unsigned int TIMEOUT = 50; // 50ms is ok enum {SUNLITE_PACKET_SIZE = 0x340}; /* * Initialize a USBDMX2 packet */ void InitPacket(uint8_t packet[SUNLITE_PACKET_SIZE]) { memset(packet, 0, SUNLITE_PACKET_SIZE); // The packet is divided into 26 chunks of 32 bytes each. Each chunk contains // the data for 20 channels (except the last one which has 12 channels of // data). for (unsigned int chunk = 0; chunk < CHUNKS_PER_PACKET; ++chunk) { unsigned int i = chunk * CHUNK_SIZE; // index into the packet unsigned int channel = chunk * CHANNELS_PER_CHUNK; packet[i] = 0x80; packet[i + 1] = channel / 2; packet[i + 2] = 0x84; packet[i + 7] = channel / 2 + 2; packet[i + 8] = 0x84; packet[i + 13] = channel / 2 + 4; if (chunk < CHUNKS_PER_PACKET - 1) { packet[i + 14] = 0x84; packet[i + 19] = channel / 2 + 6; packet[i + 20] = 0x84; packet[i + 25] = channel / 2 + 8; packet[i + 26] = 0x04; packet[i + 31] = 0x00; } else { // the last chunk is short packet[i + 14] = 0x04; } } } /* * Update a USBDMX2 packet to match the supplied DmxBuffer. */ void UpdatePacket(const DmxBuffer &buffer, uint8_t packet[SUNLITE_PACKET_SIZE]) { for (unsigned int i = 0; i < buffer.Size(); i++) { int index = ((i / CHANNELS_PER_CHUNK) * CHUNK_SIZE) + (((i / 4) % 5) * 6) + 3 + (i % 4); packet[index] = buffer.Get(i); } } } // namespace // SunliteThreadedSender // ----------------------------------------------------------------------------- /* * Sends messages to a Sunlite device in a separate thread. */ class SunliteThreadedSender: public ThreadedUsbSender { public: SunliteThreadedSender(LibUsbAdaptor *adaptor, libusb_device *usb_device, libusb_device_handle *handle); private: LibUsbAdaptor* const m_adaptor; uint8_t m_packet[SUNLITE_PACKET_SIZE]; bool TransmitBuffer(libusb_device_handle *handle, const DmxBuffer &buffer); }; SunliteThreadedSender::SunliteThreadedSender( LibUsbAdaptor *adaptor, libusb_device *usb_device, libusb_device_handle *usb_handle) : ThreadedUsbSender(usb_device, usb_handle), m_adaptor(adaptor) { InitPacket(m_packet); } bool SunliteThreadedSender::TransmitBuffer(libusb_device_handle *handle, const DmxBuffer &buffer) { UpdatePacket(buffer, m_packet); int transferred; int r = m_adaptor->BulkTransfer(handle, ENDPOINT, (unsigned char*) m_packet, SUNLITE_PACKET_SIZE, &transferred, TIMEOUT); if (transferred != SUNLITE_PACKET_SIZE) { // not sure if this is fatal or not OLA_WARN << "Sunlite driver failed to transfer all data"; } return r == 0; } // SynchronousSunlite // ----------------------------------------------------------------------------- SynchronousSunlite::SynchronousSunlite(LibUsbAdaptor *adaptor, libusb_device *usb_device) : Sunlite(adaptor, usb_device) { } bool SynchronousSunlite::Init() { libusb_device_handle *usb_handle; bool ok = m_adaptor->OpenDeviceAndClaimInterface( m_usb_device, 0, &usb_handle); if (!ok) { return false; } std::auto_ptr sender( new SunliteThreadedSender(m_adaptor, m_usb_device, usb_handle)); if (!sender->Start()) { return false; } m_sender.reset(sender.release()); return true; } bool SynchronousSunlite::SendDMX(const DmxBuffer &buffer) { return m_sender.get() ? m_sender->SendDMX(buffer) : false; } // SunliteAsyncUsbSender // ----------------------------------------------------------------------------- class SunliteAsyncUsbSender : public AsyncUsbSender { public: SunliteAsyncUsbSender(LibUsbAdaptor *adaptor, libusb_device *usb_device) : AsyncUsbSender(adaptor, usb_device) { InitPacket(m_packet); } ~SunliteAsyncUsbSender() { CancelTransfer(); } libusb_device_handle* SetupHandle() { libusb_device_handle *usb_handle; bool ok = m_adaptor->OpenDeviceAndClaimInterface( m_usb_device, 0, &usb_handle); return ok ? usb_handle : NULL; } bool PerformTransfer(const DmxBuffer &buffer) { UpdatePacket(buffer, m_packet); FillBulkTransfer(ENDPOINT, m_packet, SUNLITE_PACKET_SIZE, TIMEOUT); return (SubmitTransfer() == 0); } private: uint8_t m_packet[SUNLITE_PACKET_SIZE]; DISALLOW_COPY_AND_ASSIGN(SunliteAsyncUsbSender); }; // AsynchronousSunlite // ----------------------------------------------------------------------------- AsynchronousSunlite::AsynchronousSunlite( LibUsbAdaptor *adaptor, libusb_device *usb_device) : Sunlite(adaptor, usb_device) { m_sender.reset(new SunliteAsyncUsbSender(m_adaptor, usb_device)); } bool AsynchronousSunlite::Init() { return m_sender->Init(); } bool AsynchronousSunlite::SendDMX(const DmxBuffer &buffer) { return m_sender->SendDMX(buffer); } } // namespace usbdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbdmx/ScanlimeFadecandyFactory.cpp0000644000175000017500000000612013023355232024026 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ScanlimeFadecandyFactory.cpp * The WidgetFactory for Fadecandy widgets. * Copyright (C) 2014 Simon Newton */ #include "plugins/usbdmx/ScanlimeFadecandyFactory.h" #include "libs/usb/LibUsbAdaptor.h" #include "ola/Logging.h" #include "ola/base/Flags.h" #include "plugins/usbdmx/ScanlimeFadecandy.h" DECLARE_bool(use_async_libusb); namespace ola { namespace plugin { namespace usbdmx { using ola::usb::LibUsbAdaptor; const char ScanlimeFadecandyFactory::EXPECTED_MANUFACTURER[] = "scanlime"; const char ScanlimeFadecandyFactory::EXPECTED_PRODUCT[] = "Fadecandy"; const uint16_t ScanlimeFadecandyFactory::VENDOR_ID = 0x1D50; const uint16_t ScanlimeFadecandyFactory::PRODUCT_ID = 0x607A; bool ScanlimeFadecandyFactory::DeviceAdded( WidgetObserver *observer, libusb_device *usb_device, const struct libusb_device_descriptor &descriptor) { if (descriptor.idVendor != VENDOR_ID || descriptor.idProduct != PRODUCT_ID) { return false; } OLA_INFO << "Found a new Fadecandy device"; LibUsbAdaptor::DeviceInformation info; if (!m_adaptor->GetDeviceInfo(usb_device, descriptor, &info)) { return false; } if (!m_adaptor->CheckManufacturer(EXPECTED_MANUFACTURER, info)) { return false; } if (!m_adaptor->CheckProduct(EXPECTED_PRODUCT, info)) { return false; } // Fadecandy devices may be missing serial numbers. Since there isn't another // good way to uniquely identify a USB device, we only support one of these // types of devices per host. if (info.serial.empty()) { if (m_missing_serial_number) { OLA_WARN << "Failed to read serial number or serial number empty. " << "We can only support one device without a serial number."; return false; } else { OLA_WARN << "Failed to read serial number from " << info.manufacturer << " : " << info.product << " the device probably doesn't have one"; m_missing_serial_number = true; } } ScanlimeFadecandy *widget = NULL; if (FLAGS_use_async_libusb) { widget = new AsynchronousScanlimeFadecandy(m_adaptor, usb_device, info.serial); } else { widget = new SynchronousScanlimeFadecandy(m_adaptor, usb_device, info.serial); } return AddWidget(observer, widget); } } // namespace usbdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbdmx/ScanlimeFadecandy.h0000644000175000017500000000745713023355232022161 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ScanlimeFadecandy.h * The synchronous and asynchronous Fadecandy widgets. * Copyright (C) 2014 Simon Newton */ #ifndef PLUGINS_USBDMX_SCANLIMEFADECANDY_H_ #define PLUGINS_USBDMX_SCANLIMEFADECANDY_H_ #include #include #include #include "libs/usb/LibUsbAdaptor.h" #include "ola/DmxBuffer.h" #include "ola/base/Macro.h" #include "ola/thread/Mutex.h" #include "plugins/usbdmx/Widget.h" namespace ola { namespace plugin { namespace usbdmx { /** * @brief The interface for the Fadecandy Widgets. * * Fadecandy devices have 8 physical ports. Each port can drive 64 RGB pixels. * Ideally this means we'd model each Fadecandy port as an OLA port, but that * introduces syncronization issues, since the underlying protocol models all 8 * ports as a flat pixel array. For now we just expose the first 170 pixels. * * See https://github.com/scanlime/fadecandy/blob/master/README.md for more * information on Fadecandy devices. */ class ScanlimeFadecandy: public SimpleWidget { public: ScanlimeFadecandy(ola::usb::LibUsbAdaptor *adaptor, libusb_device *usb_device, const std::string &serial) : SimpleWidget(adaptor, usb_device), m_serial(serial) { } /** * @brief Get the serial number of this widget. * @returns The serial number of the widget. */ std::string SerialNumber() const { return m_serial; } private: std::string m_serial; }; /** * @brief An Fadecandy widget that uses synchronous libusb operations. * * Internally this spawns a new thread to avoid blocking SendDMX() calls. */ class SynchronousScanlimeFadecandy: public ScanlimeFadecandy { public: /** * @brief Create a new SynchronousScanlimeFadecandy. * @param adaptor the LibUsbAdaptor to use. * @param usb_device the libusb_device to use for the widget. * @param serial the serial number of the widget. */ SynchronousScanlimeFadecandy(ola::usb::LibUsbAdaptor *adaptor, libusb_device *usb_device, const std::string &serial); bool Init(); bool SendDMX(const DmxBuffer &buffer); private: std::auto_ptr m_sender; DISALLOW_COPY_AND_ASSIGN(SynchronousScanlimeFadecandy); }; /** * @brief An Fadecandy widget that uses asynchronous libusb operations. */ class AsynchronousScanlimeFadecandy : public ScanlimeFadecandy { public: /** * @brief Create a new AsynchronousScanlimeFadecandy. * @param adaptor the LibUsbAdaptor to use. * @param usb_device the libusb_device to use for the widget. * @param serial the serial number of the widget. */ AsynchronousScanlimeFadecandy(ola::usb::LibUsbAdaptor *adaptor, libusb_device *usb_device, const std::string &serial); bool Init(); bool SendDMX(const DmxBuffer &buffer); private: std::auto_ptr m_sender; DISALLOW_COPY_AND_ASSIGN(AsynchronousScanlimeFadecandy); }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_SCANLIMEFADECANDY_H_ ola-0.10.5.nojsmin/plugins/usbdmx/AnymauDMX.h0000644000175000017500000000664213023355232020425 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * AnymauDMX.h * The synchronous and asynchronous Anyma uDMX widgets. * Copyright (C) 2014 Simon Newton */ #ifndef PLUGINS_USBDMX_ANYMAUDMX_H_ #define PLUGINS_USBDMX_ANYMAUDMX_H_ #include #include #include #include "libs/usb/LibUsbAdaptor.h" #include "ola/DmxBuffer.h" #include "ola/base/Macro.h" #include "ola/thread/Mutex.h" #include "plugins/usbdmx/Widget.h" namespace ola { namespace plugin { namespace usbdmx { /** * @brief The base class for Anyma Widgets. */ class AnymauDMX: public SimpleWidget { public: /** * @brief Create a new AnymauDMX. * @param adaptor the LibUsbAdaptor to use. * @param usb_device the libusb_device to use for the widget. * @param serial the serial number of the widget. */ AnymauDMX(ola::usb::LibUsbAdaptor *adaptor, libusb_device *usb_device, const std::string &serial) : SimpleWidget(adaptor, usb_device), m_serial(serial) {} virtual ~AnymauDMX() {} /** * @brief Get the serial number of this widget. * @returns The serial number of the widget. */ std::string SerialNumber() const { return m_serial; } private: std::string m_serial; }; /** * @brief An Anyma widget that uses synchronous libusb operations. * * Internally this spawns a new thread to avoid blocking SendDMX() calls. */ class SynchronousAnymauDMX: public AnymauDMX { public: /** * @brief Create a new SynchronousAnymauDMX. * @param adaptor the LibUsbAdaptor to use. * @param usb_device the libusb_device to use for the widget. * @param serial the serial number of the widget. */ SynchronousAnymauDMX(ola::usb::LibUsbAdaptor *adaptor, libusb_device *usb_device, const std::string &serial); bool Init(); bool SendDMX(const DmxBuffer &buffer); private: std::auto_ptr m_sender; DISALLOW_COPY_AND_ASSIGN(SynchronousAnymauDMX); }; /** * @brief An Anyma widget that uses asynchronous libusb operations. */ class AsynchronousAnymauDMX : public AnymauDMX { public: /** * @brief Create a new AsynchronousAnymauDMX. * @param adaptor the LibUsbAdaptor to use. * @param usb_device the libusb_device to use for the widget. * @param serial the serial number of the widget. */ AsynchronousAnymauDMX(ola::usb::LibUsbAdaptor *adaptor, libusb_device *usb_device, const std::string &serial); bool Init(); bool SendDMX(const DmxBuffer &buffer); private: std::auto_ptr m_sender; DISALLOW_COPY_AND_ASSIGN(AsynchronousAnymauDMX); }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_ANYMAUDMX_H_ ola-0.10.5.nojsmin/plugins/usbdmx/JaRuleFactory.cpp0000644000175000017500000000347713023355232021672 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * JaRuleFactory.cpp * The factory for Ja Rule widgets. * Copyright (C) 2015 Simon Newton */ #include "plugins/usbdmx/JaRuleFactory.h" #include #include "libs/usb/JaRuleWidget.h" #include "ola/Logging.h" #include "ola/base/Flags.h" DECLARE_bool(use_async_libusb); namespace ola { namespace plugin { namespace usbdmx { // http://pid.codes/1209/ACED/ const uint16_t JaRuleFactory::PRODUCT_ID = 0xaced; const uint16_t JaRuleFactory::VENDOR_ID = 0x1209; bool JaRuleFactory::DeviceAdded( WidgetObserver *observer, libusb_device *usb_device, const struct libusb_device_descriptor &descriptor) { if (descriptor.idVendor != VENDOR_ID || descriptor.idProduct != PRODUCT_ID) { return false; } if (!FLAGS_use_async_libusb) { OLA_WARN << "Ja Rule devices are not supported in Synchronous mode"; return false; } OLA_INFO << "Found a new Ja Rule device"; std::auto_ptr widget( new ola::usb::JaRuleWidget(m_ss, m_adaptor, usb_device)); return AddWidget(observer, widget.release()); } } // namespace usbdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbdmx/AsyncUsbTransceiverBase.cpp0000644000175000017500000001002313023355232023671 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * AsyncUsbTransceiverBase.cpp * An Asynchronous DMX USB transceiver. * Copyright (C) 2014 Simon Newton */ #include "plugins/usbdmx/AsyncUsbTransceiverBase.h" #include "libs/usb/LibUsbAdaptor.h" #include "ola/Logging.h" namespace ola { namespace plugin { namespace usbdmx { using ola::usb::LibUsbAdaptor; namespace { /* * Called by libusb when the transfer completes. */ #ifdef _WIN32 __attribute__((__stdcall__)) #endif // _WIN32 void AsyncCallback(struct libusb_transfer *transfer) { AsyncUsbTransceiverBase *widget = reinterpret_cast( transfer->user_data); widget->TransferComplete(transfer); } } // namespace AsyncUsbTransceiverBase::AsyncUsbTransceiverBase(LibUsbAdaptor *adaptor, libusb_device *usb_device) : m_adaptor(adaptor), m_usb_device(usb_device), m_usb_handle(NULL), m_suppress_continuation(false), m_transfer_state(IDLE) { m_transfer = m_adaptor->AllocTransfer(0); m_adaptor->RefDevice(usb_device); } AsyncUsbTransceiverBase::~AsyncUsbTransceiverBase() { CancelTransfer(); m_adaptor->UnrefDevice(m_usb_device); m_adaptor->FreeTransfer(m_transfer); } bool AsyncUsbTransceiverBase::Init() { m_usb_handle = SetupHandle(); return m_usb_handle != NULL; } void AsyncUsbTransceiverBase::CancelTransfer() { if (!m_transfer) { return; } bool canceled = false; while (1) { ola::thread::MutexLocker locker(&m_mutex); if (m_transfer_state == IDLE || m_transfer_state == DISCONNECTED) { break; } if (!canceled) { m_suppress_continuation = true; if (m_adaptor->CancelTransfer(m_transfer) == 0) { canceled = true; } else { break; } } } m_suppress_continuation = false; } void AsyncUsbTransceiverBase::FillControlTransfer(unsigned char *buffer, unsigned int timeout) { m_adaptor->FillControlTransfer(m_transfer, m_usb_handle, buffer, &AsyncCallback, this, timeout); } void AsyncUsbTransceiverBase::FillBulkTransfer(unsigned char endpoint, unsigned char *buffer, int length, unsigned int timeout) { m_adaptor->FillBulkTransfer(m_transfer, m_usb_handle, endpoint, buffer, length, &AsyncCallback, this, timeout); } void AsyncUsbTransceiverBase::FillInterruptTransfer(unsigned char endpoint, unsigned char *buffer, int length, unsigned int timeout) { m_adaptor->FillInterruptTransfer(m_transfer, m_usb_handle, endpoint, buffer, length, &AsyncCallback, this, timeout); } int AsyncUsbTransceiverBase::SubmitTransfer() { int ret = m_adaptor->SubmitTransfer(m_transfer); if (ret) { OLA_WARN << "libusb_submit_transfer returned " << m_adaptor->ErrorCodeToString(ret); if (ret == LIBUSB_ERROR_NO_DEVICE) { m_transfer_state = DISCONNECTED; } return false; } m_transfer_state = IN_PROGRESS; return ret; } } // namespace usbdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbdmx/EuroliteProFactory.cpp0000644000175000017500000000544413023355232022755 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * EuroliteProFactory.cpp * The WidgetFactory for EurolitePro widgets. * Copyright (C) 2014 Simon Newton */ #include "plugins/usbdmx/EuroliteProFactory.h" #include "libs/usb/LibUsbAdaptor.h" #include "ola/Logging.h" #include "ola/base/Flags.h" DECLARE_bool(use_async_libusb); namespace ola { namespace plugin { namespace usbdmx { using ola::usb::LibUsbAdaptor; const char EuroliteProFactory::EXPECTED_MANUFACTURER[] = "Eurolite"; const char EuroliteProFactory::EXPECTED_PRODUCT[] = "Eurolite DMX512 Pro"; const uint16_t EuroliteProFactory::PRODUCT_ID = 0xfa63; const uint16_t EuroliteProFactory::VENDOR_ID = 0x04d8; bool EuroliteProFactory::DeviceAdded( WidgetObserver *observer, libusb_device *usb_device, const struct libusb_device_descriptor &descriptor) { if (descriptor.idVendor != VENDOR_ID || descriptor.idProduct != PRODUCT_ID) { return false; } OLA_INFO << "Found a new EurolitePro device"; LibUsbAdaptor::DeviceInformation info; if (!m_adaptor->GetDeviceInfo(usb_device, descriptor, &info)) { return false; } if (!m_adaptor->CheckManufacturer(EXPECTED_MANUFACTURER, info)) { return false; } if (!m_adaptor->CheckProduct(EXPECTED_PRODUCT, info)) { return false; } // The Eurolite doesn't have a serial number, so instead we use the device & // bus number. // TODO(simon): check if this supports the SERIAL NUMBER label and use that // instead. // There is no Serialnumber--> work around: bus+device number int bus_number = libusb_get_bus_number(usb_device); int device_address = libusb_get_device_address(usb_device); std::ostringstream serial_str; serial_str << bus_number << "-" << device_address; EurolitePro *widget = NULL; if (FLAGS_use_async_libusb) { widget = new AsynchronousEurolitePro(m_adaptor, usb_device, serial_str.str()); } else { widget = new SynchronousEurolitePro(m_adaptor, usb_device, serial_str.str()); } return AddWidget(observer, widget); } } // namespace usbdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbdmx/AnymauDMX.cpp0000644000175000017500000001250513023355232020753 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * AnymauDMX.cpp * The synchronous and asynchronous Anyma uDMX widgets. * Copyright (C) 2014 Simon Newton */ #include "plugins/usbdmx/AnymauDMX.h" #include #include #include "libs/usb/LibUsbAdaptor.h" #include "ola/Logging.h" #include "ola/Constants.h" #include "plugins/usbdmx/AsyncUsbSender.h" #include "plugins/usbdmx/ThreadedUsbSender.h" namespace ola { namespace plugin { namespace usbdmx { using std::string; using ola::usb::LibUsbAdaptor; namespace { static const unsigned int URB_TIMEOUT_MS = 500; static const unsigned int UDMX_SET_CHANNEL_RANGE = 0x0002; } // namespace // AnymaThreadedSender // ----------------------------------------------------------------------------- /* * Sends messages to a Anyma device in a separate thread. */ class AnymaThreadedSender: public ThreadedUsbSender { public: AnymaThreadedSender(LibUsbAdaptor *adaptor, libusb_device *usb_device, libusb_device_handle *handle) : ThreadedUsbSender(usb_device, handle), m_adaptor(adaptor) { } private: LibUsbAdaptor* const m_adaptor; bool TransmitBuffer(libusb_device_handle *handle, const DmxBuffer &buffer); }; bool AnymaThreadedSender::TransmitBuffer(libusb_device_handle *handle, const DmxBuffer &buffer) { int r = m_adaptor->ControlTransfer( handle, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT, // bmRequestType UDMX_SET_CHANNEL_RANGE, // bRequest buffer.Size(), // wValue 0, // wIndex const_cast(buffer.GetRaw()), // data buffer.Size(), // wLength URB_TIMEOUT_MS); // timeout // Sometimes we get PIPE errors here, those are non-fatal return r > 0 || r == LIBUSB_ERROR_PIPE; } // SynchronousAnymauDMX // ----------------------------------------------------------------------------- SynchronousAnymauDMX::SynchronousAnymauDMX(LibUsbAdaptor *adaptor, libusb_device *usb_device, const string &serial) : AnymauDMX(adaptor, usb_device, serial) { } bool SynchronousAnymauDMX::Init() { libusb_device_handle *usb_handle; bool ok = m_adaptor->OpenDeviceAndClaimInterface( m_usb_device, 0, &usb_handle); if (!ok) { return false; } std::auto_ptr sender( new AnymaThreadedSender(m_adaptor, m_usb_device, usb_handle)); if (!sender->Start()) { return false; } m_sender.reset(sender.release()); return true; } bool SynchronousAnymauDMX::SendDMX(const DmxBuffer &buffer) { return m_sender.get() ? m_sender->SendDMX(buffer) : false; } // AnymaAsyncUsbSender // ----------------------------------------------------------------------------- class AnymaAsyncUsbSender : public AsyncUsbSender { public: AnymaAsyncUsbSender(LibUsbAdaptor *adaptor, libusb_device *usb_device) : AsyncUsbSender(adaptor, usb_device) { m_control_setup_buffer = new uint8_t[LIBUSB_CONTROL_SETUP_SIZE + DMX_UNIVERSE_SIZE]; } ~AnymaAsyncUsbSender() { CancelTransfer(); delete[] m_control_setup_buffer; } libusb_device_handle* SetupHandle() { libusb_device_handle *usb_handle; bool ok = m_adaptor->OpenDeviceAndClaimInterface( m_usb_device, 0, &usb_handle); return ok ? usb_handle : NULL; } bool PerformTransfer(const DmxBuffer &buffer) { m_adaptor->FillControlSetup( m_control_setup_buffer, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT, // bmRequestType UDMX_SET_CHANNEL_RANGE, // bRequest buffer.Size(), // wValue 0, // wIndex buffer.Size()); // wLength unsigned int length = DMX_UNIVERSE_SIZE; buffer.Get(m_control_setup_buffer + LIBUSB_CONTROL_SETUP_SIZE, &length); FillControlTransfer(m_control_setup_buffer, URB_TIMEOUT_MS); return (SubmitTransfer() == 0); } private: uint8_t *m_control_setup_buffer; DISALLOW_COPY_AND_ASSIGN(AnymaAsyncUsbSender); }; // AsynchronousAnymauDMX // ----------------------------------------------------------------------------- AsynchronousAnymauDMX::AsynchronousAnymauDMX( LibUsbAdaptor *adaptor, libusb_device *usb_device, const string &serial) : AnymauDMX(adaptor, usb_device, serial) { m_sender.reset(new AnymaAsyncUsbSender(m_adaptor, usb_device)); } bool AsynchronousAnymauDMX::Init() { return m_sender->Init(); } bool AsynchronousAnymauDMX::SendDMX(const DmxBuffer &buffer) { return m_sender->SendDMX(buffer); } } // namespace usbdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbdmx/JaRuleOutputPort.cpp0000644000175000017500000000613113023355232022416 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * JaRuleOutputPort.cpp * A JaRule output port that uses a widget. * Copyright (C) 2015 Simon Newton */ #include "plugins/usbdmx/JaRuleOutputPort.h" #include #include "libs/usb/JaRulePortHandle.h" #include "ola/Logging.h" #include "ola/strings/Format.h" #include "olad/Device.h" namespace ola { namespace plugin { namespace usbdmx { using ola::usb::JaRulePortHandle; using ola::usb::JaRuleWidget; JaRuleOutputPort::JaRuleOutputPort(Device *parent, unsigned int index, JaRuleWidget *widget) : BasicOutputPort(parent, index, true, true), m_port_index(index), m_widget(widget), m_port_handle(NULL) { } JaRuleOutputPort::~JaRuleOutputPort() { // The shutdown process is a bit tricky, since there may be callbacks pending // in the JaRulePortHandle. Releasing the port handle will run any pending // callbacks. m_widget->ReleasePort(m_port_index); } bool JaRuleOutputPort::Init() { m_port_handle = m_widget->ClaimPort(m_port_index); return m_port_handle != NULL; } std::string JaRuleOutputPort::Description() const { return "Port " + ola::strings::IntToString(PortId() + 1); } bool JaRuleOutputPort::WriteDMX(const DmxBuffer &buffer, OLA_UNUSED uint8_t priority) { m_port_handle->SendDMX(buffer); return true; } void JaRuleOutputPort::SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *callback) { m_port_handle->SendRDMRequest(request, callback); } void JaRuleOutputPort::RunFullDiscovery( ola::rdm::RDMDiscoveryCallback *callback) { m_port_handle->RunFullDiscovery(callback); } void JaRuleOutputPort::RunIncrementalDiscovery( ola::rdm::RDMDiscoveryCallback *callback) { m_port_handle->RunIncrementalDiscovery(callback); } bool JaRuleOutputPort::PreSetUniverse(Universe *old_universe, Universe *new_universe) { if (old_universe == NULL && new_universe != NULL) { m_port_handle->SetPortMode(ola::usb::CONTROLLER_MODE); } return true; } void JaRuleOutputPort::PostSetUniverse(Universe *old_universe, Universe *new_universe) { if (old_universe != NULL && new_universe == NULL) { m_port_handle->SetPortMode(ola::usb::RESPONDER_MODE); } } } // namespace usbdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbdmx/SyncPluginImpl.cpp0000644000175000017500000001644113023355232022070 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SyncPluginImpl.cpp * The synchronous implementation of the USB DMX plugin. * Copyright (C) 2006 Simon Newton */ #include "plugins/usbdmx/SyncPluginImpl.h" #include #include #include #include #include #include #include "ola/Callback.h" #include "ola/Logging.h" #include "ola/stl/STLUtils.h" #include "ola/strings/Format.h" #include "olad/PluginAdaptor.h" #include "plugins/usbdmx/AnymauDMX.h" #include "plugins/usbdmx/AnymauDMXFactory.h" #include "plugins/usbdmx/DMXCProjectsNodleU1.h" #include "plugins/usbdmx/DMXCProjectsNodleU1Device.h" #include "plugins/usbdmx/DMXCProjectsNodleU1Factory.h" #include "plugins/usbdmx/EurolitePro.h" #include "plugins/usbdmx/EuroliteProFactory.h" #include "plugins/usbdmx/ScanlimeFadecandy.h" #include "plugins/usbdmx/ScanlimeFadecandyFactory.h" #include "plugins/usbdmx/GenericDevice.h" #include "plugins/usbdmx/Sunlite.h" #include "plugins/usbdmx/SunliteFactory.h" #include "plugins/usbdmx/VellemanK8062.h" #include "plugins/usbdmx/VellemanK8062Factory.h" namespace ola { namespace plugin { namespace usbdmx { using std::pair; using std::string; using std::vector; SyncPluginImpl::SyncPluginImpl(PluginAdaptor *plugin_adaptor, Plugin *plugin, unsigned int debug_level, Preferences *preferences) : m_plugin_adaptor(plugin_adaptor), m_plugin(plugin), m_debug_level(debug_level), m_preferences(preferences), m_context(NULL) { m_widget_factories.push_back(new AnymauDMXFactory(&m_usb_adaptor)); m_widget_factories.push_back(new DMXCProjectsNodleU1Factory(&m_usb_adaptor, m_plugin_adaptor, m_preferences)); m_widget_factories.push_back(new EuroliteProFactory(&m_usb_adaptor)); m_widget_factories.push_back(new ScanlimeFadecandyFactory(&m_usb_adaptor)); m_widget_factories.push_back(new SunliteFactory(&m_usb_adaptor)); m_widget_factories.push_back(new VellemanK8062Factory(&m_usb_adaptor)); } SyncPluginImpl::~SyncPluginImpl() { STLDeleteElements(&m_widget_factories); } bool SyncPluginImpl::Start() { if (libusb_init(&m_context)) { OLA_WARN << "Failed to init libusb"; return false; } OLA_DEBUG << "libusb debug level set to " << m_debug_level; libusb_set_debug(m_context, m_debug_level); unsigned int devices_claimed = ScanForDevices(); if (devices_claimed != m_devices.size()) { // This indicates there is firmware loading going on, schedule a callback // to check for 'new' devices once the firmware has loaded. m_plugin_adaptor->RegisterSingleTimeout( 3500, NewSingleCallback(this, &SyncPluginImpl::ReScanForDevices)); } return true; } bool SyncPluginImpl::Stop() { WidgetToDeviceMap::iterator iter; for (iter = m_devices.begin(); iter != m_devices.end(); ++iter) { m_plugin_adaptor->UnregisterDevice(iter->second); iter->second->Stop(); delete iter->second; delete iter->first; } m_devices.clear(); m_registered_devices.clear(); libusb_exit(m_context); return true; } bool SyncPluginImpl::NewWidget(AnymauDMX *widget) { return StartAndRegisterDevice( widget, new GenericDevice(m_plugin, widget, "Anyma USB Device", "anyma-" + widget->SerialNumber())); } bool SyncPluginImpl::NewWidget(DMXCProjectsNodleU1 *widget) { return StartAndRegisterDevice( widget, new DMXCProjectsNodleU1Device( m_plugin, widget, "DMXControl Projects e.V. Nodle U1 (" + widget->SerialNumber() + ")", "nodleu1-" + widget->SerialNumber(), m_plugin_adaptor)); } bool SyncPluginImpl::NewWidget(EurolitePro *widget) { return StartAndRegisterDevice( widget, new GenericDevice(m_plugin, widget, "EurolitePro USB Device", "eurolite-" + widget->SerialNumber())); } bool SyncPluginImpl::NewWidget(OLA_UNUSED ola::usb::JaRuleWidget *widget) { // This should never happen since there is no Syncronous support for Ja Rule. OLA_WARN << "::NewWidget called for a JaRuleWidget"; return false; } bool SyncPluginImpl::NewWidget(ScanlimeFadecandy *widget) { return StartAndRegisterDevice( widget, new GenericDevice( m_plugin, widget, "Fadecandy USB Device (" + widget->SerialNumber() + ")", "fadecandy-" + widget->SerialNumber())); } bool SyncPluginImpl::NewWidget(Sunlite *widget) { return StartAndRegisterDevice( widget, new GenericDevice(m_plugin, widget, "Sunlite USBDMX2 Device", "usbdmx2")); } bool SyncPluginImpl::NewWidget(VellemanK8062 *widget) { return StartAndRegisterDevice( widget, new GenericDevice(m_plugin, widget, "Velleman USB Device", "velleman")); } /* * @brief Look for USB devices. */ unsigned int SyncPluginImpl::ScanForDevices() { libusb_device **device_list; size_t device_count = libusb_get_device_list(m_context, &device_list); unsigned int claimed_device_count = 0; for (unsigned int i = 0; i < device_count; i++) { if (CheckDevice(device_list[i])) { claimed_device_count++; } } libusb_free_device_list(device_list, 1); // unref devices return claimed_device_count; } bool SyncPluginImpl::CheckDevice(libusb_device *usb_device) { struct libusb_device_descriptor device_descriptor; libusb_get_device_descriptor(usb_device, &device_descriptor); OLA_DEBUG << "USB device found, checking for widget support, vendor " << strings::ToHex(device_descriptor.idVendor) << ", product " << strings::ToHex(device_descriptor.idProduct); pair bus_dev_id(libusb_get_bus_number(usb_device), libusb_get_device_address(usb_device)); if (STLContains(m_registered_devices, bus_dev_id)) { return false; } WidgetFactories::iterator iter = m_widget_factories.begin(); for (; iter != m_widget_factories.end(); ++iter) { if ((*iter)->DeviceAdded(this, usb_device, device_descriptor)) { m_registered_devices.insert(bus_dev_id); return true; } } return false; } void SyncPluginImpl::ReScanForDevices() { ScanForDevices(); } /* * @brief Signal widget / device addition. * @param widget The widget that was added. * @param device The new olad device that uses this new widget. */ bool SyncPluginImpl::StartAndRegisterDevice(WidgetInterface *widget, Device *device) { if (!device->Start()) { delete device; return false; } STLReplace(&m_devices, widget, device); m_plugin_adaptor->RegisterDevice(device); return true; } } // namespace usbdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbdmx/JaRuleFactory.h0000644000175000017500000000401313023355232021322 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * JaRuleFactory.h * The factory for Ja Rule widgets. * Copyright (C) 2015 Simon Newton */ #ifndef PLUGINS_USBDMX_JARULEFACTORY_H_ #define PLUGINS_USBDMX_JARULEFACTORY_H_ #include "libs/usb/LibUsbAdaptor.h" #include "ola/base/Macro.h" #include "ola/io/SelectServerInterface.h" #include "ola/rdm/UID.h" #include "plugins/usbdmx/WidgetFactory.h" namespace ola { namespace usb { class JaRuleWidget; } // namespace usb namespace plugin { namespace usbdmx { /** * @brief Creates Ja Rule widgets. */ class JaRuleFactory : public BaseWidgetFactory { public: explicit JaRuleFactory(ola::io::SelectServerInterface *ss, ola::usb::AsyncronousLibUsbAdaptor *adaptor) : BaseWidgetFactory("JaRuleFactory"), m_ss(ss), m_adaptor(adaptor) { } bool DeviceAdded(WidgetObserver *observer, libusb_device *usb_device, const struct libusb_device_descriptor &descriptor); private: ola::io::SelectServerInterface *m_ss; ola::usb::AsyncronousLibUsbAdaptor *m_adaptor; static const uint16_t PRODUCT_ID; static const uint16_t VENDOR_ID; DISALLOW_COPY_AND_ASSIGN(JaRuleFactory); }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_JARULEFACTORY_H_ ola-0.10.5.nojsmin/plugins/usbdmx/SyncronizedWidgetObserver.h0000644000175000017500000000560413023355232024002 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SyncronizedWidgetObserver.h * Transfers widget add/remove events to another thread. * Copyright (C) 2014 Simon Newton */ #ifndef PLUGINS_USBDMX_SYNCRONIZEDWIDGETOBSERVER_H_ #define PLUGINS_USBDMX_SYNCRONIZEDWIDGETOBSERVER_H_ #include "plugins/usbdmx/WidgetFactory.h" #include "ola/io/SelectServerInterface.h" #include "ola/thread/Future.h" #include "ola/thread/Thread.h" namespace ola { namespace plugin { namespace usbdmx { /** * @brief Transfers widget add/remove events to another thread. * * The SyncronizedWidgetObserver ensures that all widget add/removed events are * handled in the thread that created the SyncronizedWidgetObserver object. */ class SyncronizedWidgetObserver : public WidgetObserver { public: /** * @brief Create a new SyncronizedWidgetObserver. * @param observer the observer to notify on add/remove events. * @param ss The ss to use the schedule events on. */ SyncronizedWidgetObserver(WidgetObserver *observer, ola::io::SelectServerInterface *ss); bool NewWidget(class AnymauDMX *widget) { return DispatchNewWidget(widget); } bool NewWidget(class DMXCProjectsNodleU1 *widget) { return DispatchNewWidget(widget); } bool NewWidget(class EurolitePro *widget) { return DispatchNewWidget(widget); } bool NewWidget(ola::usb::JaRuleWidget *widget) { return DispatchNewWidget(widget); } bool NewWidget(class ScanlimeFadecandy *widget) { return DispatchNewWidget(widget); } bool NewWidget(class Sunlite *widget) { return DispatchNewWidget(widget); } bool NewWidget(class VellemanK8062 *widget) { return DispatchNewWidget(widget); } private: typedef ola::thread::Future AddFuture; WidgetObserver* const m_observer; ola::io::SelectServerInterface* const m_ss; const ola::thread::ThreadId m_main_thread_id; template bool DispatchNewWidget(WidgetClass *widget); template void HandleNewWidget(WidgetClass *widget, AddFuture *f); DISALLOW_COPY_AND_ASSIGN(SyncronizedWidgetObserver); }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_SYNCRONIZEDWIDGETOBSERVER_H_ ola-0.10.5.nojsmin/plugins/usbdmx/DMXCProjectsNodleU1Device.h0000644000175000017500000000456513023355232023401 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DMXCProjectsNodleU1Device.h * A DMXCProjectsNodleU1 device that creates an input and an output port. * Copyright (C) 2015 Stefan Krupop */ #ifndef PLUGINS_USBDMX_DMXCPROJECTSNODLEU1DEVICE_H_ #define PLUGINS_USBDMX_DMXCPROJECTSNODLEU1DEVICE_H_ #include #include #include "ola/base/Macro.h" #include "olad/Device.h" #include "plugins/usbdmx/DMXCProjectsNodleU1.h" namespace ola { namespace plugin { namespace usbdmx { /** * @brief A DMXCProjectsNodleU1 device. * * This device creates an output and/or input port around a Widget. */ class DMXCProjectsNodleU1Device: public Device { public: /** * @brief Create a new DMXCProjectsNodleU1Device. * @param owner The plugin this device belongs to * @param widget The widget to use for this device. * @param device_name The name of the device. * @param device_id The id of the device. * @param plugin_adaptor a PluginAdaptor object, used by the input port. */ DMXCProjectsNodleU1Device(ola::AbstractPlugin *owner, class DMXCProjectsNodleU1 *widget, const std::string &device_name, const std::string &device_id, PluginAdaptor *plugin_adaptor); std::string DeviceId() const { return m_device_id; } protected: bool StartHook(); private: const std::string m_device_id; std::auto_ptr m_out_port; std::auto_ptr m_in_port; DISALLOW_COPY_AND_ASSIGN(DMXCProjectsNodleU1Device); }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_DMXCPROJECTSNODLEU1DEVICE_H_ ola-0.10.5.nojsmin/plugins/usbdmx/ScanlimeFadecandyFactory.h0000644000175000017500000000377513023355232023510 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ScanlimeFadecandyFactory.h * The WidgetFactory for Scanlime FadeCandy widgets. * Copyright (C) 2014 Simon Newton */ #ifndef PLUGINS_USBDMX_SCANLIMEFADECANDYFACTORY_H_ #define PLUGINS_USBDMX_SCANLIMEFADECANDYFACTORY_H_ #include "libs/usb/LibUsbAdaptor.h" #include "ola/base/Macro.h" #include "plugins/usbdmx/WidgetFactory.h" namespace ola { namespace plugin { namespace usbdmx { /** * @brief Creates Fadecandy widgets. */ class ScanlimeFadecandyFactory : public BaseWidgetFactory { public: explicit ScanlimeFadecandyFactory(ola::usb::LibUsbAdaptor *adaptor) : BaseWidgetFactory("ScanlimeFadecandyFactory"), m_missing_serial_number(false), m_adaptor(adaptor) { } bool DeviceAdded( WidgetObserver *observer, libusb_device *usb_device, const struct libusb_device_descriptor &descriptor); private: bool m_missing_serial_number; ola::usb::LibUsbAdaptor *m_adaptor; static const char EXPECTED_MANUFACTURER[]; static const char EXPECTED_PRODUCT[]; static const uint16_t PRODUCT_ID; static const uint16_t VENDOR_ID; DISALLOW_COPY_AND_ASSIGN(ScanlimeFadecandyFactory); }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_SCANLIMEFADECANDYFACTORY_H_ ola-0.10.5.nojsmin/plugins/usbdmx/ThreadedUsbSender.cpp0000644000175000017500000000521213023355232022500 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ThreadedUsbSender.cpp * Send DMX data over USB from a dedicated thread. * Copyright (C) 2014 Simon Newton */ #include "plugins/usbdmx/ThreadedUsbSender.h" #include #include "ola/Logging.h" namespace ola { namespace plugin { namespace usbdmx { ThreadedUsbSender::ThreadedUsbSender(libusb_device *usb_device, libusb_device_handle *usb_handle, int interface_number) : m_term(false), m_usb_device(usb_device), m_usb_handle(usb_handle), m_interface_number(interface_number) { libusb_ref_device(usb_device); } ThreadedUsbSender::~ThreadedUsbSender() { { ola::thread::MutexLocker locker(&m_term_mutex); m_term = true; } Join(); libusb_unref_device(m_usb_device); } bool ThreadedUsbSender::Start() { bool ret = ola::thread::Thread::Start(); if (!ret) { OLA_WARN << "Failed to start sender thread"; libusb_release_interface(m_usb_handle, m_interface_number); libusb_close(m_usb_handle); return false; } return true; } void *ThreadedUsbSender::Run() { DmxBuffer buffer; if (!m_usb_handle) return NULL; while (1) { { ola::thread::MutexLocker locker(&m_term_mutex); if (m_term) break; } { ola::thread::MutexLocker locker(&m_data_mutex); buffer.Set(m_buffer); } if (buffer.Size()) { if (!TransmitBuffer(m_usb_handle, buffer)) { OLA_WARN << "Send failed, stopping thread..."; break; } } else { // sleep for a bit usleep(40000); } } libusb_release_interface(m_usb_handle, m_interface_number); libusb_close(m_usb_handle); return NULL; } bool ThreadedUsbSender::SendDMX(const DmxBuffer &buffer) { // Store the new data in the shared buffer. ola::thread::MutexLocker locker(&m_data_mutex); m_buffer.Set(buffer); return true; } } // namespace usbdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbdmx/AnymauDMXFactory.h0000644000175000017500000000362713023355232021755 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * AnymauDMXFactory.h * The factory for Anyma uDMX widgets. * Copyright (C) 2014 Simon Newton */ #ifndef PLUGINS_USBDMX_ANYMAUDMXFACTORY_H_ #define PLUGINS_USBDMX_ANYMAUDMXFACTORY_H_ #include "libs/usb/LibUsbAdaptor.h" #include "ola/base/Macro.h" #include "plugins/usbdmx/WidgetFactory.h" namespace ola { namespace plugin { namespace usbdmx { /** * @brief Creates Anyma widgets. */ class AnymauDMXFactory : public BaseWidgetFactory { public: explicit AnymauDMXFactory(ola::usb::LibUsbAdaptor *adaptor) : BaseWidgetFactory("AnymauDMXFactory"), m_missing_serial_number(false), m_adaptor(adaptor) { } bool DeviceAdded( WidgetObserver *observer, libusb_device *usb_device, const struct libusb_device_descriptor &descriptor); private: bool m_missing_serial_number; ola::usb::LibUsbAdaptor *m_adaptor; static const char EXPECTED_MANUFACTURER[]; static const char EXPECTED_PRODUCT[]; static const uint16_t PRODUCT_ID; static const uint16_t VENDOR_ID; DISALLOW_COPY_AND_ASSIGN(AnymauDMXFactory); }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_ANYMAUDMXFACTORY_H_ ola-0.10.5.nojsmin/plugins/usbdmx/README.md0000644000175000017500000001027113023355232017721 0ustar wouterwouterUSBDMX Plugin =============================================================================== This plugin uses [libusb](http://libusb.info/) to communicate with USB devices. libusb supports synchronous and asynchronous transfers. The initial version of this plugin used the synchronous interface, and spawned a thread for every USB device present. The new version of the plugin uses the asynchronous mode of operation and a single thread for the libusb completion handling. This allows us to support hotplug. You can opt-out of the new asynchronous mode by passing the --no-use-async-libusb flag to olad. Assuming we don't find any problems, at some point the synchronous implementation will be removed. The rest of this file explains how the plugin is constructed and is aimed at developers wishing to add support for a new USB Device. It assumes the reader has an understanding of libusb. Terminology ------------------------------------------------------------------------------- *USB Device*, is the physical USB device attached to the host. *DMX512 Interface*, the physical socket on the USB Device the user plugs the DMX512 cable into. Currently all the USB Devices supported by the plugin contain a single DMX512 Interface. *libusb\_device*, is the libusb structure that represents a USB device. *Widget*, is OLA's internal object representation of a USB Device. Widgets use the corresponding libusb\_device to communicate with the USB Device. *Port*, the software representation of a DMX512 Interface. In OLA, users associate a Port with a Universe. *Device*, the software representation of a USB Device. Contains one or more Ports. Code Concepts & Structure ------------------------------------------------------------------------------- USB Devices are represented as Widgets, this allows us to de-couple the Widget code from OLA's Port representation (remember, prefer composition over inheritance). Since the majority of USB devices we support so far have a single DMX512 interface, each specific Widget (e.g. AnymauDMX) derives from the Widget class. This isn't strictly necessary, it just means we can avoid code duplication by using the GenericDevice and GenericPort classes. Multi-interface USB devices which are supported, shouldn't inherit from the Widget class (see the Nodle U1 for example, they will need to use the Device class instead). GenericPort wraps a Widget into a Port object, so it can show up in olad. GenericDevice creates a Device with a single GenericPort. For each type of USB Device, we create a common base class, e.g. AnymauDMX. This enables the WidgetObserver class (see below) to know what name it should give the resultant Device. Then for each type of USB Device, we create a synchronous and asynchronous version of the Widget. So you end up with something like: * Widget * AnymauDMX * SynchronousAnymaWidget * AsynchronousAnymaWidget * Sunlite * SynchronousSunliteWidget * AsynchronousSunliteWidget Each type of USB Device has an associated factory. When a new libusb\_device is discovered, each factory has the opportunity to claim the new device. Typically factories will check the vendor and product ID and, if they recognize the device, create a Widget to represent it. If a factory creates a new Widget, it needs to notify the WidgetObserver. The WidgetObserver can then go ahead and use the newly created Widget to setup an OLA Device & Port. Adding Support for a new USB Device ------------------------------------------------------------------------------- Adding support for a new USB device should be reasonably straightforward. This guide assumes the new USB Device has a single DMX512 Interface. 1. Create the FooWidget.{h,cpp} files. - Create the FooWidget base class, and a synchronous and asynchronous implementation of the Foo Widget. 2. Create the FooWidgetFactory.{h,cpp} files. - Write the DeviceAdded() method, to detect the new USB Device and create either a synchronous or asynchronous widget, depending on the --use-async-libusb flag. 3. Extend the WidgetObserver with new NewWidget() and WidgetRemoved() removed methods for the new FooWidget. 4. Implement the new NewWidget() and WidgetRemoved() methods in both the SyncPluginImpl and AsyncPluginImpl. ola-0.10.5.nojsmin/plugins/usbdmx/Sunlite.h0000644000175000017500000000526713023355232020247 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Sunlite.h * The synchronous and asynchronous Sunlite widgets. * Copyright (C) 2014 Simon Newton */ #ifndef PLUGINS_USBDMX_SUNLITE_H_ #define PLUGINS_USBDMX_SUNLITE_H_ #include #include #include "ola/DmxBuffer.h" #include "ola/base/Macro.h" #include "ola/thread/Mutex.h" #include "plugins/usbdmx/Widget.h" namespace ola { namespace plugin { namespace usbdmx { class SunliteThreadedSender; /** * @brief The interface for the Sunlite Widgets */ class Sunlite : public SimpleWidget { public: explicit Sunlite(ola::usb::LibUsbAdaptor *adaptor, libusb_device *usb_device) : SimpleWidget(adaptor, usb_device) { } }; /** * @brief An Sunlite widget that uses synchronous libusb operations. * * Internally this spawns a new thread to avoid blocking SendDMX() calls. */ class SynchronousSunlite: public Sunlite { public: /** * @brief Create a new SynchronousSunlite. * @param adaptor the LibUsbAdaptor to use. * @param usb_device the libusb_device to use for the widget. */ SynchronousSunlite(ola::usb::LibUsbAdaptor *adaptor, libusb_device *usb_device); bool Init(); bool SendDMX(const DmxBuffer &buffer); private: std::auto_ptr m_sender; DISALLOW_COPY_AND_ASSIGN(SynchronousSunlite); }; /** * @brief An Sunlite widget that uses asynchronous libusb operations. */ class AsynchronousSunlite: public Sunlite { public: /** * @brief Create a new AsynchronousSunlite. * @param adaptor the LibUsbAdaptor to use. * @param usb_device the libusb_device to use for the widget. */ AsynchronousSunlite(ola::usb::LibUsbAdaptor *adaptor, libusb_device *usb_device); bool Init(); bool SendDMX(const DmxBuffer &buffer); private: std::auto_ptr m_sender; DISALLOW_COPY_AND_ASSIGN(AsynchronousSunlite); }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_SUNLITE_H_ ola-0.10.5.nojsmin/plugins/usbdmx/JaRuleDevice.cpp0000644000175000017500000000330613023355232021451 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * JaRuleDevice.cpp * A Ja Rule device. * Copyright (C) 2015 Simon Newton */ #include "plugins/usbdmx/JaRuleDevice.h" #include #include #include #include "libs/usb/JaRuleWidget.h" #include "libs/usb/JaRulePortHandle.h" #include "plugins/usbdmx/JaRuleOutputPort.h" namespace ola { namespace plugin { namespace usbdmx { using std::set; using std::auto_ptr; JaRuleDevice::JaRuleDevice(ola::AbstractPlugin *owner, ola::usb::JaRuleWidget *widget, const std::string &device_name) : Device(owner, device_name), m_widget(widget), m_device_id(widget->GetUID().ToString()) { } bool JaRuleDevice::StartHook() { for (uint8_t i = 0; i < m_widget->PortCount(); i++) { auto_ptr port(new JaRuleOutputPort(this, i, m_widget)); if (!port->Init()) { continue; } AddPort(port.release()); } return true; } } // namespace usbdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbdmx/EurolitePro.h0000644000175000017500000000674613023355232021100 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * EurolitePro.h * The synchronous and asynchronous EurolitePro widgets. * Copyright (C) 2014 Simon Newton */ #ifndef PLUGINS_USBDMX_EUROLITEPRO_H_ #define PLUGINS_USBDMX_EUROLITEPRO_H_ #include #include #include #include "libs/usb/LibUsbAdaptor.h" #include "ola/DmxBuffer.h" #include "ola/base/Macro.h" #include "ola/thread/Mutex.h" #include "plugins/usbdmx/Widget.h" namespace ola { namespace plugin { namespace usbdmx { class EuroliteProThreadedSender; /** * @brief The EurolitePro Widget. */ class EurolitePro : public SimpleWidget { public: /** * @brief Create a new EurolitePro. * @param adaptor the LibUsbAdaptor to use. * @param usb_device the libusb_device to use for the widget. * @param serial the serial number of the widget. */ EurolitePro(ola::usb::LibUsbAdaptor *adaptor, libusb_device *usb_device, const std::string &serial) : SimpleWidget(adaptor, usb_device), m_serial(serial) {} /** * @brief Get the serial number of this widget. * @returns The serial number of the widget. */ std::string SerialNumber() const { return m_serial; } private: std::string m_serial; }; /** * @brief An EurolitePro widget that uses synchronous libusb operations. * * Internally this spawns a new thread to avoid blocking SendDMX() calls. */ class SynchronousEurolitePro: public EurolitePro { public: /** * @brief Create a new SynchronousEurolitePro. * @param adaptor the LibUsbAdaptor to use. * @param usb_device the libusb_device to use for the widget. * @param serial the serial number of the widget. */ SynchronousEurolitePro(ola::usb::LibUsbAdaptor *adaptor, libusb_device *usb_device, const std::string &serial); bool Init(); bool SendDMX(const DmxBuffer &buffer); private: std::auto_ptr m_sender; DISALLOW_COPY_AND_ASSIGN(SynchronousEurolitePro); }; /** * @brief An EurolitePro widget that uses asynchronous libusb operations. */ class AsynchronousEurolitePro: public EurolitePro { public: /** * @brief Create a new AsynchronousEurolitePro. * @param adaptor the LibUsbAdaptor to use. * @param usb_device the libusb_device to use for the widget. * @param serial the serial number of the widget. */ AsynchronousEurolitePro(ola::usb::LibUsbAdaptor *adaptor, libusb_device *usb_device, const std::string &serial); bool Init(); bool SendDMX(const DmxBuffer &buffer); private: std::auto_ptr m_sender; DISALLOW_COPY_AND_ASSIGN(AsynchronousEurolitePro); }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_EUROLITEPRO_H_ ola-0.10.5.nojsmin/plugins/usbdmx/ThreadedUsbReceiver.cpp0000644000175000017500000000537613023355232023037 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ThreadedUsbReceiver.cpp * Receive DMX data over USB from a dedicated thread. * Copyright (C) 2015 Stefan Krupop */ #include "plugins/usbdmx/ThreadedUsbReceiver.h" #include #include "ola/Logging.h" namespace ola { namespace plugin { namespace usbdmx { ThreadedUsbReceiver::ThreadedUsbReceiver(libusb_device *usb_device, libusb_device_handle *usb_handle, PluginAdaptor *plugin_adaptor, int interface_number) : m_term(false), m_usb_device(usb_device), m_usb_handle(usb_handle), m_interface_number(interface_number), m_plugin_adaptor(plugin_adaptor), m_receive_callback(NULL) { libusb_ref_device(usb_device); } ThreadedUsbReceiver::~ThreadedUsbReceiver() { { ola::thread::MutexLocker locker(&m_term_mutex); m_term = true; } Join(); libusb_unref_device(m_usb_device); } bool ThreadedUsbReceiver::Start() { bool ret = ola::thread::Thread::Start(); if (!ret) { OLA_WARN << "Failed to start receiver thread"; libusb_release_interface(m_usb_handle, m_interface_number); libusb_close(m_usb_handle); return false; } return true; } void *ThreadedUsbReceiver::Run() { DmxBuffer buffer; buffer.Blackout(); if (!m_usb_handle) { return NULL; } while (1) { { ola::thread::MutexLocker locker(&m_term_mutex); if (m_term) { break; } } bool buffer_updated = false; if (!ReceiveBuffer(m_usb_handle, &buffer, &buffer_updated)) { OLA_WARN << "Receive failed, stopping thread..."; break; } if (buffer_updated) { { ola::thread::MutexLocker locker(&m_data_mutex); m_buffer.Set(buffer); } if (m_receive_callback.get()) { m_plugin_adaptor->Execute(m_receive_callback.get()); } } } libusb_release_interface(m_usb_handle, m_interface_number); libusb_close(m_usb_handle); return NULL; } } // namespace usbdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbdmx/DMXCProjectsNodleU1Port.cpp0000644000175000017500000000270013023355232023446 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DMXCProjectsNodleU1Port.cpp * Output and input ports that use a widget and give the serial as desciption. * Copyright (C) 2015 Stefan Krupop */ #include "plugins/usbdmx/DMXCProjectsNodleU1Port.h" #include "ola/Logging.h" #include "olad/Device.h" namespace ola { namespace plugin { namespace usbdmx { DMXCProjectsNodleU1InputPort::DMXCProjectsNodleU1InputPort( Device *parent, unsigned int id, PluginAdaptor *plugin_adaptor, DMXCProjectsNodleU1 *widget) : BasicInputPort(parent, id, plugin_adaptor), m_widget(widget) { m_widget->SetDmxCallback(NewCallback( static_cast(this), &BasicInputPort::DmxChanged)); } } // namespace usbdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbdmx/SunliteFactory.h0000644000175000017500000000365113023355232021572 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SunliteFactory.h * The WidgetFactory for SunLite widgets. * Copyright (C) 2014 Simon Newton */ #ifndef PLUGINS_USBDMX_SUNLITEFACTORY_H_ #define PLUGINS_USBDMX_SUNLITEFACTORY_H_ #include "libs/usb/LibUsbAdaptor.h" #include "ola/base/Macro.h" #include "plugins/usbdmx/Sunlite.h" #include "plugins/usbdmx/WidgetFactory.h" namespace ola { namespace plugin { namespace usbdmx { /** * @brief Creates SunLite widgets. */ class SunliteFactory : public BaseWidgetFactory { public: explicit SunliteFactory(ola::usb::LibUsbAdaptor *adaptor) : BaseWidgetFactory("SunliteFactory"), m_adaptor(adaptor) {} bool DeviceAdded( WidgetObserver *observer, libusb_device *usb_device, const struct libusb_device_descriptor &descriptor); private: ola::usb::LibUsbAdaptor* const m_adaptor; // The product ID for widgets that are missing their firmware. static const uint16_t EMPTY_PRODUCT_ID; // The product ID for widgets with the firmware. static const uint16_t FULL_PRODUCT_ID; static const uint16_t VENDOR_ID; DISALLOW_COPY_AND_ASSIGN(SunliteFactory); }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_SUNLITEFACTORY_H_ ola-0.10.5.nojsmin/plugins/usbdmx/ScanlimeFadecandy.cpp0000644000175000017500000002527413023355232022511 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ScanlimeFadecandy.cpp * The synchronous and asynchronous Fadecandy widgets. * Copyright (C) 2014 Simon Newton */ #include "plugins/usbdmx/ScanlimeFadecandy.h" #include #include #include #include #include #include "libs/usb/LibUsbAdaptor.h" #include "ola/base/Array.h" #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/StringUtils.h" #include "ola/strings/Format.h" #include "ola/util/Utils.h" #include "plugins/usbdmx/AsyncUsbSender.h" #include "plugins/usbdmx/ThreadedUsbSender.h" namespace ola { namespace plugin { namespace usbdmx { using ola::usb::LibUsbAdaptor; using std::string; namespace { static const unsigned char ENDPOINT = 0x01; // 2s is a really long time. Can we reduce this? static const unsigned int URB_TIMEOUT_MS = 2000; static const int INTERFACE = 0; // A data frame. static const uint8_t TYPE_FRAMEBUFFER = 0x00; // The color lookup table static const uint8_t TYPE_LUT = 0x40; // The initial setup message. static const uint8_t TYPE_CONFIG = 0x80; // The final packet in a set. static const uint8_t FINAL = 0x20; // Options used in the first data byte of the config message. static const uint8_t OPTION_NO_DITHERING = 0x01; static const uint8_t OPTION_NO_INTERPOLATION = 0x02; // static const uint8_t OPTION_NO_ACTIVITY_LED = 0x03; // static const uint8_t OPTION_LED_CONTROL = 0x04; static const unsigned int NUM_CHANNELS = 3; // RGB static const unsigned int LUT_ROWS_PER_CHANNEL = 257; // Each 'packet' is 63 bytes, or 21 RGB pixels. enum { SLOTS_PER_PACKET = 63 }; static const uint8_t PACKETS_PER_UPDATE = 25; // Each LUT 'packet' is 31 LUT rows, 62 bytes, plus a padding byte static const uint8_t LUT_ROWS_PER_PACKET = 31; // The padding byte offset static const uint8_t LUT_DATA_OFFSET = 1; PACK( struct fadecandy_packet { uint8_t control; uint8_t data[SLOTS_PER_PACKET]; void Reset() { control = 0; memset(data, 0, sizeof(data)); } fadecandy_packet() { Reset(); } }); bool InitializeWidget(LibUsbAdaptor *adaptor, libusb_device_handle *usb_handle) { // Set the fadecandy configuration. fadecandy_packet packet; packet.control = TYPE_CONFIG; packet.data[0] |= OPTION_NO_DITHERING; // Default to no processing packet.data[0] |= OPTION_NO_INTERPOLATION; // packet.data[0] = OPTION_NO_ACTIVITY_LED; // Manual control of LED // packet.data[0] |= OPTION_LED_CONTROL; // Manual LED state int bytes_sent = 0; int r = adaptor->BulkTransfer(usb_handle, ENDPOINT, reinterpret_cast(&packet), sizeof(packet), &bytes_sent, URB_TIMEOUT_MS); if (r == 0) { OLA_INFO << "Config transferred " << bytes_sent << " bytes"; } else { OLA_WARN << "Config transfer failed with error " << adaptor->ErrorCodeToString(r); return false; } // Build the Look Up Table uint16_t lut[NUM_CHANNELS * LUT_ROWS_PER_CHANNEL]; memset(&lut, 0, sizeof(lut)); for (unsigned int channel = 0; channel < NUM_CHANNELS; channel++) { for (unsigned int value = 0; value < LUT_ROWS_PER_CHANNEL; value++) { // Fadecandy Python Example as C++ // lut[channel][value] = std::min( // static_cast(std::numeric_limits::max()), // int(pow(value / 256.0, 2.2) * // (std::numeric_limits::max() + 1))); // 1:1 for now // TODO(Peter): Add support for more built in or custom LUTs unsigned int overall_lut_row = (channel * LUT_ROWS_PER_CHANNEL) + value; lut[overall_lut_row] = std::min( static_cast(std::numeric_limits::max()), (value << 8)); OLA_DEBUG << "Generated LUT for channel " << channel << " value " << value << " with val " << lut[overall_lut_row]; } } OLA_DEBUG << "LUT size " << arraysize(lut); fadecandy_packet lut_packets[PACKETS_PER_UPDATE]; for (unsigned int packet_index = 0; packet_index < PACKETS_PER_UPDATE; packet_index++) { lut_packets[packet_index].Reset(); lut_packets[packet_index].control = TYPE_LUT | packet_index; if (packet_index == (PACKETS_PER_UPDATE - 1)) { lut_packets[packet_index].control |= FINAL; } unsigned int lut_offset = packet_index * LUT_ROWS_PER_PACKET; for (unsigned int row = 0; row < LUT_ROWS_PER_PACKET; row++) { unsigned int row_data_offset = (row * 2) + LUT_DATA_OFFSET; ola::utils::SplitUInt16( lut[lut_offset + row], &lut_packets[packet_index].data[(row_data_offset + 1)], &lut_packets[packet_index].data[row_data_offset]); } } bytes_sent = 0; // We do a single bulk transfer of the entire data, rather than one transfer // for each 64 bytes. r = adaptor->BulkTransfer( usb_handle, ENDPOINT, reinterpret_cast(&lut_packets), sizeof(lut_packets), &bytes_sent, URB_TIMEOUT_MS); if (r == 0) { OLA_INFO << "Successfully transfer LUT of " << bytes_sent << " bytes"; } else { OLA_WARN << "Data transfer failed with error " << adaptor->ErrorCodeToString(r); return false; } return true; } void UpdatePacketsWithDMX(fadecandy_packet packets[PACKETS_PER_UPDATE], const DmxBuffer &buffer) { for (unsigned int packet_index = 0; packet_index < PACKETS_PER_UPDATE; packet_index++) { packets[packet_index].Reset(); unsigned int dmx_offset = packet_index * SLOTS_PER_PACKET; unsigned int slots_in_packet = SLOTS_PER_PACKET; buffer.GetRange(dmx_offset, packets[packet_index].data, &slots_in_packet); packets[packet_index].control = TYPE_FRAMEBUFFER | packet_index; if (packet_index == (PACKETS_PER_UPDATE - 1)) { packets[packet_index].control |= FINAL; } } } } // namespace // FadecandyThreadedSender // ----------------------------------------------------------------------------- /* * Sends messages to a Fadecandy device in a separate thread. */ class FadecandyThreadedSender: public ThreadedUsbSender { public: FadecandyThreadedSender(LibUsbAdaptor *adaptor, libusb_device *usb_device, libusb_device_handle *handle) : ThreadedUsbSender(usb_device, handle), m_adaptor(adaptor) { } private: LibUsbAdaptor* const m_adaptor; fadecandy_packet m_data_packets[PACKETS_PER_UPDATE]; bool TransmitBuffer(libusb_device_handle *handle, const DmxBuffer &buffer); }; bool FadecandyThreadedSender::TransmitBuffer(libusb_device_handle *handle, const DmxBuffer &buffer) { UpdatePacketsWithDMX(m_data_packets, buffer); int bytes_sent = 0; // We do a single bulk transfer of the entire data, rather than one transfer // for each 64 bytes. int r = m_adaptor->BulkTransfer( handle, ENDPOINT, reinterpret_cast(&m_data_packets), sizeof(m_data_packets), &bytes_sent, URB_TIMEOUT_MS); if (r != 0) { OLA_WARN << "Data transfer failed with error " << m_adaptor->ErrorCodeToString(r); } return r == 0; } // SynchronousScanlimeFadecandy // ----------------------------------------------------------------------------- SynchronousScanlimeFadecandy::SynchronousScanlimeFadecandy( LibUsbAdaptor *adaptor, libusb_device *usb_device, const std::string &serial) : ScanlimeFadecandy(adaptor, usb_device, serial) { } bool SynchronousScanlimeFadecandy::Init() { libusb_device_handle *usb_handle; bool ok = m_adaptor->OpenDeviceAndClaimInterface( m_usb_device, INTERFACE, &usb_handle); if (!ok) { return false; } if (!InitializeWidget(m_adaptor, usb_handle)) { m_adaptor->Close(usb_handle); return false; } std::auto_ptr sender( new FadecandyThreadedSender(m_adaptor, m_usb_device, usb_handle)); if (!sender->Start()) { return false; } m_sender.reset(sender.release()); return true; } bool SynchronousScanlimeFadecandy::SendDMX(const DmxBuffer &buffer) { return m_sender.get() ? m_sender->SendDMX(buffer) : false; } // FadecandyAsyncUsbSender // ----------------------------------------------------------------------------- class FadecandyAsyncUsbSender : public AsyncUsbSender { public: FadecandyAsyncUsbSender(LibUsbAdaptor *adaptor, libusb_device *usb_device) : AsyncUsbSender(adaptor, usb_device) { } libusb_device_handle* SetupHandle(); bool PerformTransfer(const DmxBuffer &buffer); private: fadecandy_packet m_data_packets[PACKETS_PER_UPDATE]; DISALLOW_COPY_AND_ASSIGN(FadecandyAsyncUsbSender); }; libusb_device_handle* FadecandyAsyncUsbSender::SetupHandle() { libusb_device_handle *usb_handle; if (!m_adaptor->OpenDeviceAndClaimInterface( m_usb_device, INTERFACE, &usb_handle)) { return NULL; } if (!InitializeWidget(m_adaptor, usb_handle)) { m_adaptor->Close(usb_handle); return NULL; } return usb_handle; } bool FadecandyAsyncUsbSender::PerformTransfer(const DmxBuffer &buffer) { UpdatePacketsWithDMX(m_data_packets, buffer); // We do a single bulk transfer of the entire data, rather than one transfer // for each 64 bytes. FillBulkTransfer(ENDPOINT, reinterpret_cast(&m_data_packets), sizeof(m_data_packets), URB_TIMEOUT_MS); return (SubmitTransfer() == 0); } // AsynchronousScanlimeFadecandy // ----------------------------------------------------------------------------- AsynchronousScanlimeFadecandy::AsynchronousScanlimeFadecandy( LibUsbAdaptor *adaptor, libusb_device *usb_device, const std::string &serial) : ScanlimeFadecandy(adaptor, usb_device, serial) { m_sender.reset(new FadecandyAsyncUsbSender(m_adaptor, usb_device)); } bool AsynchronousScanlimeFadecandy::Init() { return m_sender->Init(); } bool AsynchronousScanlimeFadecandy::SendDMX(const DmxBuffer &buffer) { return m_sender->SendDMX(buffer); } } // namespace usbdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbdmx/PluginImplInterface.h0000644000175000017500000000326313023355232022517 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * PluginImplInterface.h * The interface for the various implementations of the USBDMX plugin. * Copyright (C) 2014 Simon Newton */ #ifndef PLUGINS_USBDMX_PLUGINIMPLINTERFACE_H_ #define PLUGINS_USBDMX_PLUGINIMPLINTERFACE_H_ #include #include #include #include #include #include "ola/plugin_id.h" #include "olad/Plugin.h" #include "ola/io/Descriptor.h" namespace ola { namespace plugin { namespace usbdmx { /** * @brief The interface for an implementation of the USB DMX plugin. */ class PluginImplInterface { public: virtual ~PluginImplInterface() {} /** * @brief Start the implementation. * @returns true if successful, false otherwise. */ virtual bool Start() = 0; /** * @brief Stop the implementation. * @returns true if successful, false otherwise. */ virtual bool Stop() = 0; }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_PLUGINIMPLINTERFACE_H_ ola-0.10.5.nojsmin/plugins/usbdmx/AsyncUsbReceiver.h0000644000175000017500000001005413023355232022026 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * AsyncUsbReceiver.h * An Asynchronous DMX USB receiver. * Copyright (C) 2015 Stefan Krupop */ #ifndef PLUGINS_USBDMX_ASYNCUSBRECEIVER_H_ #define PLUGINS_USBDMX_ASYNCUSBRECEIVER_H_ #include #include #include "AsyncUsbTransceiverBase.h" #include "libs/usb/LibUsbAdaptor.h" #include "ola/Callback.h" #include "ola/DmxBuffer.h" #include "ola/base/Macro.h" #include "ola/thread/Mutex.h" #include "olad/PluginAdaptor.h" namespace ola { namespace plugin { namespace usbdmx { /** * @brief A base class that receives DMX data asynchronously from a * libusb_device. * * This encapsulates much of the asynchronous libusb logic. Subclasses should * implement the SetupHandle() and PerformTransfer() methods. */ class AsyncUsbReceiver: public AsyncUsbTransceiverBase { public: /** * @brief Create a new AsyncUsbReceiver. * @param adaptor the LibUsbAdaptor to use. * @param usb_device the libusb_device to use for the widget. * @param plugin_adaptor the PluginAdaptor to use for the widget. */ AsyncUsbReceiver(ola::usb::LibUsbAdaptor* const adaptor, libusb_device *usb_device, PluginAdaptor *plugin_adaptor); /** * @brief Destructor */ virtual ~AsyncUsbReceiver(); /** * @brief Initialize the receiver. * @returns true if SetupHandle() returned a valid handle, false otherwise. */ bool Init(); /** * @brief Initialize the receiver with an already setup handle * @param handle the handle returned by a previous SetupHandle() call * @returns true */ bool Init(libusb_device_handle* handle); /** * @brief Start receiving DMX * @returns the value of PerformTransfer(). */ bool Start(); /** * @brief Set the callback to be called when the receive buffer is updated. * @param callback The callback to call. */ void SetReceiveCallback(Callback0 *callback) { m_receive_callback.reset(callback); } /** * @brief Get DMX Buffer * @param buffer DmxBuffer that will get updated with the current input. */ void GetDmx(DmxBuffer *buffer) { ola::thread::MutexLocker locker(&m_mutex); buffer->Set(m_rx_buffer); } /** * @brief Called from the libusb callback when the asynchronous transfer * completes. * @param transfer the completed transfer. */ void TransferComplete(struct libusb_transfer *transfer); protected: /** * @brief Start the request of data from the widget * @returns true if the transfer was scheduled, false otherwise. * * This method is implemented by the subclass. The subclass should call * FillControlTransfer() / FillBulkTransfer() as appropriate and then call * SubmitTransfer(). */ virtual bool PerformTransfer() = 0; /** * @brief Called when the transfer completes. * @param buffer the DmxBuffer to receive into * @param transferred_size the number of bytes actually transferred * returns true if the buffer was updated */ virtual bool TransferCompleted(DmxBuffer *buffer, int transferred_size) = 0; private: PluginAdaptor* const m_plugin_adaptor; bool m_inited_with_handle; DmxBuffer m_rx_buffer; // GUARDED_BY(m_mutex); std::auto_ptr > m_receive_callback; DISALLOW_COPY_AND_ASSIGN(AsyncUsbReceiver); }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_ASYNCUSBRECEIVER_H_ ola-0.10.5.nojsmin/plugins/usbdmx/DMXCProjectsNodleU1.h0000644000175000017500000001202413023355232022246 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DMXCProjectsNodleU1.h * The synchronous and asynchronous Nodle widgets. * Copyright (C) 2015 Stefan Krupop */ #ifndef PLUGINS_USBDMX_DMXCPROJECTSNODLEU1_H_ #define PLUGINS_USBDMX_DMXCPROJECTSNODLEU1_H_ #include #include #include #include "libs/usb/LibUsbAdaptor.h" #include "ola/Callback.h" #include "ola/DmxBuffer.h" #include "ola/base/Macro.h" #include "ola/thread/Mutex.h" #include "olad/PluginAdaptor.h" #include "plugins/usbdmx/Widget.h" namespace ola { namespace plugin { namespace usbdmx { /** * @brief The interface for the Nodle Widgets */ class DMXCProjectsNodleU1: public SimpleWidget { public: explicit DMXCProjectsNodleU1(ola::usb::LibUsbAdaptor *adaptor, libusb_device *usb_device, PluginAdaptor *plugin_adaptor, const std::string &serial, unsigned int mode) : SimpleWidget(adaptor, usb_device), m_serial(serial), m_mode(mode), m_plugin_adaptor(plugin_adaptor) { } /** * @brief Get the serial number of this widget. * @returns The serial number of the widget. */ std::string SerialNumber() const { return m_serial; } /** * @brief Get the current mode of this widget. * @returns The mode of the widget. */ unsigned int Mode() const { return m_mode; } virtual void SetDmxCallback(Callback0 *callback) = 0; virtual const DmxBuffer &GetDmxInBuffer() = 0; static int NODLE_DEFAULT_MODE; static int NODLE_MIN_MODE; static int NODLE_MAX_MODE; static int OUTPUT_ENABLE_MASK; static int INPUT_ENABLE_MASK; private: std::string m_serial; protected: unsigned int m_mode; PluginAdaptor *m_plugin_adaptor; }; /** * @brief An Nodle widget that uses synchronous libusb operations. * * Internally this spawns a new thread to avoid blocking SendDMX() calls. */ class SynchronousDMXCProjectsNodleU1: public DMXCProjectsNodleU1 { public: /** * @brief Create a new SynchronousDMXCProjectsNodleU1. * @param adaptor the LibUsbAdaptor to use. * @param usb_device the libusb_device to use for the widget. * @param plugin_adaptor the PluginAdaptor used to execute callbacks * @param serial the serial number of this widget * @param mode the send/receive mode to be used by the widget. */ SynchronousDMXCProjectsNodleU1(ola::usb::LibUsbAdaptor *adaptor, libusb_device *usb_device, PluginAdaptor *plugin_adaptor, const std::string &serial, unsigned int mode); bool Init(); bool SendDMX(const DmxBuffer &buffer); void SetDmxCallback(Callback0 *callback); const DmxBuffer &GetDmxInBuffer(); private: libusb_device* const m_usb_device; std::auto_ptr m_sender; std::auto_ptr m_receiver; DISALLOW_COPY_AND_ASSIGN(SynchronousDMXCProjectsNodleU1); }; /** * @brief An Nodle widget that uses asynchronous libusb operations. */ class AsynchronousDMXCProjectsNodleU1 : public DMXCProjectsNodleU1 { public: /** * @brief Create a new AsynchronousDMXCProjectsNodleU1. * @param adaptor the LibUsbAdaptor to use. * @param usb_device the libusb_device to use for the widget. * @param plugin_adaptor the PluginAdaptor used to execute callbacks * @param serial the serial number of this widget * @param mode the send/receive mode to be used by the widget. */ AsynchronousDMXCProjectsNodleU1(ola::usb::LibUsbAdaptor *adaptor, libusb_device *usb_device, PluginAdaptor *plugin_adaptor, const std::string &serial, unsigned int mode); bool Init(); bool SendDMX(const DmxBuffer &buffer); void SetDmxCallback(Callback0 *callback); const DmxBuffer &GetDmxInBuffer(); private: std::auto_ptr m_sender; std::auto_ptr m_receiver; DmxBuffer m_buffer; DISALLOW_COPY_AND_ASSIGN(AsynchronousDMXCProjectsNodleU1); }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_DMXCPROJECTSNODLEU1_H_ ola-0.10.5.nojsmin/plugins/usbdmx/AsyncUsbReceiver.cpp0000644000175000017500000000543713023355232022372 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * AsyncUsbReceiver.cpp * An Asynchronous DMX USB receiver. * Copyright (C) 2015 Stefan Krupop */ #include "plugins/usbdmx/AsyncUsbReceiver.h" #include "ola/Logging.h" namespace ola { namespace plugin { namespace usbdmx { AsyncUsbReceiver::AsyncUsbReceiver(ola::usb::LibUsbAdaptor *adaptor, libusb_device *usb_device, PluginAdaptor *plugin_adaptor) : AsyncUsbTransceiverBase(adaptor, usb_device), m_plugin_adaptor(plugin_adaptor), m_inited_with_handle(false) { } AsyncUsbReceiver::~AsyncUsbReceiver() { if (!m_inited_with_handle) { m_adaptor->Close(m_usb_handle); } } bool AsyncUsbReceiver::Init() { m_usb_handle = SetupHandle(); m_inited_with_handle = false; return m_usb_handle != NULL; } bool AsyncUsbReceiver::Init(libusb_device_handle* handle) { m_usb_handle = handle; m_inited_with_handle = true; return true; } bool AsyncUsbReceiver::Start() { if (!m_usb_handle) { OLA_WARN << "AsyncUsbReceiver hasn't been initialized"; return false; } ola::thread::MutexLocker locker(&m_mutex); return PerformTransfer(); } void AsyncUsbReceiver::TransferComplete(struct libusb_transfer *transfer) { if (transfer != m_transfer) { OLA_WARN << "Mismatched libusb transfer: " << transfer << " != " << m_transfer; return; } if (transfer->status != LIBUSB_TRANSFER_COMPLETED && transfer->status != LIBUSB_TRANSFER_TIMED_OUT ) { OLA_WARN << "Transfer returned " << transfer->status; } ola::thread::MutexLocker locker(&m_mutex); m_transfer_state = (transfer->status == LIBUSB_TRANSFER_NO_DEVICE ? DISCONNECTED : IDLE); if (m_suppress_continuation) { return; } if (transfer->status != LIBUSB_TRANSFER_TIMED_OUT) { if (TransferCompleted(&m_rx_buffer, transfer->actual_length)) { // Input changed if (m_receive_callback.get()) { m_plugin_adaptor->Execute(m_receive_callback.get()); } } } // Start next request PerformTransfer(); } } // namespace usbdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbdmx/SunliteFirmware.h0000644000175000017500000024421313023355232021740 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SunliteFirmware.h * Copyright (C) Michael Stickel * Imported into the OLA Project by Simon Newton, 2/4/2010. */ #ifndef PLUGINS_USBDMX_SUNLITEFIRMWARE_H_ #define PLUGINS_USBDMX_SUNLITEFIRMWARE_H_ #include struct sunlite_hex_record { uint16_t address; uint8_t data_size; uint8_t data[16]; }; static const uint16_t SUNLITE_END_OF_FIRMWARE = 0xffff; static const struct sunlite_hex_record sunlite_firmware[] = { { 32658, 1, { 0x1 } }, /* reset=1 */ { 32658, 1, { 0x1 } }, /* reset=1 */ { 5228, 16, { 0xc2, 0x00, 0x90, 0x7f, 0xa5, 0xe0, 0x54, 0x18, 0xff, 0x13, 0x13, 0x13, 0x54, 0x1f, 0x44, 0x50 } }, { 5244, 16, { 0xf5, 0x1c, 0x13, 0x92, 0x01, 0xd2, 0xe8, 0x90, 0x7f, 0xab, 0x74, 0xff, 0xf0, 0x90, 0x7f, 0xa9 } }, { 5260, 16, { 0xf0, 0x90, 0x7f, 0xaa, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f, 0x95, 0xe0, 0x44, 0xc0, 0xf0, 0x90 } }, { 5276, 16, { 0x7f, 0xaf, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xae, 0xe0, 0x44, 0x05, 0xf0, 0xd2, 0xaf, 0x12 } }, { 5292, 13, { 0x17, 0x5f, 0x30, 0x00, 0xfd, 0x12, 0x11, 0x00, 0xc2, 0x00, 0x80, 0xf6, 0x22 } }, { 4352, 16, { 0x90, 0x7f, 0xe9, 0xe0, 0x24, 0x5d, 0x60, 0x0d, 0x14, 0x70, 0x03, 0x02, 0x12, 0x44, 0x24, 0x02 } }, { 4368, 16, { 0x60, 0x03, 0x02, 0x12, 0x4a, 0x90, 0x7f, 0xea, 0xe0, 0x75, 0x08, 0x00, 0xf5, 0x09, 0xa3, 0xe0 } }, { 4384, 16, { 0xfe, 0xe4, 0x25, 0x09, 0xf5, 0x09, 0xee, 0x35, 0x08, 0xf5, 0x08, 0x90, 0x7f, 0xee, 0xe0, 0x75 } }, { 4400, 16, { 0xa, 0x00, 0xf5, 0x0b, 0xa3, 0xe0, 0xfe, 0xe4, 0x25, 0x0b, 0xf5, 0x0b, 0xee, 0x35, 0x0a, 0xf5 } }, { 4416, 16, { 0xa, 0x90, 0x7f, 0xe8, 0xe0, 0x64, 0xc0, 0x60, 0x03, 0x02, 0x11, 0xd4, 0xe5, 0x0b, 0x45, 0x0a } }, { 4432, 16, { 0x70, 0x03, 0x02, 0x12, 0x4a, 0xc3, 0xe5, 0x0b, 0x94, 0x40, 0xe5, 0x0a, 0x94, 0x00, 0x50, 0x08 } }, { 4448, 16, { 0x85, 0x0a, 0x0c, 0x85, 0x0b, 0x0d, 0x80, 0x06, 0x75, 0x0c, 0x00, 0x75, 0x0d, 0x40, 0x90, 0x7f } }, { 4464, 16, { 0xe9, 0xe0, 0xb4, 0xa3, 0x25, 0xae, 0x0c, 0xaf, 0x0d, 0xaa, 0x08, 0xa9, 0x09, 0x7b, 0x01, 0xc0 } }, { 4480, 16, { 0x3, 0xc0, 0x02, 0xc0, 0x01, 0x7a, 0x7f, 0x79, 0x00, 0x78, 0x00, 0x7c, 0x7f, 0xad, 0x03, 0xd0 } }, { 4496, 16, { 0x1, 0xd0, 0x02, 0xd0, 0x03, 0x12, 0x13, 0x56, 0x80, 0x0f, 0xaf, 0x09, 0xae, 0x08, 0xad, 0x0d } }, { 4512, 16, { 0x7a, 0x7f, 0x79, 0x00, 0x7b, 0x00, 0x12, 0x15, 0xa4, 0x90, 0x7f, 0xb5, 0xe5, 0x0d, 0xf0, 0xe5 } }, { 4528, 16, { 0xd, 0x25, 0x09, 0xf5, 0x09, 0xe5, 0x0c, 0x35, 0x08, 0xf5, 0x08, 0xc3, 0xe5, 0x0b, 0x95, 0x0d } }, { 4544, 16, { 0xf5, 0x0b, 0xe5, 0x0a, 0x95, 0x0c, 0xf5, 0x0a, 0x90, 0x7f, 0xb4, 0xe0, 0x20, 0xe2, 0x03, 0x02 } }, { 4560, 16, { 0x11, 0x4c, 0x80, 0xf4, 0x90, 0x7f, 0xe8, 0xe0, 0x64, 0x40, 0x70, 0x6e, 0xe5, 0x0b, 0x45, 0x0a } }, { 4576, 16, { 0x60, 0x68, 0xe4, 0x90, 0x7f, 0xc5, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x20, 0xe3, 0xf9, 0x90, 0x7f } }, { 4592, 16, { 0xc5, 0xe0, 0x75, 0x0c, 0x00, 0xf5, 0x0d, 0x90, 0x7f, 0xe9, 0xe0, 0xb4, 0xa3, 0x15, 0xae, 0x0c } }, { 4608, 16, { 0xaf, 0x0d, 0xa8, 0x09, 0xac, 0x08, 0x7d, 0x01, 0x7b, 0x01, 0x7a, 0x7e, 0x79, 0xc0, 0x12, 0x13 } }, { 4624, 16, { 0x56, 0x80, 0x0f, 0xaf, 0x09, 0xae, 0x08, 0xad, 0x0d, 0x7a, 0x7f, 0x79, 0x00, 0x7b, 0x00, 0x12 } }, { 4640, 16, { 0x14, 0xb9, 0xe5, 0x0d, 0x25, 0x09, 0xf5, 0x09, 0xe5, 0x0c, 0x35, 0x08, 0xf5, 0x08, 0xc3, 0xe5 } }, { 4656, 16, { 0xb, 0x95, 0x0d, 0xf5, 0x0b, 0xe5, 0x0a, 0x95, 0x0c, 0xf5, 0x0a, 0x90, 0x7f, 0xb4, 0xe0, 0x44 } }, { 4672, 10, { 0x2, 0xf0, 0x80, 0x98, 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x1c } }, { 4682, 1, { 0x22 } }, { 5464, 6, { 0xab, 0x07, 0xaa, 0x06, 0xac, 0x05 } }, { 5470, 16, { 0xe4, 0xfd, 0x30, 0x01, 0x11, 0xea, 0xff, 0xae, 0x05, 0x0d, 0xee, 0x24, 0x00, 0xf5, 0x82, 0xe4 } }, { 5486, 16, { 0x34, 0xe0, 0xf5, 0x83, 0xef, 0xf0, 0xeb, 0xae, 0x05, 0x0d, 0x74, 0x00, 0x2e, 0xf5, 0x82, 0xe4 } }, { 5502, 16, { 0x34, 0xe0, 0xf5, 0x83, 0xeb, 0xf0, 0xaf, 0x05, 0x0d, 0x74, 0x00, 0x2f, 0xf5, 0x82, 0xe4, 0x34 } }, { 5518, 16, { 0xe0, 0xf5, 0x83, 0xec, 0xf0, 0xaf, 0x1c, 0x7a, 0xe0, 0x7b, 0x00, 0x12, 0x17, 0x20, 0x7f, 0x0a } }, { 5534, 5, { 0x7e, 0x00, 0x12, 0x17, 0x3c } }, { 5539, 1, { 0x22 } }, { 5305, 10, { 0x8e, 0x0e, 0x8f, 0x0f, 0x8d, 0x10, 0x8a, 0x11, 0x8b, 0x12 } }, { 5315, 16, { 0xe4, 0xf5, 0x13, 0xe5, 0x13, 0xc3, 0x95, 0x10, 0x50, 0x20, 0x05, 0x0f, 0xe5, 0x0f, 0xae, 0x0e } }, { 5331, 16, { 0x70, 0x02, 0x05, 0x0e, 0x14, 0xff, 0xe5, 0x12, 0x25, 0x13, 0xf5, 0x82, 0xe4, 0x35, 0x11, 0xf5 } }, { 5347, 10, { 0x83, 0xe0, 0xfd, 0x12, 0x15, 0x58, 0x05, 0x13, 0x80, 0xd9 } }, { 5357, 1, { 0x22 } }, { 5540, 10, { 0x8e, 0x0e, 0x8f, 0x0f, 0x8d, 0x10, 0x8a, 0x11, 0x8b, 0x12 } }, { 5550, 16, { 0xe4, 0xfd, 0x30, 0x01, 0x12, 0xe5, 0x0e, 0xff, 0xae, 0x05, 0x0d, 0xee, 0x24, 0x03, 0xf5, 0x82 } }, { 5566, 16, { 0xe4, 0x34, 0xe0, 0xf5, 0x83, 0xef, 0xf0, 0xe5, 0x0f, 0xae, 0x05, 0x0d, 0x74, 0x03, 0x2e, 0xf5 } }, { 5582, 16, { 0x82, 0xe4, 0x34, 0xe0, 0xf5, 0x83, 0xe5, 0x0f, 0xf0, 0xaf, 0x1c, 0x7a, 0xe0, 0x7b, 0x03, 0x12 } }, { 5598, 13, { 0x17, 0x20, 0xaf, 0x1c, 0xad, 0x10, 0xab, 0x12, 0xaa, 0x11, 0x12, 0x17, 0x04 } }, { 5611, 1, { 0x22 } }, { 5742, 16, { 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xd2 } }, { 5758, 16, { 0x0, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x01, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85 } }, { 5774, 7, { 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32 } }, { 5700, 16, { 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x90 } }, { 5716, 16, { 0x7f, 0xc4, 0xe4, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x04, 0xf0, 0xd0, 0x86, 0xd0 } }, { 5732, 10, { 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32 } }, { 5781, 16, { 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53 } }, { 5797, 16, { 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x02, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82 } }, { 5813, 5, { 0xd0, 0x83, 0xd0, 0xe0, 0x32 } }, { 5818, 16, { 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53 } }, { 5834, 16, { 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x10, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82 } }, { 5850, 5, { 0xd0, 0x83, 0xd0, 0xe0, 0x32 } }, { 5375, 1, { 0x32 } }, { 5855, 16, { 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53 } }, { 5871, 16, { 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x08, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82 } }, { 5887, 5, { 0xd0, 0x83, 0xd0, 0xe0, 0x32 } }, { 5991, 1, { 0x32 } }, { 5992, 1, { 0x32 } }, { 5993, 1, { 0x32 } }, { 5994, 1, { 0x32 } }, { 5995, 1, { 0x32 } }, { 5996, 1, { 0x32 } }, { 5997, 1, { 0x32 } }, { 5998, 1, { 0x32 } }, { 5999, 1, { 0x32 } }, { 6000, 1, { 0x32 } }, { 6001, 1, { 0x32 } }, { 6002, 1, { 0x32 } }, { 6003, 1, { 0x32 } }, { 6004, 1, { 0x32 } }, { 6005, 1, { 0x32 } }, { 6006, 1, { 0x32 } }, { 67, 3, { 0x2, 0x15, 0x00 } }, { 5376, 16, { 0x2, 0x16, 0x6e, 0x00, 0x02, 0x16, 0x95, 0x00, 0x02, 0x16, 0x44, 0x00, 0x02, 0x16, 0xdf, 0x00 } }, { 5392, 16, { 0x2, 0x16, 0xba, 0x00, 0x02, 0x14, 0xff, 0x00, 0x02, 0x17, 0x67, 0x00, 0x02, 0x17, 0x68, 0x00 } }, { 5408, 16, { 0x2, 0x17, 0x69, 0x00, 0x02, 0x17, 0x6a, 0x00, 0x02, 0x17, 0x6b, 0x00, 0x02, 0x17, 0x6c, 0x00 } }, { 5424, 16, { 0x2, 0x17, 0x6d, 0x00, 0x02, 0x17, 0x6e, 0x00, 0x02, 0x17, 0x6f, 0x00, 0x02, 0x17, 0x70, 0x00 } }, { 5440, 16, { 0x2, 0x17, 0x71, 0x00, 0x02, 0x17, 0x72, 0x00, 0x02, 0x17, 0x73, 0x00, 0x02, 0x17, 0x74, 0x00 } }, { 5456, 8, { 0x2, 0x17, 0x75, 0x00, 0x02, 0x17, 0x76, 0x00 } }, { 5948, 16, { 0x8e, 0x14, 0x8f, 0x15, 0xe5, 0x15, 0x15, 0x15, 0xae, 0x14, 0x70, 0x02, 0x15, 0x14, 0x4e, 0x60 } }, { 5964, 7, { 0x5, 0x12, 0x14, 0xee, 0x80, 0xee, 0x22 } }, { 5983, 8, { 0xe4, 0xf5, 0x1b, 0xd2, 0xe9, 0xd2, 0xaf, 0x22 } }, { 5657, 16, { 0xa9, 0x07, 0xe5, 0x1b, 0x70, 0x23, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0, 0xe9, 0x25, 0xe0 } }, { 5673, 16, { 0x90, 0x7f, 0xa6, 0xf0, 0x8d, 0x16, 0xaf, 0x03, 0xa9, 0x07, 0x75, 0x17, 0x01, 0x8a, 0x18, 0x89 } }, { 5689, 11, { 0x19, 0xe4, 0xf5, 0x1a, 0x75, 0x1b, 0x01, 0xd3, 0x22, 0xc3, 0x22 } }, { 5612, 16, { 0xa9, 0x07, 0xe5, 0x1b, 0x70, 0x25, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0, 0xe9, 0x25, 0xe0 } }, { 5628, 16, { 0x44, 0x01, 0x90, 0x7f, 0xa6, 0xf0, 0x8d, 0x16, 0xaf, 0x03, 0xa9, 0x07, 0x75, 0x17, 0x01, 0x8a } }, { 5644, 13, { 0x18, 0x89, 0x19, 0xe4, 0xf5, 0x1a, 0x75, 0x1b, 0x03, 0xd3, 0x22, 0xc3, 0x22 } }, { 75, 3, { 0x2, 0x13, 0x7f } }, { 4991, 16, { 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xc0 } }, { 5007, 16, { 0xd0, 0x75, 0xd0, 0x00, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x06, 0xc0, 0x07 } }, { 5023, 16, { 0x90, 0x7f, 0xa5, 0xe0, 0x30, 0xe2, 0x06, 0x75, 0x1b, 0x06, 0x02, 0x14, 0x4e, 0x90, 0x7f, 0xa5 } }, { 5039, 16, { 0xe0, 0x20, 0xe1, 0x0c, 0xe5, 0x1b, 0x64, 0x02, 0x60, 0x06, 0x75, 0x1b, 0x07, 0x02, 0x14, 0x4e } }, { 5055, 16, { 0xaf, 0x1b, 0xef, 0x24, 0xfe, 0x60, 0x48, 0x14, 0x60, 0x2c, 0x24, 0xfe, 0x60, 0x77, 0x24, 0x04 } }, { 5071, 16, { 0x60, 0x03, 0x02, 0x14, 0x4e, 0xab, 0x17, 0xaa, 0x18, 0xa9, 0x19, 0xaf, 0x1a, 0x05, 0x1a, 0x8f } }, { 5087, 16, { 0x82, 0x75, 0x83, 0x00, 0x12, 0x12, 0x4b, 0x90, 0x7f, 0xa6, 0xf0, 0xe5, 0x1a, 0x65, 0x16, 0x70 } }, { 5103, 16, { 0x5e, 0x75, 0x1b, 0x05, 0x80, 0x59, 0x90, 0x7f, 0xa6, 0xe0, 0xab, 0x17, 0xaa, 0x18, 0xa9, 0x19 } }, { 5119, 16, { 0xae, 0x1a, 0x8e, 0x82, 0x75, 0x83, 0x00, 0x12, 0x12, 0x78, 0x75, 0x1b, 0x02, 0x80, 0x40, 0xe5 } }, { 5135, 16, { 0x16, 0x24, 0xfe, 0xb5, 0x1a, 0x07, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x20, 0xf0, 0xe5, 0x16, 0x14 } }, { 5151, 16, { 0xb5, 0x1a, 0x0a, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x75, 0x1b, 0x00, 0x90, 0x7f, 0xa6 } }, { 5167, 16, { 0xe0, 0xab, 0x17, 0xaa, 0x18, 0xa9, 0x19, 0xae, 0x1a, 0x8e, 0x82, 0x75, 0x83, 0x00, 0x12, 0x12 } }, { 5183, 16, { 0x78, 0x05, 0x1a, 0x80, 0x0a, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x75, 0x1b, 0x00, 0x53 } }, { 5199, 16, { 0x91, 0xdf, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0xd0 } }, { 5215, 13, { 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32 } }, { 5892, 16, { 0x12, 0x15, 0xec, 0xe5, 0x1b, 0x24, 0xfa, 0x60, 0x0e, 0x14, 0x60, 0x06, 0x24, 0x07, 0x70, 0xf3 } }, { 5908, 12, { 0xd3, 0x22, 0xe4, 0xf5, 0x1b, 0xd3, 0x22, 0xe4, 0xf5, 0x1b, 0xd3, 0x22 } }, { 5920, 16, { 0x12, 0x16, 0x19, 0xe5, 0x1b, 0x24, 0xfa, 0x60, 0x0e, 0x14, 0x60, 0x06, 0x24, 0x07, 0x70, 0xf3 } }, { 5936, 12, { 0xd3, 0x22, 0xe4, 0xf5, 0x1b, 0xd3, 0x22, 0xe4, 0xf5, 0x1b, 0xd3, 0x22 } }, { 5358, 16, { 0x74, 0x00, 0xf5, 0x86, 0x90, 0xfd, 0xa5, 0x7c, 0x05, 0xa3, 0xe5, 0x82, 0x45, 0x83, 0x70, 0xf9 } }, { 5374, 1, { 0x22 } }, { 0, 3, { 0x2, 0x17, 0x53 } }, { 5971, 12, { 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x20, 0x02, 0x14, 0x6c } }, { 4683, 16, { 0xbb, 0x01, 0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50 } }, { 4699, 16, { 0x6, 0xe9, 0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22 } }, { 4715, 13, { 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22 } }, { 4728, 16, { 0xf8, 0xbb, 0x01, 0x0d, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe8, 0xf0 } }, { 4744, 16, { 0x22, 0x50, 0x06, 0xe9, 0x25, 0x82, 0xc8, 0xf6, 0x22, 0xbb, 0xfe, 0x05, 0xe9, 0x25, 0x82, 0xc8 } }, { 4760, 2, { 0xf2, 0x22 } }, { 4762, 16, { 0xe7, 0x09, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x46, 0xe7, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x3e } }, { 4778, 16, { 0x88, 0x82, 0x8c, 0x83, 0xe7, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x32, 0xe3, 0x09, 0xf6, 0x08 } }, { 4794, 16, { 0xdf, 0xfa, 0x80, 0x6e, 0xe3, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x66, 0x88, 0x82, 0x8c, 0x83 } }, { 4810, 16, { 0xe3, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x5a, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf6, 0x08 } }, { 4826, 16, { 0xdf, 0xfa, 0x80, 0x4e, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x42 } }, { 4842, 16, { 0x80, 0xd2, 0x80, 0xfa, 0x80, 0xc6, 0x80, 0xd4, 0x80, 0x55, 0x80, 0xf2, 0x80, 0x29, 0x80, 0x10 } }, { 4858, 16, { 0x80, 0xa6, 0x80, 0xea, 0x80, 0x9a, 0x80, 0xa8, 0x80, 0xda, 0x80, 0xe2, 0x80, 0xca, 0x80, 0x29 } }, { 4874, 16, { 0x88, 0x84, 0x8c, 0x85, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0x05, 0x86, 0xf0, 0xa3, 0x05 } }, { 4890, 16, { 0x86, 0xdf, 0xf5, 0xde, 0xf3, 0x80, 0x0b, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf6, 0x08 } }, { 4906, 16, { 0xdf, 0xf9, 0xec, 0xfa, 0xa9, 0xf0, 0xed, 0xfb, 0x22, 0x88, 0x84, 0x8c, 0x85, 0x89, 0x82, 0x8a } }, { 4922, 16, { 0x83, 0xe0, 0xa3, 0x05, 0x86, 0xf0, 0xa3, 0x05, 0x86, 0xdf, 0xf6, 0xde, 0xf4, 0x80, 0xe3, 0x89 } }, { 4938, 16, { 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf2, 0x08, 0xdf, 0xf9, 0x80, 0xd6, 0x88, 0xf0, 0xed, 0x24 } }, { 4954, 16, { 0x2, 0xb4, 0x04, 0x00, 0x50, 0xcc, 0xf5, 0x82, 0xeb, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xc2 } }, { 4970, 16, { 0x23, 0x23, 0x45, 0x82, 0xf5, 0x82, 0xef, 0x4e, 0x60, 0xb8, 0xef, 0x60, 0x01, 0x0e, 0xe5, 0x82 } }, { 4986, 5, { 0x23, 0x90, 0x12, 0xea, 0x73 } }, { 32658, 1, { 0x0 } }, /* reset=0 */ { 32658, 1, { 0x1 } }, /* reset=1 */ { 1717, 16, { 0xd2, 0x00, 0x90, 0x7f, 0xa1, 0x74, 0x01, 0xf0, 0xe4, 0x90, 0x7f, 0x93, 0xf0, 0x90, 0x7f, 0x94 } }, { 1733, 16, { 0xf0, 0x90, 0x7f, 0x95, 0x74, 0x03, 0xf0, 0x90, 0x7f, 0x9c, 0x74, 0x30, 0xf0, 0xe4, 0x90, 0x7f } }, { 1749, 16, { 0x9d, 0xf0, 0x90, 0x7f, 0x9e, 0x74, 0xf2, 0xf0, 0x90, 0x7f, 0x96, 0x74, 0x20, 0xf0, 0x90, 0x7f } }, { 1765, 16, { 0x98, 0x74, 0xf2, 0xf0, 0x12, 0x0a, 0x6a, 0x12, 0x0a, 0x86, 0x90, 0x7f, 0xde, 0xe0, 0x44, 0x02 } }, { 1781, 16, { 0xf0, 0x90, 0x7f, 0xdf, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0x7f, 0xad, 0xe0, 0x44, 0x02, 0xf0, 0x90 } }, { 1797, 16, { 0x7f, 0xac, 0xe0, 0x44, 0x02, 0xf0, 0x12, 0x09, 0x90, 0x90, 0x7f, 0xb7, 0x74, 0x20, 0xf0, 0x22 } }, { 2879, 1, { 0x22 } }, { 2867, 2, { 0xd3, 0x22 } }, { 2869, 2, { 0xd3, 0x22 } }, { 2871, 2, { 0xd3, 0x22 } }, { 2847, 8, { 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x0f, 0xd3, 0x22 } }, { 2796, 14, { 0x90, 0x7f, 0x00, 0xe5, 0x0f, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0xd3, 0x22 } }, { 2855, 8, { 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x0e, 0xd3, 0x22 } }, { 2810, 14, { 0x90, 0x7f, 0x00, 0xe5, 0x0e, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0xd3, 0x22 } }, { 2873, 2, { 0xd3, 0x22 } }, { 2875, 2, { 0xd3, 0x22 } }, { 2877, 2, { 0xd3, 0x22 } }, { 2598, 16, { 0x90, 0x7f, 0xe8, 0xe0, 0x30, 0xe6, 0x1a, 0xa3, 0xe0, 0x24, 0xf0, 0x70, 0x12, 0x7f, 0x06, 0x12 } }, { 2614, 16, { 0x7, 0x15, 0x90, 0x7f, 0x00, 0xef, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x80, 0x02, 0xd3 } }, { 2630, 3, { 0x22, 0xc3, 0x22 } }, { 2370, 16, { 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xd2 } }, { 2386, 16, { 0x1, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x01, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85 } }, { 2402, 7, { 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32 } }, { 2487, 16, { 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53 } }, { 2503, 16, { 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x04, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82 } }, { 2519, 5, { 0xd0, 0x83, 0xd0, 0xe0, 0x32 } }, { 2524, 16, { 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53 } }, { 2540, 16, { 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x02, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82 } }, { 2556, 5, { 0xd0, 0x83, 0xd0, 0xe0, 0x32 } }, { 2561, 16, { 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53 } }, { 2577, 16, { 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x10, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82 } }, { 2593, 5, { 0xd0, 0x83, 0xd0, 0xe0, 0x32 } }, { 2880, 1, { 0x32 } }, { 2409, 16, { 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xd2 } }, { 2425, 16, { 0x3, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x08, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85 } }, { 2441, 7, { 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32 } }, { 2881, 1, { 0x32 } }, { 2882, 1, { 0x32 } }, { 1903, 16, { 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86 } }, { 1919, 16, { 0x0, 0xc0, 0xd0, 0x75, 0xd0, 0x00, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04 } }, { 1935, 16, { 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0x12, 0x09, 0x90, 0x90, 0x7f, 0xb7, 0x74, 0x20, 0xf0, 0x90 } }, { 1951, 16, { 0x7f, 0xa9, 0x74, 0x02, 0xf0, 0x53, 0x91, 0xef, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04 } }, { 1967, 16, { 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0xd0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85 } }, { 1983, 9, { 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32 } }, { 1619, 16, { 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86 } }, { 1635, 16, { 0x0, 0xc0, 0xd0, 0x75, 0xd0, 0x00, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04 } }, { 1651, 16, { 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0x90, 0x7f, 0x9b, 0xe0, 0x64, 0x80, 0x90, 0x7f, 0x98, 0xf0 } }, { 1667, 16, { 0x53, 0x91, 0xef, 0x90, 0x7f, 0xaa, 0x74, 0x02, 0xf0, 0x12, 0x0b, 0x08, 0x90, 0x7f, 0xc7, 0xe4 } }, { 1683, 16, { 0xf0, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0 } }, { 1699, 16, { 0x0, 0xd0, 0xd0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0 } }, { 1715, 2, { 0xe0, 0x32 } }, { 2883, 1, { 0x32 } }, { 2884, 1, { 0x32 } }, { 2885, 1, { 0x32 } }, { 2886, 1, { 0x32 } }, { 2887, 1, { 0x32 } }, { 2888, 1, { 0x32 } }, { 2889, 1, { 0x32 } }, { 2890, 1, { 0x32 } }, { 2891, 1, { 0x32 } }, { 2892, 1, { 0x32 } }, { 2893, 1, { 0x32 } }, { 2894, 1, { 0x32 } }, { 875, 16, { 0xe4, 0xf5, 0x31, 0xf5, 0x30, 0xf5, 0x2f, 0xf5, 0x2e, 0xc2, 0x03, 0xc2, 0x00, 0xc2, 0x02, 0xc2 } }, { 891, 16, { 0x1, 0x12, 0x06, 0xb5, 0x7e, 0x05, 0x7f, 0x06, 0x8e, 0x08, 0x8f, 0x09, 0x75, 0x0a, 0x05, 0x75 } }, { 907, 16, { 0xb, 0x18, 0x75, 0x0c, 0x05, 0x75, 0x0d, 0x38, 0xee, 0x54, 0xe0, 0x70, 0x03, 0x02, 0x04, 0x77 } }, { 923, 16, { 0x75, 0x32, 0x00, 0x75, 0x33, 0x80, 0x8e, 0x34, 0x8f, 0x35, 0xc3, 0x74, 0x74, 0x9f, 0xff, 0x74 } }, { 939, 16, { 0x5, 0x9e, 0xcf, 0x24, 0x02, 0xcf, 0x34, 0x00, 0xfe, 0xe4, 0x8f, 0x2d, 0x8e, 0x2c, 0xf5, 0x2b } }, { 955, 16, { 0xf5, 0x2a, 0xf5, 0x29, 0xf5, 0x28, 0xf5, 0x27, 0xf5, 0x26, 0xaf, 0x2d, 0xae, 0x2c, 0xad, 0x2b } }, { 971, 16, { 0xac, 0x2a, 0xab, 0x29, 0xaa, 0x28, 0xa9, 0x27, 0xa8, 0x26, 0xc3, 0x12, 0x08, 0x9e, 0x50, 0x26 } }, { 987, 16, { 0xe5, 0x33, 0x25, 0x29, 0xf5, 0x82, 0xe5, 0x32, 0x35, 0x28, 0xf5, 0x83, 0x74, 0xcd, 0xf0, 0xe5 } }, { 1003, 16, { 0x29, 0x24, 0x01, 0xf5, 0x29, 0xe4, 0x35, 0x28, 0xf5, 0x28, 0xe4, 0x35, 0x27, 0xf5, 0x27, 0xe4 } }, { 1019, 16, { 0x35, 0x26, 0xf5, 0x26, 0x80, 0xc4, 0xe4, 0xf5, 0x29, 0xf5, 0x28, 0xf5, 0x27, 0xf5, 0x26, 0xaf } }, { 1035, 16, { 0x2d, 0xae, 0x2c, 0xad, 0x2b, 0xac, 0x2a, 0xab, 0x29, 0xaa, 0x28, 0xa9, 0x27, 0xa8, 0x26, 0xc3 } }, { 1051, 16, { 0x12, 0x08, 0x9e, 0x50, 0x31, 0xae, 0x28, 0xaf, 0x29, 0xe5, 0x35, 0x2f, 0xf5, 0x82, 0xe5, 0x34 } }, { 1067, 16, { 0x3e, 0xf5, 0x83, 0xe0, 0xfd, 0xe5, 0x33, 0x2f, 0xf5, 0x82, 0xe5, 0x32, 0x3e, 0xf5, 0x83, 0xed } }, { 1083, 16, { 0xf0, 0xef, 0x24, 0x01, 0xf5, 0x29, 0xe4, 0x3e, 0xf5, 0x28, 0xe4, 0x35, 0x27, 0xf5, 0x27, 0xe4 } }, { 1099, 16, { 0x35, 0x26, 0xf5, 0x26, 0x80, 0xb9, 0x85, 0x32, 0x08, 0x85, 0x33, 0x09, 0x74, 0x06, 0x24, 0x80 } }, { 1115, 16, { 0xff, 0x74, 0x05, 0x34, 0xff, 0xfe, 0xc3, 0xe5, 0x0b, 0x9f, 0xf5, 0x0b, 0xe5, 0x0a, 0x9e, 0xf5 } }, { 1131, 16, { 0xa, 0xc3, 0xe5, 0x0d, 0x9f, 0xf5, 0x0d, 0xe5, 0x0c, 0x9e, 0xf5, 0x0c, 0xd2, 0xe8, 0x43, 0xd8 } }, { 1147, 16, { 0x20, 0x90, 0x7f, 0xab, 0x74, 0xff, 0xf0, 0x90, 0x7f, 0xaf, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f } }, { 1163, 16, { 0xae, 0xe0, 0x44, 0x1d, 0xf0, 0xd2, 0xaf, 0x20, 0x01, 0x41, 0x20, 0x01, 0x05, 0xd2, 0x04, 0x12 } }, { 1179, 16, { 0x8, 0xaf, 0xe4, 0xf5, 0x31, 0xf5, 0x30, 0xf5, 0x2f, 0xf5, 0x2e, 0x7f, 0x40, 0x7e, 0x92, 0x7d } }, { 1195, 16, { 0x4, 0x7c, 0x00, 0xab, 0x31, 0xaa, 0x30, 0xa9, 0x2f, 0xa8, 0x2e, 0xc3, 0x12, 0x08, 0x9e, 0x50 } }, { 1211, 16, { 0xd6, 0x20, 0x01, 0xd3, 0xe5, 0x31, 0x24, 0x01, 0xf5, 0x31, 0xe4, 0x35, 0x30, 0xf5, 0x30, 0xe4 } }, { 1227, 16, { 0x35, 0x2f, 0xf5, 0x2f, 0xe4, 0x35, 0x2e, 0xf5, 0x2e, 0x80, 0xd0, 0x53, 0x8e, 0xf8, 0x12, 0x0b } }, { 1243, 16, { 0x16, 0x30, 0x01, 0x05, 0x12, 0x00, 0x80, 0xc2, 0x01, 0x30, 0x03, 0x1a, 0x12, 0x0b, 0x33, 0x50 } }, { 1259, 16, { 0x15, 0xc2, 0x03, 0x12, 0x0a, 0x49, 0x20, 0x00, 0x07, 0x90, 0x7f, 0xd6, 0xe0, 0x20, 0xe7, 0xf3 } }, { 1275, 11, { 0x12, 0x0a, 0xa1, 0x12, 0x0b, 0x35, 0x12, 0x0b, 0x3f, 0x80, 0xd6 } }, { 128, 16, { 0x90, 0x7f, 0xe9, 0xe0, 0x70, 0x03, 0x02, 0x02, 0x10, 0x14, 0x70, 0x03, 0x02, 0x02, 0x8c, 0x24 } }, { 144, 16, { 0xfe, 0x70, 0x03, 0x02, 0x03, 0x03, 0x24, 0xfb, 0x70, 0x03, 0x02, 0x02, 0x0a, 0x14, 0x70, 0x03 } }, { 160, 16, { 0x2, 0x02, 0x04, 0x14, 0x70, 0x03, 0x02, 0x01, 0xf8, 0x14, 0x70, 0x03, 0x02, 0x01, 0xfe, 0x24 } }, { 176, 16, { 0x5, 0x60, 0x03, 0x02, 0x03, 0x57, 0x12, 0x0b, 0x37, 0x40, 0x03, 0x02, 0x03, 0x63, 0x90, 0x7f } }, { 192, 16, { 0xeb, 0xe0, 0x24, 0xfe, 0x60, 0x19, 0x14, 0x60, 0x45, 0x24, 0x02, 0x60, 0x03, 0x02, 0x01, 0xee } }, { 208, 16, { 0xe5, 0x08, 0x90, 0x7f, 0xd4, 0xf0, 0xe5, 0x09, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x03, 0x63, 0x90 } }, { 224, 16, { 0x7f, 0xea, 0xe0, 0xff, 0x12, 0x09, 0x00, 0xaa, 0x06, 0xa9, 0x07, 0x7b, 0x01, 0x8b, 0x36, 0x8a } }, { 240, 16, { 0x37, 0x89, 0x38, 0xea, 0x49, 0x60, 0x0d, 0xee, 0x90, 0x7f, 0xd4, 0xf0, 0xef, 0x90, 0x7f, 0xd5 } }, { 256, 16, { 0xf0, 0x02, 0x03, 0x63, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x03, 0x63, 0x90, 0x7f } }, { 272, 16, { 0xea, 0xe0, 0xff, 0x12, 0x07, 0xc8, 0xaa, 0x06, 0xa9, 0x07, 0x7b, 0x01, 0x8b, 0x36, 0x8a, 0x37 } }, { 288, 9, { 0x89, 0x38, 0xea, 0x49, 0x70, 0x03, 0x02, 0x01, 0xe4 } }, { 297, 16, { 0xab, 0x36, 0x8b, 0x3d, 0x8a, 0x3e, 0x89, 0x3f, 0x12, 0x08, 0x58, 0xf5, 0x40, 0x90, 0x7f, 0xee } }, { 313, 16, { 0xe0, 0xff, 0xe5, 0x40, 0xd3, 0x9f, 0x40, 0x03, 0xe0, 0xf5, 0x40, 0xe5, 0x40, 0x70, 0x03, 0x02 } }, { 329, 16, { 0x1, 0xd6, 0xe4, 0xf5, 0x3c, 0xf5, 0x3b, 0xf5, 0x3a, 0xf5, 0x39, 0xe5, 0x40, 0xc3, 0x94, 0x40 } }, { 345, 16, { 0x50, 0x04, 0xaf, 0x40, 0x80, 0x02, 0x7f, 0x40, 0xe4, 0xfc, 0xfd, 0xfe, 0xab, 0x3c, 0xaa, 0x3b } }, { 361, 16, { 0xa9, 0x3a, 0xa8, 0x39, 0xc3, 0x12, 0x08, 0x9e, 0x50, 0x32, 0xe5, 0x3f, 0x25, 0x3c, 0xf5, 0x82 } }, { 377, 16, { 0xe5, 0x3e, 0x35, 0x3b, 0xf5, 0x83, 0xe0, 0xff, 0x74, 0x00, 0x25, 0x3c, 0xf5, 0x82, 0xe4, 0x34 } }, { 393, 16, { 0x7f, 0xf5, 0x83, 0xef, 0xf0, 0xe5, 0x3c, 0x24, 0x01, 0xf5, 0x3c, 0xe4, 0x35, 0x3b, 0xf5, 0x3b } }, { 409, 16, { 0xe4, 0x35, 0x3a, 0xf5, 0x3a, 0xe4, 0x35, 0x39, 0xf5, 0x39, 0x80, 0xaf, 0xe5, 0x40, 0xc3, 0x94 } }, { 425, 16, { 0x40, 0x50, 0x04, 0xaf, 0x40, 0x80, 0x02, 0x7f, 0x40, 0x90, 0x7f, 0xb5, 0xef, 0xf0, 0xe5, 0x40 } }, { 441, 16, { 0xc3, 0x94, 0x40, 0x50, 0x04, 0xaf, 0x40, 0x80, 0x02, 0x7f, 0x40, 0xc3, 0xe5, 0x40, 0x9f, 0xf5 } }, { 457, 16, { 0x40, 0x90, 0x7f, 0xb4, 0xe0, 0x20, 0xe2, 0x03, 0x02, 0x01, 0x44, 0x80, 0xf4, 0xe4, 0x90, 0x7f } }, { 473, 8, { 0xb5, 0xf0, 0x90, 0x7f, 0xb4, 0x74, 0x02, 0xf0 } }, { 481, 16, { 0x2, 0x03, 0x63, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x03, 0x63, 0x90, 0x7f, 0xb4 } }, { 497, 16, { 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x03, 0x63, 0x12, 0x0a, 0xfa, 0x02, 0x03, 0x63, 0x12, 0x0b, 0x27 } }, { 513, 16, { 0x2, 0x03, 0x63, 0x12, 0x0b, 0x1f, 0x02, 0x03, 0x63, 0x12, 0x0a, 0xec, 0x02, 0x03, 0x63, 0x12 } }, { 529, 16, { 0xb, 0x39, 0x40, 0x03, 0x02, 0x03, 0x63, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0x7f, 0x60, 0x24, 0x14 } }, { 545, 16, { 0x60, 0x31, 0x24, 0x02, 0x70, 0x5b, 0xa2, 0x00, 0xe4, 0x33, 0xff, 0x25, 0xe0, 0xff, 0xa2, 0x02 } }, { 561, 16, { 0xe4, 0x33, 0x4f, 0x90, 0x7f, 0x00, 0xf0, 0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0 } }, { 577, 16, { 0x2, 0x03, 0x63, 0xe4, 0x90, 0x7f, 0x00, 0xf0, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0 } }, { 593, 16, { 0x2, 0x03, 0x63, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0 } }, { 609, 16, { 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe0, 0x54 } }, { 625, 16, { 0x1, 0x90, 0x7f, 0x00, 0xf0, 0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x03 } }, { 641, 16, { 0x63, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x03, 0x63, 0x12, 0x0b, 0x3b, 0x40, 0x03 } }, { 657, 16, { 0x2, 0x03, 0x63, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0xfe, 0x60, 0x1d, 0x24, 0x02, 0x60, 0x03, 0x02 } }, { 673, 16, { 0x3, 0x63, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x05, 0xc2, 0x00, 0x02, 0x03, 0x63, 0x90, 0x7f } }, { 689, 16, { 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x03, 0x63, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x3b, 0x90, 0x7f } }, { 705, 16, { 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0 } }, { 721, 16, { 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4, 0xf0, 0x90, 0x7f, 0xec, 0xe0, 0x54 } }, { 737, 16, { 0x80, 0xff, 0x13, 0x13, 0x13, 0x54, 0x1f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x90, 0x7f, 0xd7, 0xf0 } }, { 753, 3, { 0xe4, 0xf5, 0x3d } }, { 756, 16, { 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x69, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x60, 0x12 } }, { 772, 16, { 0xb, 0x3d, 0x50, 0x5b, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0xfe, 0x60, 0x18, 0x24, 0x02, 0x70, 0x4f } }, { 788, 16, { 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x04, 0xd2, 0x00, 0x80, 0x44, 0x90, 0x7f, 0xb4, 0xe0, 0x44 } }, { 804, 16, { 0x1, 0xf0, 0x80, 0x3b, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x20, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54 } }, { 820, 16, { 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82 } }, { 836, 16, { 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0x80, 0x15, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01 } }, { 852, 16, { 0xf0, 0x80, 0x0c, 0x12, 0x0a, 0x26, 0x50, 0x07, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x90 } }, { 868, 6, { 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0 } }, { 874, 1, { 0x22 } }, { 51, 3, { 0x2, 0x0b, 0x2f } }, { 2863, 4, { 0x53, 0xd8, 0xef, 0x32 } }, { 1286, 16, { 0x12, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x62, 0x09, 0x01, 0x20, 0x01, 0x00, 0x01, 0x02 } }, { 1302, 16, { 0x0, 0x01, 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0xa0, 0x00, 0x09, 0x04, 0x00, 0x00, 0x02 } }, { 1318, 16, { 0xff, 0x00, 0x00, 0x00, 0x07, 0x05, 0x01, 0x02, 0x20, 0x00, 0x00, 0x07, 0x05, 0x81, 0x02, 0x20 } }, { 1334, 16, { 0x0, 0x00, 0x04, 0x03, 0x09, 0x04, 0x26, 0x03, 0x44, 0x00, 0x69, 0x00, 0x67, 0x00, 0x69, 0x00 } }, { 1350, 16, { 0x74, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x41, 0x00, 0x72, 0x00, 0x74, 0x00, 0x20, 0x00 } }, { 1366, 16, { 0x53, 0x00, 0x79, 0x00, 0x73, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x12, 0x03, 0x53, 0x00 } }, { 1382, 16, { 0x55, 0x00, 0x49, 0x00, 0x44, 0x00, 0x49, 0x00, 0x2d, 0x00, 0x45, 0x00, 0x43, 0x00, 0x00, 0x00 } }, { 67, 3, { 0x2, 0x08, 0x00 } }, { 2048, 16, { 0x2, 0x09, 0x42, 0x00, 0x02, 0x09, 0xdc, 0x00, 0x02, 0x09, 0xb7, 0x00, 0x02, 0x09, 0x69, 0x00 } }, { 2064, 16, { 0x2, 0x0a, 0x01, 0x00, 0x02, 0x0b, 0x40, 0x00, 0x02, 0x0b, 0x41, 0x00, 0x02, 0x0b, 0x42, 0x00 } }, { 2080, 16, { 0x2, 0x07, 0x6f, 0x00, 0x02, 0x06, 0x53, 0x00, 0x02, 0x0b, 0x43, 0x00, 0x02, 0x0b, 0x44, 0x00 } }, { 2096, 16, { 0x2, 0x0b, 0x45, 0x00, 0x02, 0x0b, 0x46, 0x00, 0x02, 0x0b, 0x47, 0x00, 0x02, 0x0b, 0x48, 0x00 } }, { 2112, 16, { 0x2, 0x0b, 0x49, 0x00, 0x02, 0x0b, 0x4a, 0x00, 0x02, 0x0b, 0x4b, 0x00, 0x02, 0x0b, 0x4c, 0x00 } }, { 2128, 8, { 0x2, 0x0b, 0x4d, 0x00, 0x02, 0x0b, 0x4e, 0x00 } }, { 2721, 16, { 0x90, 0x7f, 0xd6, 0xe0, 0x30, 0xe7, 0x12, 0xe0, 0x44, 0x01, 0xf0, 0x7f, 0x14, 0x7e, 0x00, 0x12 } }, { 2737, 10, { 0xa, 0xd5, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfe, 0xf0, 0x22 } }, { 2633, 16, { 0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x80, 0xf0, 0x43, 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22 } }, { 2223, 7, { 0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x08, 0xf0 } }, { 2230, 3, { 0xe4, 0xf5, 0x36 } }, { 2233, 4, { 0xe0, 0x54, 0xfb, 0xf0 } }, { 2237, 3, { 0xe4, 0xf5, 0x36 } }, { 2240, 16, { 0xe0, 0x44, 0x08, 0xf0, 0x30, 0x04, 0x04, 0xe0, 0x44, 0x02, 0xf0, 0x7f, 0xdc, 0x7e, 0x05, 0x12 } }, { 2256, 16, { 0xa, 0xd5, 0x90, 0x7f, 0x92, 0xe0, 0x30, 0xe3, 0x07, 0x7f, 0xdc, 0x7e, 0x05, 0x12, 0x0a, 0xd5 } }, { 2272, 16, { 0x90, 0x7f, 0xab, 0x74, 0xff, 0xf0, 0x90, 0x7f, 0xa9, 0xf0, 0x90, 0x7f, 0xaa, 0xf0, 0x53, 0x91 } }, { 2288, 8, { 0xef, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xf7, 0xf0 } }, { 2296, 3, { 0xe4, 0xf5, 0x36 } }, { 2299, 5, { 0xe0, 0x44, 0x04, 0xf0, 0x22 } }, { 1992, 2, { 0xa9, 0x07 } }, { 1994, 16, { 0xae, 0x0c, 0xaf, 0x0d, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xe0, 0x64, 0x03, 0x70, 0x17, 0xad, 0x01 } }, { 2010, 16, { 0x19, 0xed, 0x70, 0x01, 0x22, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x7c, 0x00, 0x2f, 0xfd, 0xec, 0x3e } }, { 2026, 9, { 0xfe, 0xaf, 0x05, 0x80, 0xdf, 0x7e, 0x00, 0x7f, 0x00 } }, { 2035, 1, { 0x22 } }, { 2304, 16, { 0xe4, 0xfe, 0xac, 0x0a, 0xad, 0x0b, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xe0, 0x64, 0x02, 0x70, 0x2d } }, { 2320, 16, { 0xab, 0x06, 0x0e, 0xeb, 0xb5, 0x07, 0x05, 0xaf, 0x05, 0xae, 0x04, 0x22, 0x8d, 0x82, 0x8c, 0x83 } }, { 2336, 16, { 0xa3, 0xa3, 0xe0, 0xf5, 0x41, 0xa3, 0xe0, 0xf5, 0x42, 0x62, 0x41, 0xe5, 0x41, 0x62, 0x42, 0xe5 } }, { 2352, 16, { 0x42, 0x62, 0x41, 0x2d, 0xfb, 0xe5, 0x41, 0x3c, 0xfc, 0xad, 0x03, 0x80, 0xc9, 0x7e, 0x00, 0x7f } }, { 2368, 1, { 0x0 } }, { 2369, 1, { 0x22 } }, { 2773, 16, { 0x8e, 0x37, 0x8f, 0x38, 0xe5, 0x38, 0x15, 0x38, 0xae, 0x37, 0x70, 0x02, 0x15, 0x37, 0x4e, 0x60 } }, { 2789, 7, { 0x5, 0x12, 0x0a, 0x59, 0x80, 0xee, 0x22 } }, { 2649, 16, { 0x74, 0x00, 0xf5, 0x86, 0x90, 0xfd, 0xa5, 0x7c, 0x05, 0xa3, 0xe5, 0x82, 0x45, 0x83, 0x70, 0xf9 } }, { 2665, 1, { 0x22 } }, { 2666, 16, { 0xe4, 0xff, 0xfe, 0x7e, 0x02, 0x7f, 0x00, 0x90, 0x0d, 0xff, 0xe4, 0xf0, 0xa3, 0xdf, 0xfc, 0xde } }, { 2682, 11, { 0xfa, 0x7f, 0x06, 0x12, 0x07, 0x15, 0x90, 0x0f, 0xfe, 0xef, 0xf0 } }, { 2693, 1, { 0x22 } }, { 2694, 16, { 0xd2, 0x9f, 0xd2, 0x9e, 0xd2, 0x9d, 0xc2, 0x9c, 0xd2, 0x9b, 0xd2, 0xbc, 0xc2, 0xc9, 0xd2, 0xcc } }, { 2710, 11, { 0xd2, 0xcd, 0x75, 0xcb, 0xff, 0x75, 0xca, 0xfd, 0xd2, 0xca, 0x22 } }, { 2448, 16, { 0x90, 0x7f, 0x9b, 0xe0, 0xff, 0x25, 0xe0, 0x25, 0xe0, 0x54, 0x30, 0xff, 0x90, 0x7e, 0x40, 0xe0 } }, { 2464, 16, { 0x54, 0x0f, 0x4f, 0x90, 0x7e, 0x80, 0xf0, 0x90, 0x7f, 0x9a, 0xe0, 0x90, 0x7e, 0x81, 0xf0, 0xa3 } }, { 2480, 7, { 0x74, 0x01, 0xf0, 0xe4, 0xa3, 0xf0, 0x22 } }, { 2838, 9, { 0xc2, 0x99, 0xc2, 0x98, 0xd2, 0xac, 0x02, 0x0a, 0xbb } }, { 2747, 16, { 0x75, 0xcb, 0xff, 0x75, 0xca, 0xf8, 0x75, 0x10, 0x02, 0x75, 0x11, 0x59, 0xe4, 0xf5, 0x99, 0x90 } }, { 2763, 10, { 0x7f, 0x9b, 0xe0, 0x64, 0x40, 0x90, 0x7f, 0x98, 0xf0, 0x22 } }, { 35, 3, { 0x2, 0x05, 0x76 } }, { 1398, 16, { 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xc0 } }, { 1414, 16, { 0xd0, 0xc2, 0x99, 0xc3, 0xe5, 0x10, 0x94, 0x02, 0x50, 0x19, 0x74, 0xff, 0x25, 0x11, 0xf5, 0x82 } }, { 1430, 16, { 0x74, 0x0d, 0x35, 0x10, 0xf5, 0x83, 0xe0, 0xf5, 0x99, 0x05, 0x11, 0xe5, 0x11, 0x70, 0x32, 0x05 } }, { 1446, 16, { 0x10, 0x80, 0x2e, 0xe4, 0xb5, 0x11, 0x0a, 0xe5, 0x10, 0xb4, 0x02, 0x05, 0x12, 0x0a, 0xbb, 0x80 } }, { 1462, 16, { 0x20, 0xe5, 0x11, 0xb4, 0x59, 0x16, 0xe5, 0x10, 0xb4, 0x02, 0x11, 0x75, 0xcb, 0xff, 0x75, 0xca } }, { 1478, 16, { 0xfd, 0x75, 0x10, 0x00, 0x75, 0x11, 0x00, 0x75, 0x99, 0x00, 0x80, 0x05, 0x30, 0x98, 0x02, 0xc2 } }, { 1494, 16, { 0x98, 0xd0, 0xd0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32 } }, { 2824, 14, { 0x90, 0x7e, 0x40, 0xe0, 0x54, 0xf0, 0x24, 0x80, 0x70, 0x03, 0x12, 0x05, 0xe6, 0x22 } }, { 1510, 16, { 0x75, 0x22, 0x01, 0x7a, 0x7e, 0x79, 0x41, 0x75, 0x23, 0x01, 0x75, 0x24, 0x7e, 0x75, 0x25, 0x41 } }, { 1526, 16, { 0xab, 0x23, 0xaa, 0x24, 0xa9, 0x25, 0x12, 0x08, 0x58, 0x75, 0xf0, 0x02, 0xa4, 0xff, 0xae, 0xf0 } }, { 1542, 16, { 0x90, 0x00, 0x01, 0x12, 0x08, 0x71, 0xf5, 0x21, 0x74, 0x02, 0x25, 0x25, 0xf5, 0x25, 0xe4, 0x35 } }, { 1558, 16, { 0x24, 0xf5, 0x24, 0xe5, 0x21, 0x54, 0x0f, 0xfd, 0xed, 0x60, 0x29, 0xab, 0x23, 0xaa, 0x24, 0xa9 } }, { 1574, 16, { 0x25, 0x12, 0x08, 0x58, 0xfc, 0x74, 0xff, 0x2f, 0xf5, 0x82, 0x74, 0x0d, 0x3e, 0xf5, 0x83, 0xec } }, { 1590, 16, { 0xf0, 0x74, 0x01, 0x25, 0x25, 0xf5, 0x25, 0xe4, 0x35, 0x24, 0xf5, 0x24, 0x0f, 0xbf, 0x00, 0x01 } }, { 1606, 12, { 0xe, 0x1d, 0x80, 0xd4, 0xe5, 0x21, 0x54, 0x80, 0xf5, 0x22, 0x70, 0xa4 } }, { 1618, 1, { 0x22 } }, { 1813, 16, { 0xae, 0xe8, 0xc2, 0xe9, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0, 0x90, 0x7f, 0xa6, 0x74, 0xa0 } }, { 1829, 16, { 0xf0, 0x90, 0x7f, 0xa5, 0xe0, 0x30, 0xe0, 0xf9, 0x90, 0x7f, 0xa6, 0xef, 0xf0, 0x90, 0x7f, 0xa5 } }, { 1845, 16, { 0xe0, 0x30, 0xe0, 0xf9, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0, 0x90, 0x7f, 0xa6, 0x74, 0xa1 } }, { 1861, 16, { 0xf0, 0x90, 0x7f, 0xa5, 0xe0, 0x30, 0xe0, 0xf9, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x20, 0xf0, 0x90 } }, { 1877, 16, { 0x7f, 0xa6, 0xe0, 0xff, 0x90, 0x7f, 0xa5, 0xe0, 0x30, 0xe0, 0xf9, 0x90, 0x7f, 0xa5, 0xe0, 0x44 } }, { 1893, 9, { 0x40, 0xf0, 0x90, 0x7f, 0xa6, 0xe0, 0xff, 0x8e, 0xe8 } }, { 1902, 1, { 0x22 } }, { 0, 3, { 0x2, 0x07, 0xf4 } }, { 2036, 12, { 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x42, 0x02, 0x03, 0x6b } }, { 2136, 16, { 0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, 0xfe, 0x02 } }, { 2152, 9, { 0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22 } }, { 2161, 16, { 0xbb, 0x01, 0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50 } }, { 2177, 16, { 0x6, 0xe9, 0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22 } }, { 2193, 13, { 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22 } }, { 2206, 16, { 0xeb, 0x9f, 0xf5, 0xf0, 0xea, 0x9e, 0x42, 0xf0, 0xe9, 0x9d, 0x42, 0xf0, 0xe8, 0x9c, 0x45, 0xf0 } }, { 2222, 1, { 0x22 } }, { 32658, 1, { 0x1 } }, /* reset=1 */ { 32658, 1, { 0x0 } }, /* reset=0 */ { SUNLITE_END_OF_FIRMWARE, 0, {0x00}} }; static const struct sunlite_hex_record sunlite_firmware_in[] = { {0x7f92, 0x1, {0x01}}, {0x7f92, 0x1, {0x01}}, {0x146c, 0x10, {0xC2, 0x00, 0x90, 0x7F, 0xA5, 0xE0, 0x54, 0x18, 0xFF, 0x13, 0x13, 0x13, 0x54, 0x1F, 0x44, 0x50}}, {0x147c, 0x10, {0xF5, 0x1C, 0x13, 0x92, 0x01, 0xD2, 0xE8, 0x90, 0x7F, 0xAB, 0x74, 0xFF, 0xF0, 0x90, 0x7F, 0xA9}}, {0x148c, 0x10, {0xF0, 0x90, 0x7F, 0xAA, 0xF0, 0x53, 0x91, 0xEF, 0x90, 0x7F, 0x95, 0xE0, 0x44, 0xC0, 0xF0, 0x90}}, {0x149c, 0x10, {0x7F, 0xAF, 0xE0, 0x44, 0x01, 0xF0, 0x90, 0x7F, 0xAE, 0xE0, 0x44, 0x05, 0xF0, 0xD2, 0xAF, 0x12}}, {0x14ac, 0xd, {0x17, 0x5F, 0x30, 0x00, 0xFD, 0x12, 0x11, 0x00, 0xC2, 0x00, 0x80, 0xF6, 0x22}}, {0x1100, 0x10, {0x90, 0x7F, 0xE9, 0xE0, 0x24, 0x5D, 0x60, 0x0D, 0x14, 0x70, 0x03, 0x02, 0x12, 0x44, 0x24, 0x02}}, {0x1110, 0x10, {0x60, 0x03, 0x02, 0x12, 0x4A, 0x90, 0x7F, 0xEA, 0xE0, 0x75, 0x08, 0x00, 0xF5, 0x09, 0xA3, 0xE0}}, {0x1120, 0x10, {0xFE, 0xE4, 0x25, 0x09, 0xF5, 0x09, 0xEE, 0x35, 0x08, 0xF5, 0x08, 0x90, 0x7F, 0xEE, 0xE0, 0x75}}, {0x1130, 0x10, {0x0A, 0x00, 0xF5, 0x0B, 0xA3, 0xE0, 0xFE, 0xE4, 0x25, 0x0B, 0xF5, 0x0B, 0xEE, 0x35, 0x0A, 0xF5}}, {0x1140, 0x10, {0x0A, 0x90, 0x7F, 0xE8, 0xE0, 0x64, 0xC0, 0x60, 0x03, 0x02, 0x11, 0xD4, 0xE5, 0x0B, 0x45, 0x0A}}, {0x1150, 0x10, {0x70, 0x03, 0x02, 0x12, 0x4A, 0xC3, 0xE5, 0x0B, 0x94, 0x40, 0xE5, 0x0A, 0x94, 0x00, 0x50, 0x08}}, {0x1160, 0x10, {0x85, 0x0A, 0x0C, 0x85, 0x0B, 0x0D, 0x80, 0x06, 0x75, 0x0C, 0x00, 0x75, 0x0D, 0x40, 0x90, 0x7F}}, {0x1170, 0x10, {0xE9, 0xE0, 0xB4, 0xA3, 0x25, 0xAE, 0x0C, 0xAF, 0x0D, 0xAA, 0x08, 0xA9, 0x09, 0x7B, 0x01, 0xC0}}, {0x1180, 0x10, {0x03, 0xC0, 0x02, 0xC0, 0x01, 0x7A, 0x7F, 0x79, 0x00, 0x78, 0x00, 0x7C, 0x7F, 0xAD, 0x03, 0xD0}}, {0x1190, 0x10, {0x01, 0xD0, 0x02, 0xD0, 0x03, 0x12, 0x13, 0x56, 0x80, 0x0F, 0xAF, 0x09, 0xAE, 0x08, 0xAD, 0x0D}}, {0x11a0, 0x10, {0x7A, 0x7F, 0x79, 0x00, 0x7B, 0x00, 0x12, 0x15, 0xA4, 0x90, 0x7F, 0xB5, 0xE5, 0x0D, 0xF0, 0xE5}}, {0x11b0, 0x10, {0x0D, 0x25, 0x09, 0xF5, 0x09, 0xE5, 0x0C, 0x35, 0x08, 0xF5, 0x08, 0xC3, 0xE5, 0x0B, 0x95, 0x0D}}, {0x11c0, 0x10, {0xF5, 0x0B, 0xE5, 0x0A, 0x95, 0x0C, 0xF5, 0x0A, 0x90, 0x7F, 0xB4, 0xE0, 0x20, 0xE2, 0x03, 0x02}}, {0x11d0, 0x10, {0x11, 0x4C, 0x80, 0xF4, 0x90, 0x7F, 0xE8, 0xE0, 0x64, 0x40, 0x70, 0x6E, 0xE5, 0x0B, 0x45, 0x0A}}, {0x11e0, 0x10, {0x60, 0x68, 0xE4, 0x90, 0x7F, 0xC5, 0xF0, 0x90, 0x7F, 0xB4, 0xE0, 0x20, 0xE3, 0xF9, 0x90, 0x7F}}, {0x11f0, 0x10, {0xC5, 0xE0, 0x75, 0x0C, 0x00, 0xF5, 0x0D, 0x90, 0x7F, 0xE9, 0xE0, 0xB4, 0xA3, 0x15, 0xAE, 0x0C}}, {0x1200, 0x10, {0xAF, 0x0D, 0xA8, 0x09, 0xAC, 0x08, 0x7D, 0x01, 0x7B, 0x01, 0x7A, 0x7E, 0x79, 0xC0, 0x12, 0x13}}, {0x1210, 0x10, {0x56, 0x80, 0x0F, 0xAF, 0x09, 0xAE, 0x08, 0xAD, 0x0D, 0x7A, 0x7F, 0x79, 0x00, 0x7B, 0x00, 0x12}}, {0x1220, 0x10, {0x14, 0xB9, 0xE5, 0x0D, 0x25, 0x09, 0xF5, 0x09, 0xE5, 0x0C, 0x35, 0x08, 0xF5, 0x08, 0xC3, 0xE5}}, {0x1230, 0x10, {0x0B, 0x95, 0x0D, 0xF5, 0x0B, 0xE5, 0x0A, 0x95, 0x0C, 0xF5, 0x0A, 0x90, 0x7F, 0xB4, 0xE0, 0x44}}, {0x1240, 0xa, {0x02, 0xF0, 0x80, 0x98, 0x90, 0x7F, 0xEA, 0xE0, 0xF5, 0x1C}}, {0x124a, 0x1, {0x22}}, {0x1558, 0x6, {0xAB, 0x07, 0xAA, 0x06, 0xAC, 0x05}}, {0x155e, 0x10, {0xE4, 0xFD, 0x30, 0x01, 0x11, 0xEA, 0xFF, 0xAE, 0x05, 0x0D, 0xEE, 0x24, 0x00, 0xF5, 0x82, 0xE4}}, {0x156e, 0x10, {0x34, 0xE0, 0xF5, 0x83, 0xEF, 0xF0, 0xEB, 0xAE, 0x05, 0x0D, 0x74, 0x00, 0x2E, 0xF5, 0x82, 0xE4}}, {0x157e, 0x10, {0x34, 0xE0, 0xF5, 0x83, 0xEB, 0xF0, 0xAF, 0x05, 0x0D, 0x74, 0x00, 0x2F, 0xF5, 0x82, 0xE4, 0x34}}, {0x158e, 0x10, {0xE0, 0xF5, 0x83, 0xEC, 0xF0, 0xAF, 0x1C, 0x7A, 0xE0, 0x7B, 0x00, 0x12, 0x17, 0x20, 0x7F, 0x0A}}, {0x159e, 0x5, {0x7E, 0x00, 0x12, 0x17, 0x3C}}, {0x15a3, 0x1, {0x22}}, {0x14b9, 0xa, {0x8E, 0x0E, 0x8F, 0x0F, 0x8D, 0x10, 0x8A, 0x11, 0x8B, 0x12}}, {0x14c3, 0x10, {0xE4, 0xF5, 0x13, 0xE5, 0x13, 0xC3, 0x95, 0x10, 0x50, 0x20, 0x05, 0x0F, 0xE5, 0x0F, 0xAE, 0x0E}}, {0x14d3, 0x10, {0x70, 0x02, 0x05, 0x0E, 0x14, 0xFF, 0xE5, 0x12, 0x25, 0x13, 0xF5, 0x82, 0xE4, 0x35, 0x11, 0xF5}}, {0x14e3, 0xa, {0x83, 0xE0, 0xFD, 0x12, 0x15, 0x58, 0x05, 0x13, 0x80, 0xD9}}, {0x14ed, 0x1, {0x22}}, {0x15a4, 0xa, {0x8E, 0x0E, 0x8F, 0x0F, 0x8D, 0x10, 0x8A, 0x11, 0x8B, 0x12}}, {0x15ae, 0x10, {0xE4, 0xFD, 0x30, 0x01, 0x12, 0xE5, 0x0E, 0xFF, 0xAE, 0x05, 0x0D, 0xEE, 0x24, 0x03, 0xF5, 0x82}}, {0x15be, 0x10, {0xE4, 0x34, 0xE0, 0xF5, 0x83, 0xEF, 0xF0, 0xE5, 0x0F, 0xAE, 0x05, 0x0D, 0x74, 0x03, 0x2E, 0xF5}}, {0x15ce, 0x10, {0x82, 0xE4, 0x34, 0xE0, 0xF5, 0x83, 0xE5, 0x0F, 0xF0, 0xAF, 0x1C, 0x7A, 0xE0, 0x7B, 0x03, 0x12}}, {0x15de, 0xd, {0x17, 0x20, 0xAF, 0x1C, 0xAD, 0x10, 0xAB, 0x12, 0xAA, 0x11, 0x12, 0x17, 0x04}}, {0x15eb, 0x1, {0x22}}, {0x166e, 0x10, {0xC0, 0xE0, 0xC0, 0x83, 0xC0, 0x82, 0xC0, 0x85, 0xC0, 0x84, 0xC0, 0x86, 0x75, 0x86, 0x00, 0xD2}}, {0x167e, 0x10, {0x00, 0x53, 0x91, 0xEF, 0x90, 0x7F, 0xAB, 0x74, 0x01, 0xF0, 0xD0, 0x86, 0xD0, 0x84, 0xD0, 0x85}}, {0x168e, 0x7, {0xD0, 0x82, 0xD0, 0x83, 0xD0, 0xE0, 0x32}}, {0x1644, 0x10, {0xC0, 0xE0, 0xC0, 0x83, 0xC0, 0x82, 0xC0, 0x85, 0xC0, 0x84, 0xC0, 0x86, 0x75, 0x86, 0x00, 0x90}}, {0x1654, 0x10, {0x7F, 0xC4, 0xE4, 0xF0, 0x53, 0x91, 0xEF, 0x90, 0x7F, 0xAB, 0x74, 0x04, 0xF0, 0xD0, 0x86, 0xD0}}, {0x1664, 0xa, {0x84, 0xD0, 0x85, 0xD0, 0x82, 0xD0, 0x83, 0xD0, 0xE0, 0x32}}, {0x1695, 0x10, {0xC0, 0xE0, 0xC0, 0x83, 0xC0, 0x82, 0xC0, 0x85, 0xC0, 0x84, 0xC0, 0x86, 0x75, 0x86, 0x00, 0x53}}, {0x16a5, 0x10, {0x91, 0xEF, 0x90, 0x7F, 0xAB, 0x74, 0x02, 0xF0, 0xD0, 0x86, 0xD0, 0x84, 0xD0, 0x85, 0xD0, 0x82}}, {0x16b5, 0x5, {0xD0, 0x83, 0xD0, 0xE0, 0x32}}, {0x16ba, 0x10, {0xC0, 0xE0, 0xC0, 0x83, 0xC0, 0x82, 0xC0, 0x85, 0xC0, 0x84, 0xC0, 0x86, 0x75, 0x86, 0x00, 0x53}}, {0x16ca, 0x10, {0x91, 0xEF, 0x90, 0x7F, 0xAB, 0x74, 0x10, 0xF0, 0xD0, 0x86, 0xD0, 0x84, 0xD0, 0x85, 0xD0, 0x82}}, {0x16da, 0x5, {0xD0, 0x83, 0xD0, 0xE0, 0x32}}, {0x14ff, 0x1, {0x32}}, {0x16df, 0x10, {0xC0, 0xE0, 0xC0, 0x83, 0xC0, 0x82, 0xC0, 0x85, 0xC0, 0x84, 0xC0, 0x86, 0x75, 0x86, 0x00, 0x53}}, {0x16ef, 0x10, {0x91, 0xEF, 0x90, 0x7F, 0xAB, 0x74, 0x08, 0xF0, 0xD0, 0x86, 0xD0, 0x84, 0xD0, 0x85, 0xD0, 0x82}}, {0x16ff, 0x5, {0xD0, 0x83, 0xD0, 0xE0, 0x32}}, {0x1767, 0x1, {0x32}}, {0x1768, 0x1, {0x32}}, {0x1769, 0x1, {0x32}}, {0x176a, 0x1, {0x32}}, {0x176b, 0x1, {0x32}}, {0x176c, 0x1, {0x32}}, {0x176d, 0x1, {0x32}}, {0x176e, 0x1, {0x32}}, {0x176f, 0x1, {0x32}}, {0x1770, 0x1, {0x32}}, {0x1771, 0x1, {0x32}}, {0x1772, 0x1, {0x32}}, {0x1773, 0x1, {0x32}}, {0x1774, 0x1, {0x32}}, {0x1775, 0x1, {0x32}}, {0x1776, 0x1, {0x32}}, {0x43, 0x3, {0x02, 0x15, 0x00}}, {0x1500, 0x10, {0x02, 0x16, 0x6E, 0x00, 0x02, 0x16, 0x95, 0x00, 0x02, 0x16, 0x44, 0x00, 0x02, 0x16, 0xDF, 0x00}}, {0x1510, 0x10, {0x02, 0x16, 0xBA, 0x00, 0x02, 0x14, 0xFF, 0x00, 0x02, 0x17, 0x67, 0x00, 0x02, 0x17, 0x68, 0x00}}, {0x1520, 0x10, {0x02, 0x17, 0x69, 0x00, 0x02, 0x17, 0x6A, 0x00, 0x02, 0x17, 0x6B, 0x00, 0x02, 0x17, 0x6C, 0x00}}, {0x1530, 0x10, {0x02, 0x17, 0x6D, 0x00, 0x02, 0x17, 0x6E, 0x00, 0x02, 0x17, 0x6F, 0x00, 0x02, 0x17, 0x70, 0x00}}, {0x1540, 0x10, {0x02, 0x17, 0x71, 0x00, 0x02, 0x17, 0x72, 0x00, 0x02, 0x17, 0x73, 0x00, 0x02, 0x17, 0x74, 0x00}}, {0x1550, 0x8, {0x02, 0x17, 0x75, 0x00, 0x02, 0x17, 0x76, 0x00}}, {0x173c, 0x10, {0x8E, 0x14, 0x8F, 0x15, 0xE5, 0x15, 0x15, 0x15, 0xAE, 0x14, 0x70, 0x02, 0x15, 0x14, 0x4E, 0x60}}, {0x174c, 0x7, {0x05, 0x12, 0x14, 0xEE, 0x80, 0xEE, 0x22}}, {0x175f, 0x8, {0xE4, 0xF5, 0x1B, 0xD2, 0xE9, 0xD2, 0xAF, 0x22}}, {0x1619, 0x10, {0xA9, 0x07, 0xE5, 0x1B, 0x70, 0x23, 0x90, 0x7F, 0xA5, 0xE0, 0x44, 0x80, 0xF0, 0xE9, 0x25, 0xE0}}, {0x1629, 0x10, {0x90, 0x7F, 0xA6, 0xF0, 0x8D, 0x16, 0xAF, 0x03, 0xA9, 0x07, 0x75, 0x17, 0x01, 0x8A, 0x18, 0x89}}, {0x1639, 0xb, {0x19, 0xE4, 0xF5, 0x1A, 0x75, 0x1B, 0x01, 0xD3, 0x22, 0xC3, 0x22}}, {0x15ec, 0x10, {0xA9, 0x07, 0xE5, 0x1B, 0x70, 0x25, 0x90, 0x7F, 0xA5, 0xE0, 0x44, 0x80, 0xF0, 0xE9, 0x25, 0xE0}}, {0x15fc, 0x10, {0x44, 0x01, 0x90, 0x7F, 0xA6, 0xF0, 0x8D, 0x16, 0xAF, 0x03, 0xA9, 0x07, 0x75, 0x17, 0x01, 0x8A}}, {0x160c, 0xd, {0x18, 0x89, 0x19, 0xE4, 0xF5, 0x1A, 0x75, 0x1B, 0x03, 0xD3, 0x22, 0xC3, 0x22}}, {0x4b, 0x3, {0x02, 0x13, 0x7F}}, {0x137f, 0x10, {0xC0, 0xE0, 0xC0, 0x83, 0xC0, 0x82, 0xC0, 0x85, 0xC0, 0x84, 0xC0, 0x86, 0x75, 0x86, 0x00, 0xC0}}, {0x138f, 0x10, {0xD0, 0x75, 0xD0, 0x00, 0xC0, 0x00, 0xC0, 0x01, 0xC0, 0x02, 0xC0, 0x03, 0xC0, 0x06, 0xC0, 0x07}}, {0x139f, 0x10, {0x90, 0x7F, 0xA5, 0xE0, 0x30, 0xE2, 0x06, 0x75, 0x1B, 0x06, 0x02, 0x14, 0x4E, 0x90, 0x7F, 0xA5}}, {0x13af, 0x10, {0xE0, 0x20, 0xE1, 0x0C, 0xE5, 0x1B, 0x64, 0x02, 0x60, 0x06, 0x75, 0x1B, 0x07, 0x02, 0x14, 0x4E}}, {0x13bf, 0x10, {0xAF, 0x1B, 0xEF, 0x24, 0xFE, 0x60, 0x48, 0x14, 0x60, 0x2C, 0x24, 0xFE, 0x60, 0x77, 0x24, 0x04}}, {0x13cf, 0x10, {0x60, 0x03, 0x02, 0x14, 0x4E, 0xAB, 0x17, 0xAA, 0x18, 0xA9, 0x19, 0xAF, 0x1A, 0x05, 0x1A, 0x8F}}, {0x13df, 0x10, {0x82, 0x75, 0x83, 0x00, 0x12, 0x12, 0x4B, 0x90, 0x7F, 0xA6, 0xF0, 0xE5, 0x1A, 0x65, 0x16, 0x70}}, {0x13ef, 0x10, {0x5E, 0x75, 0x1B, 0x05, 0x80, 0x59, 0x90, 0x7F, 0xA6, 0xE0, 0xAB, 0x17, 0xAA, 0x18, 0xA9, 0x19}}, {0x13ff, 0x10, {0xAE, 0x1A, 0x8E, 0x82, 0x75, 0x83, 0x00, 0x12, 0x12, 0x78, 0x75, 0x1B, 0x02, 0x80, 0x40, 0xE5}}, {0x140f, 0x10, {0x16, 0x24, 0xFE, 0xB5, 0x1A, 0x07, 0x90, 0x7F, 0xA5, 0xE0, 0x44, 0x20, 0xF0, 0xE5, 0x16, 0x14}}, {0x141f, 0x10, {0xB5, 0x1A, 0x0A, 0x90, 0x7F, 0xA5, 0xE0, 0x44, 0x40, 0xF0, 0x75, 0x1B, 0x00, 0x90, 0x7F, 0xA6}}, {0x142f, 0x10, {0xE0, 0xAB, 0x17, 0xAA, 0x18, 0xA9, 0x19, 0xAE, 0x1A, 0x8E, 0x82, 0x75, 0x83, 0x00, 0x12, 0x12}}, {0x143f, 0x10, {0x78, 0x05, 0x1A, 0x80, 0x0A, 0x90, 0x7F, 0xA5, 0xE0, 0x44, 0x40, 0xF0, 0x75, 0x1B, 0x00, 0x53}}, {0x144f, 0x10, {0x91, 0xDF, 0xD0, 0x07, 0xD0, 0x06, 0xD0, 0x03, 0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, 0xD0, 0xD0}}, {0x145f, 0xd, {0xD0, 0x86, 0xD0, 0x84, 0xD0, 0x85, 0xD0, 0x82, 0xD0, 0x83, 0xD0, 0xE0, 0x32}}, {0x1704, 0x10, {0x12, 0x15, 0xEC, 0xE5, 0x1B, 0x24, 0xFA, 0x60, 0x0E, 0x14, 0x60, 0x06, 0x24, 0x07, 0x70, 0xF3}}, {0x1714, 0xc, {0xD3, 0x22, 0xE4, 0xF5, 0x1B, 0xD3, 0x22, 0xE4, 0xF5, 0x1B, 0xD3, 0x22}}, {0x1720, 0x10, {0x12, 0x16, 0x19, 0xE5, 0x1B, 0x24, 0xFA, 0x60, 0x0E, 0x14, 0x60, 0x06, 0x24, 0x07, 0x70, 0xF3}}, {0x1730, 0xc, {0xD3, 0x22, 0xE4, 0xF5, 0x1B, 0xD3, 0x22, 0xE4, 0xF5, 0x1B, 0xD3, 0x22}}, {0x14ee, 0x10, {0x74, 0x00, 0xF5, 0x86, 0x90, 0xFD, 0xA5, 0x7C, 0x05, 0xA3, 0xE5, 0x82, 0x45, 0x83, 0x70, 0xF9}}, {0x14fe, 0x1, {0x22}}, {0x0, 0x3, {0x02, 0x17, 0x53}}, {0x1753, 0xc, {0x78, 0x7F, 0xE4, 0xF6, 0xD8, 0xFD, 0x75, 0x81, 0x20, 0x02, 0x14, 0x6C}}, {0x124b, 0x10, {0xBB, 0x01, 0x0C, 0xE5, 0x82, 0x29, 0xF5, 0x82, 0xE5, 0x83, 0x3A, 0xF5, 0x83, 0xE0, 0x22, 0x50}}, {0x125b, 0x10, {0x06, 0xE9, 0x25, 0x82, 0xF8, 0xE6, 0x22, 0xBB, 0xFE, 0x06, 0xE9, 0x25, 0x82, 0xF8, 0xE2, 0x22}}, {0x126b, 0xd, {0xE5, 0x82, 0x29, 0xF5, 0x82, 0xE5, 0x83, 0x3A, 0xF5, 0x83, 0xE4, 0x93, 0x22}}, {0x1278, 0x10, {0xF8, 0xBB, 0x01, 0x0D, 0xE5, 0x82, 0x29, 0xF5, 0x82, 0xE5, 0x83, 0x3A, 0xF5, 0x83, 0xE8, 0xF0}}, {0x1288, 0x10, {0x22, 0x50, 0x06, 0xE9, 0x25, 0x82, 0xC8, 0xF6, 0x22, 0xBB, 0xFE, 0x05, 0xE9, 0x25, 0x82, 0xC8}}, {0x1298, 0x2, {0xF2, 0x22}}, {0x129a, 0x10, {0xE7, 0x09, 0xF6, 0x08, 0xDF, 0xFA, 0x80, 0x46, 0xE7, 0x09, 0xF2, 0x08, 0xDF, 0xFA, 0x80, 0x3E}}, {0x12aa, 0x10, {0x88, 0x82, 0x8C, 0x83, 0xE7, 0x09, 0xF0, 0xA3, 0xDF, 0xFA, 0x80, 0x32, 0xE3, 0x09, 0xF6, 0x08}}, {0x12ba, 0x10, {0xDF, 0xFA, 0x80, 0x6E, 0xE3, 0x09, 0xF2, 0x08, 0xDF, 0xFA, 0x80, 0x66, 0x88, 0x82, 0x8C, 0x83}}, {0x12ca, 0x10, {0xE3, 0x09, 0xF0, 0xA3, 0xDF, 0xFA, 0x80, 0x5A, 0x89, 0x82, 0x8A, 0x83, 0xE0, 0xA3, 0xF6, 0x08}}, {0x12da, 0x10, {0xDF, 0xFA, 0x80, 0x4E, 0x89, 0x82, 0x8A, 0x83, 0xE0, 0xA3, 0xF2, 0x08, 0xDF, 0xFA, 0x80, 0x42}}, {0x12ea, 0x10, {0x80, 0xD2, 0x80, 0xFA, 0x80, 0xC6, 0x80, 0xD4, 0x80, 0x55, 0x80, 0xF2, 0x80, 0x29, 0x80, 0x10}}, {0x12fa, 0x10, {0x80, 0xA6, 0x80, 0xEA, 0x80, 0x9A, 0x80, 0xA8, 0x80, 0xDA, 0x80, 0xE2, 0x80, 0xCA, 0x80, 0x29}}, {0x130a, 0x10, {0x88, 0x84, 0x8C, 0x85, 0x89, 0x82, 0x8A, 0x83, 0xE4, 0x93, 0xA3, 0x05, 0x86, 0xF0, 0xA3, 0x05}}, {0x131a, 0x10, {0x86, 0xDF, 0xF5, 0xDE, 0xF3, 0x80, 0x0B, 0x89, 0x82, 0x8A, 0x83, 0xE4, 0x93, 0xA3, 0xF6, 0x08}}, {0x132a, 0x10, {0xDF, 0xF9, 0xEC, 0xFA, 0xA9, 0xF0, 0xED, 0xFB, 0x22, 0x88, 0x84, 0x8C, 0x85, 0x89, 0x82, 0x8A}}, {0x133a, 0x10, {0x83, 0xE0, 0xA3, 0x05, 0x86, 0xF0, 0xA3, 0x05, 0x86, 0xDF, 0xF6, 0xDE, 0xF4, 0x80, 0xE3, 0x89}}, {0x134a, 0x10, {0x82, 0x8A, 0x83, 0xE4, 0x93, 0xA3, 0xF2, 0x08, 0xDF, 0xF9, 0x80, 0xD6, 0x88, 0xF0, 0xED, 0x24}}, {0x135a, 0x10, {0x02, 0xB4, 0x04, 0x00, 0x50, 0xCC, 0xF5, 0x82, 0xEB, 0x24, 0x02, 0xB4, 0x04, 0x00, 0x50, 0xC2}}, {0x136a, 0x10, {0x23, 0x23, 0x45, 0x82, 0xF5, 0x82, 0xEF, 0x4E, 0x60, 0xB8, 0xEF, 0x60, 0x01, 0x0E, 0xE5, 0x82}}, {0x137a, 0x5, {0x23, 0x90, 0x12, 0xEA, 0x73}}, {0x7f92, 0x1, {0x00}}, {0x7f92, 0x1, {0x01}}, {0xb29, 0x10, {0xD2, 0x00, 0x90, 0x7F, 0xA1, 0x74, 0x01, 0xF0, 0xE4, 0x90, 0x7F, 0x93, 0xF0, 0x90, 0x7F, 0x94}}, {0xb39, 0x10, {0xF0, 0x90, 0x7F, 0x95, 0x74, 0x03, 0xF0, 0x90, 0x7F, 0x9C, 0x74, 0x30, 0xF0, 0xE4, 0x90, 0x7F}}, {0xb49, 0x10, {0x9D, 0xF0, 0x90, 0x7F, 0x9E, 0x74, 0xF2, 0xF0, 0xE4, 0x90, 0x7F, 0x96, 0xF0, 0x90, 0x7F, 0x98}}, {0xb59, 0x10, {0x74, 0xF2, 0xF0, 0x12, 0x0D, 0x28, 0x12, 0x0D, 0xFE, 0x90, 0x7F, 0xDE, 0xE0, 0x44, 0x04, 0xF0}}, {0xb69, 0x10, {0x90, 0x7F, 0xDF, 0xE0, 0x44, 0x02, 0xF0, 0x90, 0x7F, 0xAD, 0xE0, 0x44, 0x02, 0xF0, 0x12, 0x09}}, {0xb79, 0x2, {0x26, 0x22}}, {0xe32, 0x4, {0x12, 0x03, 0x4F, 0x22}}, {0xe3a, 0x2, {0xD3, 0x22}}, {0xe3c, 0x2, {0xD3, 0x22}}, {0xe3e, 0x2, {0xD3, 0x22}}, {0xbf8, 0x8, {0x90, 0x7F, 0xEA, 0xE0, 0xF5, 0x0F, 0xD3, 0x22}}, {0xe0e, 0xe, {0x90, 0x7F, 0x00, 0xE5, 0x0F, 0xF0, 0x90, 0x7F, 0xB5, 0x74, 0x01, 0xF0, 0xD3, 0x22}}, {0xe2a, 0x8, {0x90, 0x7F, 0xEA, 0xE0, 0xF5, 0x0E, 0xD3, 0x22}}, {0xe1c, 0xe, {0x90, 0x7F, 0x00, 0xE5, 0x0E, 0xF0, 0x90, 0x7F, 0xB5, 0x74, 0x01, 0xF0, 0xD3, 0x22}}, {0xe40, 0x2, {0xD3, 0x22}}, {0xe42, 0x2, {0xD3, 0x22}}, {0xe44, 0x2, {0xD3, 0x22}}, {0xce4, 0x10, {0x90, 0x7F, 0xE8, 0xE0, 0x30, 0xE6, 0x1A, 0xA3, 0xE0, 0x24, 0xF0, 0x70, 0x12, 0x7F, 0x06, 0x12}}, {0xcf4, 0x10, {0x0A, 0xCF, 0x90, 0x7F, 0x00, 0xEF, 0xF0, 0x90, 0x7F, 0xB5, 0x74, 0x01, 0xF0, 0x80, 0x02, 0xD3}}, {0xd04, 0x3, {0x22, 0xC3, 0x22}}, {0xd5f, 0x10, {0xC0, 0xE0, 0xC0, 0x83, 0xC0, 0x82, 0xD2, 0x01, 0x53, 0x91, 0xEF, 0x90, 0x7F, 0xAB, 0x74, 0x01}}, {0xd6f, 0x8, {0xF0, 0xD0, 0x82, 0xD0, 0x83, 0xD0, 0xE0, 0x32}}, {0xda6, 0x10, {0xC0, 0xE0, 0xC0, 0x83, 0xC0, 0x82, 0x53, 0x91, 0xEF, 0x90, 0x7F, 0xAB, 0x74, 0x04, 0xF0, 0xD0}}, {0xdb6, 0x6, {0x82, 0xD0, 0x83, 0xD0, 0xE0, 0x32}}, {0xdbc, 0x10, {0xC0, 0xE0, 0xC0, 0x83, 0xC0, 0x82, 0x53, 0x91, 0xEF, 0x90, 0x7F, 0xAB, 0x74, 0x02, 0xF0, 0xD0}}, {0xdcc, 0x6, {0x82, 0xD0, 0x83, 0xD0, 0xE0, 0x32}}, {0xdd2, 0x10, {0xC0, 0xE0, 0xC0, 0x83, 0xC0, 0x82, 0x53, 0x91, 0xEF, 0x90, 0x7F, 0xAB, 0x74, 0x10, 0xF0, 0xD0}}, {0xde2, 0x6, {0x82, 0xD0, 0x83, 0xD0, 0xE0, 0x32}}, {0xe46, 0x1, {0x32}}, {0xd77, 0x10, {0xC0, 0xE0, 0xC0, 0x83, 0xC0, 0x82, 0xD2, 0x03, 0x53, 0x91, 0xEF, 0x90, 0x7F, 0xAB, 0x74, 0x08}}, {0xd87, 0x8, {0xF0, 0xD0, 0x82, 0xD0, 0x83, 0xD0, 0xE0, 0x32}}, {0xe47, 0x1, {0x32}}, {0xe48, 0x1, {0x32}}, {0xe49, 0x1, {0x32}}, {0xe4a, 0x1, {0x32}}, {0xe4b, 0x1, {0x32}}, {0xe4c, 0x1, {0x32}}, {0xe4d, 0x1, {0x32}}, {0xe4e, 0x1, {0x32}}, {0xe4f, 0x1, {0x32}}, {0xe50, 0x1, {0x32}}, {0xe51, 0x1, {0x32}}, {0xe52, 0x1, {0x32}}, {0xe53, 0x1, {0x32}}, {0xe54, 0x1, {0x32}}, {0xe55, 0x1, {0x32}}, {0xe56, 0x1, {0x32}}, {0xa5f, 0x10, {0x12, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x62, 0x09, 0x01, 0x30, 0x01, 0x11, 0x01, 0x02}}, {0xa6f, 0x10, {0x00, 0x01, 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0xA0, 0x64, 0x09, 0x04, 0x00, 0x00, 0x02}}, {0xa7f, 0x10, {0xFF, 0x00, 0x00, 0x00, 0x07, 0x05, 0x82, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x01, 0x02, 0x40}}, {0xa8f, 0x10, {0x00, 0x00, 0x04, 0x03, 0x09, 0x04, 0x26, 0x03, 0x44, 0x00, 0x69, 0x00, 0x67, 0x00, 0x69, 0x00}}, {0xa9f, 0x10, {0x74, 0x00, 0x61, 0x00, 0x6C, 0x00, 0x20, 0x00, 0x41, 0x00, 0x72, 0x00, 0x74, 0x00, 0x20, 0x00}}, {0xaaf, 0x10, {0x53, 0x00, 0x79, 0x00, 0x73, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6D, 0x00, 0x12, 0x03, 0x53, 0x00}}, {0xabf, 0x10, {0x49, 0x00, 0x55, 0x00, 0x44, 0x00, 0x49, 0x00, 0x2D, 0x00, 0x49, 0x00, 0x4E, 0x00, 0x00, 0x00}}, {0x524, 0x10, {0xE4, 0xF5, 0x2C, 0xF5, 0x2B, 0xF5, 0x2A, 0xF5, 0x29, 0xC2, 0x03, 0xC2, 0x00, 0xC2, 0x02, 0xC2}}, {0x534, 0x10, {0x01, 0x12, 0x0B, 0x29, 0x7E, 0x0A, 0x7F, 0x5F, 0x8E, 0x08, 0x8F, 0x09, 0x75, 0x0A, 0x0A, 0x75}}, {0x544, 0x10, {0x0B, 0x71, 0x75, 0x0C, 0x0A, 0x75, 0x0D, 0x91, 0xEE, 0x54, 0xE0, 0x70, 0x02, 0xC1, 0x37, 0x75}}, {0x554, 0x10, {0x2D, 0x00, 0x75, 0x2E, 0x80, 0x8E, 0x2F, 0x8F, 0x30, 0xC3, 0x74, 0xCD, 0x9F, 0xFF, 0x74, 0x0A}}, {0x564, 0x10, {0x9E, 0xCF, 0x24, 0x02, 0xCF, 0x34, 0x00, 0xFE, 0xE4, 0x8F, 0x28, 0x8E, 0x27, 0xF5, 0x26, 0xF5}}, {0x574, 0x10, {0x25, 0xF5, 0x24, 0xF5, 0x23, 0xF5, 0x22, 0xF5, 0x21, 0xAF, 0x28, 0xAE, 0x27, 0xAD, 0x26, 0xAC}}, {0x584, 0x10, {0x25, 0xAB, 0x24, 0xAA, 0x23, 0xA9, 0x22, 0xA8, 0x21, 0xC3, 0x12, 0x08, 0x2C, 0x50, 0x2A, 0xE5}}, {0x594, 0x10, {0x2E, 0x25, 0x24, 0xF5, 0x82, 0xE5, 0x2D, 0x35, 0x23, 0xF5, 0x83, 0x74, 0xCD, 0xF0, 0xE4, 0xFA}}, {0x5a4, 0x10, {0xF9, 0xF8, 0xE5, 0x24, 0x24, 0x01, 0xF5, 0x24, 0xEA, 0x35, 0x23, 0xF5, 0x23, 0xE9, 0x35, 0x22}}, {0x5b4, 0x10, {0xF5, 0x22, 0xE8, 0x35, 0x21, 0xF5, 0x21, 0x80, 0xC0, 0xE4, 0xF5, 0x24, 0xF5, 0x23, 0xF5, 0x22}}, {0x5c4, 0x10, {0xF5, 0x21, 0xAF, 0x28, 0xAE, 0x27, 0xAD, 0x26, 0xAC, 0x25, 0xAB, 0x24, 0xAA, 0x23, 0xA9, 0x22}}, {0x5d4, 0x10, {0xA8, 0x21, 0xC3, 0x12, 0x08, 0x2C, 0x50, 0x35, 0xAE, 0x23, 0xAF, 0x24, 0xE5, 0x30, 0x2F, 0xF5}}, {0x5e4, 0x10, {0x82, 0xE5, 0x2F, 0x3E, 0xF5, 0x83, 0xE0, 0xFD, 0xE5, 0x2E, 0x2F, 0xF5, 0x82, 0xE5, 0x2D, 0x3E}}, {0x5f4, 0x10, {0xF5, 0x83, 0xED, 0xF0, 0xE4, 0xFA, 0xF9, 0xF8, 0xEF, 0x24, 0x01, 0xF5, 0x24, 0xEA, 0x3E, 0xF5}}, {0x604, 0x10, {0x23, 0xE9, 0x35, 0x22, 0xF5, 0x22, 0xE8, 0x35, 0x21, 0xF5, 0x21, 0x80, 0xB5, 0x85, 0x2D, 0x08}}, {0x614, 0x10, {0x85, 0x2E, 0x09, 0x74, 0x5F, 0x24, 0x80, 0xFF, 0x74, 0x0A, 0x34, 0xFF, 0xFE, 0xC3, 0xE5, 0x0B}}, {0x624, 0x10, {0x9F, 0xF5, 0x0B, 0xE5, 0x0A, 0x9E, 0xF5, 0x0A, 0xC3, 0xE5, 0x0D, 0x9F, 0xF5, 0x0D, 0xE5, 0x0C}}, {0x634, 0x10, {0x9E, 0xF5, 0x0C, 0xD2, 0xE8, 0x43, 0xD8, 0x20, 0x90, 0x7F, 0xAB, 0x74, 0xFF, 0xF0, 0x90, 0x7F}}, {0x644, 0x10, {0xAF, 0xE0, 0x44, 0x01, 0xF0, 0x90, 0x7F, 0xAE, 0xE0, 0x44, 0x1D, 0xF0, 0xD2, 0xAF, 0x20, 0x01}}, {0x654, 0x10, {0x45, 0x20, 0x01, 0x05, 0xD2, 0x05, 0x12, 0x0B, 0x7B, 0xE4, 0xF5, 0x2C, 0xF5, 0x2B, 0xF5, 0x2A}}, {0x664, 0x10, {0xF5, 0x29, 0x7F, 0x40, 0x7E, 0x92, 0x7D, 0x04, 0x7C, 0x00, 0xAB, 0x2C, 0xAA, 0x2B, 0xA9, 0x2A}}, {0x674, 0x10, {0xA8, 0x29, 0xC3, 0x12, 0x08, 0x2C, 0x50, 0xD6, 0x20, 0x01, 0xD3, 0xE4, 0xFA, 0xF9, 0xF8, 0xE5}}, {0x684, 0x10, {0x2C, 0x24, 0x01, 0xF5, 0x2C, 0xEA, 0x35, 0x2B, 0xF5, 0x2B, 0xE9, 0x35, 0x2A, 0xF5, 0x2A, 0xE8}}, {0x694, 0x10, {0x35, 0x29, 0xF5, 0x29, 0x80, 0xCC, 0x53, 0x8E, 0xF8, 0x30, 0x01, 0x05, 0x12, 0x00, 0x80, 0xC2}}, {0x6a4, 0x10, {0x01, 0x30, 0x03, 0x1A, 0x12, 0x0E, 0x3A, 0x50, 0x15, 0xC2, 0x03, 0x12, 0x0D, 0x07, 0x20, 0x00}}, {0x6b4, 0x10, {0x07, 0x90, 0x7F, 0xD6, 0xE0, 0x20, 0xE7, 0xF3, 0x12, 0x0D, 0x45, 0x12, 0x0E, 0x3C, 0x12, 0x0E}}, {0x6c4, 0x3, {0x32, 0x80, 0xD6}}, {0x6c7, 0x1, {0x22}}, {0x80, 0x10, {0x90, 0x7F, 0xE9, 0xE0, 0x70, 0x02, 0x21, 0xFD, 0x14, 0x70, 0x02, 0x41, 0x74, 0x24, 0xFE, 0x70}}, {0x90, 0x10, {0x02, 0x41, 0xE7, 0x24, 0xFB, 0x70, 0x02, 0x21, 0xF8, 0x14, 0x70, 0x02, 0x21, 0xF3, 0x14, 0x70}}, {0xa0, 0x10, {0x02, 0x21, 0xE9, 0x14, 0x70, 0x02, 0x21, 0xEE, 0x24, 0x05, 0x60, 0x02, 0x61, 0x3B, 0x12, 0x0E}}, {0xb0, 0x10, {0x3E, 0x40, 0x02, 0x61, 0x47, 0x90, 0x7F, 0xEB, 0xE0, 0x24, 0xFE, 0x60, 0x17, 0x14, 0x60, 0x41}}, {0xc0, 0x10, {0x24, 0x02, 0x60, 0x02, 0x21, 0xE0, 0xE5, 0x08, 0x90, 0x7F, 0xD4, 0xF0, 0xE5, 0x09, 0x90, 0x7F}}, {0xd0, 0x10, {0xD5, 0xF0, 0x61, 0x47, 0x90, 0x7F, 0xEA, 0xE0, 0xFF, 0x12, 0x0C, 0xA2, 0xAA, 0x06, 0xA9, 0x07}}, {0xe0, 0x10, {0x7B, 0x01, 0x8B, 0x31, 0x8A, 0x32, 0x89, 0x33, 0xEA, 0x49, 0x60, 0x0C, 0xEE, 0x90, 0x7F, 0xD4}}, {0xf0, 0x10, {0xF0, 0xEF, 0x90, 0x7F, 0xD5, 0xF0, 0x61, 0x47, 0x90, 0x7F, 0xB4, 0xE0, 0x44, 0x01, 0xF0, 0x61}}, {0x100, 0x10, {0x47, 0x90, 0x7F, 0xEA, 0xE0, 0xFF, 0x12, 0x0B, 0xCC, 0xAA, 0x06, 0xA9, 0x07, 0x7B, 0x01, 0x8B}}, {0x110, 0xb, {0x31, 0x8A, 0x32, 0x89, 0x33, 0xEA, 0x49, 0x70, 0x02, 0x21, 0xD7}}, {0x11b, 0x10, {0xAB, 0x31, 0x8B, 0x38, 0x8A, 0x39, 0x89, 0x3A, 0x12, 0x06, 0xC8, 0xF5, 0x3B, 0x90, 0x7F, 0xEE}}, {0x12b, 0x10, {0xE0, 0xFF, 0xE5, 0x3B, 0xD3, 0x9F, 0x40, 0x03, 0xE0, 0xF5, 0x3B, 0xE5, 0x3B, 0x70, 0x02, 0x21}}, {0x13b, 0x10, {0xCA, 0xE4, 0xF5, 0x37, 0xF5, 0x36, 0xF5, 0x35, 0xF5, 0x34, 0xE5, 0x3B, 0xC3, 0x94, 0x40, 0x50}}, {0x14b, 0x10, {0x04, 0xAF, 0x3B, 0x80, 0x02, 0x7F, 0x40, 0xE4, 0xFC, 0xFD, 0xFE, 0xAB, 0x37, 0xAA, 0x36, 0xA9}}, {0x15b, 0x10, {0x35, 0xA8, 0x34, 0xC3, 0x12, 0x08, 0x2C, 0x50, 0x36, 0xE5, 0x3A, 0x25, 0x37, 0xF5, 0x82, 0xE5}}, {0x16b, 0x10, {0x39, 0x35, 0x36, 0xF5, 0x83, 0xE0, 0xFF, 0x74, 0x00, 0x25, 0x37, 0xF5, 0x82, 0xE4, 0x34, 0x7F}}, {0x17b, 0x10, {0xF5, 0x83, 0xEF, 0xF0, 0xE4, 0xFA, 0xF9, 0xF8, 0xE5, 0x37, 0x24, 0x01, 0xF5, 0x37, 0xEA, 0x35}}, {0x18b, 0x10, {0x36, 0xF5, 0x36, 0xE9, 0x35, 0x35, 0xF5, 0x35, 0xE8, 0x35, 0x34, 0xF5, 0x34, 0x80, 0xAB, 0xE5}}, {0x19b, 0x10, {0x3B, 0xC3, 0x94, 0x40, 0x50, 0x04, 0xAF, 0x3B, 0x80, 0x02, 0x7F, 0x40, 0x90, 0x7F, 0xB5, 0xEF}}, {0x1ab, 0x10, {0xF0, 0xE5, 0x3B, 0xC3, 0x94, 0x40, 0x50, 0x04, 0xAF, 0x3B, 0x80, 0x02, 0x7F, 0x40, 0xC3, 0xE5}}, {0x1bb, 0x10, {0x3B, 0x9F, 0xF5, 0x3B, 0x90, 0x7F, 0xB4, 0xE0, 0x20, 0xE2, 0x02, 0x21, 0x36, 0x80, 0xF5, 0xE4}}, {0x1cb, 0xa, {0x90, 0x7F, 0xB5, 0xF0, 0x90, 0x7F, 0xB4, 0x74, 0x02, 0xF0}}, {0x1d5, 0x10, {0x61, 0x47, 0x90, 0x7F, 0xB4, 0xE0, 0x44, 0x01, 0xF0, 0x61, 0x47, 0x90, 0x7F, 0xB4, 0xE0, 0x44}}, {0x1e5, 0x10, {0x01, 0xF0, 0x61, 0x47, 0x12, 0x0E, 0x1C, 0x61, 0x47, 0x12, 0x0E, 0x2A, 0x61, 0x47, 0x12, 0x0B}}, {0x1f5, 0x10, {0xF8, 0x61, 0x47, 0x12, 0x0E, 0x0E, 0x61, 0x47, 0x12, 0x0E, 0x40, 0x40, 0x02, 0x61, 0x47, 0x90}}, {0x205, 0x10, {0x7F, 0xE8, 0xE0, 0x24, 0x7F, 0x60, 0x23, 0x14, 0x60, 0x2F, 0x24, 0x02, 0x70, 0x58, 0xA2, 0x00}}, {0x215, 0x10, {0xE4, 0x33, 0xFF, 0x25, 0xE0, 0xFF, 0xA2, 0x02, 0xE4, 0x33, 0x4F, 0x90, 0x7F, 0x00, 0xF0, 0xE4}}, {0x225, 0x10, {0xA3, 0xF0, 0x90, 0x7F, 0xB5, 0x74, 0x02, 0xF0, 0x61, 0x47, 0xE4, 0x90, 0x7F, 0x00, 0xF0, 0xA3}}, {0x235, 0x10, {0xF0, 0x90, 0x7F, 0xB5, 0x74, 0x02, 0xF0, 0x61, 0x47, 0x90, 0x7F, 0xEC, 0xE0, 0xF4, 0x54, 0x80}}, {0x245, 0x10, {0xFF, 0xC4, 0x54, 0x0F, 0xFF, 0xE0, 0x54, 0x07, 0x2F, 0x25, 0xE0, 0x24, 0xB4, 0xF5, 0x82, 0xE4}}, {0x255, 0x10, {0x34, 0x7F, 0xF5, 0x83, 0xE0, 0x54, 0x01, 0x90, 0x7F, 0x00, 0xF0, 0xE4, 0xA3, 0xF0, 0x90, 0x7F}}, {0x265, 0x10, {0xB5, 0x74, 0x02, 0xF0, 0x61, 0x47, 0x90, 0x7F, 0xB4, 0xE0, 0x44, 0x01, 0xF0, 0x61, 0x47, 0x12}}, {0x275, 0x10, {0x0E, 0x42, 0x40, 0x02, 0x61, 0x47, 0x90, 0x7F, 0xE8, 0xE0, 0x24, 0xFE, 0x60, 0x1A, 0x24, 0x02}}, {0x285, 0x10, {0x60, 0x02, 0x61, 0x47, 0x90, 0x7F, 0xEA, 0xE0, 0xB4, 0x01, 0x04, 0xC2, 0x00, 0x61, 0x47, 0x90}}, {0x295, 0x10, {0x7F, 0xB4, 0xE0, 0x44, 0x01, 0xF0, 0x61, 0x47, 0x90, 0x7F, 0xEA, 0xE0, 0x70, 0x3B, 0x90, 0x7F}}, {0x2a5, 0x10, {0xEC, 0xE0, 0xF4, 0x54, 0x80, 0xFF, 0xC4, 0x54, 0x0F, 0xFF, 0xE0, 0x54, 0x07, 0x2F, 0x25, 0xE0}}, {0x2b5, 0x10, {0x24, 0xB4, 0xF5, 0x82, 0xE4, 0x34, 0x7F, 0xF5, 0x83, 0xE4, 0xF0, 0x90, 0x7F, 0xEC, 0xE0, 0x54}}, {0x2c5, 0x10, {0x80, 0xFF, 0x13, 0x13, 0x13, 0x54, 0x1F, 0xFF, 0xE0, 0x54, 0x07, 0x2F, 0x90, 0x7F, 0xD7, 0xF0}}, {0x2d5, 0x3, {0xE4, 0xF5, 0x38}}, {0x2d8, 0x10, {0xE0, 0x44, 0x20, 0xF0, 0x80, 0x69, 0x90, 0x7F, 0xB4, 0xE0, 0x44, 0x01, 0xF0, 0x80, 0x60, 0x12}}, {0x2e8, 0x10, {0x0E, 0x44, 0x50, 0x5B, 0x90, 0x7F, 0xE8, 0xE0, 0x24, 0xFE, 0x60, 0x18, 0x24, 0x02, 0x70, 0x4F}}, {0x2f8, 0x10, {0x90, 0x7F, 0xEA, 0xE0, 0xB4, 0x01, 0x04, 0xD2, 0x00, 0x80, 0x44, 0x90, 0x7F, 0xB4, 0xE0, 0x44}}, {0x308, 0x10, {0x01, 0xF0, 0x80, 0x3B, 0x90, 0x7F, 0xEA, 0xE0, 0x70, 0x20, 0x90, 0x7F, 0xEC, 0xE0, 0xF4, 0x54}}, {0x318, 0x10, {0x80, 0xFF, 0xC4, 0x54, 0x0F, 0xFF, 0xE0, 0x54, 0x07, 0x2F, 0x25, 0xE0, 0x24, 0xB4, 0xF5, 0x82}}, {0x328, 0x10, {0xE4, 0x34, 0x7F, 0xF5, 0x83, 0x74, 0x01, 0xF0, 0x80, 0x15, 0x90, 0x7F, 0xB4, 0xE0, 0x44, 0x01}}, {0x338, 0x10, {0xF0, 0x80, 0x0C, 0x12, 0x0C, 0xE4, 0x50, 0x07, 0x90, 0x7F, 0xB4, 0xE0, 0x44, 0x01, 0xF0, 0x90}}, {0x348, 0x6, {0x7F, 0xB4, 0xE0, 0x44, 0x02, 0xF0}}, {0x34e, 0x1, {0x22}}, {0x33, 0x3, {0x02, 0x0E, 0x36}}, {0xe36, 0x4, {0x53, 0xD8, 0xEF, 0x32}}, {0x43, 0x3, {0x02, 0x0C, 0x00}}, {0xc00, 0x10, {0x02, 0x0D, 0x5F, 0x00, 0x02, 0x0D, 0xBC, 0x00, 0x02, 0x0D, 0xA6, 0x00, 0x02, 0x0D, 0x77, 0x00}}, {0xc10, 0x10, {0x02, 0x0D, 0xD2, 0x00, 0x02, 0x0E, 0x46, 0x00, 0x02, 0x0E, 0x47, 0x00, 0x02, 0x0E, 0x48, 0x00}}, {0xc20, 0x10, {0x02, 0x0E, 0x49, 0x00, 0x02, 0x0E, 0x4A, 0x00, 0x02, 0x0E, 0x4B, 0x00, 0x02, 0x0E, 0x4C, 0x00}}, {0xc30, 0x10, {0x02, 0x0E, 0x4D, 0x00, 0x02, 0x0E, 0x4E, 0x00, 0x02, 0x0E, 0x4F, 0x00, 0x02, 0x0E, 0x50, 0x00}}, {0xc40, 0x10, {0x02, 0x0E, 0x51, 0x00, 0x02, 0x0E, 0x52, 0x00, 0x02, 0x0E, 0x53, 0x00, 0x02, 0x0E, 0x54, 0x00}}, {0xc50, 0x8, {0x02, 0x0E, 0x55, 0x00, 0x02, 0x0E, 0x56, 0x00}}, {0xd45, 0x10, {0x90, 0x7F, 0xD6, 0xE0, 0x30, 0xE7, 0x12, 0xE0, 0x44, 0x01, 0xF0, 0x7F, 0x14, 0x7E, 0x00, 0x12}}, {0xd55, 0xa, {0x0D, 0x8F, 0x90, 0x7F, 0xD6, 0xE0, 0x54, 0xFE, 0xF0, 0x22}}, {0xd07, 0x10, {0x90, 0x7F, 0xD6, 0xE0, 0x44, 0x80, 0xF0, 0x43, 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22}}, {0xb7b, 0x7, {0x90, 0x7F, 0xD6, 0xE0, 0x44, 0x08, 0xF0}}, {0xb82, 0x3, {0xE4, 0xF5, 0x31}}, {0xb85, 0x4, {0xE0, 0x54, 0xFB, 0xF0}}, {0xb89, 0x3, {0xE4, 0xF5, 0x31}}, {0xb8c, 0x10, {0xE0, 0x44, 0x08, 0xF0, 0x30, 0x05, 0x04, 0xE0, 0x44, 0x02, 0xF0, 0x7F, 0xDC, 0x7E, 0x05, 0x12}}, {0xb9c, 0x10, {0x0D, 0x8F, 0x90, 0x7F, 0x92, 0xE0, 0x30, 0xE3, 0x07, 0x7F, 0xDC, 0x7E, 0x05, 0x12, 0x0D, 0x8F}}, {0xbac, 0x10, {0x90, 0x7F, 0xAB, 0x74, 0xFF, 0xF0, 0x90, 0x7F, 0xA9, 0xF0, 0x90, 0x7F, 0xAA, 0xF0, 0x53, 0x91}}, {0xbbc, 0x8, {0xEF, 0x90, 0x7F, 0xD6, 0xE0, 0x54, 0xF7, 0xF0}}, {0xbc4, 0x3, {0xE4, 0xF5, 0x31}}, {0xbc7, 0x5, {0xE0, 0x44, 0x04, 0xF0, 0x22}}, {0xbcc, 0x2, {0xA9, 0x07}}, {0xbce, 0x10, {0xAE, 0x0C, 0xAF, 0x0D, 0x8F, 0x82, 0x8E, 0x83, 0xA3, 0xE0, 0x64, 0x03, 0x70, 0x17, 0xAD, 0x01}}, {0xbde, 0x10, {0x19, 0xED, 0x70, 0x01, 0x22, 0x8F, 0x82, 0x8E, 0x83, 0xE0, 0x7C, 0x00, 0x2F, 0xFD, 0xEC, 0x3E}}, {0xbee, 0x9, {0xFE, 0xAF, 0x05, 0x80, 0xDF, 0x7E, 0x00, 0x7F, 0x00}}, {0xbf7, 0x1, {0x22}}, {0xca2, 0x10, {0xE4, 0xFE, 0xAC, 0x0A, 0xAD, 0x0B, 0x8D, 0x82, 0x8C, 0x83, 0xA3, 0xE0, 0x64, 0x02, 0x70, 0x2D}}, {0xcb2, 0x10, {0xAB, 0x06, 0x0E, 0xEB, 0xB5, 0x07, 0x05, 0xAF, 0x05, 0xAE, 0x04, 0x22, 0x8D, 0x82, 0x8C, 0x83}}, {0xcc2, 0x10, {0xA3, 0xA3, 0xE0, 0xF5, 0x3C, 0xA3, 0xE0, 0xF5, 0x3D, 0x62, 0x3C, 0xE5, 0x3C, 0x62, 0x3D, 0xE5}}, {0xcd2, 0x10, {0x3D, 0x62, 0x3C, 0x2D, 0xFB, 0xE5, 0x3C, 0x3C, 0xFC, 0xAD, 0x03, 0x80, 0xC9, 0x7E, 0x00, 0x7F}}, {0xce2, 0x1, {0x00}}, {0xce3, 0x1, {0x22}}, {0xd8f, 0x10, {0x8E, 0x32, 0x8F, 0x33, 0xE5, 0x33, 0x15, 0x33, 0xAE, 0x32, 0x70, 0x02, 0x15, 0x32, 0x4E, 0x60}}, {0xd9f, 0x7, {0x05, 0x12, 0x0D, 0x17, 0x80, 0xEE, 0x22}}, {0xd17, 0x10, {0x74, 0x00, 0xF5, 0x86, 0x90, 0xFD, 0xA5, 0x7C, 0x05, 0xA3, 0xE5, 0x82, 0x45, 0x83, 0x70, 0xF9}}, {0xd27, 0x1, {0x22}}, {0xde8, 0x10, {0x02, 0x46, 0x00, 0x00, 0x02, 0x49, 0x00, 0x00, 0x01, 0x48, 0x01, 0x01, 0x4B, 0x03, 0x01, 0x4C}}, {0xdf8, 0x5, {0x00, 0x02, 0x44, 0x00, 0x00}}, {0x926, 0x10, {0xE4, 0xFF, 0xFE, 0x74, 0x00, 0x2F, 0xF5, 0x82, 0x74, 0x20, 0x3E, 0xF5, 0x83, 0xE4, 0xF0, 0x74}}, {0x936, 0x10, {0x06, 0x2F, 0xF5, 0x82, 0x74, 0x22, 0x3E, 0xF5, 0x83, 0xE4, 0xF0, 0x74, 0x0C, 0x2F, 0xF5, 0x82}}, {0x946, 0x10, {0x74, 0x24, 0x3E, 0xF5, 0x83, 0xE4, 0xF0, 0x0F, 0xBF, 0x00, 0x01, 0x0E, 0xBE, 0x02, 0xD4, 0xBF}}, {0x956, 0x10, {0x01, 0xD1, 0x90, 0x22, 0x01, 0x74, 0x02, 0xF0, 0xA3, 0x14, 0xF0, 0x90, 0x24, 0x07, 0x04, 0xF0}}, {0x966, 0x10, {0xA3, 0x14, 0xF0, 0xE4, 0x90, 0x26, 0x0D, 0xF0, 0xA3, 0xF0, 0x90, 0x22, 0x03, 0x04, 0xF0, 0x90}}, {0x976, 0x10, {0x24, 0x09, 0xF0, 0xE4, 0x90, 0x26, 0x0F, 0xF0, 0x90, 0x22, 0x04, 0xF0, 0x90, 0x24, 0x0A, 0xF0}}, {0x986, 0x10, {0x90, 0x26, 0x10, 0xF0, 0x90, 0x22, 0x05, 0xF0, 0x90, 0x24, 0x0B, 0xF0, 0x90, 0x26, 0x11, 0xF0}}, {0x996, 0x10, {0x75, 0x3E, 0x01, 0x75, 0x3F, 0x20, 0x75, 0x40, 0x00, 0x75, 0x41, 0x01, 0x75, 0x42, 0x24, 0x75}}, {0x9a6, 0x10, {0x43, 0x0C, 0xF5, 0x46, 0xF5, 0x47, 0xD2, 0x04, 0x75, 0x48, 0x01, 0x75, 0x4B, 0x03, 0x90, 0x7F}}, {0x9b6, 0x10, {0x9B, 0xE0, 0x44, 0x20, 0x90, 0x7F, 0x98, 0xF0, 0x90, 0x7F, 0x9B, 0xE0, 0x44, 0x40, 0x90, 0x7F}}, {0x9c6, 0xc, {0x98, 0xF0, 0x90, 0x7F, 0x9B, 0xE0, 0x44, 0x80, 0x90, 0x7F, 0x98, 0xF0}}, {0x9d2, 0x1, {0x22}}, {0xd28, 0x10, {0xD2, 0x9F, 0xD2, 0x9E, 0xD2, 0x9D, 0xD2, 0x9C, 0xC2, 0x9A, 0xD2, 0xBC, 0xC2, 0xC9, 0xC2, 0xCC}}, {0xd38, 0xd, {0xD2, 0xCD, 0x75, 0xCB, 0xFF, 0x75, 0xCA, 0xFD, 0xD2, 0xAC, 0xD2, 0xCA, 0x22}}, {0xdfe, 0x10, {0xC2, 0x8C, 0x75, 0x89, 0x0A, 0x75, 0x8C, 0xB0, 0x75, 0x8A, 0xB0, 0xD2, 0xA9, 0xD2, 0x8C, 0x22}}, {0x34f, 0x10, {0xE4, 0xF5, 0x31, 0xF5, 0x32, 0x90, 0x7F, 0xB8, 0xE0, 0x30, 0xE1, 0x02, 0xA1, 0x23, 0xAB, 0x3E}}, {0x35f, 0x10, {0xAA, 0x3F, 0xA9, 0x40, 0x90, 0x02, 0x03, 0x12, 0x06, 0xE1, 0x64, 0x01, 0x60, 0x02, 0xA1, 0x15}}, {0x36f, 0x10, {0x90, 0x02, 0x05, 0x12, 0x06, 0xE1, 0x60, 0x02, 0xA1, 0x15, 0x30, 0x04, 0x25, 0x90, 0x02, 0x01}}, {0x37f, 0x10, {0x12, 0x07, 0x5B, 0xAE, 0xF0, 0x90, 0x7E, 0x00, 0xF0, 0xEE, 0xFF, 0x33, 0x95, 0xE0, 0xEF, 0xA3}}, {0x38f, 0x10, {0xF0, 0x75, 0x32, 0x02, 0xC2, 0x04, 0x90, 0x7F, 0x9B, 0xE0, 0x64, 0x80, 0x90, 0x7F, 0x98, 0xF0}}, {0x39f, 0x10, {0x80, 0x03, 0xE4, 0xF5, 0x32, 0xAB, 0x3E, 0xAA, 0x3F, 0xA9, 0x40, 0x90, 0x02, 0x01, 0x12, 0x07}}, {0x3af, 0x10, {0x5B, 0xFF, 0xAD, 0x32, 0xED, 0x33, 0x95, 0xE0, 0xFC, 0xC3, 0x74, 0x40, 0x9D, 0xFD, 0xE4, 0x9C}}, {0x3bf, 0x10, {0xFC, 0xD3, 0xEF, 0x9D, 0xEC, 0x64, 0x80, 0xF8, 0xE5, 0xF0, 0x64, 0x80, 0x98, 0x50, 0x02, 0x81}}, {0x3cf, 0x10, {0x51, 0xE4, 0xF5, 0x31, 0xC3, 0x74, 0x40, 0x95, 0x32, 0xC3, 0x64, 0x80, 0xF8, 0xE5, 0x31, 0x64}}, {0x3df, 0x10, {0x80, 0x98, 0x50, 0x3C, 0xAB, 0x3E, 0xAA, 0x3F, 0xA9, 0x40, 0x85, 0x47, 0x82, 0x85, 0x46, 0x83}}, {0x3ef, 0x10, {0x12, 0x06, 0xE1, 0xFF, 0xE5, 0x32, 0xFD, 0x33, 0x95, 0xE0, 0xFC, 0xE5, 0x31, 0xFB, 0x33, 0x95}}, {0x3ff, 0x10, {0xE0, 0xFA, 0xEB, 0x2D, 0xFD, 0xEA, 0x3C, 0xFC, 0x74, 0x00, 0x2D, 0xF5, 0x82, 0x74, 0x7E, 0x3C}}, {0x40f, 0x10, {0xF5, 0x83, 0xEF, 0xF0, 0x05, 0x47, 0xE5, 0x47, 0x70, 0x02, 0x05, 0x46, 0x05, 0x31, 0x80, 0xB4}}, {0x41f, 0x10, {0x90, 0x7F, 0xB9, 0x74, 0x40, 0xF0, 0xAB, 0x3E, 0xE5, 0x40, 0x24, 0x01, 0xF9, 0xE5, 0x3F, 0x34}}, {0x42f, 0x10, {0x02, 0xFA, 0x12, 0x07, 0x30, 0xFF, 0xAD, 0x32, 0xED, 0x33, 0x95, 0xE0, 0xFC, 0xC3, 0x74, 0x40}}, {0x43f, 0x10, {0x9D, 0xFD, 0xE4, 0x9C, 0xFC, 0xC3, 0xEF, 0x9D, 0xFF, 0xE5, 0xF0, 0x9C, 0x8F, 0xF0, 0x12, 0x07}}, {0x44f, 0x10, {0xE0, 0x22, 0xE4, 0xF5, 0x31, 0xAB, 0x3E, 0xAA, 0x3F, 0xA9, 0x40, 0x90, 0x02, 0x01, 0x12, 0x07}}, {0x45f, 0x10, {0x5B, 0xFF, 0xAD, 0x32, 0xED, 0x33, 0x95, 0xE0, 0xFC, 0xC3, 0xEF, 0x9D, 0xFF, 0xE5, 0xF0, 0x9C}}, {0x46f, 0x10, {0xFE, 0xAD, 0x31, 0xED, 0x33, 0x95, 0xE0, 0xFC, 0xC3, 0xED, 0x9F, 0xEE, 0x64, 0x80, 0xF8, 0xEC}}, {0x47f, 0x10, {0x64, 0x80, 0x98, 0x50, 0x36, 0x85, 0x47, 0x82, 0x85, 0x46, 0x83, 0x12, 0x06, 0xE1, 0xFF, 0xE5}}, {0x48f, 0x10, {0x32, 0xFD, 0x33, 0x95, 0xE0, 0xFC, 0xE5, 0x31, 0xFB, 0x33, 0x95, 0xE0, 0xFA, 0xEB, 0x2D, 0xFD}}, {0x49f, 0x10, {0xEA, 0x3C, 0xFC, 0x74, 0x00, 0x2D, 0xF5, 0x82, 0x74, 0x7E, 0x3C, 0xF5, 0x83, 0xEF, 0xF0, 0x05}}, {0x4af, 0x10, {0x47, 0xE5, 0x47, 0x70, 0x02, 0x05, 0x46, 0x05, 0x31, 0x80, 0x9A, 0xAB, 0x3E, 0xAA, 0x3F, 0xA9}}, {0x4bf, 0x10, {0x40, 0x90, 0x02, 0x01, 0x12, 0x07, 0x5B, 0x25, 0x32, 0x90, 0x7F, 0xB9, 0xF0, 0xE4, 0xF5, 0x46}}, {0x4cf, 0x10, {0xF5, 0x47, 0x90, 0x02, 0x03, 0x12, 0x07, 0x0E, 0xD2, 0x04, 0x90, 0x02, 0x04, 0x74, 0x01, 0x12}}, {0x4df, 0x10, {0x07, 0x0E, 0xE5, 0x48, 0x24, 0xFE, 0x60, 0x14, 0x14, 0x60, 0x1E, 0x24, 0x02, 0x70, 0x35, 0x75}}, {0x4ef, 0x10, {0x3E, 0x01, 0x75, 0x3F, 0x22, 0x75, 0x40, 0x06, 0x75, 0x48, 0x02, 0x22, 0x75, 0x3E, 0x01, 0x75}}, {0x4ff, 0x10, {0x3F, 0x24, 0x75, 0x40, 0x0C, 0x75, 0x48, 0x03, 0x22, 0x75, 0x3E, 0x01, 0x75, 0x3F, 0x20, 0x75}}, {0x50f, 0x10, {0x40, 0x00, 0x75, 0x48, 0x01, 0x22, 0x90, 0x7E, 0x00, 0x74, 0xFF, 0xF0, 0xA3, 0xF0, 0x90, 0x7F}}, {0x51f, 0x4, {0xB9, 0x74, 0x02, 0xF0}}, {0x523, 0x1, {0x22}}, {0x23, 0x3, {0x02, 0x0C, 0x58}}, {0xc58, 0x10, {0xC0, 0xE0, 0xC0, 0xF0, 0xC0, 0x83, 0xC0, 0x82, 0xC0, 0xD0, 0x75, 0xD0, 0x10, 0x75, 0x8A, 0xB0}}, {0xc68, 0x10, {0xD2, 0x8C, 0xC2, 0x98, 0xAB, 0x41, 0xAA, 0x42, 0xA9, 0x43, 0x85, 0x4A, 0x82, 0x85, 0x49, 0x83}}, {0xc78, 0x10, {0xE5, 0x99, 0x12, 0x07, 0x0E, 0x05, 0x4A, 0xE5, 0x4A, 0x70, 0x02, 0x05, 0x49, 0x90, 0x02, 0x01}}, {0xc88, 0x10, {0xE4, 0x75, 0xF0, 0x01, 0x12, 0x07, 0x93, 0x90, 0x02, 0x03, 0x74, 0x01, 0x12, 0x07, 0x0E, 0xD0}}, {0xc98, 0xa, {0xD0, 0xD0, 0x82, 0xD0, 0x83, 0xD0, 0xF0, 0xD0, 0xE0, 0x32}}, {0xb, 0x3, {0x02, 0x08, 0x53}}, {0x853, 0x10, {0xC0, 0xE0, 0xC0, 0xF0, 0xC0, 0x83, 0xC0, 0x82, 0xC0, 0xD0, 0x75, 0xD0, 0x00, 0xC0, 0x00, 0xC0}}, {0x863, 0x10, {0x01, 0xC0, 0x02, 0xC0, 0x03, 0xC2, 0x8C, 0x90, 0x7F, 0x9B, 0xE0, 0x64, 0x40, 0x90, 0x7F, 0x98}}, {0x873, 0x10, {0xF0, 0xAB, 0x41, 0xAA, 0x42, 0xA9, 0x43, 0x90, 0x02, 0x03, 0x12, 0x06, 0xE1, 0x64, 0x01, 0x70}}, {0x883, 0x10, {0x6B, 0xE5, 0x4B, 0x24, 0xFE, 0x60, 0x23, 0x14, 0x60, 0x42, 0x24, 0x02, 0x70, 0x5E, 0x90, 0x24}}, {0x893, 0x10, {0x0A, 0xE0, 0x64, 0x01, 0x70, 0x56, 0x90, 0x02, 0x05, 0x12, 0x07, 0x0E, 0x75, 0x41, 0x01, 0x75}}, {0x8a3, 0x10, {0x42, 0x22, 0x75, 0x43, 0x06, 0x75, 0x4B, 0x02, 0x80, 0x42, 0x90, 0x26, 0x10, 0xE0, 0x64, 0x01}}, {0x8b3, 0x10, {0x70, 0x3A, 0xAB, 0x41, 0xAA, 0x42, 0xA9, 0x43, 0x90, 0x02, 0x05, 0x12, 0x07, 0x0E, 0x75, 0x41}}, {0x8c3, 0x10, {0x01, 0x75, 0x42, 0x24, 0x75, 0x43, 0x0C, 0x75, 0x4B, 0x03, 0x80, 0x20, 0x90, 0x22, 0x04, 0xE0}}, {0x8d3, 0x10, {0xB4, 0x01, 0x19, 0xAB, 0x41, 0xAA, 0x42, 0xA9, 0x43, 0x90, 0x02, 0x05, 0xE4, 0x12, 0x07, 0x0E}}, {0x8e3, 0x10, {0x75, 0x41, 0x01, 0x75, 0x42, 0x20, 0x75, 0x43, 0x00, 0x75, 0x4B, 0x01, 0xAB, 0x41, 0xAA, 0x42}}, {0x8f3, 0x10, {0xA9, 0x43, 0x90, 0x02, 0x05, 0x74, 0x01, 0x12, 0x07, 0x0E, 0x90, 0x02, 0x04, 0xE4, 0x12, 0x07}}, {0x903, 0x10, {0x0E, 0x75, 0x49, 0x00, 0x75, 0x4A, 0x00, 0x90, 0x02, 0x01, 0xE4, 0xF5, 0xF0, 0x12, 0x07, 0xFF}}, {0x913, 0x10, {0xD0, 0x03, 0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, 0xD0, 0xD0, 0xD0, 0x82, 0xD0, 0x83, 0xD0, 0xF0}}, {0x923, 0x3, {0xD0, 0xE0, 0x32}}, {0xacf, 0x10, {0xAE, 0xE8, 0xC2, 0xE9, 0x90, 0x7F, 0xA5, 0xE0, 0x44, 0x80, 0xF0, 0x90, 0x7F, 0xA6, 0x74, 0xA0}}, {0xadf, 0x10, {0xF0, 0x90, 0x7F, 0xA5, 0xE0, 0x30, 0xE0, 0xF9, 0x90, 0x7F, 0xA6, 0xEF, 0xF0, 0x90, 0x7F, 0xA5}}, {0xaef, 0x10, {0xE0, 0x30, 0xE0, 0xF9, 0x90, 0x7F, 0xA5, 0xE0, 0x44, 0x80, 0xF0, 0x90, 0x7F, 0xA6, 0x74, 0xA1}}, {0xaff, 0x10, {0xF0, 0x90, 0x7F, 0xA5, 0xE0, 0x30, 0xE0, 0xF9, 0x90, 0x7F, 0xA5, 0xE0, 0x44, 0x20, 0xF0, 0x90}}, {0xb0f, 0x10, {0x7F, 0xA6, 0xE0, 0xFF, 0x90, 0x7F, 0xA5, 0xE0, 0x30, 0xE0, 0xF9, 0x90, 0x7F, 0xA5, 0xE0, 0x44}}, {0xb1f, 0x9, {0x40, 0xF0, 0x90, 0x7F, 0xA6, 0xE0, 0xFF, 0x8E, 0xE8}}, {0xb28, 0x1, {0x22}}, {0x0, 0x3, {0x02, 0x09, 0xD3}}, {0x9d3, 0xc, {0x78, 0x7F, 0xE4, 0xF6, 0xD8, 0xFD, 0x75, 0x81, 0x4C, 0x02, 0x0A, 0x1A}}, {0x6c8, 0x10, {0xBB, 0x01, 0x06, 0x89, 0x82, 0x8A, 0x83, 0xE0, 0x22, 0x50, 0x02, 0xE7, 0x22, 0xBB, 0xFE, 0x02}}, {0x6d8, 0x9, {0xE3, 0x22, 0x89, 0x82, 0x8A, 0x83, 0xE4, 0x93, 0x22}}, {0x6e1, 0x10, {0xBB, 0x01, 0x0C, 0xE5, 0x82, 0x29, 0xF5, 0x82, 0xE5, 0x83, 0x3A, 0xF5, 0x83, 0xE0, 0x22, 0x50}}, {0x6f1, 0x10, {0x06, 0xE9, 0x25, 0x82, 0xF8, 0xE6, 0x22, 0xBB, 0xFE, 0x06, 0xE9, 0x25, 0x82, 0xF8, 0xE2, 0x22}}, {0x701, 0xd, {0xE5, 0x82, 0x29, 0xF5, 0x82, 0xE5, 0x83, 0x3A, 0xF5, 0x83, 0xE4, 0x93, 0x22}}, {0x70e, 0x10, {0xF8, 0xBB, 0x01, 0x0D, 0xE5, 0x82, 0x29, 0xF5, 0x82, 0xE5, 0x83, 0x3A, 0xF5, 0x83, 0xE8, 0xF0}}, {0x71e, 0x10, {0x22, 0x50, 0x06, 0xE9, 0x25, 0x82, 0xC8, 0xF6, 0x22, 0xBB, 0xFE, 0x05, 0xE9, 0x25, 0x82, 0xC8}}, {0x72e, 0x2, {0xF2, 0x22}}, {0x730, 0x10, {0xBB, 0x01, 0x0A, 0x89, 0x82, 0x8A, 0x83, 0xE0, 0xF5, 0xF0, 0xA3, 0xE0, 0x22, 0x50, 0x06, 0x87}}, {0x740, 0x10, {0xF0, 0x09, 0xE7, 0x19, 0x22, 0xBB, 0xFE, 0x07, 0xE3, 0xF5, 0xF0, 0x09, 0xE3, 0x19, 0x22, 0x89}}, {0x750, 0xb, {0x82, 0x8A, 0x83, 0xE4, 0x93, 0xF5, 0xF0, 0x74, 0x01, 0x93, 0x22}}, {0x75b, 0x10, {0xBB, 0x01, 0x10, 0xE5, 0x82, 0x29, 0xF5, 0x82, 0xE5, 0x83, 0x3A, 0xF5, 0x83, 0xE0, 0xF5, 0xF0}}, {0x76b, 0x10, {0xA3, 0xE0, 0x22, 0x50, 0x09, 0xE9, 0x25, 0x82, 0xF8, 0x86, 0xF0, 0x08, 0xE6, 0x22, 0xBB, 0xFE}}, {0x77b, 0x10, {0x0A, 0xE9, 0x25, 0x82, 0xF8, 0xE2, 0xF5, 0xF0, 0x08, 0xE2, 0x22, 0xE5, 0x83, 0x2A, 0xF5, 0x83}}, {0x78b, 0x8, {0xE9, 0x93, 0xF5, 0xF0, 0xA3, 0xE9, 0x93, 0x22}}, {0x793, 0x10, {0xBB, 0x01, 0x0D, 0xC5, 0x82, 0x29, 0xC5, 0x82, 0xC5, 0x83, 0x3A, 0xC5, 0x83, 0x02, 0x08, 0x3D}}, {0x7a3, 0x10, {0x50, 0x11, 0xC5, 0x82, 0x29, 0xF8, 0x08, 0xE5, 0xF0, 0x26, 0xF6, 0x18, 0xF5, 0xF0, 0xE5, 0x82}}, {0x7b3, 0x10, {0x36, 0xF6, 0x22, 0xBB, 0xFE, 0x11, 0xC5, 0x82, 0x29, 0xF8, 0x08, 0xE2, 0x25, 0xF0, 0xF5, 0xF0}}, {0x7c3, 0x10, {0xF2, 0x18, 0xE2, 0x35, 0x82, 0xF2, 0x22, 0xF8, 0xE5, 0x82, 0x29, 0xF5, 0x82, 0xE5, 0x83, 0x2A}}, {0x7d3, 0xd, {0xF5, 0x83, 0x74, 0x01, 0x93, 0x25, 0xF0, 0xF5, 0xF0, 0xE4, 0x93, 0x38, 0x22}}, {0x7e0, 0x10, {0xBB, 0x01, 0x0A, 0x89, 0x82, 0x8A, 0x83, 0xF0, 0xE5, 0xF0, 0xA3, 0xF0, 0x22, 0x50, 0x06, 0xF7}}, {0x7f0, 0xf, {0x09, 0xA7, 0xF0, 0x19, 0x22, 0xBB, 0xFE, 0x06, 0xF3, 0xE5, 0xF0, 0x09, 0xF3, 0x19, 0x22}}, {0x7ff, 0x10, {0xF8, 0xBB, 0x01, 0x11, 0xE5, 0x82, 0x29, 0xF5, 0x82, 0xE5, 0x83, 0x3A, 0xF5, 0x83, 0xE8, 0xF0}}, {0x80f, 0x10, {0xE5, 0xF0, 0xA3, 0xF0, 0x22, 0x50, 0x09, 0xE9, 0x25, 0x82, 0xC8, 0xF6, 0x08, 0xA6, 0xF0, 0x22}}, {0x81f, 0xd, {0xBB, 0xFE, 0x09, 0xE9, 0x25, 0x82, 0xC8, 0xF2, 0xE5, 0xF0, 0x08, 0xF2, 0x22}}, {0x82c, 0x10, {0xEB, 0x9F, 0xF5, 0xF0, 0xEA, 0x9E, 0x42, 0xF0, 0xE9, 0x9D, 0x42, 0xF0, 0xE8, 0x9C, 0x45, 0xF0}}, {0x83c, 0x1, {0x22}}, {0x9df, 0x10, {0x02, 0x05, 0x24, 0xE4, 0x93, 0xA3, 0xF8, 0xE4, 0x93, 0xA3, 0x40, 0x03, 0xF6, 0x80, 0x01, 0xF2}}, {0x9ef, 0x10, {0x08, 0xDF, 0xF4, 0x80, 0x29, 0xE4, 0x93, 0xA3, 0xF8, 0x54, 0x07, 0x24, 0x0C, 0xC8, 0xC3, 0x33}}, {0x9ff, 0x10, {0xC4, 0x54, 0x0F, 0x44, 0x20, 0xC8, 0x83, 0x40, 0x04, 0xF4, 0x56, 0x80, 0x01, 0x46, 0xF6, 0xDF}}, {0xa0f, 0x10, {0xE4, 0x80, 0x0B, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x0D, 0xE8, 0xE4, 0x7E}}, {0xa1f, 0x10, {0x01, 0x93, 0x60, 0xBC, 0xA3, 0xFF, 0x54, 0x3F, 0x30, 0xE5, 0x09, 0x54, 0x1F, 0xFE, 0xE4, 0x93}}, {0xa2f, 0x10, {0xA3, 0x60, 0x01, 0x0E, 0xCF, 0x54, 0xC0, 0x25, 0xE0, 0x60, 0xA8, 0x40, 0xB8, 0xE4, 0x93, 0xA3}}, {0xa3f, 0x10, {0xFA, 0xE4, 0x93, 0xA3, 0xF8, 0xE4, 0x93, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, 0xCA, 0xC5, 0x83, 0xCA}}, {0xa4f, 0x10, {0xF0, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, 0xCA, 0xC5, 0x83, 0xCA, 0xDF, 0xE9, 0xDE, 0xE7, 0x80, 0xBE}}, {0xdfd, 0x1, {0x00}}, {0x83d, 0x10, {0xC5, 0xF0, 0xF8, 0xA3, 0xE0, 0x28, 0xF0, 0xC5, 0xF0, 0xF8, 0xE5, 0x82, 0x15, 0x82, 0x70, 0x02}}, {0x84d, 0x6, {0x15, 0x83, 0xE0, 0x38, 0xF0, 0x22}}, {0x7f92, 0x1, {0x01}}, {0x7f92, 0x1, {0x00}}, {SUNLITE_END_OF_FIRMWARE, 0, {0x00}} }; #endif // PLUGINS_USBDMX_SUNLITEFIRMWARE_H_ ola-0.10.5.nojsmin/plugins/usbdmx/UsbDmxPlugin.cpp0000644000175000017500000000723613023355232021536 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * UsbDmxPlugin.cpp * A plugin that uses libusb to communicate with USB devices. * Copyright (C) 2006 Simon Newton */ #include "plugins/usbdmx/UsbDmxPlugin.h" #include #include "ola/Logging.h" #include "ola/base/Flags.h" #include "olad/Preferences.h" #include "plugins/usbdmx/AsyncPluginImpl.h" #include "plugins/usbdmx/PluginImplInterface.h" #include "plugins/usbdmx/SyncPluginImpl.h" DECLARE_bool(use_async_libusb); namespace ola { namespace plugin { namespace usbdmx { using std::string; const char UsbDmxPlugin::PLUGIN_NAME[] = "USB"; const char UsbDmxPlugin::PLUGIN_PREFIX[] = "usbdmx"; const char UsbDmxPlugin::LIBUSB_DEBUG_LEVEL_KEY[] = "libusb_debug_level"; int UsbDmxPlugin::LIBUSB_DEFAULT_DEBUG_LEVEL = 0; int UsbDmxPlugin::LIBUSB_MAX_DEBUG_LEVEL = 4; UsbDmxPlugin::UsbDmxPlugin(PluginAdaptor *plugin_adaptor) : Plugin(plugin_adaptor) { } UsbDmxPlugin::~UsbDmxPlugin() {} bool UsbDmxPlugin::StartHook() { if (m_impl.get()) { return true; } unsigned int debug_level; if (!StringToInt(m_preferences->GetValue(LIBUSB_DEBUG_LEVEL_KEY) , &debug_level)) { debug_level = LIBUSB_DEFAULT_DEBUG_LEVEL; } std::auto_ptr impl; if (FLAGS_use_async_libusb) { impl.reset( new AsyncPluginImpl(m_plugin_adaptor, this, debug_level, m_preferences)); } else { impl.reset( new SyncPluginImpl(m_plugin_adaptor, this, debug_level, m_preferences)); } if (impl->Start()) { m_impl.reset(impl.release()); return true; } else { return false; } } bool UsbDmxPlugin::StopHook() { if (m_impl.get()) { m_impl->Stop(); } return true; } string UsbDmxPlugin::Description() const { return "USB DMX Plugin\n" "----------------------------\n" "\n" "This plugin supports various USB DMX devices including the \n" "Anyma uDMX, DMXControl Projects e.V. Nodle U1, Eurolite, Fadecandy, " "Sunlite USBDMX2 and Velleman K8062.\n" "\n" "--- Config file : ola-usbdmx.conf ---\n" "\n" "libusb_debug_level = {0,1,2,3,4}\n" "The debug level for libusb, see http://libusb.sourceforge.net/api-1.0/ .\n" "0 = No logging, 4 = Verbose debug.\n" "\n" "nodle--mode = {0,1,2,3,4,5,6,7}\n" "The mode for the Nodle U1 interface with serial number " "to operate in. Default = 6\n" "0 - Standby\n" "1 - DMX In -> DMX Out\n" "2 - PC Out -> DMX Out\n" "3 - DMX In + PC Out -> DMX Out\n" "4 - DMX In -> PC In\n" "5 - DMX In -> DMX Out & DMX In -> PC In\n" "6 - PC Out -> DMX Out & DMX In -> PC In\n" "7 - DMX In + PC Out -> DMX Out & DMX In -> PC In\n" "\n"; } bool UsbDmxPlugin::SetDefaultPreferences() { if (!m_preferences) { return false; } bool save = m_preferences->SetDefaultValue( LIBUSB_DEBUG_LEVEL_KEY, UIntValidator(LIBUSB_DEFAULT_DEBUG_LEVEL, LIBUSB_MAX_DEBUG_LEVEL), LIBUSB_DEFAULT_DEBUG_LEVEL); if (save) { m_preferences->Save(); } return true; } } // namespace usbdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbdmx/SyncPluginImpl.h0000644000175000017500000000732313023355232021534 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SyncPluginImpl.h * The synchronous implementation of the USB DMX plugin. * Copyright (C) 2010 Simon Newton */ #ifndef PLUGINS_USBDMX_SYNCPLUGINIMPL_H_ #define PLUGINS_USBDMX_SYNCPLUGINIMPL_H_ #include #include #include #include #include #include #include "libs/usb/LibUsbAdaptor.h" #include "ola/base/Macro.h" #include "olad/Preferences.h" #include "plugins/usbdmx/PluginImplInterface.h" #include "plugins/usbdmx/Widget.h" #include "plugins/usbdmx/WidgetFactory.h" namespace ola { class Device; namespace plugin { namespace usbdmx { /** * @brief The legacy implementation. * * This implementation spawns a thread for each dongle, and then uses * synchronous calls to libusb. * * This does not support hotplug. */ class SyncPluginImpl: public PluginImplInterface, public WidgetObserver { public: /** * @brief Create a new SyncPluginImpl. * @param plugin_adaptor The PluginAdaptor to use, ownership is not * transferred. * @param plugin The parent Plugin object which is used when creating * devices. * @param debug_level the debug level to use for libusb. * @param preferences The Preferences container used by the plugin */ SyncPluginImpl(PluginAdaptor *plugin_adaptor, Plugin *plugin, unsigned int debug_level, Preferences *preferences); ~SyncPluginImpl(); bool Start(); bool Stop(); bool NewWidget(class AnymauDMX *widget); bool NewWidget(class DMXCProjectsNodleU1 *widget); bool NewWidget(class EurolitePro *widget); bool NewWidget(ola::usb::JaRuleWidget *widget); bool NewWidget(class ScanlimeFadecandy *widget); bool NewWidget(class Sunlite *widget); bool NewWidget(class VellemanK8062 *widget); void WidgetRemoved(OLA_UNUSED class AnymauDMX *widget) {} void WidgetRemoved(OLA_UNUSED class DMXCProjectsNodleU1 *widget) {} void WidgetRemoved(OLA_UNUSED class EurolitePro *widget) {} void WidgetRemoved(OLA_UNUSED ola::usb::JaRuleWidget *widget) {} void WidgetRemoved(OLA_UNUSED class ScanlimeFadecandy *widget) {} void WidgetRemoved(OLA_UNUSED class Sunlite *widget) {} void WidgetRemoved(OLA_UNUSED class VellemanK8062 *widget) {} private: typedef std::vector WidgetFactories; typedef std::map WidgetToDeviceMap; PluginAdaptor* const m_plugin_adaptor; Plugin* const m_plugin; const unsigned int m_debug_level; ola::usb::SyncronousLibUsbAdaptor m_usb_adaptor; Preferences* const m_preferences; WidgetFactories m_widget_factories; libusb_context *m_context; WidgetToDeviceMap m_devices; std::set > m_registered_devices; unsigned int ScanForDevices(); void ReScanForDevices(); bool CheckDevice(libusb_device *device); bool StartAndRegisterDevice(class WidgetInterface *widget, Device *device); DISALLOW_COPY_AND_ASSIGN(SyncPluginImpl); }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_SYNCPLUGINIMPL_H_ ola-0.10.5.nojsmin/plugins/usbdmx/DMXCProjectsNodleU1.cpp0000644000175000017500000004020013023355232022576 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DMXCProjectsNodleU1.cpp * The synchronous and asynchronous Nodle widgets. * Copyright (C) 2015 Stefan Krupop */ #include "plugins/usbdmx/DMXCProjectsNodleU1.h" #include #include #include #include #include "ola/Logging.h" #include "ola/Constants.h" #include "ola/StringUtils.h" #include "plugins/usbdmx/AsyncUsbReceiver.h" #include "plugins/usbdmx/AsyncUsbSender.h" #include "plugins/usbdmx/ThreadedUsbReceiver.h" #include "plugins/usbdmx/ThreadedUsbSender.h" namespace ola { namespace plugin { namespace usbdmx { using std::string; int DMXCProjectsNodleU1::NODLE_DEFAULT_MODE = 6; int DMXCProjectsNodleU1::NODLE_MIN_MODE = 0; int DMXCProjectsNodleU1::NODLE_MAX_MODE = 7; int DMXCProjectsNodleU1::OUTPUT_ENABLE_MASK = 2; int DMXCProjectsNodleU1::INPUT_ENABLE_MASK = 4; namespace { static const unsigned char WRITE_ENDPOINT = 0x02; static const unsigned char READ_ENDPOINT = 0x81; static const unsigned int URB_TIMEOUT_MS = 50; static const int CONFIGURATION = 1; static const int INTERFACE = 0; static const unsigned int DATABLOCK_SIZE = 33; /* * @brief Send chosen mode to the DMX device * @param handle the libusb_device_handle to use. * @returns true if mode was set */ bool SetInterfaceMode(ola::usb::LibUsbAdaptor *adaptor, libusb_device_handle *handle, uint8_t mode) { unsigned char usb_data[DATABLOCK_SIZE]; int transferred; memset(usb_data, 0, sizeof(usb_data)); usb_data[0] = 16; usb_data[1] = mode; int ret = adaptor->InterruptTransfer( handle, WRITE_ENDPOINT, reinterpret_cast(usb_data), DATABLOCK_SIZE, &transferred, URB_TIMEOUT_MS); if (ret) { OLA_WARN << "InterruptTransfer(): " << adaptor->ErrorCodeToString(ret) << ", transferred " << transferred << " / " << DATABLOCK_SIZE; } return ret == 0; } /* * @brief Attempt to open a handle to a Nodle widget. * @param adaptor the LibUsbAdaptor to use. * @param usb_device the libusb_device to use. * @returns A libusb_device_handle or NULL if it failed. */ libusb_device_handle *OpenDMXCProjectsNodleU1Widget( ola::usb::LibUsbAdaptor *adaptor, libusb_device *usb_device) { libusb_device_handle *usb_handle; bool ok = adaptor->OpenDevice(usb_device, &usb_handle); if (!ok) { return NULL; } int ret_code = adaptor->DetachKernelDriver(usb_handle, INTERFACE); if (ret_code != 0 && ret_code != LIBUSB_ERROR_NOT_FOUND) { OLA_WARN << "Failed to detach kernel driver: " << adaptor->ErrorCodeToString(ret_code); adaptor->Close(usb_handle); return NULL; } // this device only has one configuration ret_code = adaptor->SetConfiguration(usb_handle, CONFIGURATION); if (ret_code) { OLA_WARN << "Nodle set config failed, with libusb error code " << adaptor->ErrorCodeToString(ret_code); adaptor->Close(usb_handle); return NULL; } if (adaptor->ClaimInterface(usb_handle, INTERFACE)) { OLA_WARN << "Failed to claim Nodle USB device"; adaptor->Close(usb_handle); return NULL; } return usb_handle; } } // namespace // DMXCProjectsNodleU1ThreadedSender // ----------------------------------------------------------------------------- /* * Sends messages to a Nodle device in a separate thread. */ class DMXCProjectsNodleU1ThreadedSender: public ThreadedUsbSender { public: DMXCProjectsNodleU1ThreadedSender(ola::usb::LibUsbAdaptor *adaptor, libusb_device *usb_device, libusb_device_handle *handle) : ThreadedUsbSender(usb_device, handle), m_adaptor(adaptor) { m_last_tx_buffer.Blackout(); } private: ola::usb::LibUsbAdaptor* const m_adaptor; DmxBuffer m_last_tx_buffer; bool TransmitBuffer(libusb_device_handle *handle, const DmxBuffer &buffer); bool SendDataChunk(libusb_device_handle *handle, uint8_t *usb_data); }; bool DMXCProjectsNodleU1ThreadedSender::TransmitBuffer( libusb_device_handle *handle, const DmxBuffer &buffer) { unsigned char usb_data[DATABLOCK_SIZE]; const unsigned int size = buffer.Size(); const uint8_t *data = buffer.GetRaw(); const uint8_t *last_data = m_last_tx_buffer.GetRaw(); unsigned int i = 0; memset(usb_data, 0, sizeof(usb_data)); while (i < size - 32) { if (memcmp(data + i, last_data + i, 32) != 0) { usb_data[0] = i / 32; memcpy(usb_data + 1, data + i, 32); m_last_tx_buffer.SetRange(i, data + i, 32); if (!SendDataChunk(handle, usb_data)) { return false; } } i += 32; } if (memcmp(data + i, last_data + i, size - i) != 0) { usb_data[0] = i / 32; memcpy(usb_data + 1, data + i, size - i); m_last_tx_buffer.SetRange(i, data + i, size - i); if (!SendDataChunk(handle, usb_data)) { return false; } } return true; } bool DMXCProjectsNodleU1ThreadedSender::SendDataChunk( libusb_device_handle *handle, uint8_t *usb_data) { int transferred; int ret = m_adaptor->InterruptTransfer( handle, WRITE_ENDPOINT, reinterpret_cast(usb_data), DATABLOCK_SIZE, &transferred, URB_TIMEOUT_MS); if (ret) { OLA_WARN << "InterruptTransfer(): " << m_adaptor->ErrorCodeToString(ret) << ", transferred " << transferred << " / " << DATABLOCK_SIZE; } return ret == 0; } // DMXCProjectsNodleU1ThreadedReceiver // ----------------------------------------------------------------------------- /* * Receives messages from a Nodle device in a separate thread. */ class DMXCProjectsNodleU1ThreadedReceiver: public ThreadedUsbReceiver { public: DMXCProjectsNodleU1ThreadedReceiver(ola::usb::LibUsbAdaptor *adaptor, libusb_device *usb_device, libusb_device_handle *handle, PluginAdaptor *plugin_adaptor) : ThreadedUsbReceiver(usb_device, handle, plugin_adaptor), m_adaptor(adaptor) { } private: ola::usb::LibUsbAdaptor* const m_adaptor; bool ReceiveBuffer(libusb_device_handle *handle, DmxBuffer *buffer, bool *buffer_updated); bool ReadDataChunk(libusb_device_handle *handle, uint8_t *usb_data); }; bool DMXCProjectsNodleU1ThreadedReceiver::ReceiveBuffer( libusb_device_handle *handle, DmxBuffer *buffer, bool *buffer_updated) { unsigned char usb_data[DATABLOCK_SIZE]; if (ReadDataChunk(handle, usb_data)) { if (usb_data[0] < 16) { uint16_t start_offset = usb_data[0] * 32; buffer->SetRange(start_offset, &usb_data[1], 32); *buffer_updated = true; } } return true; } bool DMXCProjectsNodleU1ThreadedReceiver::ReadDataChunk( libusb_device_handle *handle, uint8_t *usb_data) { int transferred; int ret = m_adaptor->InterruptTransfer( handle, READ_ENDPOINT, reinterpret_cast(usb_data), DATABLOCK_SIZE, &transferred, URB_TIMEOUT_MS); if (ret && ret != LIBUSB_ERROR_TIMEOUT) { OLA_WARN << "InterruptTransfer(): " << m_adaptor->ErrorCodeToString(ret) << ", transferred " << transferred << " / " << DATABLOCK_SIZE; } return ret == 0; } // SynchronousDMXCProjectsNodleU1 // ----------------------------------------------------------------------------- SynchronousDMXCProjectsNodleU1::SynchronousDMXCProjectsNodleU1( ola::usb::LibUsbAdaptor *adaptor, libusb_device *usb_device, PluginAdaptor *plugin_adaptor, const string &serial, unsigned int mode) : DMXCProjectsNodleU1(adaptor, usb_device, plugin_adaptor, serial, mode), m_usb_device(usb_device) { } bool SynchronousDMXCProjectsNodleU1::Init() { libusb_device_handle *usb_handle = OpenDMXCProjectsNodleU1Widget( m_adaptor, m_usb_device); if (!usb_handle) { return false; } SetInterfaceMode(m_adaptor, usb_handle, m_mode); if (m_mode & OUTPUT_ENABLE_MASK) { // output port active std::auto_ptr sender( new DMXCProjectsNodleU1ThreadedSender(m_adaptor, m_usb_device, usb_handle)); if (!sender->Start()) { return false; } m_sender.reset(sender.release()); } if (m_mode & INPUT_ENABLE_MASK) { // input port active std::auto_ptr receiver( new DMXCProjectsNodleU1ThreadedReceiver(m_adaptor, m_usb_device, usb_handle, m_plugin_adaptor)); if (!receiver->Start()) { return false; } m_receiver.reset(receiver.release()); } return true; } bool SynchronousDMXCProjectsNodleU1::SendDMX(const DmxBuffer &buffer) { if (m_sender.get()) { return m_sender->SendDMX(buffer); } else { return false; } } void SynchronousDMXCProjectsNodleU1::SetDmxCallback( Callback0 *callback) { if (m_receiver.get()) { m_receiver->SetReceiveCallback(callback); } else { delete callback; } } const DmxBuffer &SynchronousDMXCProjectsNodleU1::GetDmxInBuffer() { return m_receiver->GetDmxInBuffer(); } // DMXCProjectsNodleU1AsyncUsbReceiver // ----------------------------------------------------------------------------- class DMXCProjectsNodleU1AsyncUsbReceiver : public AsyncUsbReceiver { public: DMXCProjectsNodleU1AsyncUsbReceiver(ola::usb::LibUsbAdaptor *adaptor, libusb_device *usb_device, PluginAdaptor *plugin_adaptor, unsigned int mode) : AsyncUsbReceiver(adaptor, usb_device, plugin_adaptor), m_mode(mode) { } ~DMXCProjectsNodleU1AsyncUsbReceiver() { CancelTransfer(); } libusb_device_handle* SetupHandle() { libusb_device_handle *handle = OpenDMXCProjectsNodleU1Widget(m_adaptor, m_usb_device); if (handle) { SetInterfaceMode(m_adaptor, handle, m_mode); } return handle; } bool PerformTransfer(); bool TransferCompleted(DmxBuffer *buffer, int transferred_size); private: unsigned int m_mode; uint8_t m_packet[DATABLOCK_SIZE]; DISALLOW_COPY_AND_ASSIGN(DMXCProjectsNodleU1AsyncUsbReceiver); }; bool DMXCProjectsNodleU1AsyncUsbReceiver::PerformTransfer() { FillInterruptTransfer(READ_ENDPOINT, m_packet, DATABLOCK_SIZE, URB_TIMEOUT_MS); return (SubmitTransfer() == 0); } bool DMXCProjectsNodleU1AsyncUsbReceiver::TransferCompleted( DmxBuffer *buffer, int transferred_size) { if (m_packet[0] < 16 && transferred_size >= static_cast(DATABLOCK_SIZE)) { uint16_t start_offset = m_packet[0] * 32; buffer->SetRange(start_offset, &m_packet[1], 32); return true; } return false; } // DMXCProjectsNodleU1AsyncUsbSender // ----------------------------------------------------------------------------- class DMXCProjectsNodleU1AsyncUsbSender : public AsyncUsbSender { public: DMXCProjectsNodleU1AsyncUsbSender(ola::usb::LibUsbAdaptor *adaptor, libusb_device *usb_device, unsigned int mode) : AsyncUsbSender(adaptor, usb_device), m_mode(mode), m_buffer_offset(0) { m_tx_buffer.Blackout(); } ~DMXCProjectsNodleU1AsyncUsbSender() { CancelTransfer(); } libusb_device_handle* SetupHandle() { libusb_device_handle *handle = OpenDMXCProjectsNodleU1Widget(m_adaptor, m_usb_device); if (handle) { SetInterfaceMode(m_adaptor, handle, m_mode); } return handle; } bool PerformTransfer(const DmxBuffer &buffer); void PostTransferHook(); private: unsigned int m_mode; DmxBuffer m_tx_buffer; // This tracks where we are in m_tx_buffer. A value of 0 means we're at the // start of a DMX frame. unsigned int m_buffer_offset; uint8_t m_packet[DATABLOCK_SIZE]; bool ContinueTransfer(); bool SendInitialChunk(const DmxBuffer &buffer); bool SendChunk() { FillInterruptTransfer(WRITE_ENDPOINT, m_packet, DATABLOCK_SIZE, URB_TIMEOUT_MS); return (SubmitTransfer() == 0); } DISALLOW_COPY_AND_ASSIGN(DMXCProjectsNodleU1AsyncUsbSender); }; bool DMXCProjectsNodleU1AsyncUsbSender::PerformTransfer( const DmxBuffer &buffer) { if (m_buffer_offset == 0) { return SendInitialChunk(buffer); } // Otherwise we're part way through a transfer, do nothing. return true; } void DMXCProjectsNodleU1AsyncUsbSender::PostTransferHook() { if (m_buffer_offset < m_tx_buffer.Size()) { ContinueTransfer(); } else if (m_buffer_offset >= m_tx_buffer.Size()) { // That was the last chunk. m_buffer_offset = 0; if (TransferPending()) { // If we have a pending transfer, the next chunk is going to be sent // once we return. m_tx_buffer.Reset(); } } } bool DMXCProjectsNodleU1AsyncUsbSender::ContinueTransfer() { unsigned int length = 32; m_packet[0] = m_buffer_offset / 32; m_tx_buffer.GetRange(m_buffer_offset, m_packet + 1, &length); memset(m_packet + 1 + length, 0, 32 - length); m_buffer_offset += length; return (SendChunk() == 0); } bool DMXCProjectsNodleU1AsyncUsbSender::SendInitialChunk( const DmxBuffer &buffer) { unsigned int length = 32; m_tx_buffer.SetRange(0, buffer.GetRaw(), buffer.Size()); m_packet[0] = 0; m_tx_buffer.GetRange(0, m_packet + 1, &length); memset(m_packet + 1 + length, 0, 32 - length); unsigned int slots_sent = length; if (slots_sent < m_tx_buffer.Size()) { // There are more frames to send. m_buffer_offset = slots_sent; } return (SendChunk() == 0); } // AsynchronousDMXCProjectsNodleU1 // ----------------------------------------------------------------------------- AsynchronousDMXCProjectsNodleU1::AsynchronousDMXCProjectsNodleU1( ola::usb::LibUsbAdaptor *adaptor, libusb_device *usb_device, PluginAdaptor *plugin_adaptor, const string &serial, unsigned int mode) : DMXCProjectsNodleU1(adaptor, usb_device, plugin_adaptor, serial, mode) { if (mode & OUTPUT_ENABLE_MASK) { // output port active m_sender.reset(new DMXCProjectsNodleU1AsyncUsbSender(m_adaptor, usb_device, mode)); } if (mode & INPUT_ENABLE_MASK) { // input port active m_receiver.reset(new DMXCProjectsNodleU1AsyncUsbReceiver(m_adaptor, usb_device, plugin_adaptor, mode)); } } bool AsynchronousDMXCProjectsNodleU1::Init() { bool ok = true; if (m_sender.get()) { ok &= m_sender->Init(); } if (m_receiver.get()) { if (m_sender.get()) { // If we have a sender, use it's USB handle ok &= m_receiver->Init(m_sender->GetHandle()); } else { ok &= m_receiver->Init(); } if (ok) { m_receiver->Start(); } } return ok; } bool AsynchronousDMXCProjectsNodleU1::SendDMX(const DmxBuffer &buffer) { return m_sender.get() ? m_sender->SendDMX(buffer) : false; } void AsynchronousDMXCProjectsNodleU1::SetDmxCallback( Callback0 *callback) { if (m_receiver.get()) { m_receiver->SetReceiveCallback(callback); } else { delete callback; } } const DmxBuffer &AsynchronousDMXCProjectsNodleU1::GetDmxInBuffer() { if (m_receiver.get()) { m_receiver->GetDmx(&m_buffer); } return m_buffer; } } // namespace usbdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbdmx/AsyncUsbSender.cpp0000644000175000017500000000465513023355232022047 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * AsyncUsbSender.cpp * An Asynchronous DMX USB sender. * Copyright (C) 2014 Simon Newton */ #include "plugins/usbdmx/AsyncUsbSender.h" #include "libs/usb/LibUsbAdaptor.h" #include "ola/Logging.h" namespace ola { namespace plugin { namespace usbdmx { using ola::usb::LibUsbAdaptor; AsyncUsbSender::AsyncUsbSender(LibUsbAdaptor *adaptor, libusb_device *usb_device) : AsyncUsbTransceiverBase(adaptor, usb_device), m_pending_tx(false) { } AsyncUsbSender::~AsyncUsbSender() { m_adaptor->Close(m_usb_handle); } bool AsyncUsbSender::SendDMX(const DmxBuffer &buffer) { if (!m_usb_handle) { OLA_WARN << "AsyncUsbSender hasn't been initialized"; return false; } ola::thread::MutexLocker locker(&m_mutex); if (m_transfer_state == IDLE) { PerformTransfer(buffer); } else { // Buffer incoming data so we can send it when the outstanding transfers // complete. m_pending_tx = true; m_tx_buffer.Set(buffer); } return true; } void AsyncUsbSender::TransferComplete(struct libusb_transfer *transfer) { if (transfer != m_transfer) { OLA_WARN << "Mismatched libusb transfer: " << transfer << " != " << m_transfer; return; } if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { OLA_WARN << "Transfer returned " << transfer->status; } ola::thread::MutexLocker locker(&m_mutex); m_transfer_state = (transfer->status == LIBUSB_TRANSFER_NO_DEVICE ? DISCONNECTED : IDLE); if (m_suppress_continuation) { return; } PostTransferHook(); if ((m_transfer_state == IDLE) && m_pending_tx) { m_pending_tx = false; PerformTransfer(m_tx_buffer); } } } // namespace usbdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbdmx/EuroliteProFactory.h0000644000175000017500000000365113023355232022420 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * EuroliteProFactory.h * The WidgetFactory for EurolitePro widgets. * Copyright (C) 2014 Simon Newton */ #ifndef PLUGINS_USBDMX_EUROLITEPROFACTORY_H_ #define PLUGINS_USBDMX_EUROLITEPROFACTORY_H_ #include "libs/usb/LibUsbAdaptor.h" #include "ola/base/Macro.h" #include "plugins/usbdmx/EurolitePro.h" #include "plugins/usbdmx/WidgetFactory.h" namespace ola { namespace plugin { namespace usbdmx { /** * @brief Creates EurolitePro widgets. */ class EuroliteProFactory : public BaseWidgetFactory { public: explicit EuroliteProFactory(ola::usb::LibUsbAdaptor *adaptor) : BaseWidgetFactory("EuroliteProFactory"), m_adaptor(adaptor) {} bool DeviceAdded(WidgetObserver *observer, libusb_device *usb_device, const struct libusb_device_descriptor &descriptor); private: ola::usb::LibUsbAdaptor *m_adaptor; static const uint16_t PRODUCT_ID; static const uint16_t VENDOR_ID; static const char EXPECTED_MANUFACTURER[]; static const char EXPECTED_PRODUCT[]; DISALLOW_COPY_AND_ASSIGN(EuroliteProFactory); }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_EUROLITEPROFACTORY_H_ ola-0.10.5.nojsmin/plugins/usbdmx/ThreadedUsbReceiver.h0000644000175000017500000000776713023355232022512 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ThreadedUsbReceiver.h * Receive DMX data over USB from a dedicated thread. * Copyright (C) 2015 Stefan Krupop */ #ifndef PLUGINS_USBDMX_THREADEDUSBRECEIVER_H_ #define PLUGINS_USBDMX_THREADEDUSBRECEIVER_H_ #include #include #include "ola/base/Macro.h" #include "ola/Callback.h" #include "ola/DmxBuffer.h" #include "ola/thread/Thread.h" #include "olad/PluginAdaptor.h" namespace ola { namespace plugin { namespace usbdmx { /** * @brief Receive DMX data using libusb, from a separate thread. * * The synchronous libusb calls can sometimes take a while to complete, I've * seen cases of up to 21ms. * * To avoid blocking the main thread, we need to perform the libusb transfer * calls in a separate thread. This class contains all the thread management * code, leaving the subclass to implement ReceiveBuffer(), which performs the * actual transfer. * * ThreadedUsbReceiver can be used as a building block for synchronous widgets. */ class ThreadedUsbReceiver: private ola::thread::Thread { public: /** * @brief Create a new ThreadedUsbReceiver. * @param usb_device The usb_device to use. The ThreadedUsbReceiver takes a ref * on the device, while the ThreadedUsbReceiver object exists. * @param usb_handle The handle to use for the DMX transfer. * @param plugin_adaptor the PluginAdaptor used to execute callbacks * @param interface_number the USB interface number of the widget. Defaults to 0. */ ThreadedUsbReceiver(libusb_device *usb_device, libusb_device_handle *usb_handle, PluginAdaptor *plugin_adaptor, int interface_number = 0); virtual ~ThreadedUsbReceiver(); /** * @brief Start the new thread. * @returns true if the thread is running, false otherwise. */ bool Start(); /** * @brief Entry point for the new thread. * @returns NULL. */ void *Run(); /** * @brief Set the callback to be called when the receive buffer is updated. * @param callback The callback to call. */ void SetReceiveCallback(Callback0 *callback) { m_receive_callback.reset(callback); } /** * @brief Get DMX Buffer * @returns DmxBuffer with current input values. */ const DmxBuffer &GetDmxInBuffer() const { return m_buffer; } protected: /** * @brief Perform the DMX transfer. * @param handle the libusb_device_handle to use for the transfer. * @param buffer The DmxBuffer to be updated. * @param buffer_updated set to true when buffer was updated (=data received) * @returns true if the transfer was completed, false otherwise. * * This is called from the receiver thread. */ virtual bool ReceiveBuffer(libusb_device_handle *handle, DmxBuffer *buffer, bool *buffer_updated) = 0; private: bool m_term; libusb_device* const m_usb_device; libusb_device_handle* const m_usb_handle; int const m_interface_number; PluginAdaptor* const m_plugin_adaptor; std::auto_ptr > m_receive_callback; DmxBuffer m_buffer; ola::thread::Mutex m_data_mutex; ola::thread::Mutex m_term_mutex; DISALLOW_COPY_AND_ASSIGN(ThreadedUsbReceiver); }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_THREADEDUSBRECEIVER_H_ ola-0.10.5.nojsmin/plugins/usbdmx/FirmwareLoader.h0000644000175000017500000000226213023355232021517 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * FirmwareLoader.h * The base class for FirmwareLoaders. * Copyright (C) 2010 Simon Newton */ #ifndef PLUGINS_USBDMX_FIRMWARELOADER_H_ #define PLUGINS_USBDMX_FIRMWARELOADER_H_ namespace ola { namespace plugin { namespace usbdmx { class FirmwareLoader { public: FirmwareLoader() {} virtual ~FirmwareLoader() {} virtual bool LoadFirmware() = 0; }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_FIRMWARELOADER_H_ ola-0.10.5.nojsmin/plugins/usbdmx/SunliteFirmwareLoader.cpp0000644000175000017500000000417713023355232023425 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SunliteFirmwareLoader.cpp * Load the firmware onto a USBDMX2 device. * Copyright (C) 2010 Simon Newton */ #include "ola/Logging.h" #include "plugins/usbdmx/SunliteFirmware.h" #include "plugins/usbdmx/SunliteFirmwareLoader.h" namespace ola { namespace plugin { namespace usbdmx { /* * Load the firmware */ bool SunliteFirmwareLoader::LoadFirmware() { libusb_device_handle *handle; if (libusb_open(m_device, &handle)) { OLA_WARN << "Failed to open sunlite device"; return false; } if (libusb_claim_interface(handle, INTERFACE_NUMBER)) { OLA_WARN << "Failed to claim sunlite device."; libusb_close(handle); return false; } const struct sunlite_hex_record *record = sunlite_firmware; while (record->address != SUNLITE_END_OF_FIRMWARE) { int ret = libusb_control_transfer( handle, UPLOAD_REQUEST_TYPE, UPLOAD_REQUEST, record->address, 0, (unsigned char*) record->data, record->data_size, UPLOAD_TIMEOUT); if (ret != record->data_size) { OLA_WARN << "Sunlite firmware load failed, address: " << record->address << ", ret value was " << ret; libusb_release_interface(handle, INTERFACE_NUMBER); libusb_close(handle); } record++; } libusb_release_interface(handle, INTERFACE_NUMBER); libusb_close(handle); return true; } } // namespace usbdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbdmx/AsyncUsbSender.h0000644000175000017500000000624113023355232021505 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * AsyncUsbSender.h * An Asynchronous DMX USB sender. * Copyright (C) 2014 Simon Newton */ #ifndef PLUGINS_USBDMX_ASYNCUSBSENDER_H_ #define PLUGINS_USBDMX_ASYNCUSBSENDER_H_ #include #include "AsyncUsbTransceiverBase.h" #include "libs/usb/LibUsbAdaptor.h" #include "ola/DmxBuffer.h" #include "ola/base/Macro.h" #include "ola/thread/Mutex.h" namespace ola { namespace plugin { namespace usbdmx { /** * @brief A base class that send DMX data asynchronously to a libusb_device. * * This encapsulates much of the asynchronous libusb logic. Subclasses should * implement the SetupHandle() and PerformTransfer() methods. */ class AsyncUsbSender: public AsyncUsbTransceiverBase { public: /** * @brief Create a new AsyncUsbSender. * @param adaptor the LibUsbAdaptor to use. * @param usb_device the libusb_device to use for the widget. */ AsyncUsbSender(ola::usb::LibUsbAdaptor* const adaptor, libusb_device *usb_device); /** * @brief Destructor */ virtual ~AsyncUsbSender(); /** * @brief Send one frame of DMX data. * @param buffer the DMX data to send. * @returns the value of PerformTransfer(). */ bool SendDMX(const DmxBuffer &buffer); /** * @brief Called from the libusb callback when the asynchronous transfer * completes. * @param transfer the completed transfer. */ void TransferComplete(struct libusb_transfer *transfer); protected: /** * @brief Perform the DMX transfer. * @param buffer the DMX buffer to send. * @returns true if the transfer was scheduled, false otherwise. * * This method is implemented by the subclass. The subclass should call * FillControlTransfer() / FillBulkTransfer() as appropriate and then call * SubmitTransfer(). */ virtual bool PerformTransfer(const DmxBuffer &buffer) = 0; /** * @brief Called when the transfer completes. * * Some devices require multiple transfers per DMX frame. This provides a * hook for continuation. */ virtual void PostTransferHook() {} /** * @brief Check if there is a pending transfer. * @returns true if there is a transfer in progress, false otherwise. */ bool TransferPending() const { return m_pending_tx; } private: DmxBuffer m_tx_buffer; // GUARDED_BY(m_mutex); bool m_pending_tx; // GUARDED_BY(m_mutex); DISALLOW_COPY_AND_ASSIGN(AsyncUsbSender); }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_ASYNCUSBSENDER_H_ ola-0.10.5.nojsmin/plugins/usbdmx/VellemanK8062Factory.cpp0000644000175000017500000000343013023355232022673 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * VellemanK8062Factory.cpp * The WidgetFactory for Velleman widgets. * Copyright (C) 2014 Simon Newton */ #include "plugins/usbdmx/VellemanK8062Factory.h" #include "ola/Logging.h" #include "ola/base/Flags.h" #include "plugins/usbdmx/VellemanK8062.h" DECLARE_bool(use_async_libusb); namespace ola { namespace plugin { namespace usbdmx { const uint16_t VellemanK8062Factory::VENDOR_ID = 0x10cf; const uint16_t VellemanK8062Factory::PRODUCT_ID = 0x8062; bool VellemanK8062Factory::DeviceAdded( WidgetObserver *observer, libusb_device *usb_device, const struct libusb_device_descriptor &descriptor) { if (descriptor.idVendor != VENDOR_ID || descriptor.idProduct != PRODUCT_ID) { return false; } OLA_INFO << "Found a new Velleman device"; VellemanK8062 *widget = NULL; if (FLAGS_use_async_libusb) { widget = new AsynchronousVellemanK8062(m_adaptor, usb_device); } else { widget = new SynchronousVellemanK8062(m_adaptor, usb_device); } return AddWidget(observer, widget); } } // namespace usbdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbdmx/GenericDevice.cpp0000644000175000017500000000300113023355232021633 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * GenericDevice.cpp * A Generic device that creates a single port. * Copyright (C) 2014 Simon Newton */ #include "plugins/usbdmx/GenericDevice.h" #include #include "plugins/usbdmx/Widget.h" #include "plugins/usbdmx/GenericOutputPort.h" namespace ola { namespace plugin { namespace usbdmx { GenericDevice::GenericDevice(ola::AbstractPlugin *owner, WidgetInterface *widget, const std::string &device_name, const std::string &device_id) : Device(owner, device_name), m_device_id(device_id), m_port(new GenericOutputPort(this, 0, widget)) { } bool GenericDevice::StartHook() { AddPort(m_port.release()); return true; } } // namespace usbdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbdmx/Widget.h0000644000175000017500000000476513023355232020051 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Widget.h * A generic USB Widget. * Copyright (C) 2014 Simon Newton */ #ifndef PLUGINS_USBDMX_WIDGET_H_ #define PLUGINS_USBDMX_WIDGET_H_ #include "libs/usb/LibUsbAdaptor.h" #include "libs/usb/Types.h" #include "ola/DmxBuffer.h" namespace ola { namespace plugin { namespace usbdmx { /** * @brief The interface for a simple widget that supports a single universe of * DMX. */ class WidgetInterface { public: virtual ~WidgetInterface() {} /** * @brief Initialize the widget. * @returns true if this widget was initialized correctly, false otherwise. */ virtual bool Init() = 0; /** * @brief The device ID of this widget. * @returns The USBDeviceID. */ virtual ola::usb::USBDeviceID GetDeviceId() const = 0; /** * @brief Send DMX data from this widget * @param buffer The DmxBuffer containing the data to send. * @returns true if the data was sent, false otherwise. */ virtual bool SendDMX(const DmxBuffer &buffer) = 0; }; /** * @brief A base simple widget class. * * This holds a pointer to a LibUsbAdaptor so we don't have to duplicate that * code in all the Widgets. */ class SimpleWidget : public WidgetInterface { public: /** * @brief Create a new SimpleWidget. * @param adaptor the LibUsbAdaptor to use. * @param usb_device The libusb_device for this widget. */ explicit SimpleWidget(ola::usb::LibUsbAdaptor *adaptor, libusb_device *usb_device) : m_adaptor(adaptor), m_usb_device(usb_device) { } ola::usb::USBDeviceID GetDeviceId() const { return m_adaptor->GetDeviceId(m_usb_device); } protected: ola::usb::LibUsbAdaptor* const m_adaptor; libusb_device* const m_usb_device; }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_WIDGET_H_ ola-0.10.5.nojsmin/plugins/usbdmx/GenericOutputPort.cpp0000644000175000017500000000272713023355232022617 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * GenericOutputPort.cpp * A Generic output port that uses a widget. * Copyright (C) 2014 Simon Newton */ #include "plugins/usbdmx/GenericOutputPort.h" #include "ola/Logging.h" #include "olad/Device.h" #include "plugins/usbdmx/Widget.h" namespace ola { namespace plugin { namespace usbdmx { GenericOutputPort::GenericOutputPort(Device *parent, unsigned int id, WidgetInterface *widget) : BasicOutputPort(parent, id), m_widget(widget) { } bool GenericOutputPort::WriteDMX(const DmxBuffer &buffer, OLA_UNUSED uint8_t priority) { m_widget->SendDMX(buffer); return true; } } // namespace usbdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbdmx/VellemanK8062.cpp0000644000175000017500000004116613023355232021353 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * VellemanK8062.cpp * The synchronous and asynchronous Velleman widgets. * Copyright (C) 2014 Simon Newton */ #include "plugins/usbdmx/VellemanK8062.h" #include #include #include #include #include "libs/usb/LibUsbAdaptor.h" #include "ola/Logging.h" #include "ola/Constants.h" #include "ola/StringUtils.h" #include "plugins/usbdmx/AsyncUsbSender.h" #include "plugins/usbdmx/ThreadedUsbSender.h" namespace ola { namespace plugin { namespace usbdmx { using ola::usb::LibUsbAdaptor; using std::string; namespace { static const unsigned char ENDPOINT = 0x01; // 25ms seems to be about the shortest we can go static const unsigned int URB_TIMEOUT_MS = 25; static const int CONFIGURATION = 1; static const int INTERFACE = 0; static const unsigned int DEFAULT_CHUNK_SIZE = 8; static const unsigned int UPGRADED_CHUNK_SIZE = 64; static const unsigned int HEADER_SIZE = 2; // Message types // Length: 8 or 64 for the extended version. // Data: [2] [slot N] [slot N + 1] [slot N + 2] ... [slot N + 6] static const uint8_t INTERMEDIATE_FRAME_MSG = 2; // Length: 8 or 64 for the extended version. // Data: [3] [slot N] [undef] [undef] [undef] ... static const uint8_t SINGLE_SLOT_MSG = 3; // This must be used to indicate a new DMX512 frame. // Length: 8 or 64 for the extended version. // Data: [4] [number of leading 0s] [slot N] [slot N + 1] [slot N + 2] ... static const uint8_t BREAK_MSG = 4; // Length: 8 or 64 for the extended version. // [5] [number of leading 0s] [slot N] [slot N + 1] [slot N + 2] ... static const uint8_t INTERMEDIATE_COMPRESSED_FRAME_MSG = 5; // Length: 64, only defined for the extended version. // Data: [4] [data size] [slot 0] [slot 1] [slot 2] ... static const uint8_t VARIABLE_FRAME_CONTINUATION_MSG = 6; // Length: 64, only defined for the extended version. // Data: [4] [data size] [slot 0] [slot 1] [slot 2] ... static const uint8_t FULL_FRAME_MSG = 7; /* * @brief Attempt to open a handle to a Velleman widget. * @param adaptor the LibUsbAdaptor to use. * @param usb_device the libusb_device to use. * @param[out] The chunk size of the device, this determines if the enhanced * firmware is present. * @returns A libusb_device_handle of NULL if it failed. */ libusb_device_handle *OpenVellemenWidget(LibUsbAdaptor *adaptor, libusb_device *usb_device, unsigned int *chunk_size) { libusb_config_descriptor *config; if (adaptor->GetActiveConfigDescriptor(usb_device, &config)) { OLA_WARN << "Could not get active config descriptor"; return NULL; } // determine the max packet size, see // https://wiki.openlighting.org/index.php/Velleman_K8062_Upgrade // The standard size is 8. *chunk_size = DEFAULT_CHUNK_SIZE; if (config && config->interface && config->interface->altsetting && config->interface->altsetting->endpoint) { uint16_t max_packet_size = config->interface->altsetting->endpoint->wMaxPacketSize; OLA_DEBUG << "Velleman K8062 max packet size is " << max_packet_size; if (max_packet_size == UPGRADED_CHUNK_SIZE) { // this means the upgrade is present *chunk_size = max_packet_size; } } adaptor->FreeConfigDescriptor(config); libusb_device_handle *usb_handle; bool ok = adaptor->OpenDevice(usb_device, &usb_handle); if (!ok) { return NULL; } int ret_code = adaptor->DetachKernelDriver(usb_handle, INTERFACE); if (ret_code != 0 && ret_code != LIBUSB_ERROR_NOT_FOUND) { OLA_WARN << "Failed to detach kernel driver: " << adaptor->ErrorCodeToString(ret_code); adaptor->Close(usb_handle); return NULL; } // this device only has one configuration ret_code = adaptor->SetConfiguration(usb_handle, CONFIGURATION); if (ret_code) { OLA_WARN << "Velleman set config failed, with libusb error code " << ret_code; adaptor->Close(usb_handle); return NULL; } if (adaptor->ClaimInterface(usb_handle, INTERFACE)) { OLA_WARN << "Failed to claim Velleman usb device"; adaptor->Close(usb_handle); return NULL; } return usb_handle; } /* * @brief Count the number of leading 0s in a block of data. * @params data the data to count the 0s in. * @param data_length the length of the data. * @param chunk_size the size of the chunks we send to the widget. * @returns the number of leading 0s in the data. */ unsigned int CountLeadingZeros(const uint8_t *data, unsigned int data_length, unsigned int chunk_size) { unsigned int leading_zero_count = 0; // This could be up to 254 for the standard interface but then the shutdown // process gets wacky. Limit it to 100 for the standard and 255 for the // extended. unsigned int max_leading_zeros = (chunk_size == UPGRADED_CHUNK_SIZE) ? 254 : 100; unsigned int rest_of_chunk = chunk_size - 2; while (leading_zero_count < max_leading_zeros && leading_zero_count + rest_of_chunk < data_length && data[leading_zero_count] == 0) { leading_zero_count++; } return leading_zero_count; } } // namespace // VellemanThreadedSender // ----------------------------------------------------------------------------- /* * Sends messages to a Velleman device in a separate thread. */ class VellemanThreadedSender: public ThreadedUsbSender { public: VellemanThreadedSender(LibUsbAdaptor *adaptor, libusb_device *usb_device, libusb_device_handle *handle, unsigned int chunk_size) : ThreadedUsbSender(usb_device, handle), m_adaptor(adaptor), m_chunk_size(chunk_size) { m_tx_buffer.Blackout(); } private: LibUsbAdaptor* const m_adaptor; DmxBuffer m_tx_buffer; const unsigned int m_chunk_size; bool TransmitBuffer(libusb_device_handle *handle, const DmxBuffer &buffer); bool SendDataChunk(libusb_device_handle *handle, uint8_t *usb_data, unsigned int chunk_size); }; bool VellemanThreadedSender::TransmitBuffer(libusb_device_handle *handle, const DmxBuffer &buffer) { m_tx_buffer.SetRange(0, buffer.GetRaw(), buffer.Size()); unsigned char usb_data[m_chunk_size]; const unsigned int size = m_tx_buffer.Size(); const uint8_t *data = m_tx_buffer.GetRaw(); unsigned int i = 0; unsigned int compressed_channel_count = m_chunk_size - 2; unsigned int channel_count = m_chunk_size - 1; memset(usb_data, 0, sizeof(usb_data)); if (m_chunk_size == UPGRADED_CHUNK_SIZE && size <= m_chunk_size - 2) { // if the upgrade is present and we can fit the data in a single packet // use FULL_FRAME_MSG. usb_data[0] = FULL_FRAME_MSG; usb_data[1] = size; // number of channels in packet memcpy(usb_data + HEADER_SIZE, data, std::min(size, m_chunk_size - 2)); } else { unsigned int leading_zero_count = CountLeadingZeros( data, size, m_chunk_size); usb_data[0] = BREAK_MSG; usb_data[1] = leading_zero_count + 1; // include start code memcpy(usb_data + HEADER_SIZE, data + leading_zero_count, compressed_channel_count); i += leading_zero_count + compressed_channel_count; } if (!SendDataChunk(handle, usb_data, m_chunk_size)) { return false; } while (i < size - channel_count) { unsigned int leading_zero_count = CountLeadingZeros( data + i, size - i, m_chunk_size); if (leading_zero_count) { // we have leading zeros usb_data[0] = INTERMEDIATE_COMPRESSED_FRAME_MSG; usb_data[1] = leading_zero_count; memcpy(usb_data + HEADER_SIZE, data + i + leading_zero_count, compressed_channel_count); i += leading_zero_count + compressed_channel_count; } else { usb_data[0] = INTERMEDIATE_FRAME_MSG; memcpy(usb_data + 1, data + i, channel_count); i += channel_count; } if (!SendDataChunk(handle, usb_data, m_chunk_size)) { return false; } } // send the last channels if (m_chunk_size == UPGRADED_CHUNK_SIZE) { // if running in extended mode we can use the 6 message type to send // everything at once. usb_data[0] = VARIABLE_FRAME_CONTINUATION_MSG; usb_data[1] = size - i; memcpy(usb_data + HEADER_SIZE, data + i, size - i); if (!SendDataChunk(handle, usb_data, m_chunk_size)) { return false; } } else { // else we use the 3 message type to send one at a time for (; i != size; i++) { usb_data[0] = SINGLE_SLOT_MSG; usb_data[1] = data[i]; if (!SendDataChunk(handle, usb_data, m_chunk_size)) { return false; } } } return true; } bool VellemanThreadedSender::SendDataChunk(libusb_device_handle *handle, uint8_t *usb_data, unsigned int chunk_size) { int transferred; int ret = m_adaptor->InterruptTransfer( handle, ENDPOINT, reinterpret_cast(usb_data), chunk_size, &transferred, URB_TIMEOUT_MS); if (ret) { OLA_WARN << "InterruptTransfer():" << m_adaptor->ErrorCodeToString(ret) << ", transferred " << transferred << " / " << chunk_size; } return ret == 0; } // SynchronousVellemanK8062 // ----------------------------------------------------------------------------- SynchronousVellemanK8062::SynchronousVellemanK8062( LibUsbAdaptor *adaptor, libusb_device *usb_device) : VellemanK8062(adaptor, usb_device) { } bool SynchronousVellemanK8062::Init() { unsigned int chunk_size = DEFAULT_CHUNK_SIZE; libusb_device_handle *usb_handle = OpenVellemenWidget( m_adaptor, m_usb_device, &chunk_size); if (!usb_handle) { return false; } std::auto_ptr sender( new VellemanThreadedSender(m_adaptor, m_usb_device, usb_handle, chunk_size)); if (!sender->Start()) { return false; } m_sender.reset(sender.release()); return true; } bool SynchronousVellemanK8062::SendDMX(const DmxBuffer &buffer) { return m_sender.get() ? m_sender->SendDMX(buffer) : false; } // VellemanAsyncUsbSender // ----------------------------------------------------------------------------- class VellemanAsyncUsbSender : public AsyncUsbSender { public: VellemanAsyncUsbSender(LibUsbAdaptor *adaptor, libusb_device *usb_device) : AsyncUsbSender(adaptor, usb_device), m_chunk_size(DEFAULT_CHUNK_SIZE), m_buffer_offset(0), m_packet(NULL) { m_tx_buffer.Blackout(); } ~VellemanAsyncUsbSender() { CancelTransfer(); if (m_packet) { delete[] m_packet; } } libusb_device_handle* SetupHandle() { libusb_device_handle *handle = OpenVellemenWidget(m_adaptor, m_usb_device, &m_chunk_size); m_packet = new uint8_t[m_chunk_size]; return handle; } bool PerformTransfer(const DmxBuffer &buffer); void PostTransferHook(); private: // These are set once we known the type of device we're talking to. unsigned int m_chunk_size; DmxBuffer m_tx_buffer; // This tracks where were are in m_tx_buffer. A value of 0 means we're at the // start of a DMX frame. unsigned int m_buffer_offset; uint8_t *m_packet; bool ContinueTransfer(); bool SendInitialChunk(const DmxBuffer &buffer); bool SendIntermediateChunk(); bool SendSingleSlotChunk(); bool SendChunk() { FillInterruptTransfer(ENDPOINT, m_packet, m_chunk_size, URB_TIMEOUT_MS); return (SubmitTransfer() == 0); } DISALLOW_COPY_AND_ASSIGN(VellemanAsyncUsbSender); }; bool VellemanAsyncUsbSender::PerformTransfer(const DmxBuffer &buffer) { if (m_buffer_offset == 0) { return SendInitialChunk(buffer); } // Otherwise we're part way through a transfer, do nothing. return true; } void VellemanAsyncUsbSender::PostTransferHook() { if (m_buffer_offset < m_tx_buffer.Size()) { ContinueTransfer(); } else if (m_buffer_offset >= m_tx_buffer.Size()) { // That was the last chunk. m_buffer_offset = 0; if (TransferPending()) { // If we have a pending transfer, the next chunk is going to be sent // once we return. m_tx_buffer.Reset(); } else { // No pending transfer. The widget only actually sends a frame once the // next frame begins, so kick off the next frame here. PerformTransfer(m_tx_buffer); } } } bool VellemanAsyncUsbSender::ContinueTransfer() { if (m_buffer_offset + m_chunk_size < m_tx_buffer.Size()) { return SendIntermediateChunk(); } if (m_chunk_size == UPGRADED_CHUNK_SIZE) { // If running in extended mode we can use the 6 message type to send // everything at once. unsigned int length = m_chunk_size - HEADER_SIZE; m_packet[0] = VARIABLE_FRAME_CONTINUATION_MSG; m_packet[1] = m_tx_buffer.Size() - m_buffer_offset; m_tx_buffer.GetRange(m_buffer_offset, m_packet + HEADER_SIZE, &length); memset(m_packet + HEADER_SIZE + length, 0, m_chunk_size - length - HEADER_SIZE); return (SendChunk() == 0); } else { // The trailing slots are sent individually. return SendSingleSlotChunk(); } } bool VellemanAsyncUsbSender::SendInitialChunk(const DmxBuffer &buffer) { unsigned int length = m_chunk_size - HEADER_SIZE; if (m_chunk_size == UPGRADED_CHUNK_SIZE && buffer.Size() <= m_chunk_size - HEADER_SIZE) { // If the upgrade is present and we can fit the data in a single chunk // use the FULL_FRAME_MSG message type. m_packet[0] = FULL_FRAME_MSG; m_packet[1] = m_tx_buffer.Size(); // number of slots in the frame. buffer.Get(m_packet + HEADER_SIZE, &length); memset(m_packet + HEADER_SIZE + length, 0, m_chunk_size - length - HEADER_SIZE); } else { m_tx_buffer.SetRange(0, buffer.GetRaw(), buffer.Size()); // Otherwise use BREAK_MSG to signal the start of frame. unsigned int leading_zero_count = CountLeadingZeros( m_tx_buffer.GetRaw(), m_tx_buffer.Size(), m_chunk_size); m_packet[0] = BREAK_MSG; m_packet[1] = leading_zero_count + 1; // include start code m_tx_buffer.GetRange(leading_zero_count, m_packet + HEADER_SIZE, &length); memset(m_packet + HEADER_SIZE + length, 0, m_chunk_size - length - HEADER_SIZE); unsigned int slots_sent = leading_zero_count + length; if (slots_sent < m_tx_buffer.Size()) { // There are more frames to send. m_buffer_offset = slots_sent; } } return (SendChunk() == 0); } bool VellemanAsyncUsbSender::SendIntermediateChunk() { // Intermediate frame. unsigned int zeros = CountLeadingZeros( m_tx_buffer.GetRaw() + m_buffer_offset, m_tx_buffer.Size() - m_buffer_offset, m_chunk_size); unsigned int length = m_chunk_size - 1; if (zeros) { // we have leading zeros m_packet[0] = INTERMEDIATE_COMPRESSED_FRAME_MSG; m_packet[1] = zeros; length--; m_tx_buffer.GetRange(m_buffer_offset + zeros, m_packet + HEADER_SIZE, &length); m_buffer_offset += zeros + length; } else { m_packet[0] = INTERMEDIATE_FRAME_MSG; m_tx_buffer.GetRange(m_buffer_offset, m_packet + 1, &length); memset(m_packet + 1 + length, 0, m_chunk_size - length - 1); m_buffer_offset += length; } return (SendChunk() == 0); } bool VellemanAsyncUsbSender::SendSingleSlotChunk() { memset(m_packet, 0, m_chunk_size); m_packet[0] = SINGLE_SLOT_MSG; m_packet[1] = m_tx_buffer.Get(m_buffer_offset); m_buffer_offset++; return (SendChunk() == 0); } // AsynchronousVellemanK8062 // ----------------------------------------------------------------------------- AsynchronousVellemanK8062::AsynchronousVellemanK8062( LibUsbAdaptor *adaptor, libusb_device *usb_device) : VellemanK8062(adaptor, usb_device) { m_sender.reset(new VellemanAsyncUsbSender(m_adaptor, usb_device)); } bool AsynchronousVellemanK8062::Init() { return m_sender->Init(); } bool AsynchronousVellemanK8062::SendDMX(const DmxBuffer &buffer) { return m_sender->SendDMX(buffer); } } // namespace usbdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbdmx/Flags.cpp0000644000175000017500000000171013023355232020200 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Flags.cpp * Flags for the libusb plugin. * Copyright (C) 2014 Simon Newton */ #include "ola/base/Flags.h" DEFINE_default_bool(use_async_libusb, true, "Disable the use of the asyncronous libusb calls, revert to syncronous"); ola-0.10.5.nojsmin/plugins/usbdmx/DMXCProjectsNodleU1Port.h0000644000175000017500000000425613023355232023123 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DMXCProjectsNodleU1Port.h * Output and input ports that use a widget and give the serial as desciption. * Copyright (C) 2015 Stefan Krupop */ #ifndef PLUGINS_USBDMX_DMXCPROJECTSNODLEU1PORT_H_ #define PLUGINS_USBDMX_DMXCPROJECTSNODLEU1PORT_H_ #include #include #include "ola/base/Macro.h" #include "olad/Port.h" #include "plugins/usbdmx/DMXCProjectsNodleU1.h" namespace ola { class Device; namespace plugin { namespace usbdmx { /** * @brief A thin wrapper around a Widget so that it can operate as a Port. */ class DMXCProjectsNodleU1InputPort: public BasicInputPort { public: /** * @brief Create a new DMXCProjectsNodleU1InputPort. * @param parent The parent device for this port. * @param id The port id. * @param plugin_adaptor a PluginAdaptor object, used by the base class. * @param widget The widget to use to receive DMX frames. */ DMXCProjectsNodleU1InputPort(Device *parent, unsigned int id, PluginAdaptor *plugin_adaptor, class DMXCProjectsNodleU1 *widget); const DmxBuffer &ReadDMX() const { return m_widget->GetDmxInBuffer(); } std::string Description() const { return ""; } private: class DMXCProjectsNodleU1* const m_widget; DISALLOW_COPY_AND_ASSIGN(DMXCProjectsNodleU1InputPort); }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_DMXCPROJECTSNODLEU1PORT_H_ ola-0.10.5.nojsmin/plugins/usbdmx/ThreadedUsbSender.h0000644000175000017500000000653713023355232022160 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ThreadedUsbSender.h * Send DMX data over USB from a dedicated thread. * Copyright (C) 2010 Simon Newton */ #ifndef PLUGINS_USBDMX_THREADEDUSBSENDER_H_ #define PLUGINS_USBDMX_THREADEDUSBSENDER_H_ #include #include "ola/base/Macro.h" #include "ola/DmxBuffer.h" #include "ola/thread/Thread.h" namespace ola { namespace plugin { namespace usbdmx { /** * @brief Send DMX data using libusb, from a separate thread. * * The synchronous libusb calls can sometimes take a while to complete, I've * seen cases of up to 21ms. * * To avoid blocking the main thread, we need to perform the libusb transfer * calls in a separate thread. This class contains all the thread management * code, leaving the subclass to implement TransmitBuffer(), which performs the * actual transfer. * * ThreadedUsbSender can be used as a building block for synchronous widgets. */ class ThreadedUsbSender: private ola::thread::Thread { public: /** * @brief Create a new ThreadedUsbSender. * @param usb_device The usb_device to use. The ThreadedUsbSender takes a ref * on the device, while the ThreadedUsbSender object exists. * @param usb_handle The handle to use for the DMX transfer. * @param interface_number the USB interface number of the widget. Defaults to 0. */ ThreadedUsbSender(libusb_device *usb_device, libusb_device_handle *usb_handle, int interface_number = 0); virtual ~ThreadedUsbSender(); /** * @brief Start the new thread. * @returns true if the thread is running, false otherwise. */ bool Start(); /** * @brief Entry point for the new thread. * @returns NULL. */ void *Run(); /** * @brief Buffer a DMX frame for sending. * @param buffer the DmxBuffer to send. * * This should be called in the main thread. */ bool SendDMX(const DmxBuffer &buffer); protected: /** * @brief Perform the DMX transfer. * @param handle the libusb_device_handle to use for the transfer. * @param buffer The DmxBuffer to transfer. * @returns true if the transfer was completed, false otherwise. * * This is called from the sender thread. */ virtual bool TransmitBuffer(libusb_device_handle *handle, const DmxBuffer &buffer) = 0; private: bool m_term; libusb_device* const m_usb_device; libusb_device_handle* const m_usb_handle; int const m_interface_number; DmxBuffer m_buffer; ola::thread::Mutex m_data_mutex; ola::thread::Mutex m_term_mutex; DISALLOW_COPY_AND_ASSIGN(ThreadedUsbSender); }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_THREADEDUSBSENDER_H_ ola-0.10.5.nojsmin/plugins/usbdmx/JaRuleOutputPort.h0000644000175000017500000000505713023355232022071 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * JaRuleOutputPort.h * A JaRule output port that uses a widget. * Copyright (C) 2015 Simon Newton */ #ifndef PLUGINS_USBDMX_JARULEOUTPUTPORT_H_ #define PLUGINS_USBDMX_JARULEOUTPUTPORT_H_ #include #include "ola/base/Macro.h" #include "olad/Port.h" #include "libs/usb/JaRulePortHandle.h" #include "libs/usb/JaRuleWidget.h" namespace ola { class Device; namespace plugin { namespace usbdmx { /** * @brief A thin wrapper around a JaRulePortHandle so that it can operate as an * OLA Port. */ class JaRuleOutputPort: public BasicOutputPort { public: /** * @brief Create a new JaRuleOutputPort. * @param parent The parent device for this port. * @param index The port index, starting from 0 * @param widget The widget to use. */ JaRuleOutputPort(Device *parent, unsigned int index, ola::usb::JaRuleWidget *widget); /** * @brief Destructor */ ~JaRuleOutputPort(); /** * @brief Initialize the port. * @returns true if ok, false if initialization failed. */ bool Init(); bool WriteDMX(const DmxBuffer &buffer, uint8_t priority); std::string Description() const; void SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *callback); void RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback); void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback); bool PreSetUniverse(Universe *old_universe, Universe *new_universe); void PostSetUniverse(Universe *old_universe, Universe *new_universe); private: const unsigned int m_port_index; ola::usb::JaRuleWidget *m_widget; // not owned ola::usb::JaRulePortHandle *m_port_handle; // not owned DISALLOW_COPY_AND_ASSIGN(JaRuleOutputPort); }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_JARULEOUTPUTPORT_H_ ola-0.10.5.nojsmin/plugins/usbdmx/DMXCProjectsNodleU1Factory.cpp0000644000175000017500000000542713023355232024142 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DMXCProjectsNodleU1Factory.cpp * The WidgetFactory for Nodle widgets. * Copyright (C) 2015 Stefan Krupop */ #include "plugins/usbdmx/DMXCProjectsNodleU1Factory.h" #include "ola/Logging.h" #include "ola/base/Flags.h" #include "plugins/usbdmx/DMXCProjectsNodleU1.h" DECLARE_bool(use_async_libusb); namespace ola { namespace plugin { namespace usbdmx { const uint16_t DMXCProjectsNodleU1Factory::VENDOR_ID = 0x16d0; const uint16_t DMXCProjectsNodleU1Factory::PRODUCT_ID = 0x0830; bool DMXCProjectsNodleU1Factory::DeviceAdded( WidgetObserver *observer, libusb_device *usb_device, const struct libusb_device_descriptor &descriptor) { if (descriptor.idVendor != VENDOR_ID || descriptor.idProduct != PRODUCT_ID) { return false; } OLA_INFO << "Found a new Nodle U1 device"; ola::usb::LibUsbAdaptor::DeviceInformation info; if (!m_adaptor->GetDeviceInfo(usb_device, descriptor, &info)) { return false; } OLA_INFO << "Nodle U1 serial: " << info.serial; if (m_preferences->SetDefaultValue( "nodle-" + info.serial + "-mode", UIntValidator(DMXCProjectsNodleU1::NODLE_MIN_MODE, DMXCProjectsNodleU1::NODLE_MAX_MODE), DMXCProjectsNodleU1::NODLE_DEFAULT_MODE)) { m_preferences->Save(); } unsigned int mode; if (!StringToInt(m_preferences->GetValue("nodle-" + info.serial + "-mode"), &mode)) { mode = DMXCProjectsNodleU1::NODLE_DEFAULT_MODE; } OLA_INFO << "Setting Nodle U1 mode to " << mode; DMXCProjectsNodleU1 *widget = NULL; if (FLAGS_use_async_libusb) { widget = new AsynchronousDMXCProjectsNodleU1(m_adaptor, usb_device, m_plugin_adaptor, info.serial, mode); } else { widget = new SynchronousDMXCProjectsNodleU1(m_adaptor, usb_device, m_plugin_adaptor, info.serial, mode); } return AddWidget(observer, widget); } } // namespace usbdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbdmx/AsyncPluginImpl.h0000644000175000017500000000711513023355232021674 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * AsyncPluginImpl.h * The asynchronous libusb implementation. * Copyright (C) 2014 Simon Newton */ #ifndef PLUGINS_USBDMX_ASYNCPLUGINIMPL_H_ #define PLUGINS_USBDMX_ASYNCPLUGINIMPL_H_ #include #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #include #include #include #include #include "libs/usb/Types.h" #include "libs/usb/HotplugAgent.h" #include "ola/base/Macro.h" #include "ola/thread/Future.h" #include "olad/Preferences.h" #include "plugins/usbdmx/PluginImplInterface.h" #include "plugins/usbdmx/SyncronizedWidgetObserver.h" #include "plugins/usbdmx/WidgetFactory.h" namespace ola { namespace usb { class LibUsbThread; class AsyncronousLibUsbAdaptor; } // namespace usb class Device; namespace plugin { namespace usbdmx { /** * @brief The asynchronous libusb implementation. */ class AsyncPluginImpl: public PluginImplInterface, public WidgetObserver { public: /** * @brief Create a new AsyncPluginImpl. * @param plugin_adaptor The PluginAdaptor to use, ownership is not * transferred. * @param plugin The parent Plugin object which is used when creating * devices. * @param debug_level the debug level to use for libusb. * @param preferences The Preferences container used by the plugin */ AsyncPluginImpl(PluginAdaptor *plugin_adaptor, Plugin *plugin, unsigned int debug_level, Preferences *preferences); ~AsyncPluginImpl(); bool Start(); bool Stop(); // These are all run in the main SelectServer thread. bool NewWidget(class AnymauDMX *widget); bool NewWidget(class DMXCProjectsNodleU1 *widget); bool NewWidget(class EurolitePro *widget); bool NewWidget(ola::usb::JaRuleWidget *widget); bool NewWidget(class ScanlimeFadecandy *widget); bool NewWidget(class Sunlite *widget); bool NewWidget(class VellemanK8062 *widget); private: typedef std::vector WidgetFactories; typedef std::map USBDeviceMap; PluginAdaptor* const m_plugin_adaptor; Plugin* const m_plugin; const unsigned int m_debug_level; std::auto_ptr m_agent; Preferences* const m_preferences; SyncronizedWidgetObserver m_widget_observer; ola::usb::AsyncronousLibUsbAdaptor *m_usb_adaptor; // not owned WidgetFactories m_widget_factories; USBDeviceMap m_device_map; void DeviceEvent(ola::usb::HotplugAgent::EventType event, struct libusb_device *device); void SetupUSBDevice(libusb_device *device); template bool StartAndRegisterDevice(Widget *widget, Device *device); void ShutdownDevice(Device *device, ola::thread::Future *f); DISALLOW_COPY_AND_ASSIGN(AsyncPluginImpl); }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_ASYNCPLUGINIMPL_H_ ola-0.10.5.nojsmin/plugins/usbdmx/GenericDevice.h0000644000175000017500000000372513023355232021315 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * GenericDevice.h * A Generic device that creates a single port. * Copyright (C) 2014 Simon Newton */ #ifndef PLUGINS_USBDMX_GENERICDEVICE_H_ #define PLUGINS_USBDMX_GENERICDEVICE_H_ #include #include #include "ola/base/Macro.h" #include "olad/Device.h" namespace ola { namespace plugin { namespace usbdmx { /** * @brief A Generic device. * * This simple generic device creates a single output port around a Widget. */ class GenericDevice: public Device { public: /** * @brief Create a new GenericDevice. * @param owner The plugin this device belongs to * @param widget The widget to use for this device. * @param device_name The name of the device. * @param device_id The id of the device. */ GenericDevice(ola::AbstractPlugin *owner, class WidgetInterface *widget, const std::string &device_name, const std::string &device_id); std::string DeviceId() const { return m_device_id; } protected: bool StartHook(); private: const std::string m_device_id; std::auto_ptr m_port; DISALLOW_COPY_AND_ASSIGN(GenericDevice); }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_GENERICDEVICE_H_ ola-0.10.5.nojsmin/plugins/usbdmx/AnymauDMXFactory.cpp0000644000175000017500000000561513023355232022307 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * AnymauDMXFactory.cpp * The factory for Anyma uDMX widgets. * Copyright (C) 2014 Simon Newton */ #include "plugins/usbdmx/AnymauDMXFactory.h" #include "libs/usb/LibUsbAdaptor.h" #include "ola/Logging.h" #include "ola/base/Flags.h" #include "plugins/usbdmx/AnymauDMX.h" DECLARE_bool(use_async_libusb); namespace ola { namespace plugin { namespace usbdmx { using ola::usb::LibUsbAdaptor; const char AnymauDMXFactory::EXPECTED_MANUFACTURER[] = "www.anyma.ch"; const char AnymauDMXFactory::EXPECTED_PRODUCT[] = "uDMX"; const uint16_t AnymauDMXFactory::PRODUCT_ID = 0x05DC; const uint16_t AnymauDMXFactory::VENDOR_ID = 0x16C0; bool AnymauDMXFactory::DeviceAdded( WidgetObserver *observer, libusb_device *usb_device, const struct libusb_device_descriptor &descriptor) { if (descriptor.idVendor != VENDOR_ID || descriptor.idProduct != PRODUCT_ID) { return false; } OLA_INFO << "Found a new Anyma device"; LibUsbAdaptor::DeviceInformation info; if (!m_adaptor->GetDeviceInfo(usb_device, descriptor, &info)) { return false; } if (!m_adaptor->CheckManufacturer(EXPECTED_MANUFACTURER, info)) { return false; } if (!m_adaptor->CheckProduct(EXPECTED_PRODUCT, info)) { return false; } // Some Anyma devices don't have serial numbers. Since there isn't another // good way to uniquely identify a USB device, we only support one of these // types of devices per host. if (info.serial.empty()) { if (m_missing_serial_number) { OLA_WARN << "Failed to read serial number or serial number empty. " << "We can only support one device without a serial number."; return false; } else { OLA_WARN << "Failed to read serial number from " << info.manufacturer << " : " << info.product << " the device probably doesn't have one"; m_missing_serial_number = true; } } AnymauDMX *widget = NULL; if (FLAGS_use_async_libusb) { widget = new AsynchronousAnymauDMX(m_adaptor, usb_device, info.serial); } else { widget = new SynchronousAnymauDMX(m_adaptor, usb_device, info.serial); } return AddWidget(observer, widget); } } // namespace usbdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbdmx/AsyncPluginImpl.cpp0000644000175000017500000002423013023355232022224 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * AsyncPluginImpl.cpp * The asynchronous libusb implementation. * Copyright (C) 2014 Simon Newton */ #include "plugins/usbdmx/AsyncPluginImpl.h" #include #include #include #include "ola/Logging.h" #include "ola/StringUtils.h" #include "ola/stl/STLUtils.h" #include "ola/strings/Format.h" #include "ola/thread/Future.h" #include "ola/util/Deleter.h" #include "olad/PluginAdaptor.h" #include "libs/usb/JaRuleWidget.h" #include "libs/usb/LibUsbAdaptor.h" #include "libs/usb/LibUsbThread.h" #include "libs/usb/Types.h" #include "plugins/usbdmx/AnymauDMX.h" #include "plugins/usbdmx/AnymauDMXFactory.h" #include "plugins/usbdmx/DMXCProjectsNodleU1.h" #include "plugins/usbdmx/DMXCProjectsNodleU1Device.h" #include "plugins/usbdmx/DMXCProjectsNodleU1Factory.h" #include "plugins/usbdmx/EuroliteProFactory.h" #include "plugins/usbdmx/GenericDevice.h" #include "plugins/usbdmx/JaRuleDevice.h" #include "plugins/usbdmx/JaRuleFactory.h" #include "plugins/usbdmx/ScanlimeFadecandy.h" #include "plugins/usbdmx/ScanlimeFadecandyFactory.h" #include "plugins/usbdmx/SunliteFactory.h" #include "plugins/usbdmx/VellemanK8062.h" #include "plugins/usbdmx/VellemanK8062Factory.h" namespace ola { namespace plugin { namespace usbdmx { using ola::usb::HotplugAgent; using ola::usb::JaRuleWidget; using ola::usb::USBDeviceID; using ola::NewSingleCallback; using std::auto_ptr; using ola::thread::Future; class DeviceState { public: typedef ola::SingleUseCallback0 DeleterCallback; DeviceState() : factory(NULL), ola_device(NULL), m_deleter(NULL) {} void SetDeleteCallback(DeleterCallback *cb) { m_deleter = cb; } void DeleteWidget() { if (m_deleter) { m_deleter->Run(); m_deleter = NULL; } } WidgetFactory *factory; // The factory that owns this device. Device *ola_device; // The OLA device that uses this USB device. private: DeleterCallback *m_deleter; }; AsyncPluginImpl::AsyncPluginImpl(PluginAdaptor *plugin_adaptor, Plugin *plugin, unsigned int debug_level, Preferences *preferences) : m_plugin_adaptor(plugin_adaptor), m_plugin(plugin), m_debug_level(debug_level), m_preferences(preferences), m_widget_observer(this, plugin_adaptor), m_usb_adaptor(NULL) { } AsyncPluginImpl::~AsyncPluginImpl() { STLDeleteElements(&m_widget_factories); } bool AsyncPluginImpl::Start() { auto_ptr agent(new HotplugAgent( NewCallback(this, &AsyncPluginImpl::DeviceEvent), m_debug_level)); if (!agent->Init()) { return false; } m_usb_adaptor = agent->GetUSBAdaptor(); // Setup the factories. m_widget_factories.push_back(new AnymauDMXFactory(m_usb_adaptor)); m_widget_factories.push_back( new DMXCProjectsNodleU1Factory(m_usb_adaptor, m_plugin_adaptor, m_preferences)); m_widget_factories.push_back( new EuroliteProFactory(m_usb_adaptor)); m_widget_factories.push_back( new JaRuleFactory(m_plugin_adaptor, m_usb_adaptor)); m_widget_factories.push_back( new ScanlimeFadecandyFactory(m_usb_adaptor)); m_widget_factories.push_back(new SunliteFactory(m_usb_adaptor)); m_widget_factories.push_back(new VellemanK8062Factory(m_usb_adaptor)); // If we're using hotplug, this starts the hotplug thread. if (!agent->Start()) { STLDeleteElements(&m_widget_factories); return false; } m_agent.reset(agent.release()); return true; } bool AsyncPluginImpl::Stop() { if (!m_agent.get()) { return true; } m_agent->HaltNotifications(); // Now we're free to use m_device_map. USBDeviceMap::iterator iter = m_device_map.begin(); for (; iter != m_device_map.end(); ++iter) { DeviceState *state = iter->second; if (state->ola_device) { m_plugin_adaptor->UnregisterDevice(state->ola_device); state->ola_device->Stop(); delete state->ola_device; } state->DeleteWidget(); } STLDeleteValues(&m_device_map); STLDeleteElements(&m_widget_factories); m_agent->Stop(); m_agent.reset(); return true; } bool AsyncPluginImpl::NewWidget(AnymauDMX *widget) { return StartAndRegisterDevice( widget, new GenericDevice(m_plugin, widget, "Anyma USB Device", "anyma-" + widget->SerialNumber())); } bool AsyncPluginImpl::NewWidget(DMXCProjectsNodleU1 *widget) { return StartAndRegisterDevice( widget, new DMXCProjectsNodleU1Device( m_plugin, widget, "DMXControl Projects e.V. Nodle U1 (" + widget->SerialNumber() + ")", "nodleu1-" + widget->SerialNumber(), m_plugin_adaptor)); } bool AsyncPluginImpl::NewWidget(EurolitePro *widget) { return StartAndRegisterDevice( widget, new GenericDevice(m_plugin, widget, "EurolitePro USB Device", "eurolite-" + widget->SerialNumber())); } bool AsyncPluginImpl::NewWidget(JaRuleWidget *widget) { std::ostringstream str; str << widget->ProductString() << " (" << widget->GetUID() << ")"; return StartAndRegisterDevice(widget, new JaRuleDevice(m_plugin, widget, str.str())); } bool AsyncPluginImpl::NewWidget(ScanlimeFadecandy *widget) { return StartAndRegisterDevice( widget, new GenericDevice( m_plugin, widget, "Fadecandy USB Device (" + widget->SerialNumber() + ")", "fadecandy-" + widget->SerialNumber())); } bool AsyncPluginImpl::NewWidget(Sunlite *widget) { return StartAndRegisterDevice( widget, new GenericDevice(m_plugin, widget, "Sunlite USBDMX2 Device", "usbdmx2")); } bool AsyncPluginImpl::NewWidget(VellemanK8062 *widget) { return StartAndRegisterDevice( widget, new GenericDevice(m_plugin, widget, "Velleman USB Device", "velleman")); } /** * This is run in either the thread calling Start() or a hotplug thread, * but not both at once. */ void AsyncPluginImpl::DeviceEvent(HotplugAgent::EventType event, struct libusb_device *device) { if (event == HotplugAgent::DEVICE_ADDED) { SetupUSBDevice(device); } else { USBDeviceID device_id = m_usb_adaptor->GetDeviceId(device); DeviceState *state; if (!STLLookupAndRemove(&m_device_map, device_id, &state) || !state) { return; } // At some point we'll need to notify the factory here. For instance in the // Sunlite plugin, if we make the f/w load async we'll need to let the // factory cancel the load. // Unregister & delete the device in the main thread. if (state->ola_device) { Future f; m_plugin_adaptor->Execute( NewSingleCallback(this, &AsyncPluginImpl::ShutdownDevice, state->ola_device, &f)); f.Get(); state->ola_device = NULL; } state->DeleteWidget(); } } /** * @brief Signal a new USB device has been added. * * This can be called more than once for a given device, in this case we'll * avoid calling the factories twice. * * This can be called from either the libusb thread or the main thread. However * only one of those will be active at once, so we can avoid locking. */ void AsyncPluginImpl::SetupUSBDevice(libusb_device *usb_device) { USBDeviceID device_id = m_usb_adaptor->GetDeviceId(usb_device); USBDeviceMap::iterator iter = STLLookupOrInsertNew(&m_device_map, device_id); DeviceState *state = iter->second; if (state->factory) { // Already claimed return; } struct libusb_device_descriptor descriptor; libusb_get_device_descriptor(usb_device, &descriptor); OLA_DEBUG << "USB device added, checking for widget support, vendor " << strings::ToHex(descriptor.idVendor) << ", product " << strings::ToHex(descriptor.idProduct); WidgetFactories::iterator factory_iter = m_widget_factories.begin(); for (; factory_iter != m_widget_factories.end(); ++factory_iter) { if ((*factory_iter)->DeviceAdded(&m_widget_observer, usb_device, descriptor)) { OLA_INFO << "Device " << device_id << " claimed by " << (*factory_iter)->Name(); state->factory = *factory_iter; return; } } } /* * @brief Called when a new OLA device is ready. * @param widget The Widget used for this device. * @param device The new olad device that uses this new widget. * * This is run within the main thread. */ template bool AsyncPluginImpl::StartAndRegisterDevice(Widget *widget, Device *device) { DeviceState *state = STLFindOrNull(m_device_map, widget->GetDeviceId()); if (!state) { OLA_WARN << "Failed to find state for device " << widget->GetDeviceId(); delete device; return false; } if (state->ola_device) { OLA_WARN << "Clobbering an old device!"; m_plugin_adaptor->UnregisterDevice(state->ola_device); state->ola_device->Stop(); delete state->ola_device; state->ola_device = NULL; } if (!device->Start()) { delete device; return false; } m_plugin_adaptor->RegisterDevice(device); state->ola_device = device; state->SetDeleteCallback(ola::DeletePointerCallback(widget)); return true; } /* * @brief Signal widget removal. * @param device_id The device id to remove. * * This is run within the main thread. */ void AsyncPluginImpl::ShutdownDevice(Device *device, Future *f) { m_plugin_adaptor->UnregisterDevice(device); device->Stop(); delete device; if (f) { f->Set(); } } } // namespace usbdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbdmx/SunliteFactory.cpp0000644000175000017500000000413113023355232022117 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * SunliteFactory.cpp * The WidgetFactory for SunLite widgets. * Copyright (C) 2014 Simon Newton */ #include "plugins/usbdmx/SunliteFactory.h" #include "ola/Logging.h" #include "ola/base/Flags.h" #include "plugins/usbdmx/SunliteFirmwareLoader.h" DECLARE_bool(use_async_libusb); namespace ola { namespace plugin { namespace usbdmx { const uint16_t SunliteFactory::EMPTY_PRODUCT_ID = 0x2000; const uint16_t SunliteFactory::FULL_PRODUCT_ID = 0x2001; const uint16_t SunliteFactory::VENDOR_ID = 0x0962; bool SunliteFactory::DeviceAdded( WidgetObserver *observer, libusb_device *usb_device, const struct libusb_device_descriptor &descriptor) { if (descriptor.idVendor == VENDOR_ID && descriptor.idProduct == EMPTY_PRODUCT_ID) { OLA_INFO << "New empty SunliteDevice"; // TODO(simon): Make this async. SunliteFirmwareLoader loader(usb_device); loader.LoadFirmware(); return true; } else if (descriptor.idVendor == VENDOR_ID && descriptor.idProduct == FULL_PRODUCT_ID) { OLA_INFO << "Found a new Sunlite device"; Sunlite *widget = NULL; if (FLAGS_use_async_libusb) { widget = new AsynchronousSunlite(m_adaptor, usb_device); } else { widget = new SynchronousSunlite(m_adaptor, usb_device); } return AddWidget(observer, widget); } return false; } } // namespace usbdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbdmx/WidgetFactory.h0000644000175000017500000001455513023355232021377 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * WidgetFactory.h * Creates USB Widgets. * Copyright (C) 2014 Simon Newton */ #ifndef PLUGINS_USBDMX_WIDGETFACTORY_H_ #define PLUGINS_USBDMX_WIDGETFACTORY_H_ #include #include #include #include "ola/Logging.h" #include "ola/base/Macro.h" #include "ola/stl/STLUtils.h" namespace ola { namespace usb { class JaRuleWidget; } // namespace usb namespace plugin { namespace usbdmx { /** * @brief Receives notifications when Widgets are added or removed. * * Classes implementing the WidgetObserver can be used with WidgetFactories to * receive notifcations when widgets are added. * * On adding a new Widget, the appropriate NewWidget() method is called. The * observer can mark a widget as in-use by returning true. */ class WidgetObserver { public: virtual ~WidgetObserver() {} /** * @brief Called when a new AnymauDMX is added. * @param widget the new Widget, ownership is not transferred but the object * may be used until the corresponding WidgetRemoved() call is made. * @returns true if the widget has been claimed, false if the widget was * ignored. */ virtual bool NewWidget(class AnymauDMX *widget) = 0; /** * @brief Called when a new DMXCProjects Nodle U1 widget is added. * @param widget the new Widget, ownership is not transferred but the object * may be used until the corresponding WidgetRemoved() call is made. * @returns true if the widget has been claimed, false if the widget was * ignored. */ virtual bool NewWidget(class DMXCProjectsNodleU1 *widget) = 0; /** * @brief Called when a new EurolitePro is added. * @param widget the new Widget, ownership is not transferred but the object * may be used until the corresponding WidgetRemoved() call is made. * @returns true if the widget has been claimed, false if the widget was * ignored. */ virtual bool NewWidget(class EurolitePro *widget) = 0; /** * @brief Called when a new Ja Rule widget is added. * @param widget the new Widget, ownership is not transferred but the object * may be used until the corresponding WidgetRemoved() call is made. * @returns true if the widget has been claimed, false if the widget was * ignored. */ virtual bool NewWidget(ola::usb::JaRuleWidget *widget) = 0; /** * @brief Called when a new ScanlimeFadecandy is added. * @param widget the new Widget, ownership is not transferred but the object * may be used until the corresponding WidgetRemoved() call is made. * @returns true if the widget has been claimed, false if the widget was * ignored. */ virtual bool NewWidget(class ScanlimeFadecandy *widget) = 0; /** * @brief Called when a new Sunlite is added. * @param widget the new Widget, ownership is not transferred but the object * may be used until the corresponding WidgetRemoved() call is made. * @returns true if the widget has been claimed, false if the widget was * ignored. */ virtual bool NewWidget(class Sunlite *widget) = 0; /** * @brief Called when a new VellemanK8062 is added. * @param widget the new Widget, ownership is not transferred but the object * may be used until the corresponding WidgetRemoved() call is made. * @returns true if the widget has been claimed, false if the widget was * ignored. */ virtual bool NewWidget(class VellemanK8062 *widget) = 0; }; /** * @brief Creates new Widget objects to represent DMX USB hardware. * * WidgetFactories are called when new USB devices are located. By inspecting * the device's vendor and product ID, they may choose to create a new Widget * object. The WidgetFactory then calls the WidgetObserver object to indicate a * new Widget has been added. */ class WidgetFactory { public: virtual ~WidgetFactory() {} /** * @brief Called when a new USB device is added. * @param observer The WidgetObserver to notify if this results in a new * widget. * @param usb_device the libusb_device that was added. * @param descriptor the libusb_device_descriptor that corresponds to the * usb_device. * @returns True if this factory has claimed the usb_device, false otherwise. */ virtual bool DeviceAdded( WidgetObserver *observer, libusb_device *usb_device, const struct libusb_device_descriptor &descriptor) = 0; /** * @brief The name of this factory. * @returns The name of this factory. */ virtual std::string Name() const = 0; }; /** * @brief A partial implementation of WidgetFactory. * * This handles the mapping of libusb_devices to widgets and notifying the * observer when widgets are added or removed. */ template class BaseWidgetFactory : public WidgetFactory { public: explicit BaseWidgetFactory(const std::string &name) : m_name(name) {} std::string Name() const { return m_name; } protected: /** * @brief Initialize a widget and notify the observer. * @param observer The WidgetObserver to notify of the new widget. * @param widget the new Widget, ownership is transferred. * @returns True if the widget was added, false otherwise. */ bool AddWidget(WidgetObserver *observer, WidgetType *widget); private: const std::string m_name; DISALLOW_COPY_AND_ASSIGN(BaseWidgetFactory); }; template bool BaseWidgetFactory::AddWidget(WidgetObserver *observer, WidgetType *widget) { if (!widget->Init()) { delete widget; return false; } if (!observer->NewWidget(widget)) { delete widget; return false; } return true; } } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_WIDGETFACTORY_H_ ola-0.10.5.nojsmin/plugins/usbdmx/GenericOutputPort.h0000644000175000017500000000351713023355232022262 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * GenericOutputPort.h * A Generic output port that uses a widget. * Copyright (C) 2014 Simon Newton */ #ifndef PLUGINS_USBDMX_GENERICOUTPUTPORT_H_ #define PLUGINS_USBDMX_GENERICOUTPUTPORT_H_ #include #include "ola/base/Macro.h" #include "olad/Port.h" namespace ola { class Device; namespace plugin { namespace usbdmx { class Widget; /** * @brief A thin wrapper around a Widget so that it can operate as a Port. */ class GenericOutputPort: public BasicOutputPort { public: /** * @brief Create a new GenericOutputPort. * @param parent The parent device for this port. * @param id The port id. * @param widget The widget to use to send DMX frames. */ GenericOutputPort(Device *parent, unsigned int id, class WidgetInterface *widget); bool WriteDMX(const DmxBuffer &buffer, uint8_t priority); std::string Description() const { return ""; } private: class WidgetInterface* const m_widget; DISALLOW_COPY_AND_ASSIGN(GenericOutputPort); }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_GENERICOUTPUTPORT_H_ ola-0.10.5.nojsmin/plugins/usbdmx/EurolitePro.cpp0000644000175000017500000001731413023355232021424 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * EurolitePro.cpp * The synchronous and asynchronous EurolitePro widgets. * Copyright (C) 2014 Simon Newton */ #include "plugins/usbdmx/EurolitePro.h" #include #include #include "libs/usb/LibUsbAdaptor.h" #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/util/Utils.h" #include "plugins/usbdmx/AsyncUsbSender.h" #include "plugins/usbdmx/ThreadedUsbSender.h" namespace ola { namespace plugin { namespace usbdmx { using std::string; using ola::usb::LibUsbAdaptor; namespace { // Why is this so long? static const unsigned int URB_TIMEOUT_MS = 500; static const uint8_t DMX_LABEL = 6; static const uint8_t START_OF_MESSAGE = 0x7e; static const uint8_t END_OF_MESSAGE = 0xe7; static const unsigned char ENDPOINT = 0x02; enum { EUROLITE_PRO_FRAME_SIZE = 518 }; /* * Create a Eurolite Pro message to match the supplied DmxBuffer. */ void CreateFrame( const DmxBuffer &buffer, uint8_t frame[EUROLITE_PRO_FRAME_SIZE]) { unsigned int frame_size = buffer.Size(); // header frame[0] = START_OF_MESSAGE; frame[1] = DMX_LABEL; // Label // LSB first. utils::SplitUInt16(DMX_UNIVERSE_SIZE + 1, &frame[3], &frame[2]); frame[4] = DMX512_START_CODE; buffer.Get(frame + 5, &frame_size); memset(frame + 5 + frame_size, 0, DMX_UNIVERSE_SIZE - frame_size); // End message delimiter frame[EUROLITE_PRO_FRAME_SIZE - 1] = END_OF_MESSAGE; } /* * Find the interface with the endpoint we're after. Usually this is interface * 1 but we check them all just in case. */ bool LocateInterface(LibUsbAdaptor *adaptor, libusb_device *usb_device, int *interface_number) { struct libusb_config_descriptor *device_config; if (adaptor->GetConfigDescriptor(usb_device, 0, &device_config) != 0) { OLA_WARN << "Failed to get device config descriptor"; return false; } OLA_DEBUG << static_cast(device_config->bNumInterfaces) << " interfaces found"; for (unsigned int i = 0; i < device_config->bNumInterfaces; i++) { const struct libusb_interface *interface = &device_config->interface[i]; for (int j = 0; j < interface->num_altsetting; j++) { const struct libusb_interface_descriptor *iface_descriptor = &interface->altsetting[j]; for (uint8_t k = 0; k < iface_descriptor->bNumEndpoints; k++) { const struct libusb_endpoint_descriptor *endpoint = &iface_descriptor->endpoint[k]; OLA_DEBUG << "Interface " << i << ", altsetting " << j << ", endpoint " << static_cast(k) << ", endpoint address 0x" << std::hex << static_cast(endpoint->bEndpointAddress); if (endpoint->bEndpointAddress == ENDPOINT) { OLA_INFO << "Using interface " << i; *interface_number = i; adaptor->FreeConfigDescriptor(device_config); return true; } } } } OLA_WARN << "Failed to locate endpoint for EurolitePro device."; adaptor->FreeConfigDescriptor(device_config); return false; } } // namespace // EuroliteProThreadedSender // ----------------------------------------------------------------------------- /* * Sends messages to a EurolitePro device in a separate thread. */ class EuroliteProThreadedSender: public ThreadedUsbSender { public: EuroliteProThreadedSender(LibUsbAdaptor *adaptor, libusb_device *usb_device, libusb_device_handle *handle); private: LibUsbAdaptor* const m_adaptor; bool TransmitBuffer(libusb_device_handle *handle, const DmxBuffer &buffer); }; EuroliteProThreadedSender::EuroliteProThreadedSender( LibUsbAdaptor *adaptor, libusb_device *usb_device, libusb_device_handle *usb_handle) : ThreadedUsbSender(usb_device, usb_handle), m_adaptor(adaptor) { } bool EuroliteProThreadedSender::TransmitBuffer(libusb_device_handle *handle, const DmxBuffer &buffer) { uint8_t frame[EUROLITE_PRO_FRAME_SIZE]; CreateFrame(buffer, frame); int transferred; int r = m_adaptor->BulkTransfer(handle, ENDPOINT, frame, EUROLITE_PRO_FRAME_SIZE, &transferred, URB_TIMEOUT_MS); if (transferred != EUROLITE_PRO_FRAME_SIZE) { // not sure if this is fatal or not OLA_WARN << "EurolitePro driver failed to transfer all data"; } return r == 0; } // SynchronousEurolitePro // ----------------------------------------------------------------------------- SynchronousEurolitePro::SynchronousEurolitePro( LibUsbAdaptor *adaptor, libusb_device *usb_device, const string &serial) : EurolitePro(adaptor, usb_device, serial) { } bool SynchronousEurolitePro::Init() { libusb_device_handle *usb_handle; int interface_number; if (!LocateInterface(m_adaptor, m_usb_device, &interface_number)) { return false; } bool ok = m_adaptor->OpenDeviceAndClaimInterface( m_usb_device, interface_number, &usb_handle); if (!ok) { return false; } std::auto_ptr sender( new EuroliteProThreadedSender(m_adaptor, m_usb_device, usb_handle)); if (!sender->Start()) { return false; } m_sender.reset(sender.release()); return true; } bool SynchronousEurolitePro::SendDMX(const DmxBuffer &buffer) { return m_sender.get() ? m_sender->SendDMX(buffer) : false; } // EuroliteProAsyncUsbSender // ----------------------------------------------------------------------------- class EuroliteProAsyncUsbSender : public AsyncUsbSender { public: EuroliteProAsyncUsbSender(LibUsbAdaptor *adaptor, libusb_device *usb_device) : AsyncUsbSender(adaptor, usb_device) { } ~EuroliteProAsyncUsbSender() { CancelTransfer(); } libusb_device_handle* SetupHandle() { int interface_number; if (!LocateInterface(m_adaptor, m_usb_device, &interface_number)) { return NULL; } libusb_device_handle *usb_handle; bool ok = m_adaptor->OpenDeviceAndClaimInterface( m_usb_device, interface_number, &usb_handle); return ok ? usb_handle : NULL; } bool PerformTransfer(const DmxBuffer &buffer) { CreateFrame(buffer, m_tx_frame); FillBulkTransfer(ENDPOINT, m_tx_frame, EUROLITE_PRO_FRAME_SIZE, URB_TIMEOUT_MS); return (SubmitTransfer() == 0); } private: uint8_t m_tx_frame[EUROLITE_PRO_FRAME_SIZE]; DISALLOW_COPY_AND_ASSIGN(EuroliteProAsyncUsbSender); }; // AsynchronousEurolitePro // ----------------------------------------------------------------------------- AsynchronousEurolitePro::AsynchronousEurolitePro( LibUsbAdaptor *adaptor, libusb_device *usb_device, const string &serial) : EurolitePro(adaptor, usb_device, serial) { m_sender.reset(new EuroliteProAsyncUsbSender(m_adaptor, usb_device)); } bool AsynchronousEurolitePro::Init() { return m_sender->Init(); } bool AsynchronousEurolitePro::SendDMX(const DmxBuffer &buffer) { return m_sender->SendDMX(buffer); } } // namespace usbdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbdmx/DMXCProjectsNodleU1Device.cpp0000644000175000017500000000406513023355232023727 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DMXCProjectsNodleU1Device.cpp * A DMXCProjectsNodleU1 device that creates an input and an output port. * Copyright (C) 2015 Stefan Krupop */ #include "plugins/usbdmx/DMXCProjectsNodleU1Device.h" #include #include "plugins/usbdmx/DMXCProjectsNodleU1Port.h" #include "plugins/usbdmx/GenericOutputPort.h" namespace ola { namespace plugin { namespace usbdmx { DMXCProjectsNodleU1Device::DMXCProjectsNodleU1Device( ola::AbstractPlugin *owner, DMXCProjectsNodleU1 *widget, const std::string &device_name, const std::string &device_id, PluginAdaptor *plugin_adaptor) : Device(owner, device_name), m_device_id(device_id), m_out_port(), m_in_port() { unsigned int mode = widget->Mode(); if (mode & DMXCProjectsNodleU1::OUTPUT_ENABLE_MASK) { // output port active m_out_port.reset(new GenericOutputPort(this, 0, widget)); } if (mode & DMXCProjectsNodleU1::INPUT_ENABLE_MASK) { // input port active m_in_port.reset(new DMXCProjectsNodleU1InputPort(this, 0, plugin_adaptor, widget)); } } bool DMXCProjectsNodleU1Device::StartHook() { if (m_out_port.get()) { AddPort(m_out_port.release()); } if (m_in_port.get()) { AddPort(m_in_port.release()); } return true; } } // namespace usbdmx } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/usbdmx/AsyncUsbTransceiverBase.h0000644000175000017500000001011113023355232023334 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * AsyncUsbTransceiverBase.h * An Asynchronous DMX USB transceiver. * Copyright (C) 2014 Simon Newton */ #ifndef PLUGINS_USBDMX_ASYNCUSBTRANSCEIVERBASE_H_ #define PLUGINS_USBDMX_ASYNCUSBTRANSCEIVERBASE_H_ #include #include "libs/usb/LibUsbAdaptor.h" #include "ola/DmxBuffer.h" #include "ola/base/Macro.h" #include "ola/thread/Mutex.h" namespace ola { namespace plugin { namespace usbdmx { /** * @brief A base class that implements common functionality to send or receive * DMX asynchronously to a libusb_device. */ class AsyncUsbTransceiverBase { public: /** * @brief Create a new AsyncUsbTransceiverBase. * @param adaptor the LibUsbAdaptor to use. * @param usb_device the libusb_device to use for the widget. */ AsyncUsbTransceiverBase(ola::usb::LibUsbAdaptor* const adaptor, libusb_device *usb_device); /** * @brief Destructor */ virtual ~AsyncUsbTransceiverBase(); /** * @brief Initialize the transceiver. * @returns true if SetupHandle() returned a valid handle, false otherwise. */ bool Init(); /** * @brief Called from the libusb callback when the asynchronous transfer * completes. * @param transfer the completed transfer. */ virtual void TransferComplete(struct libusb_transfer *transfer) = 0; /** * @brief Get the libusb_device_handle of an already opened widget * @returns the handle of the widget or NULL if it was not opened */ libusb_device_handle *GetHandle() { return m_usb_handle; } protected: /** * @brief The LibUsbAdaptor passed in the constructor. */ ola::usb::LibUsbAdaptor* const m_adaptor; /** * @brief The libusb_device passed in the constructor. */ libusb_device* const m_usb_device; /** * @brief Open the device handle. * @returns A valid libusb_device_handle or NULL if the device could not be * opened. */ virtual libusb_device_handle* SetupHandle() = 0; /** * @brief Called when the transfer completes. * * Some devices require multiple transfers per DMX frame. This provides a * hook for continuation. */ virtual void PostTransferHook() {} /** * @brief Cancel any pending transfers. */ void CancelTransfer(); /** * @brief Fill a control transfer. * @param buffer passed to libusb_fill_control_transfer. * @param timeout passed to libusb_fill_control_transfer. */ void FillControlTransfer(unsigned char *buffer, unsigned int timeout); /** * @brief Fill a bulk transfer. */ void FillBulkTransfer(unsigned char endpoint, unsigned char *buffer, int length, unsigned int timeout); /** * @brief Fill an interrupt transfer. */ void FillInterruptTransfer(unsigned char endpoint, unsigned char *buffer, int length, unsigned int timeout); /** * @brief Submit the transfer for tx. * @returns the result of libusb_submit_transfer(). */ int SubmitTransfer(); enum TransferState { IDLE, IN_PROGRESS, DISCONNECTED, }; libusb_device_handle *m_usb_handle; bool m_suppress_continuation; struct libusb_transfer *m_transfer; TransferState m_transfer_state; // GUARDED_BY(m_mutex); ola::thread::Mutex m_mutex; private: DISALLOW_COPY_AND_ASSIGN(AsyncUsbTransceiverBase); }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_ASYNCUSBTRANSCEIVERBASE_H_ ola-0.10.5.nojsmin/plugins/usbdmx/DMXCProjectsNodleU1Factory.h0000644000175000017500000000432513023355232023603 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DMXCProjectsNodleU1Factory.h * The WidgetFactory for Nodle widgets. * Copyright (C) 2015 Stefan Krupop */ #ifndef PLUGINS_USBDMX_DMXCPROJECTSNODLEU1FACTORY_H_ #define PLUGINS_USBDMX_DMXCPROJECTSNODLEU1FACTORY_H_ #include "libs/usb/LibUsbAdaptor.h" #include "ola/base/Macro.h" #include "olad/PluginAdaptor.h" #include "olad/Preferences.h" #include "plugins/usbdmx/WidgetFactory.h" namespace ola { namespace plugin { namespace usbdmx { /** * @brief Creates Nodle widgets. */ class DMXCProjectsNodleU1Factory : public BaseWidgetFactory { public: explicit DMXCProjectsNodleU1Factory(ola::usb::LibUsbAdaptor *adaptor, PluginAdaptor *plugin_adaptor, Preferences *preferences) : BaseWidgetFactory( "DMXCProjectsNodleU1Factory"), m_adaptor(adaptor), m_plugin_adaptor(plugin_adaptor), m_preferences(preferences) { } bool DeviceAdded( WidgetObserver *observer, libusb_device *usb_device, const struct libusb_device_descriptor &descriptor); private: ola::usb::LibUsbAdaptor* const m_adaptor; PluginAdaptor* const m_plugin_adaptor; Preferences* const m_preferences; static const uint16_t VENDOR_ID; static const uint16_t PRODUCT_ID; DISALLOW_COPY_AND_ASSIGN(DMXCProjectsNodleU1Factory); }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_DMXCPROJECTSNODLEU1FACTORY_H_ ola-0.10.5.nojsmin/plugins/usbdmx/VellemanK8062.h0000644000175000017500000000551013023355232021011 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * VellemanK8062.h * The synchronous and asynchronous Velleman widgets. * Copyright (C) 2014 Simon Newton */ #ifndef PLUGINS_USBDMX_VELLEMANK8062_H_ #define PLUGINS_USBDMX_VELLEMANK8062_H_ #include #include #include #include "libs/usb/LibUsbAdaptor.h" #include "ola/DmxBuffer.h" #include "ola/base/Macro.h" #include "ola/thread/Mutex.h" #include "plugins/usbdmx/Widget.h" namespace ola { namespace plugin { namespace usbdmx { /** * @brief The interface for the Velleman Widgets */ class VellemanK8062: public SimpleWidget { public: explicit VellemanK8062(ola::usb::LibUsbAdaptor *adaptor, libusb_device *usb_device) : SimpleWidget(adaptor, usb_device) { } }; /** * @brief An Velleman widget that uses synchronous libusb operations. * * Internally this spawns a new thread to avoid blocking SendDMX() calls. */ class SynchronousVellemanK8062: public VellemanK8062 { public: /** * @brief Create a new SynchronousVellemanK8062. * @param adaptor the LibUsbAdaptor to use. * @param usb_device the libusb_device to use for the widget. */ SynchronousVellemanK8062(ola::usb::LibUsbAdaptor *adaptor, libusb_device *usb_device); bool Init(); bool SendDMX(const DmxBuffer &buffer); private: std::auto_ptr m_sender; DISALLOW_COPY_AND_ASSIGN(SynchronousVellemanK8062); }; /** * @brief An Velleman widget that uses asynchronous libusb operations. */ class AsynchronousVellemanK8062 : public VellemanK8062 { public: /** * @brief Create a new AsynchronousVellemanK8062. * @param adaptor the LibUsbAdaptor to use. * @param usb_device the libusb_device to use for the widget. */ AsynchronousVellemanK8062(ola::usb::LibUsbAdaptor *adaptor, libusb_device *usb_device); bool Init(); bool SendDMX(const DmxBuffer &buffer); private: std::auto_ptr m_sender; DISALLOW_COPY_AND_ASSIGN(AsynchronousVellemanK8062); }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_VELLEMANK8062_H_ ola-0.10.5.nojsmin/plugins/usbdmx/VellemanK8062Factory.h0000644000175000017500000000345713023355232022351 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * VellemanK8062Factory.h * The WidgetFactory for Velleman widgets. * Copyright (C) 2014 Simon Newton */ #ifndef PLUGINS_USBDMX_VELLEMANK8062FACTORY_H_ #define PLUGINS_USBDMX_VELLEMANK8062FACTORY_H_ #include "libs/usb/LibUsbAdaptor.h" #include "ola/base/Macro.h" #include "plugins/usbdmx/WidgetFactory.h" namespace ola { namespace plugin { namespace usbdmx { /** * @brief Creates Velleman widgets. */ class VellemanK8062Factory : public BaseWidgetFactory { public: explicit VellemanK8062Factory(ola::usb::LibUsbAdaptor *adaptor) : BaseWidgetFactory("VellemanK8062Factory"), m_adaptor(adaptor) { } bool DeviceAdded( WidgetObserver *observer, libusb_device *usb_device, const struct libusb_device_descriptor &descriptor); private: ola::usb::LibUsbAdaptor* const m_adaptor; static const uint16_t VENDOR_ID; static const uint16_t PRODUCT_ID; DISALLOW_COPY_AND_ASSIGN(VellemanK8062Factory); }; } // namespace usbdmx } // namespace plugin } // namespace ola #endif // PLUGINS_USBDMX_VELLEMANK8062FACTORY_H_ ola-0.10.5.nojsmin/plugins/artnet/0000755000175000017500000000000013155164170016441 5ustar wouterwouterola-0.10.5.nojsmin/plugins/artnet/Makefile.mk0000644000175000017500000000321513134123277020510 0ustar wouterwouterinclude plugins/artnet/messages/Makefile.mk # LIBRARIES ################################################## if USE_ARTNET # This is a library which isn't coupled to olad noinst_LTLIBRARIES += plugins/artnet/libolaartnetnode.la plugins_artnet_libolaartnetnode_la_SOURCES = \ plugins/artnet/ArtNetPackets.h \ plugins/artnet/ArtNetNode.cpp \ plugins/artnet/ArtNetNode.h plugins_artnet_libolaartnetnode_la_LIBADD = common/libolacommon.la # The OLA artnet plugin lib_LTLIBRARIES += plugins/artnet/libolaartnet.la plugins_artnet_libolaartnet_la_SOURCES = \ plugins/artnet/ArtNetPlugin.cpp \ plugins/artnet/ArtNetPlugin.h \ plugins/artnet/ArtNetDevice.cpp \ plugins/artnet/ArtNetDevice.h \ plugins/artnet/ArtNetPort.cpp \ plugins/artnet/ArtNetPort.h plugins_artnet_libolaartnet_la_CXXFLAGS = $(COMMON_PROTOBUF_CXXFLAGS) plugins_artnet_libolaartnet_la_LIBADD = \ olad/plugin_api/libolaserverplugininterface.la \ plugins/artnet/libolaartnetnode.la \ plugins/artnet/messages/libolaartnetconf.la # PROGRAMS ################################################## noinst_PROGRAMS += plugins/artnet/artnet_loadtest plugins_artnet_artnet_loadtest_SOURCES = plugins/artnet/artnet_loadtest.cpp plugins_artnet_artnet_loadtest_LDADD = plugins/artnet/libolaartnetnode.la # TESTS ################################################## test_programs += plugins/artnet/ArtNetTester plugins_artnet_ArtNetTester_SOURCES = plugins/artnet/ArtNetNodeTest.cpp plugins_artnet_ArtNetTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) plugins_artnet_ArtNetTester_LDADD = $(COMMON_TESTING_LIBS) \ plugins/artnet/libolaartnetnode.la endif ola-0.10.5.nojsmin/plugins/artnet/ArtNetNodeTest.cpp0000644000175000017500000020154013023355232022005 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ArtNetNodeTest.cpp * Test fixture for the ArtNetNode class * Copyright (C) 2010 Simon Newton */ #include #include #include #include #include #include "ola/Callback.h" #include "ola/DmxBuffer.h" #include "ola/Logging.h" #include "ola/io/SelectServer.h" #include "ola/network/IPV4Address.h" #include "ola/network/Interface.h" #include "ola/network/MACAddress.h" #include "ola/network/NetworkUtils.h" #include "ola/network/Socket.h" #include "ola/rdm/RDMCommand.h" #include "ola/rdm/RDMCommandSerializer.h" #include "ola/rdm/RDMReply.h" #include "ola/rdm/RDMResponseCodes.h" #include "ola/rdm/UID.h" #include "ola/rdm/UIDSet.h" #include "ola/testing/MockUDPSocket.h" #include "ola/timecode/TimeCodeEnums.h" #include "ola/timecode/TimeCode.h" #include "plugins/artnet/ArtNetNode.h" #include "ola/testing/TestUtils.h" using ola::DmxBuffer; using ola::network::IPV4Address; using ola::network::Interface; using ola::network::MACAddress; using ola::plugin::artnet::ArtNetNode; using ola::plugin::artnet::ArtNetNodeOptions; using ola::rdm::RDMCallback; using ola::rdm::RDMCommand; using ola::rdm::RDMCommandSerializer; using ola::rdm::RDMGetRequest; using ola::rdm::RDMReply; using ola::rdm::RDMRequest; using ola::rdm::RDMResponse; using ola::rdm::UID; using ola::rdm::UIDSet; using ola::timecode::TimeCode; using ola::testing::MockUDPSocket; using ola::testing::SocketVerifier; using std::string; using std::vector; class ArtNetNodeTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(ArtNetNodeTest); CPPUNIT_TEST(testBasicBehaviour); CPPUNIT_TEST(testConfigurationMode); CPPUNIT_TEST(testExtendedInputPorts); CPPUNIT_TEST(testBroadcastSendDMX); CPPUNIT_TEST(testBroadcastSendDMXZeroUniverse); CPPUNIT_TEST(testLimitedBroadcastDMX); CPPUNIT_TEST(testNonBroadcastSendDMX); CPPUNIT_TEST(testReceiveDMX); CPPUNIT_TEST(testReceiveDMXZeroUniverse); CPPUNIT_TEST(testHTPMerge); CPPUNIT_TEST(testLTPMerge); CPPUNIT_TEST(testControllerDiscovery); CPPUNIT_TEST(testControllerIncrementalDiscovery); CPPUNIT_TEST(testUnsolicitedTod); CPPUNIT_TEST(testResponderDiscovery); CPPUNIT_TEST(testRDMResponder); CPPUNIT_TEST(testRDMRequest); CPPUNIT_TEST(testRDMRequestTimeout); CPPUNIT_TEST(testRDMRequestIPMismatch); CPPUNIT_TEST(testRDMRequestUIDMismatch); CPPUNIT_TEST(testTimeCode); CPPUNIT_TEST_SUITE_END(); public: ArtNetNodeTest() : CppUnit::TestFixture(), ss(NULL, &m_clock), m_got_dmx(false), m_got_rdm_timeout(false), m_discovery_done(false), m_tod_flush(false), m_tod_request(false), m_rdm_request(NULL), m_rdm_callback(NULL), m_rdm_response(NULL), m_port_id(1), broadcast_ip(IPV4Address::Broadcast()), m_socket(new MockUDPSocket()) { } void setUp(); void testBasicBehaviour(); void testConfigurationMode(); void testExtendedInputPorts(); void testBroadcastSendDMX(); void testBroadcastSendDMXZeroUniverse(); void testLimitedBroadcastDMX(); void testNonBroadcastSendDMX(); void testReceiveDMX(); void testReceiveDMXZeroUniverse(); void testHTPMerge(); void testLTPMerge(); void testControllerDiscovery(); void testControllerIncrementalDiscovery(); void testUnsolicitedTod(); void testResponderDiscovery(); void testRDMResponder(); void testRDMRequest(); void testRDMRequestTimeout(); void testRDMRequestIPMismatch(); void testRDMRequestUIDMismatch(); void testTimeCode(); private: ola::MockClock m_clock; ola::io::SelectServer ss; bool m_got_dmx; bool m_got_rdm_timeout; bool m_discovery_done; bool m_tod_flush; bool m_tod_request; UIDSet m_uids; const RDMRequest *m_rdm_request; RDMCallback *m_rdm_callback; const RDMResponse *m_rdm_response; uint8_t m_port_id; Interface iface; IPV4Address peer_ip, peer_ip2, peer_ip3; IPV4Address broadcast_ip; MockUDPSocket *m_socket; /** * Called when new DMX arrives */ void NewDmx() { m_got_dmx = true; } void DiscoveryComplete(const UIDSet &uids) { m_uids = uids; m_discovery_done = true; } void TodRequest() { m_tod_request = true; } void Flush() { m_tod_flush = true; } void HandleRDM(RDMRequest *request, RDMCallback *callback) { m_rdm_request = request; m_rdm_callback = callback; } void FinalizeRDM(RDMReply *reply) { OLA_ASSERT_EQ(ola::rdm::RDM_COMPLETED_OK, reply->StatusCode()); m_rdm_response = reply->Response()->Duplicate(); } void ExpectTimeout(RDMReply *reply) { OLA_ASSERT_EQ(ola::rdm::RDM_TIMEOUT, reply->StatusCode()); OLA_ASSERT_NULL(reply->Response()); m_got_rdm_timeout = true; } void ExpectedSend(const uint8_t *data, unsigned int data_size, const IPV4Address &address) { m_socket->AddExpectedData(data, data_size, address, ARTNET_PORT); } void ExpectedBroadcast(const uint8_t *data, unsigned int data_size) { ExpectedSend(data, data_size, iface.bcast_address); } void ReceiveFromPeer(const uint8_t *data, unsigned int data_size, const IPV4Address &address) { ss.RunOnce(); // update the wake up time m_socket->InjectData(data, data_size, address, ARTNET_PORT); } void SetupInputPort(ArtNetNode *node) { node->SetNetAddress(4); node->SetSubnetAddress(2); node->SetInputPortUniverse(m_port_id, 3); } void SetupOutputPort(ArtNetNode *node) { node->SetNetAddress(4); node->SetSubnetAddress(2); node->SetOutputPortUniverse(m_port_id, 3); } // This sends a tod data so 7s70:00000000 is insert into the tod void PopulateTod() { SocketVerifier verifer(m_socket); const uint8_t art_tod[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x81, 0x0, 14, 1, // rdm standard 1, // first port 0, 0, 0, 0, 0, 0, 0, 4, // net 0, // full tod 0x23, // universe address 0, 1, // uid count 0, // block count 1, // uid count 0x7a, 0x70, 0, 0, 0, 0, }; ReceiveFromPeer(art_tod, sizeof(art_tod), peer_ip); } void SendRDMRequest(ArtNetNode *node, RDMCallback *callback) { UID source(1, 2); UID destination(0x7a70, 0); RDMGetRequest *request = new RDMGetRequest( source, destination, 0, // transaction # 1, // port id 10, // sub device 296, // param id NULL, // data 0); // data length const uint8_t rdm_request[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x83, 0x0, 14, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, // net 0, // process 0x23, // rdm data 1, 24, // sub code & length 0x7a, 0x70, 0, 0, 0, 0, // dst uid 0, 1, 0, 0, 0, 2, // src uid 0, 1, 0, 0, 10, // transaction, port id, msg count & sub device 0x20, 0x1, 0x28, 0, // command, param id, param data length 0x02, 0x26 }; ExpectedSend(rdm_request, sizeof(rdm_request), peer_ip); node->SendRDMRequest(m_port_id, request, callback); } static const uint8_t POLL_MESSAGE[]; static const uint8_t POLL_REPLY_MESSAGE[]; static const uint8_t TOD_CONTROL[]; static const uint16_t ARTNET_PORT = 6454; }; CPPUNIT_TEST_SUITE_REGISTRATION(ArtNetNodeTest); const uint8_t ArtNetNodeTest::POLL_MESSAGE[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x20, 0x0, 14, 0x2, 0 }; const uint8_t ArtNetNodeTest::POLL_REPLY_MESSAGE[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x21, 10, 0, 0, 1, 0x36, 0x19, 0, 0, 4, 2, // subnet address 0x4, 0x31, // oem 0, 0xd2, 0x70, 0x7a, // esta 'S', 'h', 'o', 'r', 't', ' ', 'N', 'a', 'm', 'e', 0, 0, 0, 0, 0, 0, 0, 0, // short name 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 't', 'h', 'e', ' ', 'v', 'e', 'r', 'y', ' ', 'l', 'o', 'n', 'g', ' ', 'n', 'a', 'm', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // long name '#', '0', '0', '0', '1', ' ', '[', '0', ']', ' ', 'O', 'L', 'A', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // node report 0, 4, // num ports 0xc0, 0xc0, 0xc0, 0xc0, 8, 8, 8, 8, 0x80, 0, 0, 0, 0x20, 0x20, 0x20, 0x20, // swin 0x23, 0x20, 0x20, 0x20, // swout 0, 0, 0, 0, 0, 0, 0, // video, macro, remote, spare, style 0xa, 0xb, 0xc, 0x12, 0x34, 0x56, // mac address 0xa, 0x0, 0x0, 0x1, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // filler }; const uint8_t ArtNetNodeTest::TOD_CONTROL[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x82, 0x0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, // net 1, // flush 0x23 }; void ArtNetNodeTest::setUp() { ola::InitLogging(ola::OLA_LOG_INFO, ola::OLA_LOG_STDERR); ola::network::InterfaceBuilder interface_builder; OLA_ASSERT(interface_builder.SetAddress("10.0.0.1")); OLA_ASSERT(interface_builder.SetSubnetMask("255.0.0.0")); OLA_ASSERT(interface_builder.SetBroadcast("10.255.255.255")); interface_builder.SetHardwareAddress( MACAddress::FromStringOrDie("0a:0b:0c:12:34:56")); iface = interface_builder.Construct(); ola::network::IPV4Address::FromString("10.0.0.10", &peer_ip); ola::network::IPV4Address::FromString("10.0.0.11", &peer_ip2); ola::network::IPV4Address::FromString("10.0.0.12", &peer_ip3); } /** * Check that the discovery sequence works correctly. */ void ArtNetNodeTest::testBasicBehaviour() { ArtNetNodeOptions node_options; ArtNetNode node(iface, &ss, node_options, m_socket); node.SetShortName("Short Name"); OLA_ASSERT_EQ(string("Short Name"), node.ShortName()); node.SetLongName("This is the very long name"); OLA_ASSERT_EQ(string("This is the very long name"), node.LongName()); node.SetNetAddress(4); OLA_ASSERT_EQ((uint8_t) 4, node.NetAddress()); node.SetSubnetAddress(2); OLA_ASSERT_EQ((uint8_t) 2, node.SubnetAddress()); node.SetOutputPortUniverse(0, 3); OLA_ASSERT(!node.SetOutputPortUniverse(4, 3)); OLA_ASSERT_EQ((uint8_t) 0x23, node.GetOutputPortUniverse(0)); OLA_ASSERT_EQ((uint8_t) 0x20, node.GetOutputPortUniverse(1)); OLA_ASSERT(node.Start()); ss.RemoveReadDescriptor(m_socket); m_socket->Verify(); OLA_ASSERT(m_socket->CheckNetworkParamsMatch(true, true, 6454, true)); // check port states OLA_ASSERT_EQ((uint8_t) 4, node.InputPortCount()); OLA_ASSERT_FALSE(node.InputPortState(0)); OLA_ASSERT_FALSE(node.InputPortState(1)); OLA_ASSERT_FALSE(node.InputPortState(2)); OLA_ASSERT_FALSE(node.InputPortState(3)); OLA_ASSERT(node.OutputPortState(0)); OLA_ASSERT_FALSE(node.OutputPortState(1)); OLA_ASSERT_FALSE(node.OutputPortState(2)); OLA_ASSERT_FALSE(node.OutputPortState(3)); // enable an input port and check that we send a poll ExpectedBroadcast(POLL_MESSAGE, sizeof(POLL_MESSAGE)); // we should see an unsolicted poll reply sent because conditions have // changed. uint8_t expected_poll_reply_packet[sizeof(POLL_REPLY_MESSAGE)]; memcpy(expected_poll_reply_packet, POLL_REPLY_MESSAGE, sizeof(POLL_REPLY_MESSAGE)); expected_poll_reply_packet[115] = '1'; // node report expected_poll_reply_packet[179] = 0; // good input expected_poll_reply_packet[187] = 0x22; // swin ExpectedBroadcast(expected_poll_reply_packet, sizeof(expected_poll_reply_packet)); node.SetInputPortUniverse(1, 2); OLA_ASSERT_EQ((uint8_t) 0x20, node.GetInputPortUniverse(0)); OLA_ASSERT_EQ((uint8_t) 0x22, node.GetInputPortUniverse(1)); m_socket->Verify(); // check sending a poll works ExpectedBroadcast(POLL_MESSAGE, sizeof(POLL_MESSAGE)); OLA_ASSERT(node.SendPoll()); m_socket->Verify(); OLA_ASSERT(node.Stop()); } /** * Check that configuration mode works correctly. */ void ArtNetNodeTest::testConfigurationMode() { ArtNetNodeOptions node_options; ArtNetNode node(iface, &ss, node_options, m_socket); OLA_ASSERT(node.Start()); ss.RemoveReadDescriptor(m_socket); m_socket->Verify(); // no changes should cause no messages node.EnterConfigurationMode(); node.EnterConfigurationMode(); // enter a second time node.ExitConfigurationMode(); m_socket->Verify(); // exit again just to make sure node.ExitConfigurationMode(); m_socket->Verify(); uint8_t poll_reply_message[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x21, 10, 0, 0, 1, 0x36, 0x19, 0, 0, 0, 0, // subnet address 0x4, 0x31, // oem 0, 0xd2, 0x70, 0x7a, // esta 'S', 'h', 'o', 'r', 't', ' ', 'N', 'a', 'm', 'e', 0, 0, 0, 0, 0, 0, 0, 0, // short name 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // long name '#', '0', '0', '0', '1', ' ', '[', '1', ']', ' ', 'O', 'L', 'A', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // node report 0, 4, // num ports 0xc0, 0xc0, 0xc0, 0xc0, // port types 8, 8, 8, 8, // good input 0, 0, 0, 0, // good output 0x0, 0x0, 0x0, 0x0, // swin 0x0, 0x0, 0x0, 0x0, // swout 0, 0, 0, 0, 0, 0, 0, // video, macro, remote, spare, style 0xa, 0xb, 0xc, 0x12, 0x34, 0x56, // mac address 0xa, 0x0, 0x0, 0x1, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // filler }; node.EnterConfigurationMode(); node.SetShortName("Short Name"); m_socket->Verify(); OLA_ASSERT_EQ(string("Short Name"), node.ShortName()); ExpectedBroadcast(poll_reply_message, sizeof(poll_reply_message)); node.ExitConfigurationMode(); m_socket->Verify(); node.EnterConfigurationMode(); const string long_name("This is a long name"); node.SetLongName(long_name); m_socket->Verify(); OLA_ASSERT_EQ(long_name, node.LongName()); strncpy(reinterpret_cast(&poll_reply_message[44]), long_name.c_str(), long_name.size()); poll_reply_message[115] = '2'; ExpectedBroadcast(poll_reply_message, sizeof(poll_reply_message)); node.ExitConfigurationMode(); m_socket->Verify(); node.EnterConfigurationMode(); node.SetNetAddress(4); m_socket->Verify(); OLA_ASSERT_EQ((uint8_t) 4, node.NetAddress()); poll_reply_message[18] = 4; poll_reply_message[115] = '3'; ExpectedBroadcast(poll_reply_message, sizeof(poll_reply_message)); node.ExitConfigurationMode(); m_socket->Verify(); node.EnterConfigurationMode(); node.SetSubnetAddress(2); OLA_ASSERT_EQ((uint8_t) 2, node.SubnetAddress()); poll_reply_message[19] = 2; poll_reply_message[115] = '4'; for (unsigned int i = 186; i <= 193; i++) { poll_reply_message[i] = 0x20; } ExpectedBroadcast(poll_reply_message, sizeof(poll_reply_message)); node.ExitConfigurationMode(); m_socket->Verify(); node.EnterConfigurationMode(); node.SetOutputPortUniverse(0, 3); OLA_ASSERT(!node.SetOutputPortUniverse(4, 3)); OLA_ASSERT(node.OutputPortState(0)); OLA_ASSERT_EQ((uint8_t) 0x23, node.GetOutputPortUniverse(0)); poll_reply_message[182] = 0x80; poll_reply_message[190] = 0x23; poll_reply_message[115] = '5'; ExpectedBroadcast(poll_reply_message, sizeof(poll_reply_message)); node.ExitConfigurationMode(); m_socket->Verify(); // now try an input port, this should trigger a poll node.EnterConfigurationMode(); node.SetInputPortUniverse(0, 2); OLA_ASSERT(node.OutputPortState(0)); OLA_ASSERT_EQ((uint8_t) 0x22, node.GetInputPortUniverse(0)); poll_reply_message[178] = 0; poll_reply_message[186] = 0x22; poll_reply_message[115] = '6'; ExpectedBroadcast(POLL_MESSAGE, sizeof(POLL_MESSAGE)); ExpectedBroadcast(poll_reply_message, sizeof(poll_reply_message)); node.ExitConfigurationMode(); m_socket->Verify(); // change the subnet, which should trigger another poll node.EnterConfigurationMode(); node.SetSubnetAddress(4); poll_reply_message[19] = 4; poll_reply_message[186] = 0x42; poll_reply_message[187] = 0x40; poll_reply_message[188] = 0x40; poll_reply_message[189] = 0x40; poll_reply_message[190] = 0x43; poll_reply_message[191] = 0x40; poll_reply_message[192] = 0x40; poll_reply_message[193] = 0x40; poll_reply_message[115] = '7'; ExpectedBroadcast(POLL_MESSAGE, sizeof(POLL_MESSAGE)); ExpectedBroadcast(poll_reply_message, sizeof(poll_reply_message)); node.ExitConfigurationMode(); m_socket->Verify(); // if nothing changes, no messages are sent node.EnterConfigurationMode(); node.SetShortName("Short Name"); node.SetLongName(long_name); node.SetNetAddress(4); node.SetSubnetAddress(4); node.SetOutputPortUniverse(0, 3); node.SetInputPortUniverse(0, 2); node.ExitConfigurationMode(); m_socket->Verify(); // disable input port node.EnterConfigurationMode(); node.DisableInputPort(0); poll_reply_message[115] = '8'; poll_reply_message[178] = 0x8; ExpectedBroadcast(poll_reply_message, sizeof(poll_reply_message)); node.ExitConfigurationMode(); m_socket->Verify(); // disable output port node.EnterConfigurationMode(); node.DisableOutputPort(0); poll_reply_message[115] = '9'; poll_reply_message[182] = 0; ExpectedBroadcast(poll_reply_message, sizeof(poll_reply_message)); node.ExitConfigurationMode(); m_socket->Verify(); OLA_ASSERT(node.Stop()); } /** * Check a node with more than the default number of input ports. */ void ArtNetNodeTest::testExtendedInputPorts() { ArtNetNodeOptions node_options; node_options.input_port_count = 8; ArtNetNode node(iface, &ss, node_options, m_socket); OLA_ASSERT(node.Start()); ss.RemoveReadDescriptor(m_socket); m_socket->Verify(); OLA_ASSERT_EQ((uint8_t) 8, node.InputPortCount()); OLA_ASSERT_FALSE(node.InputPortState(0)); OLA_ASSERT_FALSE(node.InputPortState(1)); OLA_ASSERT_FALSE(node.InputPortState(2)); OLA_ASSERT_FALSE(node.InputPortState(3)); OLA_ASSERT_FALSE(node.InputPortState(4)); OLA_ASSERT_FALSE(node.InputPortState(5)); OLA_ASSERT_FALSE(node.InputPortState(6)); OLA_ASSERT_FALSE(node.InputPortState(6)); OLA_ASSERT_FALSE(node.InputPortState(7)); OLA_ASSERT_FALSE(node.OutputPortState(0)); OLA_ASSERT_FALSE(node.OutputPortState(1)); OLA_ASSERT_FALSE(node.OutputPortState(2)); OLA_ASSERT_FALSE(node.OutputPortState(3)); OLA_ASSERT_FALSE(node.OutputPortState(4)); OLA_ASSERT_FALSE(node.OutputPortState(5)); OLA_ASSERT_FALSE(node.OutputPortState(6)); OLA_ASSERT_FALSE(node.OutputPortState(7)); // no changes should cause no messages node.EnterConfigurationMode(); node.ExitConfigurationMode(); m_socket->Verify(); } /** * Check sending DMX using broadcast works. */ void ArtNetNodeTest::testBroadcastSendDMX() { m_socket->SetDiscardMode(true); ArtNetNodeOptions node_options; node_options.always_broadcast = true; ArtNetNode node(iface, &ss, node_options, m_socket); SetupInputPort(&node); OLA_ASSERT(node.Start()); ss.RemoveReadDescriptor(m_socket); m_socket->Verify(); m_socket->SetDiscardMode(false); { SocketVerifier verifer(m_socket); const uint8_t DMX_MESSAGE[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x50, 0x0, 14, 0, // seq # 1, // physical port 0x23, 4, // subnet & net address 0, 6, // dmx length 0, 1, 2, 3, 4, 5 }; ExpectedBroadcast(DMX_MESSAGE, sizeof(DMX_MESSAGE)); DmxBuffer dmx; dmx.SetFromString("0,1,2,3,4,5"); OLA_ASSERT(node.SendDMX(m_port_id, dmx)); } // send an odd sized dmx frame, we should pad this to a multiple of two { SocketVerifier verifer(m_socket); const uint8_t DMX_MESSAGE2[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x50, 0x0, 14, 1, // seq # 1, // physical port 0x23, 4, // subnet & net address 0, 6, // dmx length 0, 1, 2, 3, 4, 0 }; ExpectedBroadcast(DMX_MESSAGE2, sizeof(DMX_MESSAGE2)); DmxBuffer dmx; dmx.SetFromString("0,1,2,3,4"); OLA_ASSERT(node.SendDMX(m_port_id, dmx)); } { // attempt to send on a invalid port SocketVerifier verifer(m_socket); DmxBuffer dmx; dmx.SetFromString("0,1,2,3,4"); OLA_ASSERT_FALSE(node.SendDMX(4, dmx)); } { // attempt to send an empty fram SocketVerifier verifer(m_socket); DmxBuffer empty_buffer; OLA_ASSERT(node.SendDMX(m_port_id, empty_buffer)); } } /** * Check sending DMX using broadcast works to ArtNet universe 0. */ void ArtNetNodeTest::testBroadcastSendDMXZeroUniverse() { m_socket->SetDiscardMode(true); ArtNetNodeOptions node_options; node_options.always_broadcast = true; ArtNetNode node(iface, &ss, node_options, m_socket); node.SetNetAddress(0); node.SetSubnetAddress(0); node.SetInputPortUniverse(m_port_id, 0); OLA_ASSERT(node.Start()); ss.RemoveReadDescriptor(m_socket); m_socket->Verify(); m_socket->SetDiscardMode(false); { SocketVerifier verifer(m_socket); const uint8_t DMX_MESSAGE[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x50, 0x0, 14, 0, // seq # 1, // physical port 0, 0, // subnet & net address 0, 6, // dmx length 0, 1, 2, 3, 4, 5 }; ExpectedBroadcast(DMX_MESSAGE, sizeof(DMX_MESSAGE)); DmxBuffer dmx; dmx.SetFromString("0,1,2,3,4,5"); OLA_ASSERT(node.SendDMX(m_port_id, dmx)); } // Now disable, and set to a different universe. { uint8_t poll_reply_message[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x21, 10, 0, 0, 1, 0x36, 0x19, 0, 0, 0, 0, // subnet address 0x4, 0x31, // oem 0, 0xd2, 0x70, 0x7a, // esta 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // short name 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // long name '#', '0', '0', '0', '1', ' ', '[', '1', ']', ' ', 'O', 'L', 'A', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // node report 0, 4, // num ports 0xc0, 0xc0, 0xc0, 0xc0, // port types 8, 0, 8, 8, // good input 0, 0, 0, 0, // good output 0x0, 0x0, 0x0, 0x0, // swin 0x0, 0x0, 0x0, 0x0, // swout 0, 0, 0, 0, 0, 0, 0, // video, macro, remote, spare, style 0xa, 0xb, 0xc, 0x12, 0x34, 0x56, // mac address 0xa, 0x0, 0x0, 0x1, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // filler }; ExpectedBroadcast(poll_reply_message, sizeof(poll_reply_message)); node.EnterConfigurationMode(); node.DisableInputPort(m_port_id); node.SetInputPortUniverse(m_port_id, 0); node.ExitConfigurationMode(); m_socket->Verify(); } { SocketVerifier verifer(m_socket); const uint8_t DMX_MESSAGE[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x50, 0x0, 14, 1, // seq # 1, // physical port 0, 0, // subnet & net address 0, 6, // dmx length 10, 11, 12, 13, 14, 15 }; ExpectedBroadcast(DMX_MESSAGE, sizeof(DMX_MESSAGE)); DmxBuffer dmx; dmx.SetFromString("10,11,12,13,14,15"); OLA_ASSERT(node.SendDMX(m_port_id, dmx)); } } /* * Check sending DMX using the limited broadcast address. */ void ArtNetNodeTest::testLimitedBroadcastDMX() { m_socket->SetDiscardMode(true); ArtNetNodeOptions node_options; node_options.always_broadcast = true; node_options.use_limited_broadcast_address = true; ArtNetNode node(iface, &ss, node_options, m_socket); SetupInputPort(&node); OLA_ASSERT(node.Start()); ss.RemoveReadDescriptor(m_socket); m_socket->Verify(); m_socket->SetDiscardMode(false); { SocketVerifier verifer(m_socket); const uint8_t DMX_MESSAGE[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x50, 0x0, 14, 0, // seq # 1, // physical port 0x23, 4, // subnet & net address 0, 6, // dmx length 0, 1, 2, 3, 4, 5 }; ExpectedSend(DMX_MESSAGE, sizeof(DMX_MESSAGE), broadcast_ip); DmxBuffer dmx; dmx.SetFromString("0,1,2,3,4,5"); OLA_ASSERT(node.SendDMX(m_port_id, dmx)); } } /** * Check sending DMX using unicast works. */ void ArtNetNodeTest::testNonBroadcastSendDMX() { m_socket->SetDiscardMode(true); ArtNetNodeOptions node_options; ArtNetNode node(iface, &ss, node_options, m_socket); SetupInputPort(&node); OLA_ASSERT(node.Start()); ss.RemoveReadDescriptor(m_socket); m_socket->Verify(); m_socket->SetDiscardMode(false); DmxBuffer dmx; dmx.SetFromString("0,1,2,3,4,5"); // we don't expect any data here because there are no nodes active OLA_ASSERT(node.SendDMX(m_port_id, dmx)); m_socket->Verify(); // used to check GetSubscribedNodes() vector node_addresses; { SocketVerifier verifer(m_socket); const uint8_t poll_reply_message[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x21, 10, 0, 0, 10, 0x36, 0x19, 0, 0, 4, 2, // subnet address 0x4, 0x31, // oem 0, 0xd2, 0x70, 0x7a, // esta 'P', 'e', 'e', 'r', ' ', '1', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // short name 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 't', 'h', 'e', ' ', 'v', 'e', 'r', 'y', ' ', 'l', 'o', 'n', 'g', ' ', 'n', 'a', 'm', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // long name '#', '0', '0', '0', '1', ' ', '[', '0', ']', ' ', 'O', 'L', 'A', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // node report 0, 4, // num ports 0x80, 0x80, 0x80, 0x80, // 4 output ports 8, 8, 8, 8, 0, 0, 0, 0, 0x0, 0x0, 0x0, 0x0, // swin 0x23, 0x0, 0x0, 0x0, // swout 0, 0, 0, 0, 0, 0, 0, // video, macro, remote, spare, style 0x12, 0x34, 0x56, 0x12, 0x34, 0x56, // mac address 0xa, 0x0, 0x0, 0xa, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // filler }; // Fake an ArtPollReply ReceiveFromPeer(poll_reply_message, sizeof(poll_reply_message), peer_ip); // check the node list is up to date node_addresses.clear(); node.GetSubscribedNodes(m_port_id, &node_addresses); OLA_ASSERT_EQ(static_cast(1), node_addresses.size()); OLA_ASSERT_EQ(peer_ip, node_addresses[0]); // send a DMX frame, this should get unicast const uint8_t DMX_MESSAGE[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x50, 0x0, 14, 0, // seq # 1, // physical port 0x23, 4, // subnet & net address 0, 6, // dmx length 0, 1, 2, 3, 4, 5 }; ExpectedSend(DMX_MESSAGE, sizeof(DMX_MESSAGE), peer_ip); OLA_ASSERT(node.SendDMX(m_port_id, dmx)); } // add another peer { SocketVerifier verifer(m_socket); const uint8_t poll_reply_message2[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x21, 10, 0, 0, 11, 0x36, 0x19, 0, 0, 4, 2, // subnet address 0x4, 0x31, // oem 0, 0xd2, 0x70, 0x7a, // esta 'P', 'e', 'e', 'r', ' ', '2', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // short name 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 't', 'h', 'e', ' ', 'v', 'e', 'r', 'y', ' ', 'l', 'o', 'n', 'g', ' ', 'n', 'a', 'm', 'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // long name '#', '0', '0', '0', '1', ' ', '[', '0', ']', ' ', 'O', 'L', 'A', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // node report 0, 4, // num ports 0x80, 0x80, 0x80, 0x80, // 4 output ports 8, 8, 8, 8, 0, 0, 0, 0, 0x0, 0x0, 0x0, 0x0, // swin 0x23, 0x0, 0x0, 0x0, // swout 0, 0, 0, 0, 0, 0, 0, // video, macro, remote, spare, style 0x12, 0x34, 0x56, 0x12, 0x34, 0x56, // mac address 0xa, 0x0, 0x0, 0xb, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // filler }; // Fake an ArtPollReply ReceiveFromPeer(poll_reply_message2, sizeof(poll_reply_message2), peer_ip2); // check the node list is up to date node_addresses.clear(); node.GetSubscribedNodes(m_port_id, &node_addresses); OLA_ASSERT_EQ(static_cast(2), node_addresses.size()); OLA_ASSERT_EQ(peer_ip, node_addresses[0]); OLA_ASSERT_EQ(peer_ip2, node_addresses[1]); } // send another DMX frame, this should get unicast twice { SocketVerifier verifer(m_socket); const uint8_t DMX_MESSAGE2[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x50, 0x0, 14, 1, // seq # 1, // physical port 0x23, 4, // subnet & net address 0, 6, // dmx length 10, 11, 12, 0, 1, 2 }; dmx.SetFromString("10,11,12,0,1,2"); ExpectedSend(DMX_MESSAGE2, sizeof(DMX_MESSAGE2), peer_ip); ExpectedSend(DMX_MESSAGE2, sizeof(DMX_MESSAGE2), peer_ip2); OLA_ASSERT(node.SendDMX(m_port_id, dmx)); } // adjust the broadcast threshold { SocketVerifier verifer(m_socket); node.SetBroadcastThreshold(2); // send another DMX frame, this should get broadcast const uint8_t DMX_MESSAGE3[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x50, 0x0, 14, 2, // seq # 1, // physical port 0x23, 4, // subnet & net address 0, 6, // dmx length 11, 13, 14, 7, 8, 9 }; dmx.SetFromString("11,13,14,7,8,9"); ExpectedBroadcast(DMX_MESSAGE3, sizeof(DMX_MESSAGE3)); OLA_ASSERT(node.SendDMX(m_port_id, dmx)); } } /** * Check that receiving DMX works */ void ArtNetNodeTest::testReceiveDMX() { m_socket->SetDiscardMode(true); ArtNetNodeOptions node_options; ArtNetNode node(iface, &ss, node_options, m_socket); SetupOutputPort(&node); DmxBuffer input_buffer; node.SetDMXHandler(m_port_id, &input_buffer, ola::NewCallback(this, &ArtNetNodeTest::NewDmx)); OLA_ASSERT(node.Start()); ss.RemoveReadDescriptor(m_socket); m_socket->Verify(); m_socket->SetDiscardMode(false); uint8_t DMX_MESSAGE[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x50, 0x0, 14, 0, // seq # 1, // physical port 0x23, 4, // subnet & net address 0, 6, // dmx length 0, 1, 2, 3, 4, 5 }; // 'receive' a DMX message { SocketVerifier verifer(m_socket); OLA_ASSERT_FALSE(m_got_dmx); ReceiveFromPeer(DMX_MESSAGE, sizeof(DMX_MESSAGE), peer_ip); OLA_ASSERT(m_got_dmx); OLA_ASSERT_EQ(string("0,1,2,3,4,5"), input_buffer.ToString()); } // send a second frame { SocketVerifier verifer(m_socket); uint8_t DMX_MESSAGE2[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x50, 0x0, 14, 1, // different seq # this time 1, // physical port 0x23, 4, // subnet & net address 0, 6, // dmx length 5, 4, 3, 2, 1, 0 }; m_got_dmx = false; ReceiveFromPeer(DMX_MESSAGE2, sizeof(DMX_MESSAGE2), peer_ip); OLA_ASSERT(m_got_dmx); OLA_ASSERT_EQ(string("5,4,3,2,1,0"), input_buffer.ToString()); } // advance the clock by more than the merge timeout (10s) { SocketVerifier verifer(m_socket); m_clock.AdvanceTime(11, 0); // send another message, but first update the seq # DMX_MESSAGE[12] = 2; m_got_dmx = false; OLA_ASSERT_FALSE(m_got_dmx); ReceiveFromPeer(DMX_MESSAGE, sizeof(DMX_MESSAGE), peer_ip); OLA_ASSERT(m_got_dmx); OLA_ASSERT_EQ(string("0,1,2,3,4,5"), input_buffer.ToString()); } } /** * Check that receiving DMX for universe 0 works. */ void ArtNetNodeTest::testReceiveDMXZeroUniverse() { m_socket->SetDiscardMode(true); ArtNetNodeOptions node_options; ArtNetNode node(iface, &ss, node_options, m_socket); node.SetNetAddress(0); node.SetSubnetAddress(0); node.SetOutputPortUniverse(m_port_id, 0); DmxBuffer input_buffer; node.SetDMXHandler(m_port_id, &input_buffer, ola::NewCallback(this, &ArtNetNodeTest::NewDmx)); OLA_ASSERT(node.Start()); ss.RemoveReadDescriptor(m_socket); m_socket->Verify(); m_socket->SetDiscardMode(false); // 'receive' a DMX message { uint8_t DMX_MESSAGE[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x50, 0x0, 14, 0, // seq # 1, // physical port 0, 0, // subnet & net address 0, 6, // dmx length 0, 1, 2, 3, 4, 5 }; SocketVerifier verifer(m_socket); OLA_ASSERT_FALSE(m_got_dmx); ReceiveFromPeer(DMX_MESSAGE, sizeof(DMX_MESSAGE), peer_ip); OLA_ASSERT(m_got_dmx); OLA_ASSERT_EQ(string("0,1,2,3,4,5"), input_buffer.ToString()); } // Now disable, and set to a different universe. { node.EnterConfigurationMode(); node.DisableInputPort(m_port_id); node.SetInputPortUniverse(m_port_id, 0); node.ExitConfigurationMode(); m_socket->Verify(); } m_got_dmx = false; // 'receive' another DMX message { uint8_t DMX_MESSAGE[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x50, 0x0, 14, 1, // seq # 1, // physical port 0, 0, // subnet & net address 0, 4, // dmx length 10, 11, 12, 13 }; SocketVerifier verifer(m_socket); OLA_ASSERT_FALSE(m_got_dmx); ReceiveFromPeer(DMX_MESSAGE, sizeof(DMX_MESSAGE), peer_ip); OLA_ASSERT(m_got_dmx); OLA_ASSERT_EQ(string("10,11,12,13"), input_buffer.ToString()); } } /** * Check that merging works */ void ArtNetNodeTest::testHTPMerge() { m_socket->SetDiscardMode(true); ArtNetNodeOptions node_options; ArtNetNode node(iface, &ss, node_options, m_socket); SetupOutputPort(&node); DmxBuffer input_buffer; node.SetDMXHandler(m_port_id, &input_buffer, ola::NewCallback(this, &ArtNetNodeTest::NewDmx)); OLA_ASSERT(node.Start()); ss.RemoveReadDescriptor(m_socket); m_socket->Verify(); m_socket->SetDiscardMode(false); // 'receive' a DMX message from the first peer { SocketVerifier verifer(m_socket); uint8_t source1_message1[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x50, 0x0, 14, 0, // seq # 1, // physical port 0x23, 4, // subnet & net address 0, 6, // dmx length 0, 1, 2, 3, 4, 5 }; OLA_ASSERT_FALSE(m_got_dmx); ReceiveFromPeer(source1_message1, sizeof(source1_message1), peer_ip); OLA_ASSERT(m_got_dmx); OLA_ASSERT_EQ(string("0,1,2,3,4,5"), input_buffer.ToString()); } // receive a message from a second peer { SocketVerifier verifer(m_socket); uint8_t source2_message1[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x50, 0x0, 14, 0, // seq # 1, // physical port 0x23, 4, // subnet & net address 0, 6, // dmx length 5, 4, 3, 2, 1, 0 }; m_got_dmx = false; OLA_ASSERT_FALSE(m_got_dmx); // this will engage merge mode, so the node will send an ArtPolReply uint8_t poll_reply_message[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x21, 10, 0, 0, 1, 0x36, 0x19, 0, 0, 4, 2, // subnet address 0x4, 0x31, // oem 0, 0xd2, 0x70, 0x7a, // esta 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // short name 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // long name '#', '0', '0', '0', '1', ' ', '[', '1', ']', ' ', 'O', 'L', 'A', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // node report 0, 4, // num ports 0xc0, 0xc0, 0xc0, 0xc0, 8, 8, 8, 8, 0, 0x88, 0, 0, // 0x88 indicates we're merging data 0x20, 0x20, 0x20, 0x20, // swin 0x20, 0x23, 0x20, 0x20, // swout 0, 0, 0, 0, 0, 0, 0, // video, macro, remote, spare, style 0xa, 0xb, 0xc, 0x12, 0x34, 0x56, // mac address 0xa, 0x0, 0x0, 0x1, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // filler }; ExpectedBroadcast(poll_reply_message, sizeof(poll_reply_message)); ReceiveFromPeer(source2_message1, sizeof(source2_message1), peer_ip2); OLA_ASSERT(m_got_dmx); OLA_ASSERT_EQ(string("5,4,3,3,4,5"), input_buffer.ToString()); } // send a packet from a third source, this shouldn't result in any new dmx { SocketVerifier verifer(m_socket); const uint8_t source3_message1[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x50, 0x0, 14, 0, // seq # 1, // physical port 0x23, 4, // subnet & net address 0, 4, // dmx length 255, 255, 255, 0 }; m_got_dmx = false; OLA_ASSERT_FALSE(m_got_dmx); ReceiveFromPeer(source3_message1, sizeof(source3_message1), peer_ip3); OLA_ASSERT_FALSE(m_got_dmx); OLA_ASSERT_EQ(string("5,4,3,3,4,5"), input_buffer.ToString()); } // send another packet from the first source { SocketVerifier verifer(m_socket); uint8_t source1_message2[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x50, 0x0, 14, 1, // seq # 1, // physical port 0x23, 4, // subnet & net address 0, 8, // dmx length 10, 11, 12, 1, 2, 1, 0, 0 }; m_got_dmx = false; OLA_ASSERT_FALSE(m_got_dmx); ReceiveFromPeer(source1_message2, sizeof(source1_message2), peer_ip); OLA_ASSERT(m_got_dmx); OLA_ASSERT_EQ(string("10,11,12,2,2,1,0,0"), input_buffer.ToString()); } // advance the clock by half the merge timeout m_clock.AdvanceTime(5, 0); // send another packet from the first source { SocketVerifier verifer(m_socket); uint8_t source1_message3[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x50, 0x0, 14, 2, // seq # 1, // physical port 0x23, 4, // subnet & net address 0, 8, // dmx length 0, 1, 2, 3, 4, 5, 7, 9 }; m_got_dmx = false; OLA_ASSERT_FALSE(m_got_dmx); ReceiveFromPeer(source1_message3, sizeof(source1_message3), peer_ip); OLA_ASSERT(m_got_dmx); OLA_ASSERT_EQ(string("5,4,3,3,4,5,7,9"), input_buffer.ToString()); } // advance the clock so the second source times out m_clock.AdvanceTime(6, 0); // send another packet from the first source { SocketVerifier verifer(m_socket); uint8_t source1_message4[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x50, 0x0, 14, 3, // seq # 1, // physical port 0x23, 4, // subnet & net address 0, 8, // dmx length 0, 1, 2, 3, 4, 5, 7, 9 }; m_got_dmx = false; OLA_ASSERT_FALSE(m_got_dmx); ReceiveFromPeer(source1_message4, sizeof(source1_message4), peer_ip); OLA_ASSERT(m_got_dmx); OLA_ASSERT_EQ(string("0,1,2,3,4,5,7,9"), input_buffer.ToString()); } } /** * Check that LTP merging works */ void ArtNetNodeTest::testLTPMerge() { m_socket->SetDiscardMode(true); ArtNetNodeOptions node_options; ArtNetNode node(iface, &ss, node_options, m_socket); SetupOutputPort(&node); DmxBuffer input_buffer; node.SetDMXHandler(m_port_id, &input_buffer, ola::NewCallback(this, &ArtNetNodeTest::NewDmx)); OLA_ASSERT(node.Start()); ss.RemoveReadDescriptor(m_socket); m_socket->Verify(); m_socket->SetDiscardMode(false); // switch to LTP merge mode, this will trigger an art poll reply { SocketVerifier verifer(m_socket); uint8_t poll_reply_message[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x21, 10, 0, 0, 1, 0x36, 0x19, 0, 0, 4, 2, // subnet address 0x4, 0x31, // oem 0, 0xd2, 0x70, 0x7a, // esta 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // short name 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // long name '#', '0', '0', '0', '1', ' ', '[', '1', ']', ' ', 'O', 'L', 'A', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // node report 0, 4, // num ports 0xc0, 0xc0, 0xc0, 0xc0, 8, 8, 8, 8, 0, 0x82, 0, 0, // 0x82 indicates we're configured for LTP merge 0x20, 0x20, 0x20, 0x20, // swin 0x20, 0x23, 0x20, 0x20, // swout 0, 0, 0, 0, 0, 0, 0, // video, macro, remote, spare, style 0xa, 0xb, 0xc, 0x12, 0x34, 0x56, // mac address 0xa, 0x0, 0x0, 0x1, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // filler }; ExpectedBroadcast(poll_reply_message, sizeof(poll_reply_message)); node.SetMergeMode(m_port_id, ola::plugin::artnet::ARTNET_MERGE_LTP); } // 'receive' a DMX message from the first peer { SocketVerifier verifer(m_socket); uint8_t source1_message1[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x50, 0x0, 14, 0, // seq # 1, // physical port 0x23, 4, // subnet & net address 0, 6, // dmx length 0, 1, 2, 3, 4, 5 }; OLA_ASSERT_FALSE(m_got_dmx); ReceiveFromPeer(source1_message1, sizeof(source1_message1), peer_ip); OLA_ASSERT(m_got_dmx); OLA_ASSERT_EQ(string("0,1,2,3,4,5"), input_buffer.ToString()); } // receive a message from a second peer { SocketVerifier verifer(m_socket); uint8_t source2_message1[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x50, 0x0, 14, 0, // seq # 1, // physical port 0x23, 4, // subnet & net address 0, 6, // dmx length 5, 4, 3, 2, 1, 0 }; m_got_dmx = false; OLA_ASSERT_FALSE(m_got_dmx); // this will engage merge mode, so the node will send another ArtPolReply uint8_t poll_reply_message2[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x21, 10, 0, 0, 1, 0x36, 0x19, 0, 0, 4, 2, // subnet address 0x4, 0x31, // oem 0, 0xd2, 0x70, 0x7a, // esta 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // short name 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // long name '#', '0', '0', '0', '1', ' ', '[', '2', ']', ' ', 'O', 'L', 'A', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // node report 0, 4, // num ports 0xc0, 0xc0, 0xc0, 0xc0, 8, 8, 8, 8, 0, 0x8a, 0, 0, // 0x8a indicates we're LTP merging 0x20, 0x20, 0x20, 0x20, // swin 0x20, 0x23, 0x20, 0x20, // swout 0, 0, 0, 0, 0, 0, 0, // video, macro, remote, spare, style 0xa, 0xb, 0xc, 0x12, 0x34, 0x56, // mac address 0xa, 0x0, 0x0, 0x1, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // filler }; ExpectedBroadcast(poll_reply_message2, sizeof(poll_reply_message2)); ReceiveFromPeer(source2_message1, sizeof(source2_message1), peer_ip2); OLA_ASSERT(m_got_dmx); OLA_ASSERT_EQ(string("5,4,3,2,1,0"), input_buffer.ToString()); } // advance the clock so the second source times out m_clock.AdvanceTime(11, 0); // send another packet from the first source { SocketVerifier verifer(m_socket); uint8_t source1_message2[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x50, 0x0, 14, 1, // seq # 1, // physical port 0x23, 4, // subnet & net address 0, 8, // dmx length 0, 1, 2, 3, 4, 5, 7, 9 }; m_got_dmx = false; OLA_ASSERT_FALSE(m_got_dmx); ReceiveFromPeer(source1_message2, sizeof(source1_message2), peer_ip); OLA_ASSERT(m_got_dmx); OLA_ASSERT_EQ(string("0,1,2,3,4,5,7,9"), input_buffer.ToString()); } } /** * Check the node can act as an RDM controller. */ void ArtNetNodeTest::testControllerDiscovery() { m_socket->SetDiscardMode(true); ArtNetNodeOptions node_options; ArtNetNode node(iface, &ss, node_options, m_socket); SetupInputPort(&node); OLA_ASSERT(node.Start()); ss.RemoveReadDescriptor(m_socket); m_socket->Verify(); m_socket->SetDiscardMode(false); UID uid1(0x7a70, 0); UID uid2(0x7a70, 1); UID uid3(0x7a70, 2); // send a tod control { SocketVerifier verifer(m_socket); ExpectedBroadcast(TOD_CONTROL, sizeof(TOD_CONTROL)); node.RunFullDiscovery( m_port_id, ola::NewSingleCallback(this, &ArtNetNodeTest::DiscoveryComplete)); OLA_ASSERT_FALSE(m_discovery_done); } // advance the clock and run the select server { SocketVerifier verifer(m_socket); m_clock.AdvanceTime(5, 0); // tod timeout is 4s ss.RunOnce(); // update the wake up time OLA_ASSERT(m_discovery_done); UIDSet uids; OLA_ASSERT_EQ(uids, m_uids); } // run discovery again, this time returning a ArtTod from a peer { SocketVerifier verifer(m_socket); m_discovery_done = false; ExpectedBroadcast(TOD_CONTROL, sizeof(TOD_CONTROL)); node.RunFullDiscovery( m_port_id, ola::NewSingleCallback(this, &ArtNetNodeTest::DiscoveryComplete)); OLA_ASSERT_FALSE(m_discovery_done); // send a ArtTod const uint8_t art_tod1[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x81, 0x0, 14, 1, // rdm standard 1, // first port 0, 0, 0, 0, 0, 0, 0, 4, // net 0, // full tod 0x23, // universe address 0, 3, // uid count 0, // block count 3, // uid count 0x7a, 0x70, 0, 0, 0, 0, 0x7a, 0x70, 0, 0, 0, 1, 0x7a, 0x70, 0, 0, 0, 2, }; ReceiveFromPeer(art_tod1, sizeof(art_tod1), peer_ip); OLA_ASSERT_FALSE(m_discovery_done); } // advance the clock and run the select server { SocketVerifier verifer(m_socket); m_clock.AdvanceTime(5, 0); // tod timeout is 4s ss.RunOnce(); // update the wake up time OLA_ASSERT(m_discovery_done); UIDSet uids; uids.AddUID(uid1); uids.AddUID(uid2); uids.AddUID(uid3); OLA_ASSERT_EQ(uids, m_uids); } // run discovery again, removing one UID, and moving another from peer1 // to peer2 { SocketVerifier verifer(m_socket); m_discovery_done = false; ExpectedBroadcast(TOD_CONTROL, sizeof(TOD_CONTROL)); node.RunFullDiscovery( m_port_id, ola::NewSingleCallback(this, &ArtNetNodeTest::DiscoveryComplete)); OLA_ASSERT_FALSE(m_discovery_done); // send a ArtTod const uint8_t art_tod2[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x81, 0x0, 14, 1, // rdm standard 1, // first port 0, 0, 0, 0, 0, 0, 0, 4, // net 0, // full tod 0x23, // universe address 0, 1, // uid count 0, // block count 1, // uid count 0x7a, 0x70, 0, 0, 0, 0, }; ReceiveFromPeer(art_tod2, sizeof(art_tod2), peer_ip); const uint8_t art_tod3[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x81, 0x0, 14, 1, // rdm standard 1, // first port 0, 0, 0, 0, 0, 0, 0, 4, // net 0, // full tod 0x23, // universe address 0, 1, // uid count 0, // block count 1, // uid count 0x7a, 0x70, 0, 0, 0, 1, }; ReceiveFromPeer(art_tod3, sizeof(art_tod3), peer_ip2); OLA_ASSERT_FALSE(m_discovery_done); } // advance the clock and run the select server { SocketVerifier verifer(m_socket); m_clock.AdvanceTime(5, 0); // tod timeout is 4s ss.RunOnce(); // update the wake up time OLA_ASSERT(m_discovery_done); UIDSet uids; uids.AddUID(uid1); uids.AddUID(uid2); OLA_ASSERT_EQ(uids, m_uids); } // try running discovery for a invalid port id { SocketVerifier verifer(m_socket); m_discovery_done = false; node.RunFullDiscovery( 4, ola::NewSingleCallback(this, &ArtNetNodeTest::DiscoveryComplete)); OLA_ASSERT(m_discovery_done); UIDSet uids; OLA_ASSERT_EQ(uids, m_uids); } } /** * Check that incremental discovery works */ void ArtNetNodeTest::testControllerIncrementalDiscovery() { m_socket->SetDiscardMode(true); ArtNetNodeOptions node_options; ArtNetNode node(iface, &ss, node_options, m_socket); SetupInputPort(&node); OLA_ASSERT(node.Start()); ss.RemoveReadDescriptor(m_socket); m_socket->Verify(); m_socket->SetDiscardMode(false); // send a tod request { SocketVerifier verifer(m_socket); const uint8_t tod_request[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x80, 0x0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, // net 0, // full 1, // universe array size 0x23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; ExpectedBroadcast(tod_request, sizeof(tod_request)); node.RunIncrementalDiscovery( m_port_id, ola::NewSingleCallback(this, &ArtNetNodeTest::DiscoveryComplete)); OLA_ASSERT_FALSE(m_discovery_done); } // respond with a tod { SocketVerifier verifer(m_socket); const uint8_t art_tod1[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x81, 0x0, 14, 1, // rdm standard 1, // first port 0, 0, 0, 0, 0, 0, 0, 4, // net 0, // full tod 0x23, // universe address 0, 1, // uid count 0, // block count 1, // uid count 0x7a, 0x70, 0, 0, 0, 0, }; ReceiveFromPeer(art_tod1, sizeof(art_tod1), peer_ip); OLA_ASSERT_FALSE(m_discovery_done); // advance the clock and run the select server m_clock.AdvanceTime(5, 0); // tod timeout is 4s ss.RunOnce(); // update the wake up time OLA_ASSERT(m_discovery_done); UIDSet uids; UID uid1(0x7a70, 0); uids.AddUID(uid1); OLA_ASSERT_EQ(uids, m_uids); } // try running discovery for a invalid port id { SocketVerifier verifer(m_socket); m_discovery_done = false; node.RunIncrementalDiscovery( 4, ola::NewSingleCallback(this, &ArtNetNodeTest::DiscoveryComplete)); OLA_ASSERT(m_discovery_done); UIDSet uids; OLA_ASSERT_EQ(uids, m_uids); } } /** * Check that unsolicated TOD messages work */ void ArtNetNodeTest::testUnsolicitedTod() { m_socket->SetDiscardMode(true); ArtNetNodeOptions node_options; ArtNetNode node(iface, &ss, node_options, m_socket); SetupInputPort(&node); OLA_ASSERT(node.SetUnsolicitedUIDSetHandler( m_port_id, ola::NewCallback(this, &ArtNetNodeTest::DiscoveryComplete))); OLA_ASSERT(node.Start()); ss.RemoveReadDescriptor(m_socket); m_socket->Verify(); m_socket->SetDiscardMode(false); // receive a tod { SocketVerifier verifer(m_socket); OLA_ASSERT_FALSE(m_discovery_done); // receive a ArtTod const uint8_t art_tod[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x81, 0x0, 14, 1, // rdm standard 1, // first port 0, 0, 0, 0, 0, 0, 0, 4, // net 0, // full tod 0x23, // universe address 0, 1, // uid count 0, // block count 1, // uid count 0x7a, 0x70, 0, 0, 0, 0, }; ReceiveFromPeer(art_tod, sizeof(art_tod), peer_ip); OLA_ASSERT(m_discovery_done); UIDSet uids; UID uid1(0x7a70, 0); uids.AddUID(uid1); } } /** * Check that we respond to Tod messages */ void ArtNetNodeTest::testResponderDiscovery() { m_socket->SetDiscardMode(true); ArtNetNodeOptions node_options; ArtNetNode node(iface, &ss, node_options, m_socket); SetupOutputPort(&node); OLA_ASSERT(node.Start()); ss.RemoveReadDescriptor(m_socket); m_socket->Verify(); m_socket->SetDiscardMode(false); OLA_ASSERT(node.SetOutputPortRDMHandlers( m_port_id, ola::NewCallback(this, &ArtNetNodeTest::TodRequest), ola::NewCallback(this, &ArtNetNodeTest::Flush), NULL)); // receive a tod request { SocketVerifier verifer(m_socket); const uint8_t tod_request[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x80, 0x0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, // net 0, // full 1, // universe array size 0x23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; OLA_ASSERT_FALSE(m_tod_request); ReceiveFromPeer(tod_request, sizeof(tod_request), peer_ip); OLA_ASSERT(m_tod_request); } // respond with a Tod { SocketVerifier verifer(m_socket); const uint8_t art_tod1[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x81, 0x0, 14, 1, // rdm standard 2, // first port 0, 0, 0, 0, 0, 0, 0, 4, // net 0, // full tod 0x23, // universe address 0, 1, // uid count 0, // block count 1, // uid count 0x7a, 0x70, 0, 0, 0, 0, }; ExpectedBroadcast(art_tod1, sizeof(art_tod1)); UIDSet uids; UID uid1(0x7a70, 0); uids.AddUID(uid1); OLA_ASSERT(node.SendTod(m_port_id, uids)); } // try a tod request a universe that doesn't match ours { SocketVerifier verifer(m_socket); m_tod_request = false; const uint8_t tod_request2[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x80, 0x0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, // net 0, // full 2, // universe array size 0x13, 0x24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; OLA_ASSERT_FALSE(m_tod_request); ReceiveFromPeer(tod_request2, sizeof(tod_request2), peer_ip); OLA_ASSERT_FALSE(m_tod_request); } // check TodControl { SocketVerifier verifer(m_socket); OLA_ASSERT_FALSE(m_tod_flush); const uint8_t tod_control[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x82, 0x0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, // net 1, // flush 0x23 }; ReceiveFromPeer(tod_control, sizeof(tod_control), peer_ip); OLA_ASSERT(m_tod_flush); } // try a tod control a universe that doesn't match ours { SocketVerifier verifer(m_socket); m_tod_flush = false; OLA_ASSERT_FALSE(m_tod_flush); const uint8_t tod_control2[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x82, 0x0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, // net 1, // flush 0x13 }; ReceiveFromPeer(tod_control2, sizeof(tod_control2), peer_ip); OLA_ASSERT_FALSE(m_tod_flush); } } /** * Check that we respond to Tod messages */ void ArtNetNodeTest::testRDMResponder() { m_socket->SetDiscardMode(true); ArtNetNodeOptions node_options; ArtNetNode node(iface, &ss, node_options, m_socket); SetupOutputPort(&node); OLA_ASSERT(node.Start()); ss.RemoveReadDescriptor(m_socket); m_socket->Verify(); m_socket->SetDiscardMode(false); OLA_ASSERT(node.SetOutputPortRDMHandlers( m_port_id, NULL, NULL, ola::NewCallback(this, &ArtNetNodeTest::HandleRDM))); { SocketVerifier verifer(m_socket); const uint8_t rdm_request[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x83, 0x0, 14, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, // net 0, // process 0x23, // rdm data 1, 24, // sub code & length 0, 3, 0, 0, 0, 4, // dst uid 0, 1, 0, 0, 0, 2, // src uid 0, 1, 0, 0, 10, // transaction, port id, msg count & sub device 0x20, 1, 40, 0, // command, param id, param data length 0x01, 0x43 }; OLA_ASSERT_FALSE(m_rdm_request); OLA_ASSERT_FALSE(m_rdm_callback); ReceiveFromPeer(rdm_request, sizeof(rdm_request), peer_ip); OLA_ASSERT(m_rdm_request); OLA_ASSERT(m_rdm_callback); // check the request UID source(1, 2); UID destination(3, 4); OLA_ASSERT_EQ(source, m_rdm_request->SourceUID()); OLA_ASSERT_EQ(destination, m_rdm_request->DestinationUID()); OLA_ASSERT_EQ((uint8_t) 0, m_rdm_request->TransactionNumber()); OLA_ASSERT_EQ((uint8_t) 1, m_rdm_request->PortId()); OLA_ASSERT_EQ((uint8_t) 0, m_rdm_request->MessageCount()); OLA_ASSERT_EQ((uint16_t) 10, m_rdm_request->SubDevice()); OLA_ASSERT_EQ(RDMCommand::GET_COMMAND, m_rdm_request->CommandClass()); OLA_ASSERT_EQ((uint16_t) 296, m_rdm_request->ParamId()); OLA_ASSERT_EQ(static_cast(NULL), m_rdm_request->ParamData()); OLA_ASSERT_EQ(0u, m_rdm_request->ParamDataSize()); OLA_ASSERT_EQ(25u, RDMCommandSerializer::RequiredSize(*m_rdm_request)); } // run the RDM callback, triggering the response { SocketVerifier verifer(m_socket); const uint8_t rdm_response[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x83, 0x0, 14, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, // net 0, // process 0x23, // rdm data 1, 28, // sub code & length 0, 1, 0, 0, 0, 2, // dst uid 0, 3, 0, 0, 0, 4, // src uid 0, 0, 0, 0, 10, // transaction, port id, msg count & sub device 0x21, 1, 40, 4, // command, param id, param data length 0x5a, 0xa5, 0x5a, 0xa5, // param data 0x3, 0x49 // checksum, filled in below }; ExpectedSend(rdm_response, sizeof(rdm_response), peer_ip); uint8_t param_data[] = {0x5a, 0xa5, 0x5a, 0xa5}; RDMResponse *response = GetResponseFromData(m_rdm_request, param_data, sizeof(param_data)); RDMReply reply(ola::rdm::RDM_COMPLETED_OK, response); m_rdm_callback->Run(&reply); // clean up delete m_rdm_request; m_rdm_request = NULL; } } /** * Check that the node works as a RDM controller. */ void ArtNetNodeTest::testRDMRequest() { m_socket->SetDiscardMode(true); ArtNetNodeOptions node_options; ArtNetNode node(iface, &ss, node_options, m_socket); SetupInputPort(&node); OLA_ASSERT(node.Start()); ss.RemoveReadDescriptor(m_socket); m_socket->Verify(); m_socket->SetDiscardMode(false); // We need to send a TodData so we populate the node's UID map PopulateTod(); // create a new RDM request { SocketVerifier verifer(m_socket); SendRDMRequest( &node, ola::NewSingleCallback(this, &ArtNetNodeTest::FinalizeRDM)); } // send a response { SocketVerifier verifer(m_socket); const uint8_t rdm_response[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x83, 0x0, 14, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, // net 0, // process 0x23, // rdm data 1, 28, // sub code & length 0, 1, 0, 0, 0, 2, // dst uid 0x7a, 0x70, 0, 0, 0, 0, // dst uid 0, 0, 0, 0, 10, // transaction, port id, msg count & sub device 0x21, 1, 40, 4, // command, param id, param data length 0x5a, 0xa5, 0x5a, 0xa5, // param data 0x4, 0x2c // checksum, filled in below }; OLA_ASSERT_FALSE(m_rdm_response); ReceiveFromPeer(rdm_response, sizeof(rdm_response), peer_ip); OLA_ASSERT(m_rdm_response); delete m_rdm_response; } } /** * Check that request times out if we don't get a response. */ void ArtNetNodeTest::testRDMRequestTimeout() { m_socket->SetDiscardMode(true); ArtNetNodeOptions node_options; ArtNetNode node(iface, &ss, node_options, m_socket); SetupInputPort(&node); OLA_ASSERT(node.Start()); ss.RemoveReadDescriptor(m_socket); m_socket->Verify(); m_socket->SetDiscardMode(false); // We need to send a TodData so we populate the node's UID map PopulateTod(); // create a new RDM request { SocketVerifier verifer(m_socket); SendRDMRequest( &node, ola::NewSingleCallback(this, &ArtNetNodeTest::ExpectTimeout)); } m_clock.AdvanceTime(3, 0); // timeout is 2s ss.RunOnce(); OLA_ASSERT(m_got_rdm_timeout); } /** * Check we don't accept responses from a different src IP */ void ArtNetNodeTest::testRDMRequestIPMismatch() { m_socket->SetDiscardMode(true); ArtNetNodeOptions node_options; ArtNetNode node(iface, &ss, node_options, m_socket); SetupInputPort(&node); OLA_ASSERT(node.Start()); ss.RemoveReadDescriptor(m_socket); m_socket->Verify(); m_socket->SetDiscardMode(false); // We need to send a TodData so we populate the node's UID map PopulateTod(); // create a new RDM request { SocketVerifier verifer(m_socket); SendRDMRequest( &node, ola::NewSingleCallback(this, &ArtNetNodeTest::ExpectTimeout)); } // send a response from a different IP { SocketVerifier verifer(m_socket); const uint8_t rdm_response[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x83, 0x0, 14, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, // net 0, // process 0x23, // rdm data 1, 28, // sub code & length 0, 1, 0, 0, 0, 2, // dst uid 0x7a, 0x70, 0, 0, 0, 0, // src uid 0, 0, 0, 0, 10, // transaction, port id, msg count & sub device 0x21, 1, 40, 4, // command, param id, param data length 0x5a, 0xa5, 0x5a, 0xa5, // param data 0x4, 0x2c // checksum, filled in below }; OLA_ASSERT_FALSE(m_rdm_response); ReceiveFromPeer(rdm_response, sizeof(rdm_response), peer_ip2); OLA_ASSERT_FALSE(m_rdm_response); } m_clock.AdvanceTime(3, 0); // timeout is 2s ss.RunOnce(); OLA_ASSERT(m_got_rdm_timeout); } /** * Check we don't accept responses with a different UID */ void ArtNetNodeTest::testRDMRequestUIDMismatch() { m_socket->SetDiscardMode(true); ArtNetNodeOptions node_options; ArtNetNode node(iface, &ss, node_options, m_socket); SetupInputPort(&node); OLA_ASSERT(node.Start()); ss.RemoveReadDescriptor(m_socket); m_socket->Verify(); m_socket->SetDiscardMode(false); // We need to send a TodData so we populate the node's UID map PopulateTod(); // create a new RDM request { SocketVerifier verifer(m_socket); SendRDMRequest( &node, ola::NewSingleCallback(this, &ArtNetNodeTest::ExpectTimeout)); } // send a response from a different IP { SocketVerifier verifer(m_socket); const uint8_t rdm_response[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x83, 0x0, 14, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, // net 0, // process 0x23, // rdm data 1, 28, // sub code & length 0, 1, 0, 0, 0, 2, // dst uid 0x7a, 0x70, 0, 0, 0, 1, // src uid 0, 0, 0, 0, 10, // transaction, port id, msg count & sub device 0x21, 1, 40, 4, // command, param id, param data length 0x5a, 0xa5, 0x5a, 0xa5, // param data 0x4, 0x2d // checksum, filled in below }; OLA_ASSERT_FALSE(m_rdm_response); ReceiveFromPeer(rdm_response, sizeof(rdm_response), peer_ip); OLA_ASSERT_FALSE(m_rdm_response); } m_clock.AdvanceTime(3, 0); // timeout is 2s ss.RunOnce(); OLA_ASSERT(m_got_rdm_timeout); } /** * Check Timecode sending works */ void ArtNetNodeTest::testTimeCode() { m_socket->SetDiscardMode(true); ArtNetNodeOptions node_options; ArtNetNode node(iface, &ss, node_options, m_socket); OLA_ASSERT(node.Start()); ss.RemoveReadDescriptor(m_socket); m_socket->Verify(); m_socket->SetDiscardMode(false); { SocketVerifier verifer(m_socket); const uint8_t timecode_message[] = { 'A', 'r', 't', '-', 'N', 'e', 't', 0x00, 0x00, 0x97, 0x0, 14, 0, 0, 11, 30, 20, 10, 3 }; ExpectedBroadcast(timecode_message, sizeof(timecode_message)); TimeCode t1(ola::timecode::TIMECODE_SMPTE, 10, 20, 30, 11); OLA_ASSERT(node.SendTimeCode(t1)); } } ola-0.10.5.nojsmin/plugins/artnet/messages/0000755000175000017500000000000013134123611020240 5ustar wouterwouterola-0.10.5.nojsmin/plugins/artnet/messages/Makefile.mk0000644000175000017500000000244413023355232022315 0ustar wouterwouter# The ArtNet plugin config messages. This needs to be available to client # programs. EXTRA_DIST += plugins/artnet/messages/ArtNetConfigMessages.proto # pkg-config ################################################## pkgconfig_DATA += plugins/artnet/messages/libolaartnetconf.pc # LIBRARIES ################################################## if USE_ARTNET lib_LTLIBRARIES += plugins/artnet/messages/libolaartnetconf.la artnetincludedir = $(includedir)/ola/artnet nodist_artnetinclude_HEADERS = \ plugins/artnet/messages/ArtNetConfigMessages.pb.h built_sources += plugins/artnet/messages/ArtNetConfigMessages.pb.cc \ plugins/artnet/messages/ArtNetConfigMessages.pb.h nodist_plugins_artnet_messages_libolaartnetconf_la_SOURCES = \ plugins/artnet/messages/ArtNetConfigMessages.pb.cc plugins_artnet_messages_libolaartnetconf_la_CXXFLAGS = $(COMMON_PROTOBUF_CXXFLAGS) plugins_artnet_messages_libolaartnetconf_la_LIBADD = $(libprotobuf_LIBS) plugins/artnet/messages/ArtNetConfigMessages.pb.cc plugins/artnet/messages/ArtNetConfigMessages.pb.h: plugins/artnet/messages/Makefile.mk plugins/artnet/messages/ArtNetConfigMessages.proto $(PROTOC) --cpp_out plugins/artnet/messages/ --proto_path $(srcdir)/plugins/artnet/messages $(srcdir)/plugins/artnet/messages/ArtNetConfigMessages.proto endif ola-0.10.5.nojsmin/plugins/artnet/messages/ArtNetConfigMessages.proto0000644000175000017500000000372013023355232025345 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ArtNetConfigMessages.proto * Defines the protocol buffers used to configure the Artnet device * Copyright (C) 2005 Simon Newton */ package ola.plugin.artnet; // This adjusts the ArtNet settings for this node. message OptionsRequest { optional string short_name = 1; optional string long_name = 2; optional int32 subnet = 3; optional int32 net = 4; } message OptionsReply { required uint32 status = 1; required string short_name = 2; required string long_name = 3; required int32 subnet = 4; required int32 net = 5; } // This returns a list of nodes configured to receive on a particular universe. message NodeListRequest { required int32 universe = 1; } message OutputNode { required uint32 ip_address = 1; } // The list of output nodes message NodeListReply { repeated OutputNode node = 1; } message Request { enum RequestType { ARTNET_OPTIONS_REQUEST = 1; ARTNET_NODE_LIST_REQUEST = 2; } required RequestType type = 1; optional OptionsRequest options = 2; optional NodeListRequest node_list = 3; } message Reply { enum ReplyType { ARTNET_OPTIONS_REPLY = 1; ARTNET_NODE_LIST_REPLY = 2; } required ReplyType type = 1; optional OptionsReply options = 2; optional NodeListReply node_list = 3; } ola-0.10.5.nojsmin/plugins/artnet/messages/libolaartnetconf.pc.in0000644000175000017500000000031713023355232024523 0ustar wouterwouterprefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libolaartnetconf Version: @VERSION@ Description: Open Lighting Architecture - Artnet Config Messages Libs: -lprotobuf ola-0.10.5.nojsmin/plugins/artnet/ArtNetPlugin.cpp0000644000175000017500000001701313134123277021523 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ArtNetPlugin.cpp * The ArtNet plugin for ola * Copyright (C) 2005 Simon Newton */ #include #include #include #include "ola/Logging.h" #include "olad/PluginAdaptor.h" #include "olad/Preferences.h" #include "plugins/artnet/ArtNetPlugin.h" #include "plugins/artnet/ArtNetDevice.h" namespace ola { namespace plugin { namespace artnet { using std::string; const char ArtNetPlugin::ARTNET_LONG_NAME[] = "OLA - ArtNet node"; const char ArtNetPlugin::ARTNET_SHORT_NAME[] = "OLA - ArtNet node"; const char ArtNetPlugin::PLUGIN_NAME[] = "ArtNet"; const char ArtNetPlugin::PLUGIN_PREFIX[] = "artnet"; bool ArtNetPlugin::StartHook() { m_device = new ArtNetDevice(this, m_preferences, m_plugin_adaptor); if (!m_device->Start()) { delete m_device; return false; } // Register device will restore the port settings. To avoid a flurry of // ArtPoll / ArtPollReply messages, we enter config mode here. m_device->EnterConfigurationMode(); m_plugin_adaptor->RegisterDevice(m_device); m_device->ExitConfigurationMode(); return true; } bool ArtNetPlugin::StopHook() { if (m_device) { // stop the device m_plugin_adaptor->UnregisterDevice(m_device); bool ret = m_device->Stop(); delete m_device; return ret; } return true; } string ArtNetPlugin::Description() const { return "ArtNet Plugin\n" "----------------------------\n" "\n" "This plugin creates a single device with four input and four output \n" "ports and supports ArtNet, ArtNet 2 and ArtNet 3.\n" "\n" "ArtNet limits a single device (identified by a unique IP) to four\n" "input and four output ports, each bound to a separate ArtNet Port\n" "Address (see the ArtNet spec for more details). The ArtNet Port\n" "Address is a 16 bits int, defined as follows: \n" "\n" " Bit 15 | Bits 14 - 8 | Bits 7 - 4 | Bits 3 - 0\n" " 0 | Net | Sub-Net | Universe\n" "\n" "For OLA, the Net and Sub-Net values can be controlled by the config\n" "file. The Universe bits are the OLA Universe number modulo 16.\n" "\n" " ArtNet Net | ArtNet Subnet | OLA Universe | ArtNet Port Address\n" " 0 | 0 | 0 | 0\n" " 0 | 0 | 1 | 1\n" " 0 | 0 | 15 | 15\n" " 0 | 0 | 16 | 0\n" " 0 | 0 | 17 | 1\n" " 0 | 1 | 0 | 16\n" " 0 | 1 | 1 | 17\n" " 0 | 15 | 0 | 240\n" " 0 | 15 | 15 | 255\n" " 1 | 0 | 0 | 256\n" " 1 | 0 | 1 | 257\n" " 1 | 0 | 15 | 271\n" " 1 | 1 | 0 | 272\n" " 1 | 15 | 0 | 496\n" " 1 | 15 | 15 | 511\n" "\n" "That is Port Address = (Net << 8) + (Subnet << 4) + (Universe % 4)\n" "\n" "--- Config file : ola-artnet.conf ---\n" "\n" "always_broadcast = [true|false]\n" "Use ArtNet v1 and always broadcast the DMX data. Turn this on if\n" "you have devices that don't respond to ArtPoll messages.\n" "\n" "ip = [a.b.c.d|]\n" "The ip address or interface name to bind to. If not specified it will\n" "use the first non-loopback interface.\n" "\n" "long_name = ola - ArtNet node\n" "The long name of the node.\n" "\n" "net = 0\n" "The ArtNet Net to use (0-127).\n" "\n" "output_ports = 4\n" "The number of output ports (Send ArtNet) to create. Only the first 4\n" "will appear in ArtPoll messages\n" "\n" "short_name = ola - ArtNet node\n" "The short name of the node (first 17 chars will be used).\n" "\n" "subnet = 0\n" "The ArtNet subnet to use (0-15).\n" "\n" "use_limited_broadcast = [true|false]\n" "When broadcasting, use the limited broadcast address (255.255.255.255)\n" "rather than the subnet directed broadcast address. Some devices which \n" "don't follow the ArtNet spec require this. This only affects ArtDMX \n" "packets.\n" "\n" "use_loopback = [true|false]\n" "Enable use of the loopback device.\n" "\n"; } bool ArtNetPlugin::SetDefaultPreferences() { bool save = false; if (!m_preferences) { return false; } save |= m_preferences->SetDefaultValue(ArtNetDevice::K_IP_KEY, StringValidator(true), ""); save |= m_preferences->SetDefaultValue(ArtNetDevice::K_SHORT_NAME_KEY, StringValidator(), ARTNET_SHORT_NAME); save |= m_preferences->SetDefaultValue(ArtNetDevice::K_LONG_NAME_KEY, StringValidator(), ARTNET_LONG_NAME); save |= m_preferences->SetDefaultValue(ArtNetDevice::K_NET_KEY, UIntValidator(0, 127), ArtNetDevice::K_ARTNET_NET); save |= m_preferences->SetDefaultValue(ArtNetDevice::K_SUBNET_KEY, UIntValidator(0, 15), ArtNetDevice::K_ARTNET_SUBNET); save |= m_preferences->SetDefaultValue( ArtNetDevice::K_OUTPUT_PORT_KEY, UIntValidator(0, 16), ArtNetDevice::K_DEFAULT_OUTPUT_PORT_COUNT); save |= m_preferences->SetDefaultValue(ArtNetDevice::K_ALWAYS_BROADCAST_KEY, BoolValidator(), false); save |= m_preferences->SetDefaultValue(ArtNetDevice::K_LIMITED_BROADCAST_KEY, BoolValidator(), false); save |= m_preferences->SetDefaultValue(ArtNetDevice::K_LOOPBACK_KEY, BoolValidator(), false); if (save) { m_preferences->Save(); } // check if this saved correctly // we don't want to use it if null if (m_preferences->GetValue(ArtNetDevice::K_SHORT_NAME_KEY).empty() || m_preferences->GetValue(ArtNetDevice::K_LONG_NAME_KEY).empty() || m_preferences->GetValue(ArtNetDevice::K_SUBNET_KEY).empty() || m_preferences->GetValue(ArtNetDevice::K_OUTPUT_PORT_KEY).empty() || m_preferences->GetValue(ArtNetDevice::K_NET_KEY).empty()) { return false; } return true; } } // namespace artnet } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/artnet/ArtNetPlugin.h0000644000175000017500000000404113023355232021160 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ArtNetPlugin.h * Interface for the ArtNet plugin class * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_ARTNET_ARTNETPLUGIN_H_ #define PLUGINS_ARTNET_ARTNETPLUGIN_H_ #include #include "olad/Plugin.h" #include "ola/plugin_id.h" namespace ola { namespace plugin { namespace artnet { class ArtNetDevice; class ArtNetPlugin : public Plugin { public: explicit ArtNetPlugin(PluginAdaptor *plugin_adaptor): Plugin(plugin_adaptor), m_device(NULL) {} ~ArtNetPlugin() {} std::string Name() const { return PLUGIN_NAME; } ola_plugin_id Id() const { return OLA_PLUGIN_ARTNET; } std::string Description() const; std::string PluginPrefix() const { return PLUGIN_PREFIX; } private: /** * Start the plugin, for now we just have one device. * @todo Allow multiple devices on different IPs? * @return true if we started ok, false otherwise */ bool StartHook(); bool StopHook(); bool SetDefaultPreferences(); ArtNetDevice *m_device; // only have one device static const char ARTNET_NET[]; static const char ARTNET_SUBNET[]; static const char ARTNET_LONG_NAME[]; static const char ARTNET_SHORT_NAME[]; static const char PLUGIN_NAME[]; static const char PLUGIN_PREFIX[]; }; } // namespace artnet } // namespace plugin } // namespace ola #endif // PLUGINS_ARTNET_ARTNETPLUGIN_H_ ola-0.10.5.nojsmin/plugins/artnet/ArtNetPort.h0000644000175000017500000000623013023355232020650 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ArtNetPort.h * The ArtNet plugin for ola * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_ARTNET_ARTNETPORT_H_ #define PLUGINS_ARTNET_ARTNETPORT_H_ #include #include "ola/rdm/RDMControllerInterface.h" #include "olad/Port.h" #include "plugins/artnet/ArtNetDevice.h" #include "plugins/artnet/ArtNetNode.h" namespace ola { namespace plugin { namespace artnet { class ArtNetInputPort: public BasicInputPort { public: ArtNetInputPort(ArtNetDevice *parent, unsigned int port_id, class PluginAdaptor *plugin_adaptor, ArtNetNode *node) : BasicInputPort(parent, port_id, plugin_adaptor, true), m_node(node) {} const DmxBuffer &ReadDMX() const { return m_buffer; } /** * Set the DMX Handlers as needed */ void PostSetUniverse(Universe *old_universe, Universe *new_universe); /* * Respond With Tod */ void RespondWithTod(); std::string Description() const; private: DmxBuffer m_buffer; ArtNetNode *m_node; /** * Send a list of UIDs in a TOD */ void SendTODWithUIDs(const ola::rdm::UIDSet &uids); /** * Run the RDM discovery routine */ void TriggerDiscovery(); }; class ArtNetOutputPort: public BasicOutputPort { public: ArtNetOutputPort(ArtNetDevice *device, unsigned int port_id, ArtNetNode *node) : BasicOutputPort(device, port_id, true, true), m_node(node) {} bool WriteDMX(const DmxBuffer &buffer, uint8_t priority); /* * Handle an RDMRequest */ void SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *on_complete); /* * Run the full RDM discovery process */ void RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback); /* * Run the incremental RDM discovery process */ void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback); /* * Set the RDM handlers as appropriate */ void PostSetUniverse(Universe *old_universe, Universe *new_universe); std::string Description() const; // only the first output port supports timecode, otherwise we send it // multiple times. bool SupportsTimeCode() const { return PortId() == 0; } bool SendTimeCode(const ola::timecode::TimeCode &timecode) { return m_node->SendTimeCode(timecode); } private: ArtNetNode *m_node; }; } // namespace artnet } // namespace plugin } // namespace ola #endif // PLUGINS_ARTNET_ARTNETPORT_H_ ola-0.10.5.nojsmin/plugins/artnet/ArtNetDevice.cpp0000644000175000017500000002013613023355232021457 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ArtNetDevice.cpp * Art-Net device * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include #include #include #include #include #include "common/rpc/RpcController.h" #include "ola/Callback.h" #include "ola/CallbackRunner.h" #include "ola/Logging.h" #include "ola/StringUtils.h" #include "ola/network/IPV4Address.h" #include "ola/network/InterfacePicker.h" #include "ola/network/NetworkUtils.h" #include "olad/PluginAdaptor.h" #include "olad/Port.h" #include "olad/Preferences.h" #include "plugins/artnet/ArtNetDevice.h" #include "plugins/artnet/ArtNetPort.h" namespace ola { namespace plugin { namespace artnet { using ola::rpc::RpcController; using ola::StringToInt; using ola::network::IPV4Address; using ola::plugin::artnet::Reply; using ola::plugin::artnet::Request; using std::auto_ptr; using std::ostringstream; using std::string; using std::vector; const char ArtNetDevice::K_ALWAYS_BROADCAST_KEY[] = "always_broadcast"; const char ArtNetDevice::K_DEVICE_NAME[] = "ArtNet"; const char ArtNetDevice::K_IP_KEY[] = "ip"; const char ArtNetDevice::K_LIMITED_BROADCAST_KEY[] = "use_limited_broadcast"; const char ArtNetDevice::K_LONG_NAME_KEY[] = "long_name"; const char ArtNetDevice::K_LOOPBACK_KEY[] = "use_loopback"; const char ArtNetDevice::K_NET_KEY[] = "net"; const char ArtNetDevice::K_OUTPUT_PORT_KEY[] = "output_ports"; const char ArtNetDevice::K_SHORT_NAME_KEY[] = "short_name"; const char ArtNetDevice::K_SUBNET_KEY[] = "subnet"; const unsigned int ArtNetDevice::K_ARTNET_NET = 0; const unsigned int ArtNetDevice::K_ARTNET_SUBNET = 0; const unsigned int ArtNetDevice::K_DEFAULT_OUTPUT_PORT_COUNT = 4; ArtNetDevice::ArtNetDevice(AbstractPlugin *owner, ola::Preferences *preferences, PluginAdaptor *plugin_adaptor) : Device(owner, K_DEVICE_NAME), m_preferences(preferences), m_node(NULL), m_plugin_adaptor(plugin_adaptor), m_timeout_id(ola::thread::INVALID_TIMEOUT) { } bool ArtNetDevice::StartHook() { unsigned int subnet = StringToIntOrDefault( m_preferences->GetValue(K_SUBNET_KEY), K_ARTNET_SUBNET); unsigned int net = StringToIntOrDefault( m_preferences->GetValue(K_NET_KEY), K_ARTNET_NET); ola::network::Interface iface; auto_ptr picker( ola::network::InterfacePicker::NewPicker()); ola::network::InterfacePicker::Options options; options.include_loopback = m_preferences->GetValueAsBool(K_LOOPBACK_KEY); if (!picker->ChooseInterface(&iface, m_preferences->GetValue(K_IP_KEY), options)) { OLA_INFO << "Failed to find an interface"; return false; } ArtNetNodeOptions node_options; node_options.always_broadcast = m_preferences->GetValueAsBool( K_ALWAYS_BROADCAST_KEY); node_options.use_limited_broadcast_address = m_preferences->GetValueAsBool( K_LIMITED_BROADCAST_KEY); // OLA Output ports are ArtNet input ports node_options.input_port_count = StringToIntOrDefault( m_preferences->GetValue(K_OUTPUT_PORT_KEY), K_DEFAULT_OUTPUT_PORT_COUNT); m_node = new ArtNetNode(iface, m_plugin_adaptor, node_options); m_node->SetNetAddress(net); m_node->SetSubnetAddress(subnet); m_node->SetShortName(m_preferences->GetValue(K_SHORT_NAME_KEY)); m_node->SetLongName(m_preferences->GetValue(K_LONG_NAME_KEY)); for (unsigned int i = 0; i < node_options.input_port_count; i++) { AddPort(new ArtNetOutputPort(this, i, m_node)); } for (unsigned int i = 0; i < ARTNET_MAX_PORTS; i++) { AddPort(new ArtNetInputPort(this, i, m_plugin_adaptor, m_node)); } if (!m_node->Start()) { DeleteAllPorts(); delete m_node; m_node = NULL; return false; } ostringstream str; str << K_DEVICE_NAME << " [" << iface.ip_address << "]"; SetName(str.str()); m_timeout_id = m_plugin_adaptor->RegisterRepeatingTimeout( POLL_INTERVAL, NewCallback(m_node, &ArtNetNode::SendPoll)); return true; } void ArtNetDevice::PrePortStop() { if (m_timeout_id != ola::thread::INVALID_TIMEOUT) { m_plugin_adaptor->RemoveTimeout(m_timeout_id); m_timeout_id = ola::thread::INVALID_TIMEOUT; } m_node->Stop(); } void ArtNetDevice::PostPortStop() { delete m_node; m_node = NULL; } void ArtNetDevice::Configure(RpcController *controller, const string &request, string *response, ConfigureCallback *done) { CallbackRunner runner(done); Request request_pb; if (!request_pb.ParseFromString(request)) { controller->SetFailed("Invalid Request"); return; } switch (request_pb.type()) { case ola::plugin::artnet::Request::ARTNET_OPTIONS_REQUEST: HandleOptions(&request_pb, response); break; case ola::plugin::artnet::Request::ARTNET_NODE_LIST_REQUEST: HandleNodeList(&request_pb, response, controller); break; default: controller->SetFailed("Invalid Request"); } } void ArtNetDevice::HandleOptions(Request *request, string *response) { bool status = true; if (request->has_options()) { const ola::plugin::artnet::OptionsRequest options = request->options(); if (options.has_short_name()) { status &= m_node->SetShortName(options.short_name()); } if (options.has_long_name()) { status &= m_node->SetLongName(options.long_name()); } if (options.has_subnet()) { status &= m_node->SetSubnetAddress(options.subnet()); } if (options.has_net()) { status &= m_node->SetNetAddress(options.net()); } } ola::plugin::artnet::Reply reply; reply.set_type(ola::plugin::artnet::Reply::ARTNET_OPTIONS_REPLY); ola::plugin::artnet::OptionsReply *options_reply = reply.mutable_options(); options_reply->set_status(status); options_reply->set_short_name(m_node->ShortName()); options_reply->set_long_name(m_node->LongName()); options_reply->set_subnet(m_node->SubnetAddress()); options_reply->set_net(m_node->NetAddress()); reply.SerializeToString(response); } void ArtNetDevice::HandleNodeList(Request *request, string *response, RpcController *controller) { if (!request->has_node_list()) { controller->SetFailed("Missing NodeListRequest"); return; } unsigned int universe_id = request->node_list().universe(); vector node_addresses; vector output_ports; OutputPorts(&output_ports); vector::const_iterator port_iter = output_ports.begin(); for (; port_iter != output_ports.end(); port_iter++) { Universe *universe = (*port_iter)->GetUniverse(); if (universe && universe->UniverseId() == universe_id) { m_node->GetSubscribedNodes((*port_iter)->PortId(), &node_addresses); break; } } ola::plugin::artnet::Reply reply; reply.set_type(ola::plugin::artnet::Reply::ARTNET_NODE_LIST_REPLY); ola::plugin::artnet::NodeListReply *node_list_reply = reply.mutable_node_list(); vector::const_iterator iter = node_addresses.begin(); for (; iter != node_addresses.end(); ++iter) { OutputNode *node = node_list_reply->add_node(); node->set_ip_address(iter->AsInt()); } reply.SerializeToString(response); } } // namespace artnet } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/artnet/ArtNetNode.cpp0000644000175000017500000016321313023355232021151 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ArtNetNode.cpp * An ArtNet node * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include #include #include #include #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/base/Array.h" #include "ola/network/IPV4Address.h" #include "ola/network/NetworkUtils.h" #include "ola/network/SocketAddress.h" #include "ola/rdm/RDMCommandSerializer.h" #include "ola/rdm/RDMEnums.h" #include "ola/stl/STLUtils.h" #include "ola/strings/Format.h" #include "ola/strings/Utils.h" #include "plugins/artnet/ArtNetNode.h" namespace ola { namespace plugin { namespace artnet { using ola::Callback0; using ola::Callback1; using ola::network::HostToLittleEndian; using ola::network::HostToNetwork; using ola::network::IPV4Address; using ola::network::IPV4SocketAddress; using ola::network::LittleEndianToHost; using ola::network::NetworkToHost; using ola::network::UDPSocket; using ola::rdm::RDMCallback; using ola::rdm::RDMCommand; using ola::rdm::RDMCommandSerializer; using ola::rdm::RDMDiscoveryCallback; using ola::rdm::RDMFrame; using ola::rdm::RDMReply; using ola::rdm::RDMRequest; using ola::rdm::RunRDMCallback; using ola::rdm::UID; using ola::rdm::UIDSet; using ola::strings::CopyToFixedLengthBuffer; using ola::strings::ToHex; using std::auto_ptr; using std::map; using std::pair; using std::set; using std::string; using std::vector; const char ArtNetNodeImpl::ARTNET_ID[] = "Art-Net"; // UID to the IP Address it came from, and the number of times since we last // saw it in an ArtTod message. typedef map > uid_map; // Input ports are ones that send data using ArtNet class ArtNetNodeImpl::InputPort { public: InputPort() : enabled(false), sequence_number(0), discovery_callback(NULL), discovery_timeout(ola::thread::INVALID_TIMEOUT), rdm_request_callback(NULL), pending_request(NULL), rdm_send_timeout(ola::thread::INVALID_TIMEOUT), m_port_address(0), m_tod_callback(NULL) { } ~InputPort() {} // Returns true if the address changed. bool SetUniverseAddress(uint8_t universe_address) { universe_address = universe_address & 0x0f; if ((m_port_address & 0x0f) == universe_address) { return false; } m_port_address = ((m_port_address & 0xf0) | universe_address); uids.clear(); subscribed_nodes.clear(); return true; } void ClearSubscribedNodes() { subscribed_nodes.clear(); } // Returns true if the address changed. bool SetSubNetAddress(uint8_t subnet_address) { subnet_address = subnet_address << 4; if (subnet_address == (m_port_address & 0xf0)) { return false; } m_port_address = subnet_address | (m_port_address & 0x0f); uids.clear(); subscribed_nodes.clear(); return true; } // The 8-bit port address, which is made up of the sub-net and universe // address. uint8_t PortAddress() const { return m_port_address; } void SetTodCallback(RDMDiscoveryCallback *callback) { m_tod_callback.reset(callback); } void RunTodCallback() { if (m_tod_callback.get()) { RunRDMCallbackWithUIDs(uids, m_tod_callback.get()); } } void RunDiscoveryCallback() { if (discovery_callback) { RDMDiscoveryCallback *callback = discovery_callback; discovery_callback = NULL; RunRDMCallbackWithUIDs(uids, callback); } } void IncrementUIDCounts() { for (uid_map::iterator iter = uids.begin(); iter != uids.end(); ++iter) { iter->second.second++; } } bool enabled; uint8_t sequence_number; map subscribed_nodes; uid_map uids; // used to keep track of the UIDs // NULL if discovery isn't running, otherwise the callback to run when it // finishes RDMDiscoveryCallback *discovery_callback; // The set of nodes we're expecting a response from set discovery_node_set; // the timeout_id for the discovery timer ola::thread::timeout_id discovery_timeout; // the in-flight request and it's callback RDMCallback *rdm_request_callback; const RDMRequest *pending_request; IPV4Address rdm_ip_destination; // these control the sending of RDM requests. ola::thread::timeout_id rdm_send_timeout; private: uint8_t m_port_address; // The callback to run if we receive an TOD and the discovery process // isn't running auto_ptr m_tod_callback; void RunRDMCallbackWithUIDs(const uid_map &uids, RDMDiscoveryCallback *callback) { UIDSet uid_set; uid_map::const_iterator uid_iter = uids.begin(); for (; uid_iter != uids.end(); ++uid_iter) { uid_set.AddUID(uid_iter->first); } callback->Run(uid_set); } }; ArtNetNodeImpl::ArtNetNodeImpl(const ola::network::Interface &iface, ola::io::SelectServerInterface *ss, const ArtNetNodeOptions &options, ola::network::UDPSocketInterface *socket) : m_running(false), m_net_address(0), m_send_reply_on_change(true), m_short_name(""), m_long_name(""), m_broadcast_threshold(options.broadcast_threshold), m_unsolicited_replies(0), m_ss(ss), m_always_broadcast(options.always_broadcast), m_use_limited_broadcast_address(options.use_limited_broadcast_address), m_in_configuration_mode(false), m_artpoll_required(false), m_artpollreply_required(false), m_interface(iface), m_socket(socket) { if (!m_socket.get()) { m_socket.reset(new UDPSocket()); } for (unsigned int i = 0; i < options.input_port_count; i++) { m_input_ports.push_back(new InputPort()); } // reset all the port structures for (unsigned int i = 0; i < ARTNET_MAX_PORTS; i++) { m_output_ports[i].universe_address = 0; m_output_ports[i].sequence_number = 0; m_output_ports[i].enabled = false; m_output_ports[i].is_merging = false; m_output_ports[i].merge_mode = ARTNET_MERGE_HTP; m_output_ports[i].buffer = NULL; m_output_ports[i].on_data = NULL; m_output_ports[i].on_discover = NULL; m_output_ports[i].on_flush = NULL; m_output_ports[i].on_rdm_request = NULL; } } ArtNetNodeImpl::~ArtNetNodeImpl() { Stop(); STLDeleteElements(&m_input_ports); for (unsigned int i = 0; i < ARTNET_MAX_PORTS; i++) { if (m_output_ports[i].on_data) { delete m_output_ports[i].on_data; } if (m_output_ports[i].on_discover) { delete m_output_ports[i].on_discover; } if (m_output_ports[i].on_flush) { delete m_output_ports[i].on_flush; } if (m_output_ports[i].on_rdm_request) { delete m_output_ports[i].on_rdm_request; } } } bool ArtNetNodeImpl::Start() { if (m_running || !InitNetwork()) { return false; } m_running = true; return true; } bool ArtNetNodeImpl::Stop() { if (!m_running) { return false; } // clean up any in-flight rdm requests InputPorts::iterator iter = m_input_ports.begin(); for (; iter != m_input_ports.end(); ++iter) { InputPort *port = *iter; // clean up discovery state if (port->discovery_timeout != ola::thread::INVALID_TIMEOUT) { m_ss->RemoveTimeout(port->discovery_timeout); port->discovery_timeout = ola::thread::INVALID_TIMEOUT; } port->RunDiscoveryCallback(); // clean up request state if (port->rdm_send_timeout != ola::thread::INVALID_TIMEOUT) { m_ss->RemoveTimeout(port->rdm_send_timeout); port->rdm_send_timeout = ola::thread::INVALID_TIMEOUT; } if (port->pending_request) { delete port->pending_request; port->pending_request = NULL; } if (port->rdm_request_callback) { RDMCallback *callback = port->rdm_request_callback; port->rdm_request_callback = NULL; RunRDMCallback(callback, ola::rdm::RDM_TIMEOUT); } } m_ss->RemoveReadDescriptor(m_socket.get()); m_running = false; return true; } bool ArtNetNodeImpl::EnterConfigurationMode() { if (m_in_configuration_mode) { return false; } m_in_configuration_mode = true; m_artpoll_required = false; m_artpollreply_required = false; return true; } bool ArtNetNodeImpl::ExitConfigurationMode() { if (!m_in_configuration_mode) { return false; } m_in_configuration_mode = false; if (m_artpoll_required) { SendPoll(); m_artpoll_required = false; } if (m_artpollreply_required) { SendPollReplyIfRequired(); } return true; } bool ArtNetNodeImpl::SetShortName(const string &name) { if (m_short_name == name) { return true; } m_short_name = name; return SendPollReplyIfRequired(); } bool ArtNetNodeImpl::SetLongName(const string &name) { if (m_long_name == name) { return true; } m_long_name = name; return SendPollReplyIfRequired(); } bool ArtNetNodeImpl::SetNetAddress(uint8_t net_address) { if (net_address & 0x80) { OLA_WARN << "Artnet net address > 127, truncating"; net_address = net_address & 0x7f; } if (net_address == m_net_address) { return true; } m_net_address = net_address; bool input_ports_enabled = false; vector::iterator iter = m_input_ports.begin(); for (; iter != m_input_ports.end(); ++iter) { input_ports_enabled |= (*iter)->enabled; (*iter)->ClearSubscribedNodes(); } if (input_ports_enabled) { SendPollIfAllowed(); } return SendPollReplyIfRequired(); } bool ArtNetNodeImpl::SetSubnetAddress(uint8_t subnet_address) { // Set for all input ports. bool changed = false; bool input_ports_enabled = false; vector::iterator iter = m_input_ports.begin(); for (; iter != m_input_ports.end(); ++iter) { input_ports_enabled |= (*iter)->enabled; changed |= (*iter)->SetSubNetAddress(subnet_address); } if (input_ports_enabled && changed) { SendPollIfAllowed(); } // set for all output ports. uint8_t old_address = m_output_ports[0].universe_address >> 4; if (old_address == subnet_address && !changed) { return true; } subnet_address = subnet_address << 4; for (unsigned int i = 0; i < ARTNET_MAX_PORTS; i++) { m_output_ports[i].universe_address = subnet_address | (m_output_ports[i].universe_address & 0x0f); } return SendPollReplyIfRequired(); } uint8_t ArtNetNodeImpl::InputPortCount() const { return m_input_ports.size(); } bool ArtNetNodeImpl::SetInputPortUniverse(uint8_t port_id, uint8_t universe_id) { InputPort *port = GetInputPort(port_id); if (!port) { return false; } port->enabled = true; if (port->SetUniverseAddress(universe_id)) { SendPollIfAllowed(); return SendPollReplyIfRequired(); } return true; } uint8_t ArtNetNodeImpl::GetInputPortUniverse(uint8_t port_id) const { const InputPort *port = GetInputPort(port_id); return port ? port->PortAddress() : 0; } void ArtNetNodeImpl::DisableInputPort(uint8_t port_id) { InputPort *port = GetInputPort(port_id); bool was_enabled = false; if (port) { was_enabled = port->enabled; port->enabled = false; } if (was_enabled) { SendPollReplyIfRequired(); } } bool ArtNetNodeImpl::InputPortState(uint8_t port_id) const { const InputPort *port = GetInputPort(port_id); return port ? port->enabled : false; } bool ArtNetNodeImpl::SetOutputPortUniverse(uint8_t port_id, uint8_t universe_id) { OutputPort *port = GetOutputPort(port_id); if (!port) { return false; } if (port->enabled && (port->universe_address & 0xf) == (universe_id & 0xf)) { return true; } port->universe_address = ( (universe_id & 0x0f) | (port->universe_address & 0xf0)); port->enabled = true; return SendPollReplyIfRequired(); } uint8_t ArtNetNodeImpl::GetOutputPortUniverse(uint8_t port_id) { OutputPort *port = GetOutputPort(port_id); return port ? port->universe_address : 0; } void ArtNetNodeImpl::DisableOutputPort(uint8_t port_id) { OutputPort *port = GetOutputPort(port_id); if (!port) { return; } bool was_enabled = port->enabled; port->enabled = false; if (was_enabled) { SendPollReplyIfRequired(); } } bool ArtNetNodeImpl::OutputPortState(uint8_t port_id) const { const OutputPort *port = GetOutputPort(port_id); return port ? port->enabled : false; } bool ArtNetNodeImpl::SetMergeMode(uint8_t port_id, artnet_merge_mode merge_mode) { OutputPort *port = GetOutputPort(port_id); if (!port) { return false; } port->merge_mode = merge_mode; return SendPollReplyIfRequired(); } bool ArtNetNodeImpl::SendPoll() { if (!m_running) { return false; } bool send = false; InputPorts::const_iterator iter = m_input_ports.begin(); for (; iter != m_input_ports.end(); ++iter) { send |= (*iter)->enabled; } if (!send) { return true; } OLA_DEBUG << "Sending ArtPoll"; artnet_packet packet; PopulatePacketHeader(&packet, ARTNET_POLL); memset(&packet.data.poll, 0, sizeof(packet.data.poll)); packet.data.poll.version = HostToNetwork(ARTNET_VERSION); // send PollReplies when something changes packet.data.poll.talk_to_me = 0x02; unsigned int size = sizeof(packet.data.poll); return SendPacket(packet, size, m_interface.bcast_address); } bool ArtNetNodeImpl::SendDMX(uint8_t port_id, const DmxBuffer &buffer) { InputPort *port = GetEnabledInputPort(port_id, "ArtDMX"); if (!port) { return false; } if (!buffer.Size()) { OLA_DEBUG << "Not sending 0 length packet"; return true; } artnet_packet packet; PopulatePacketHeader(&packet, ARTNET_DMX); memset(&packet.data.dmx, 0, sizeof(packet.data.dmx)); packet.data.poll.version = HostToNetwork(ARTNET_VERSION); packet.data.dmx.sequence = port->sequence_number; packet.data.dmx.physical = port_id; packet.data.dmx.universe = port->PortAddress(); packet.data.dmx.net = m_net_address; unsigned int buffer_size = buffer.Size(); buffer.Get(packet.data.dmx.data, &buffer_size); // the dmx frame size needs to be a multiple of two, correct here if needed if (buffer_size % 2) { packet.data.dmx.data[buffer_size] = 0; buffer_size++; } packet.data.dmx.length[0] = buffer_size >> 8; packet.data.dmx.length[1] = buffer_size & 0xff; unsigned int size = sizeof(packet.data.dmx) - DMX_UNIVERSE_SIZE + buffer_size; bool sent_ok = false; if (port->subscribed_nodes.size() >= m_broadcast_threshold || m_always_broadcast) { sent_ok = SendPacket( packet, size, m_use_limited_broadcast_address ? IPV4Address::Broadcast() : m_interface.bcast_address); port->sequence_number++; } else { map::iterator iter = port->subscribed_nodes.begin(); TimeStamp last_heard_threshold = ( *m_ss->WakeUpTime() - TimeInterval(NODE_TIMEOUT, 0)); while (iter != port->subscribed_nodes.end()) { // if this node has timed out, remove it from the set if (iter->second < last_heard_threshold) { port->subscribed_nodes.erase(iter++); continue; } sent_ok |= SendPacket(packet, size, iter->first); ++iter; } if (port->subscribed_nodes.empty()) { OLA_DEBUG << "Suppressing data transmit due to no active nodes for " "universe " << static_cast(port->PortAddress()); sent_ok = true; } else { // We sent at least one packet, increment the sequence number port->sequence_number++; } } if (!sent_ok) { OLA_WARN << "Failed to send ArtNet DMX packet"; } return sent_ok; } void ArtNetNodeImpl::RunFullDiscovery(uint8_t port_id, RDMDiscoveryCallback *callback) { InputPort *port = GetEnabledInputPort(port_id, "ArtTodControl"); if (!port) { UIDSet uids; callback->Run(uids); return; } if (!StartDiscoveryProcess(port, callback)) { return; } OLA_DEBUG << "Sending ArtTodControl"; artnet_packet packet; PopulatePacketHeader(&packet, ARTNET_TODCONTROL); memset(&packet.data.tod_control, 0, sizeof(packet.data.tod_control)); packet.data.tod_control.version = HostToNetwork(ARTNET_VERSION); packet.data.tod_control.net = m_net_address; packet.data.tod_control.command = TOD_FLUSH_COMMAND; packet.data.tod_control.address = port->PortAddress(); unsigned int size = sizeof(packet.data.tod_control); if (!SendPacket(packet, size, m_interface.bcast_address)) { port->RunDiscoveryCallback(); } } void ArtNetNodeImpl::RunIncrementalDiscovery( uint8_t port_id, RDMDiscoveryCallback *callback) { InputPort *port = GetEnabledInputPort(port_id, "ArtTodRequest"); if (!port) { UIDSet uids; callback->Run(uids); return; } if (!StartDiscoveryProcess(port, callback)) { return; } OLA_DEBUG << "Sending ArtTodRequest for address " << static_cast(port->PortAddress()); artnet_packet packet; PopulatePacketHeader(&packet, ARTNET_TODREQUEST); memset(&packet.data.tod_request, 0, sizeof(packet.data.tod_request)); packet.data.tod_request.version = HostToNetwork(ARTNET_VERSION); packet.data.tod_request.net = m_net_address; packet.data.tod_request.address_count = 1; // only one universe address packet.data.tod_request.addresses[0] = port->PortAddress(); unsigned int size = sizeof(packet.data.tod_request); if (!SendPacket(packet, size, m_interface.bcast_address)) { port->RunDiscoveryCallback(); } } void ArtNetNodeImpl::SendRDMRequest(uint8_t port_id, RDMRequest *request_ptr, RDMCallback *on_complete) { auto_ptr request(request_ptr); if (request->CommandClass() == RDMCommand::DISCOVER_COMMAND) { RunRDMCallback(on_complete, ola::rdm::RDM_PLUGIN_DISCOVERY_NOT_SUPPORTED); return; } InputPort *port = GetEnabledInputPort(port_id, "ArtRDM"); if (!port) { RunRDMCallback(on_complete, ola::rdm::RDM_FAILED_TO_SEND); return; } if (port->rdm_request_callback) { OLA_FATAL << "Previous request hasn't completed yet, dropping request"; RunRDMCallback(on_complete, ola::rdm::RDM_FAILED_TO_SEND); return; } port->rdm_ip_destination = m_interface.bcast_address; const UID &uid_destination = request->DestinationUID(); uid_map::const_iterator iter = port->uids.find(uid_destination); if (iter == port->uids.end()) { if (!uid_destination.IsBroadcast()) { OLA_WARN << "Couldn't find " << uid_destination << " in the uid map, broadcasting packet"; } } else { port->rdm_ip_destination = iter->second.first; } port->rdm_request_callback = on_complete; port->pending_request = request.release(); bool r = SendRDMCommand(*port->pending_request, port->rdm_ip_destination, port->PortAddress()); if (r && !uid_destination.IsBroadcast()) { port->rdm_send_timeout = m_ss->RegisterSingleTimeout( RDM_REQUEST_TIMEOUT_MS, ola::NewSingleCallback(this, &ArtNetNodeImpl::TimeoutRDMRequest, port)); } else { delete port->pending_request; port->pending_request = NULL; port->rdm_request_callback = NULL; RunRDMCallback( on_complete, uid_destination.IsBroadcast() ? ola::rdm::RDM_WAS_BROADCAST : ola::rdm::RDM_FAILED_TO_SEND); } } bool ArtNetNodeImpl::SetUnsolicitedUIDSetHandler( uint8_t port_id, ola::Callback1 *tod_callback) { InputPort *port = GetInputPort(port_id); if (port) { port->SetTodCallback(tod_callback); } return port; } void ArtNetNodeImpl::GetSubscribedNodes( uint8_t port_id, vector *node_addresses) { InputPort *port = GetInputPort(port_id); if (!port) { return; } map &subscribed_nodes = port->subscribed_nodes; map::const_iterator iter = subscribed_nodes.begin(); for (; iter != subscribed_nodes.end(); ++iter) { TimeStamp last_heard_threshold = ( *m_ss->WakeUpTime() - TimeInterval(NODE_TIMEOUT, 0)); if (iter->second >= last_heard_threshold) { node_addresses->push_back(iter->first); } } } bool ArtNetNodeImpl::SetDMXHandler(uint8_t port_id, DmxBuffer *buffer, Callback0 *on_data) { OutputPort *port = GetOutputPort(port_id); if (!port) { return false; } if (port->on_data) { delete m_output_ports[port_id].on_data; } port->buffer = buffer; port->on_data = on_data; return true; } bool ArtNetNodeImpl::SendTod(uint8_t port_id, const UIDSet &uid_set) { OutputPort *port = GetEnabledOutputPort(port_id, "ArtTodData"); if (!port) { return false; } OLA_DEBUG << "Sending ArtTodRequest"; artnet_packet packet; PopulatePacketHeader(&packet, ARTNET_TODDATA); memset(&packet.data.tod_data, 0, sizeof(packet.data.tod_data)); packet.data.tod_data.version = HostToNetwork(ARTNET_VERSION); packet.data.tod_data.rdm_version = RDM_VERSION; packet.data.tod_data.port = 1 + port_id; packet.data.tod_request.net = m_net_address; packet.data.tod_data.address = port->universe_address; uint16_t uids = std::min(uid_set.Size(), (unsigned int) MAX_UIDS_PER_UNIVERSE); packet.data.tod_data.uid_total = HostToNetwork(uids); packet.data.tod_data.uid_count = ARTNET_MAX_UID_COUNT; uint8_t (*ptr)[ola::rdm::UID::UID_SIZE] = packet.data.tod_data.tod; unsigned int i = 0; UIDSet::Iterator iter = uid_set.Begin(); while (iter != uid_set.End()) { iter->Pack(*ptr, ola::rdm::UID::UID_SIZE); i++; iter++; if (i % ARTNET_MAX_UID_COUNT == 0) { packet.data.tod_data.block_count = i / ARTNET_MAX_UID_COUNT - 1; SendPacket(packet, sizeof(packet.data.tod_data), m_interface.bcast_address); ptr = packet.data.tod_data.tod; } else { ptr++; } } if (i == 0 || i % ARTNET_MAX_UID_COUNT) { packet.data.tod_data.uid_count = i % ARTNET_MAX_UID_COUNT; packet.data.tod_data.block_count = i / ARTNET_MAX_UID_COUNT; unsigned int size = sizeof(packet.data.tod_data) - sizeof(packet.data.tod_data.tod) + i * ola::rdm::UID::UID_SIZE; SendPacket(packet, size, m_interface.bcast_address); } return true; } bool ArtNetNodeImpl::SetOutputPortRDMHandlers( uint8_t port_id, ola::Callback0 *on_discover, ola::Callback0 *on_flush, ola::Callback2 *on_rdm_request) { OutputPort *port = GetOutputPort(port_id); if (!port) { return false; } if (port->on_discover) { delete port->on_discover; } if (port->on_flush) { delete port->on_flush; } if (port->on_rdm_request) { delete port->on_rdm_request; } port->on_discover = on_discover; port->on_flush = on_flush; port->on_rdm_request = on_rdm_request; return true; } bool ArtNetNodeImpl::SendTimeCode(const ola::timecode::TimeCode &timecode) { artnet_packet packet; PopulatePacketHeader(&packet, ARTNET_TIME_CODE); memset(&packet.data.timecode, 0, sizeof(packet.data.timecode)); packet.data.timecode.version = HostToNetwork(ARTNET_VERSION); packet.data.timecode.frames = timecode.Frames(); packet.data.timecode.seconds = timecode.Seconds(); packet.data.timecode.minutes = timecode.Minutes(); packet.data.timecode.hours = timecode.Hours(); packet.data.timecode.type = timecode.Type(); if (!SendPacket(packet, sizeof(packet.data.timecode), m_interface.bcast_address)) { OLA_INFO << "Failed to send ArtTimeCode"; return false; } return true; } void ArtNetNodeImpl::SocketReady() { artnet_packet packet; ssize_t packet_size = sizeof(packet); ola::network::IPV4SocketAddress source; if (!m_socket->RecvFrom(reinterpret_cast(&packet), &packet_size, &source)) { return; } HandlePacket(source.Host(), packet, packet_size); } bool ArtNetNodeImpl::SendPollIfAllowed() { if (!m_running) { return true; } if (m_in_configuration_mode) { m_artpoll_required = true; } else { return SendPoll(); } return true; } bool ArtNetNodeImpl::SendPollReplyIfRequired() { if (m_running && m_send_reply_on_change) { if (m_in_configuration_mode) { m_artpollreply_required = true; } else { m_unsolicited_replies++; return SendPollReply(m_interface.bcast_address); } } return true; } bool ArtNetNodeImpl::SendPollReply(const IPV4Address &destination) { artnet_packet packet; PopulatePacketHeader(&packet, ARTNET_REPLY); memset(&packet.data.reply, 0, sizeof(packet.data.reply)); m_interface.ip_address.Get(packet.data.reply.ip); packet.data.reply.port = HostToLittleEndian(ARTNET_PORT); packet.data.reply.net_address = m_net_address; packet.data.reply.subnet_address = m_output_ports[0].universe_address >> 4; packet.data.reply.oem = HostToNetwork(OEM_CODE); packet.data.reply.status1 = 0xd2; // normal indicators, rdm enabled packet.data.reply.esta_id = HostToLittleEndian(OPEN_LIGHTING_ESTA_CODE); strings::StrNCopy(packet.data.reply.short_name, m_short_name.data()); strings::StrNCopy(packet.data.reply.long_name, m_long_name.data()); std::ostringstream str; str << "#0001 [" << m_unsolicited_replies << "] OLA"; CopyToFixedLengthBuffer(str.str(), packet.data.reply.node_report, arraysize(packet.data.reply.node_report)); packet.data.reply.number_ports[1] = ARTNET_MAX_PORTS; for (unsigned int i = 0; i < ARTNET_MAX_PORTS; i++) { InputPort *iport = GetInputPort(i, false); packet.data.reply.port_types[i] = iport ? 0xc0 : 0x80; packet.data.reply.good_input[i] = iport && iport->enabled ? 0x0 : 0x8; packet.data.reply.sw_in[i] = iport ? iport->PortAddress() : 0; packet.data.reply.good_output[i] = ( (m_output_ports[i].enabled ? 0x80 : 0x00) | (m_output_ports[i].merge_mode == ARTNET_MERGE_LTP ? 0x2 : 0x0) | (m_output_ports[i].is_merging ? 0x8 : 0x0)); packet.data.reply.sw_out[i] = m_output_ports[i].universe_address; } packet.data.reply.style = NODE_CODE; m_interface.hw_address.Get(packet.data.reply.mac); m_interface.ip_address.Get(packet.data.reply.bind_ip); // maybe set status2 here if the web UI is enabled packet.data.reply.status2 = 0x08; // node supports 15 bit port addresses if (!SendPacket(packet, sizeof(packet.data.reply), destination)) { OLA_INFO << "Failed to send ArtPollReply"; return false; } return true; } bool ArtNetNodeImpl::SendIPReply(const IPV4Address &destination) { artnet_packet packet; PopulatePacketHeader(&packet, ARTNET_REPLY); memset(&packet.data.ip_reply, 0, sizeof(packet.data.ip_reply)); packet.data.ip_reply.version = HostToNetwork(ARTNET_VERSION); m_interface.ip_address.Get(packet.data.ip_reply.ip); m_interface.subnet_mask.Get(packet.data.ip_reply.subnet); packet.data.ip_reply.port = HostToLittleEndian(ARTNET_PORT); if (!SendPacket(packet, sizeof(packet.data.ip_reply), destination)) { OLA_INFO << "Failed to send ArtIpProgReply"; return false; } return true; } void ArtNetNodeImpl::HandlePacket(const IPV4Address &source_address, const artnet_packet &packet, unsigned int packet_size) { unsigned int header_size = sizeof(packet) - sizeof(packet.data); if (packet_size <= header_size) { OLA_WARN << "Skipping small artnet packet received, size=" << packet_size; return; } switch (LittleEndianToHost(packet.op_code)) { case ARTNET_POLL: HandlePollPacket(source_address, packet.data.poll, packet_size - header_size); break; case ARTNET_REPLY: HandleReplyPacket(source_address, packet.data.reply, packet_size - header_size); break; case ARTNET_DMX: HandleDataPacket(source_address, packet.data.dmx, packet_size - header_size); break; case ARTNET_TODREQUEST: HandleTodRequest(source_address, packet.data.tod_request, packet_size - header_size); break; case ARTNET_TODDATA: HandleTodData(source_address, packet.data.tod_data, packet_size - header_size); break; case ARTNET_TODCONTROL: HandleTodControl(source_address, packet.data.tod_control, packet_size - header_size); break; case ARTNET_RDM: HandleRdm(source_address, packet.data.rdm, packet_size - header_size); break; case ARTNET_IP_PROGRAM: HandleIPProgram(source_address, packet.data.ip_program, packet_size - header_size); break; case ARTNET_RDM_SUB: // Not implemented break; case ARTNET_TIME_CODE: // Not implemented break; default: OLA_INFO << "ArtNet got unknown packet " << std::hex << LittleEndianToHost(packet.op_code); } } void ArtNetNodeImpl::HandlePollPacket(const IPV4Address &source_address, const artnet_poll_t &packet, unsigned int packet_size) { if (!CheckPacketSize(source_address, "ArtPoll", packet_size, sizeof(packet))) { return; } if (!CheckPacketVersion(source_address, "ArtPoll", packet.version)) { return; } m_send_reply_on_change = packet.talk_to_me & 0x02; // It's unclear if this should be broadcast or unicast, stick with broadcast SendPollReply(m_interface.bcast_address); (void) source_address; } void ArtNetNodeImpl::HandleReplyPacket(const IPV4Address &source_address, const artnet_reply_t &packet, unsigned int packet_size) { if (m_interface.ip_address == source_address) { return; } // Older versions don't have the bind_ip and the extra filler, make sure we // support these unsigned int minimum_reply_size = ( sizeof(packet) - sizeof(packet.filler) - sizeof(packet.status2) - sizeof(packet.bind_index) - sizeof(packet.bind_ip)); if (!CheckPacketSize(source_address, "ArtPollReply", packet_size, minimum_reply_size)) { return; } if (packet.net_address != m_net_address) { OLA_DEBUG << "Received ArtPollReply for net " << static_cast(packet.net_address) << " which doesn't match our net address " << static_cast(m_net_address) << ", discarding"; return; } // Update the subscribed nodes list unsigned int port_limit = std::min((uint8_t) ARTNET_MAX_PORTS, packet.number_ports[1]); for (unsigned int i = 0; i < port_limit; i++) { if (packet.port_types[i] & 0x80) { // port is of type output uint8_t universe_id = packet.sw_out[i]; InputPorts::iterator iter = m_input_ports.begin(); for (; iter != m_input_ports.end(); ++iter) { if ((*iter)->enabled && (*iter)->PortAddress() == universe_id) { STLReplace(&(*iter)->subscribed_nodes, source_address, *m_ss->WakeUpTime()); } } } } } void ArtNetNodeImpl::HandleDataPacket(const IPV4Address &source_address, const artnet_dmx_t &packet, unsigned int packet_size) { // The data section needs to be at least 2 bytes according to the spec unsigned int header_size = sizeof(artnet_dmx_t) - DMX_UNIVERSE_SIZE; if (!CheckPacketSize(source_address, "ArtDmx", packet_size, header_size + 2)) { return; } if (!CheckPacketVersion(source_address, "ArtDmx", packet.version)) { return; } if (packet.net != m_net_address) { OLA_DEBUG << "Received ArtDmx for net " << static_cast(packet.net) << " which doesn't match our net address " << static_cast(m_net_address) << ", discarding"; return; } uint16_t universe_id = LittleEndianToHost(packet.universe); uint16_t data_size = std::min( (unsigned int) ((packet.length[0] << 8) + packet.length[1]), packet_size - header_size); for (unsigned int port_id = 0; port_id < ARTNET_MAX_PORTS; port_id++) { if (m_output_ports[port_id].enabled && m_output_ports[port_id].universe_address == universe_id && m_output_ports[port_id].on_data && m_output_ports[port_id].buffer) { // update this port, doing a merge if necessary DMXSource source; source.address = source_address; source.timestamp = *m_ss->WakeUpTime(); source.buffer.Set(packet.data, data_size); UpdatePortFromSource(&m_output_ports[port_id], source); } } } void ArtNetNodeImpl::HandleTodRequest(const IPV4Address &source_address, const artnet_todrequest_t &packet, unsigned int packet_size) { unsigned int header_size = sizeof(packet) - sizeof(packet.addresses); if (!CheckPacketSize(source_address, "ArtTodRequest", packet_size, header_size)) { return; } if (!CheckPacketVersion(source_address, "ArtTodRequest", packet.version)) { return; } if (packet.net != m_net_address) { OLA_DEBUG << "Received ArtTodRequest for net " << static_cast(packet.net) << " which doesn't match our net address " << static_cast(m_net_address) << ", discarding"; return; } if (packet.command) { OLA_INFO << "ArtTodRequest received but command field was " << static_cast(packet.command); return; } unsigned int addresses = std::min( packet_size - header_size, static_cast(packet.address_count)); addresses = std::min( static_cast(ARTNET_MAX_RDM_ADDRESS_COUNT), addresses); bool handler_called[ARTNET_MAX_PORTS]; memset(handler_called, 0, sizeof(handler_called)); for (unsigned int i = 0; i < addresses; i++) { for (unsigned int port_id = 0; port_id < ARTNET_MAX_PORTS; port_id++) { if (m_output_ports[port_id].enabled && m_output_ports[port_id].universe_address == packet.addresses[i] && m_output_ports[port_id].on_discover && !handler_called[port_id]) { m_output_ports[port_id].on_discover->Run(); handler_called[port_id] = true; } } } } void ArtNetNodeImpl::HandleTodData(const IPV4Address &source_address, const artnet_toddata_t &packet, unsigned int packet_size) { unsigned int expected_size = sizeof(packet) - sizeof(packet.tod); if (!CheckPacketSize(source_address, "ArtTodData", packet_size, expected_size)) { return; } if (!CheckPacketVersion(source_address, "ArtTodData", packet.version)) { return; } if (packet.rdm_version != RDM_VERSION) { OLA_WARN << "Dropping non standard RDM version: " << static_cast(packet.rdm_version); return; } if (packet.net != m_net_address) { OLA_DEBUG << "Received ArtTodData for net " << static_cast(packet.net) << " which doesn't match our net address " << static_cast(m_net_address) << ", discarding"; return; } if (packet.command_response) { OLA_WARN << "Command response " << ToHex(packet.command_response) << " != 0x0"; return; } InputPorts::iterator iter = m_input_ports.begin(); for (; iter != m_input_ports.end(); ++iter) { if ((*iter)->enabled && (*iter)->PortAddress() == packet.address) { UpdatePortFromTodPacket(*iter, source_address, packet, packet_size); } } } void ArtNetNodeImpl::HandleTodControl(const IPV4Address &source_address, const artnet_todcontrol_t &packet, unsigned int packet_size) { if (!CheckPacketSize(source_address, "ArtTodControl", packet_size, sizeof(packet))) { return; } if (!CheckPacketVersion(source_address, "ArtTodControl", packet.version)) { return; } if (packet.net != m_net_address) { OLA_DEBUG << "Received ArtTodControl for net " << static_cast(packet.net) << " which doesn't match our net address " << static_cast(m_net_address) << ", discarding"; return; } if (packet.command != TOD_FLUSH_COMMAND) { return; } for (unsigned int port_id = 0; port_id < ARTNET_MAX_PORTS; port_id++) { if (m_output_ports[port_id].enabled && m_output_ports[port_id].universe_address == packet.address && m_output_ports[port_id].on_flush) { m_output_ports[port_id].on_flush->Run(); } } } void ArtNetNodeImpl::HandleRdm(const IPV4Address &source_address, const artnet_rdm_t &packet, unsigned int packet_size) { unsigned int header_size = sizeof(packet) - ARTNET_MAX_RDM_DATA; if (!CheckPacketSize(source_address, "ArtRDM", packet_size, header_size)) { return; } if (!CheckPacketVersion(source_address, "ArtRDM", packet.version)) { return; } if (packet.rdm_version != RDM_VERSION) { OLA_INFO << "Dropping non standard RDM version: " << static_cast(packet.rdm_version); return; } if (packet.command) { OLA_WARN << "Unknown RDM command " << static_cast(packet.command); return; } if (packet.net != m_net_address) { OLA_DEBUG << "Received ArtRDM for net " << static_cast(packet.net) << " which doesn't match our net address " << static_cast(m_net_address) << ", discarding"; return; } unsigned int rdm_length = packet_size - header_size; if (!rdm_length) { return; } // look for the port that this was sent to, once we know the port we can try // to parse the message for (uint8_t port_id = 0; port_id < ARTNET_MAX_PORTS; port_id++) { if (m_output_ports[port_id].enabled && m_output_ports[port_id].universe_address == packet.address && m_output_ports[port_id].on_rdm_request) { RDMRequest *request = RDMRequest::InflateFromData(packet.data, rdm_length); if (request) { m_output_ports[port_id].on_rdm_request->Run( request, NewSingleCallback(this, &ArtNetNodeImpl::RDMRequestCompletion, source_address, port_id, m_output_ports[port_id].universe_address)); } } } // The ArtNet packet does not include the RDM start code. Prepend that. RDMFrame rdm_response(packet.data, rdm_length, RDMFrame::Options(true)); InputPorts::iterator iter = m_input_ports.begin(); for (; iter != m_input_ports.end(); ++iter) { if ((*iter)->enabled && (*iter)->PortAddress() == packet.address) { HandleRDMResponse(*iter, rdm_response, source_address); } } } void ArtNetNodeImpl::RDMRequestCompletion( IPV4Address destination, uint8_t port_id, uint8_t universe_address, RDMReply *reply) { OutputPort *port = GetEnabledOutputPort(port_id, "ArtRDM"); if (!port) { return; } if (port->universe_address == universe_address) { if (reply->StatusCode() == ola::rdm::RDM_COMPLETED_OK) { // TODO(simon): handle fragmenation here SendRDMCommand(*reply->Response(), destination, universe_address); } else if (reply->StatusCode() == ola::rdm::RDM_UNKNOWN_UID) { // call the on discovery handler, which will send a new TOD and // hopefully update the remote controller port->on_discover->Run(); } else { OLA_WARN << "ArtNet RDM request failed with code " << reply->StatusCode(); } } else { // the universe address has changed we need to drop this request OLA_WARN << "ArtNet Output port has changed mid request, dropping response"; } } void ArtNetNodeImpl::HandleRDMResponse(InputPort *port, const RDMFrame &frame, const IPV4Address &source_address) { auto_ptr reply(ola::rdm::RDMReply::FromFrame(frame)); // Without a valid response, we don't know which request this matches. This // makes ArtNet rather useless for RDM regression testing if (!reply->Response()) { return; } if (!port->pending_request) { return; } const RDMRequest *request = port->pending_request; if (request->SourceUID() != reply->Response()->DestinationUID() || request->DestinationUID() != reply->Response()->SourceUID()) { OLA_INFO << "Got response from/to unexpected UID: req " << request->SourceUID() << " -> " << request->DestinationUID() << ", res " << reply->Response()->SourceUID() << " -> " << reply->Response()->DestinationUID(); return; } if (request->ParamId() != ola::rdm::PID_QUEUED_MESSAGE && request->ParamId() != reply->Response()->ParamId()) { OLA_INFO << "Param ID mismatch, request was " << ToHex(request->ParamId()) << ", response was " << ToHex(reply->Response()->ParamId()); return; } if (request->ParamId() != ola::rdm::PID_QUEUED_MESSAGE && request->SubDevice() != ola::rdm::ALL_RDM_SUBDEVICES && request->SubDevice() != reply->Response()->SubDevice()) { OLA_INFO << "Subdevice mismatch, request was for" << request->SubDevice() << ", response was " << reply->Response()->SubDevice(); return; } if (request->CommandClass() == RDMCommand::GET_COMMAND && reply->Response()->CommandClass() != RDMCommand::GET_COMMAND_RESPONSE && request->ParamId() != ola::rdm::PID_QUEUED_MESSAGE) { OLA_INFO << "Invalid return CC in response to get, was " << ToHex(reply->Response()->CommandClass()); return; } if (request->CommandClass() == RDMCommand::SET_COMMAND && reply->Response()->CommandClass() != RDMCommand::SET_COMMAND_RESPONSE) { OLA_INFO << "Invalid return CC in response to set, was " << ToHex(reply->Response()->CommandClass()); return; } if (port->rdm_ip_destination != m_interface.bcast_address && port->rdm_ip_destination != source_address) { OLA_INFO << "IP address of RDM response didn't match"; return; } // at this point we've decided it's for us port->pending_request = NULL; delete request; RDMCallback *callback = port->rdm_request_callback; port->rdm_request_callback = NULL; // remove the timeout if (port->rdm_send_timeout != ola::thread::INVALID_TIMEOUT) { m_ss->RemoveTimeout(port->rdm_send_timeout); port->rdm_send_timeout = ola::thread::INVALID_TIMEOUT; } callback->Run(reply.get()); } void ArtNetNodeImpl::HandleIPProgram(const IPV4Address &source_address, const artnet_ip_prog_t &packet, unsigned int packet_size) { if (!CheckPacketSize(source_address, "ArtIpProg", packet_size, sizeof(packet))) { return; } if (!CheckPacketVersion(source_address, "ArtIpProg", packet.version)) { return; } OLA_INFO << "Got ArtIpProgram, ignoring because we don't support remote " << "configuration"; } void ArtNetNodeImpl::PopulatePacketHeader(artnet_packet *packet, uint16_t op_code) { CopyToFixedLengthBuffer(ARTNET_ID, reinterpret_cast(packet->id), arraysize(packet->id)); packet->op_code = HostToLittleEndian(op_code); } bool ArtNetNodeImpl::SendPacket(const artnet_packet &packet, unsigned int size, const IPV4Address &ip_destination) { size += sizeof(packet.id) + sizeof(packet.op_code); unsigned int bytes_sent = m_socket->SendTo( reinterpret_cast(&packet), size, IPV4SocketAddress(ip_destination, ARTNET_PORT)); if (bytes_sent != size) { OLA_INFO << "Only sent " << bytes_sent << " of " << size; return false; } return true; } void ArtNetNodeImpl::TimeoutRDMRequest(InputPort *port) { OLA_INFO << "RDM Request timed out."; port->rdm_send_timeout = ola::thread::INVALID_TIMEOUT; delete port->pending_request; port->pending_request = NULL; RDMCallback *callback = port->rdm_request_callback; port->rdm_request_callback = NULL; RunRDMCallback(callback, ola::rdm::RDM_TIMEOUT); } bool ArtNetNodeImpl::SendRDMCommand(const RDMCommand &command, const IPV4Address &destination, uint8_t universe) { artnet_packet packet; PopulatePacketHeader(&packet, ARTNET_RDM); memset(&packet.data.rdm, 0, sizeof(packet.data.rdm)); packet.data.rdm.version = HostToNetwork(ARTNET_VERSION); packet.data.rdm.rdm_version = RDM_VERSION; packet.data.rdm.net = m_net_address; packet.data.rdm.address = universe; unsigned int rdm_size = ARTNET_MAX_RDM_DATA; if (!RDMCommandSerializer::Pack(command, packet.data.rdm.data, &rdm_size)) { OLA_WARN << "Failed to construct RDM command"; return false; } unsigned int packet_size = sizeof(packet.data.rdm) - ARTNET_MAX_RDM_DATA + rdm_size; return SendPacket(packet, packet_size, destination); } void ArtNetNodeImpl::UpdatePortFromSource(OutputPort *port, const DMXSource &source) { TimeStamp merge_time_threshold = ( *m_ss->WakeUpTime() - TimeInterval(MERGE_TIMEOUT, 0)); // the index of the first empty slot, of MAX_MERGE_SOURCES if we're already // tracking MAX_MERGE_SOURCES sources. unsigned int first_empty_slot = MAX_MERGE_SOURCES; // the index for this source, or MAX_MERGE_SOURCES if it wasn't found unsigned int source_slot = MAX_MERGE_SOURCES; unsigned int active_sources = 0; // locate the source within the list of tracked sources, also find the first // empty source location in case this source is new, and timeout any sources // we haven't heard from. for (unsigned int i = 0; i < MAX_MERGE_SOURCES; i++) { if (port->sources[i].address == source.address) { source_slot = i; continue; } // timeout old sources if (port->sources[i].timestamp < merge_time_threshold) { port->sources[i].address = IPV4Address(); } if (!port->sources[i].address.IsWildcard()) { active_sources++; } else if (i < first_empty_slot) { first_empty_slot = i; } } if (source_slot == MAX_MERGE_SOURCES) { // this is a new source if (first_empty_slot == MAX_MERGE_SOURCES) { // No room at the inn OLA_WARN << "Max merge sources reached, ignoring"; return; } if (active_sources == 0) { port->is_merging = false; } else { OLA_INFO << "Entered merge mode for universe " << static_cast(port->universe_address); port->is_merging = true; SendPollReplyIfRequired(); } source_slot = first_empty_slot; } else if (active_sources == 1) { port->is_merging = false; } port->sources[source_slot] = source; // Now we need to merge if (port->merge_mode == ARTNET_MERGE_LTP) { // the current source is the latest (*port->buffer) = source.buffer; } else { // HTP merge bool first = true; for (unsigned int i = 0; i < MAX_MERGE_SOURCES; i++) { if (!port->sources[i].address.IsWildcard()) { if (first) { (*port->buffer) = port->sources[i].buffer; first = false; } else { port->buffer->HTPMerge(port->sources[i].buffer); } } } } port->on_data->Run(); } bool ArtNetNodeImpl::CheckPacketVersion(const IPV4Address &source_address, const string &packet_type, uint16_t version) { if (NetworkToHost(version) != ARTNET_VERSION) { OLA_INFO << packet_type << " version mismatch, was " << NetworkToHost(version) << " from " << source_address; return false; } return true; } bool ArtNetNodeImpl::CheckPacketSize(const IPV4Address &source_address, const string &packet_type, unsigned int actual_size, unsigned int expected_size) { if (actual_size < expected_size) { OLA_INFO << packet_type << " from " << source_address << " was too small, got " << actual_size << " required at least " << expected_size; return false; } return true; } ArtNetNodeImpl::InputPort *ArtNetNodeImpl::GetInputPort(uint8_t port_id, bool warn) { if (port_id >= m_input_ports.size()) { if (warn) { OLA_WARN << "Port index of out bounds: " << static_cast(port_id) << " >= " << m_input_ports.size(); } return NULL; } return m_input_ports[port_id]; } const ArtNetNodeImpl::InputPort *ArtNetNodeImpl::GetInputPort( uint8_t port_id) const { if (port_id >= m_input_ports.size()) { OLA_WARN << "Port index of out bounds: " << static_cast(port_id) << " >= " << m_input_ports.size(); return NULL; } return m_input_ports[port_id]; } ArtNetNodeImpl::InputPort *ArtNetNodeImpl::GetEnabledInputPort( uint8_t port_id, const string &action) { if (!m_running) { return NULL; } InputPort *port = GetInputPort(port_id); bool ok = port ? port->enabled : false; if (!ok) { OLA_INFO << "Attempt to send " << action << " on an inactive port"; } return ok ? port : NULL; } ArtNetNodeImpl::OutputPort *ArtNetNodeImpl::GetOutputPort(uint8_t port_id) { if (port_id >= ARTNET_MAX_PORTS) { OLA_WARN << "Port index of out bounds: " << static_cast(port_id) << " >= " << ARTNET_MAX_PORTS; return NULL; } return &m_output_ports[port_id]; } const ArtNetNodeImpl::OutputPort *ArtNetNodeImpl::GetOutputPort( uint8_t port_id) const { if (port_id >= ARTNET_MAX_PORTS) { OLA_WARN << "Port index of out bounds: " << static_cast(port_id) << " >= " << ARTNET_MAX_PORTS; return NULL; } return &m_output_ports[port_id]; } ArtNetNodeImpl::OutputPort *ArtNetNodeImpl::GetEnabledOutputPort( uint8_t port_id, const string &action) { if (!m_running) { return NULL; } OutputPort *port = GetOutputPort(port_id); bool ok = port ? port->enabled : false; if (!ok) { OLA_INFO << "Attempt to send " << action << " on an inactive port"; } return ok ? port : NULL; } bool ArtNetNodeImpl::InitNetwork() { if (!m_socket->Init()) { OLA_WARN << "Socket init failed"; return false; } if (!m_socket->Bind(IPV4SocketAddress(IPV4Address::WildCard(), ARTNET_PORT))) { return false; } if (!m_socket->EnableBroadcast()) { OLA_WARN << "Failed to enable broadcasting"; return false; } m_socket->SetOnData(NewCallback(this, &ArtNetNodeImpl::SocketReady)); m_ss->AddReadDescriptor(m_socket.get()); return true; } void ArtNetNodeImpl::UpdatePortFromTodPacket(InputPort *port, const IPV4Address &source_address, const artnet_toddata_t &packet, unsigned int packet_size) { unsigned int tod_size = packet_size - (sizeof(packet) - sizeof(packet.tod)); unsigned int uid_count = std::min(tod_size / ola::rdm::UID::UID_SIZE, (unsigned int) packet.uid_count); OLA_DEBUG << "Got TOD data packet with " << uid_count << " UIDs"; uid_map &port_uids = port->uids; UIDSet uid_set; for (unsigned int i = 0; i < uid_count; i++) { UID uid(packet.tod[i]); uid_set.AddUID(uid); uid_map::iterator iter = port_uids.find(uid); if (iter == port_uids.end()) { port_uids[uid] = std::pair(source_address, 0); } else { if (iter->second.first != source_address) { OLA_WARN << "UID " << uid << " changed from " << iter->second.first << " to " << source_address; iter->second.first = source_address; } iter->second.second = 0; } } // If this is the one and only block from this node, we can remove all uids // that don't appear in it. // There is a bug in ArtNet nodes where sometimes UidCount > UidTotal. if (uid_count >= NetworkToHost(packet.uid_total)) { uid_map::iterator iter = port_uids.begin(); while (iter != port_uids.end()) { if (iter->second.first == source_address && !uid_set.Contains(iter->first)) { port_uids.erase(iter++); } else { ++iter; } } // mark this node as complete if (port->discovery_node_set.erase(source_address)) { // if the set is now 0, and it was non-0 initally and we have a // discovery_callback, then we can short circuit the discovery // process if (port->discovery_node_set.empty() && port->discovery_callback) { m_ss->RemoveTimeout(port->discovery_timeout); ReleaseDiscoveryLock(port); } } } // Removing uids from multi-block messages is much harder as you need to // consider dropped packets. For the moment we rely on the // RDM_MISSED_TODDATA_LIMIT to clean these up. // TODO(simon): figure this out sometime // if we're not in the middle of a discovery process, send an unsolicited // update if we have a callback if (!port->discovery_callback) port->RunTodCallback(); } bool ArtNetNodeImpl::StartDiscoveryProcess(InputPort *port, RDMDiscoveryCallback *callback) { if (port->discovery_callback) { OLA_FATAL << "ArtNet UID discovery already running, something has gone " "wrong with the DiscoverableQueueingRDMController."; port->RunTodCallback(); return false; } port->discovery_callback = callback; port->IncrementUIDCounts(); // populate the discovery set with the nodes we know about, this allows us to // 'finish' the discovery process when we receive ArtTod packets from all // these nodes. If ArtTod packets arrive after discovery completes, we'll // call the unsolicited handler port->discovery_node_set.clear(); map::const_iterator node_iter = port->subscribed_nodes.begin(); for (; node_iter != port->subscribed_nodes.end(); node_iter++) port->discovery_node_set.insert(node_iter->first); port->discovery_timeout = m_ss->RegisterSingleTimeout( RDM_TOD_TIMEOUT_MS, ola::NewSingleCallback(this, &ArtNetNodeImpl::ReleaseDiscoveryLock, port)); return true; } void ArtNetNodeImpl::ReleaseDiscoveryLock(InputPort *port) { OLA_INFO << "Artnet RDM discovery complete"; port->discovery_timeout = ola::thread::INVALID_TIMEOUT; port->discovery_node_set.clear(); // delete all uids that have reached the max count uid_map::iterator iter = port->uids.begin(); while (iter != port->uids.end()) { if (iter->second.second == RDM_MISSED_TODDATA_LIMIT) { port->uids.erase(iter++); } else { ++iter; } } port->RunDiscoveryCallback(); } ArtNetNode::ArtNetNode(const ola::network::Interface &iface, ola::io::SelectServerInterface *ss, const ArtNetNodeOptions &options, ola::network::UDPSocketInterface *socket): m_impl(iface, ss, options, socket) { for (unsigned int i = 0; i < options.input_port_count; i++) { ArtNetNodeImplRDMWrapper *wrapper = new ArtNetNodeImplRDMWrapper(&m_impl, i); m_wrappers.push_back(wrapper); m_controllers.push_back(new ola::rdm::DiscoverableQueueingRDMController( wrapper, options.rdm_queue_size)); } } ArtNetNode::~ArtNetNode() { STLDeleteElements(&m_controllers); STLDeleteElements(&m_wrappers); } void ArtNetNode::RunFullDiscovery(uint8_t port_id, RDMDiscoveryCallback *callback) { if (!CheckInputPortId(port_id)) { ola::rdm::UIDSet uids; callback->Run(uids); } else { m_controllers[port_id]->RunFullDiscovery(callback); } } void ArtNetNode::RunIncrementalDiscovery(uint8_t port_id, RDMDiscoveryCallback *callback) { if (!CheckInputPortId(port_id)) { ola::rdm::UIDSet uids; callback->Run(uids); } else { m_controllers[port_id]->RunIncrementalDiscovery(callback); } } void ArtNetNode::SendRDMRequest(uint8_t port_id, RDMRequest *request, RDMCallback *on_complete) { if (!CheckInputPortId(port_id)) { RunRDMCallback(on_complete, ola::rdm::RDM_FAILED_TO_SEND); delete request; } else { m_controllers[port_id]->SendRDMRequest(request, on_complete); } } bool ArtNetNode::CheckInputPortId(uint8_t port_id) { if (port_id >= m_controllers.size()) { OLA_WARN << "Port index of out bounds: " << static_cast(port_id) << " >= " << m_controllers.size(); return false; } return true; } } // namespace artnet } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/artnet/ArtNetPort.cpp0000644000175000017500000001254413023355232021210 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ArtNetPort.cpp * The ArtNet plugin for ola * Copyright (C) 2005 Simon Newton */ #include #include #include #include "ola/Logging.h" #include "olad/Universe.h" #include "plugins/artnet/ArtNetDevice.h" #include "plugins/artnet/ArtNetPort.h" namespace ola { namespace plugin { namespace artnet { using ola::NewCallback; using ola::rdm::RDMCommand; using std::string; using std::vector; namespace { static const uint8_t ARTNET_UNIVERSE_COUNT = 16; }; // namespace void ArtNetInputPort::PostSetUniverse(Universe *old_universe, Universe *new_universe) { if (new_universe) { m_node->SetOutputPortUniverse( PortId(), new_universe->UniverseId() % ARTNET_UNIVERSE_COUNT); } else { m_node->DisableOutputPort(PortId()); } if (new_universe && !old_universe) { m_node->SetDMXHandler( PortId(), &m_buffer, NewCallback(static_cast(this), &ArtNetInputPort::DmxChanged)); m_node->SetOutputPortRDMHandlers( PortId(), NewCallback( this, &ArtNetInputPort::RespondWithTod), NewCallback( this, &ArtNetInputPort::TriggerDiscovery), ola::NewCallback( static_cast(this), &ArtNetInputPort::HandleRDMRequest)); } else if (!new_universe) { m_node->SetDMXHandler(PortId(), NULL, NULL); m_node->SetOutputPortRDMHandlers(PortId(), NULL, NULL, NULL); } if (new_universe) { TriggerRDMDiscovery( NewSingleCallback(this, &ArtNetInputPort::SendTODWithUIDs)); } } void ArtNetInputPort::RespondWithTod() { ola::rdm::UIDSet uids; if (GetUniverse()) { GetUniverse()->GetUIDs(&uids); } SendTODWithUIDs(uids); } string ArtNetInputPort::Description() const { if (!GetUniverse()) { return ""; } std::ostringstream str; str << "ArtNet Universe " << static_cast(m_node->NetAddress()) << ":" << static_cast(m_node->SubnetAddress()) << ":" << static_cast(m_node->GetOutputPortUniverse(PortId())); return str.str(); } void ArtNetInputPort::SendTODWithUIDs(const ola::rdm::UIDSet &uids) { m_node->SendTod(PortId(), uids); } void ArtNetInputPort::TriggerDiscovery() { TriggerRDMDiscovery( NewSingleCallback(this, &ArtNetInputPort::SendTODWithUIDs)); } bool ArtNetOutputPort::WriteDMX(const DmxBuffer &buffer, OLA_UNUSED uint8_t priority) { if (PortId() >= ARTNET_MAX_PORTS) { OLA_WARN << "Invalid artnet port id " << PortId(); return false; } return m_node->SendDMX(PortId(), buffer); } void ArtNetOutputPort::SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *on_complete) { // Discovery requests aren't proxied if (request->CommandClass() == RDMCommand::DISCOVER_COMMAND) { OLA_WARN << "Blocked attempt to send discovery command via Artnet"; ola::rdm::RunRDMCallback(on_complete, ola::rdm::RDM_PLUGIN_DISCOVERY_NOT_SUPPORTED); delete request; } else { m_node->SendRDMRequest(PortId(), request, on_complete); } } void ArtNetOutputPort::RunFullDiscovery( ola::rdm::RDMDiscoveryCallback *callback) { m_node->RunFullDiscovery(PortId(), callback); } void ArtNetOutputPort::RunIncrementalDiscovery( ola::rdm::RDMDiscoveryCallback *callback) { // ArtNet nodes seem to run incremental discovery in the background. The // protocol doesn't provide a way of triggering incremental discovery so we // just do a full flush. m_node->RunIncrementalDiscovery(PortId(), callback); } void ArtNetOutputPort::PostSetUniverse(Universe *old_universe, Universe *new_universe) { if (new_universe) { m_node->SetInputPortUniverse( PortId(), new_universe->UniverseId() % ARTNET_UNIVERSE_COUNT); } else { m_node->DisableInputPort(PortId()); } if (new_universe && !old_universe) { m_node->SetUnsolicitedUIDSetHandler( PortId(), ola::NewCallback( static_cast(this), &ArtNetOutputPort::UpdateUIDs)); } else if (!new_universe) { m_node->SetUnsolicitedUIDSetHandler(PortId(), NULL); } } string ArtNetOutputPort::Description() const { if (!GetUniverse()) { return ""; } std::ostringstream str; str << "ArtNet Universe " << static_cast(m_node->NetAddress()) << ":" << static_cast(m_node->SubnetAddress()) << ":" << static_cast(m_node->GetInputPortUniverse(PortId())); return str.str(); } } // namespace artnet } // namespace plugin } // namespace ola ola-0.10.5.nojsmin/plugins/artnet/ArtNetNode.h0000644000175000017500000006460413023355232020622 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ArtNetNode.h * Header file for the ArtNetNodeImpl class * Copyright (C) 2005 Simon Newton */ #ifndef PLUGINS_ARTNET_ARTNETNODE_H_ #define PLUGINS_ARTNET_ARTNETNODE_H_ #include #include #include #include #include #include "ola/Callback.h" #include "ola/Clock.h" #include "ola/DmxBuffer.h" #include "ola/network/IPV4Address.h" #include "ola/network/Interface.h" #include "ola/io/SelectServerInterface.h" #include "ola/network/Socket.h" #include "ola/rdm/QueueingRDMController.h" #include "ola/rdm/RDMCommand.h" #include "ola/rdm/RDMFrame.h" #include "ola/rdm/RDMControllerInterface.h" #include "ola/rdm/UIDSet.h" #include "ola/timecode/TimeCode.h" #include "plugins/artnet/ArtNetPackets.h" namespace ola { namespace plugin { namespace artnet { // The directions are the opposite from what OLA uses typedef enum { ARTNET_INPUT_PORT, // sends ArtNet data ARTNET_OUTPUT_PORT, // receives ArtNet data } artnet_port_type; typedef enum { ARTNET_MERGE_HTP, // default ARTNET_MERGE_LTP, } artnet_merge_mode; // This can be passed to SetPortUniverse to disable ports static const uint8_t ARTNET_DISABLE_PORT = 0xf0; class ArtNetNodeOptions { public: ArtNetNodeOptions() : always_broadcast(false), use_limited_broadcast_address(false), rdm_queue_size(20), broadcast_threshold(30), input_port_count(4) { } bool always_broadcast; bool use_limited_broadcast_address; unsigned int rdm_queue_size; unsigned int broadcast_threshold; uint8_t input_port_count; }; class ArtNetNodeImpl { public: /** * @brief Create a new node * @param iface the interface to use. * @param ss a pointer to a SelectServerInterface to use * @param options the ArtNetNodeOptions for the node. * @param socket a pointer to a UDPSocketInterface to use */ ArtNetNodeImpl(const ola::network::Interface &iface, ola::io::SelectServerInterface *ss, const ArtNetNodeOptions &options, ola::network::UDPSocketInterface *socket = NULL); /** * @brief Cleanup */ virtual ~ArtNetNodeImpl(); /** * @brief Start this node. The port modifying functions can be called before this. */ bool Start(); /** * @brief Stop this node */ bool Stop(); /** * @brief Start the configuration transaction. * * Configuration mode allows the caller to make changes without triggering an * ArtPoll or ArtPollReply per change. e.g. * @examplepara * @code * node.EnterConfigurationMode() * node.SetShortName() * node.SetInputPortUniverse() * node.SetOutputPortUniverse() * // The poll / poll reply is sent here * node.ExitConfigurationMode() * @endcode * @return false if there is already a transaction pending. */ bool EnterConfigurationMode(); /** * @brief End the configuration transaction. * @returns false if we weren't in a transaction. * @sa EnterConfigurationMode */ bool ExitConfigurationMode(); // Various parameters to control the behaviour /** * @brief Set the short name. * @param name the short node name */ bool SetShortName(const std::string &name); std::string ShortName() const { return m_short_name; } /** * @brief Set the long name. * @param name the long node name */ bool SetLongName(const std::string &name); std::string LongName() const { return m_long_name; } /** * @brief Set the the net address for this node * @param net_address the ArtNet 'net' address */ bool SetNetAddress(uint8_t net_address); uint8_t NetAddress() const { return m_net_address; } /** * @brief Set the the subnet address for this node * @param subnet_address the ArtNet 'subnet' address, 4 bits. */ bool SetSubnetAddress(uint8_t subnet_address); uint8_t SubnetAddress() const { return m_output_ports[0].universe_address >> 4; } /** * Get the number of input ports * @returns the number of input ports */ uint8_t InputPortCount() const; /** * Set the universe address of an input port */ bool SetInputPortUniverse(uint8_t port_id, uint8_t universe_id); /** * @brief Get an input port universe address * * Return the 8bit universe address for a port. This does not include the * ArtNet III net-address. * @param port_id a port id between 0 and ARTNET_MAX_PORTS - 1 * @return The universe address for the port. Invalid port_ids return 0. */ uint8_t GetInputPortUniverse(uint8_t port_id) const; /** * @brief Disable an input port. * @param port_id a port id between 0 and ARTNET_MAX_PORTS - 1 */ void DisableInputPort(uint8_t port_id); /** * @brief Check the state of an input port * @param port_id a port id between 0 and ARTNET_MAX_PORTS - 1 * @return the state (enabled or disabled) of an input port. An invalid * port_id returns false. */ bool InputPortState(uint8_t port_id) const; /** * @brief Set the universe for an output port. * @param port_id a port id between 0 and ARTNET_MAX_PORTS - 1 * @param universe_id the new universe id. */ bool SetOutputPortUniverse(uint8_t port_id, uint8_t universe_id); /** * Return the current universe address for an output port * @param port_id a port id between 0 and ARTNET_MAX_PORTS - 1 * @return the universe address for the port */ uint8_t GetOutputPortUniverse(uint8_t port_id); /** * @brief Disable an output port. * @param port_id a port id between 0 and ARTNET_MAX_PORTS - 1 */ void DisableOutputPort(uint8_t port_id); /** * @brief Check the state of an output port * @param port_id a port id between 0 and ARTNET_MAX_PORTS - 1 * @return the state (enabled or disabled) of an output port. An invalid * port_id returns false. */ bool OutputPortState(uint8_t port_id) const; void SetBroadcastThreshold(unsigned int threshold) { m_broadcast_threshold = threshold; } /** * @brief Set the merge mode for an output port * @param port_id a port id between 0 and ARTNET_MAX_PORTS - 1 * @param merge_mode the artnet_merge_mode */ bool SetMergeMode(uint8_t port_id, artnet_merge_mode merge_mode); /** * @brief Send an ArtPoll if any of the ports are sending data * * This should be called periodically if we're sending data. */ bool SendPoll(); // The following apply to Input Ports (those which send data) /** * @brief Send some DMX data * @param port_id port to send on * @param buffer the DMX data * @return true if it was send successfully, false otherwise */ bool SendDMX(uint8_t port_id, const ola::DmxBuffer &buffer); /** * @brief Flush the TOD and force a full discovery. * * The DiscoverableQueueingRDMController ensures this is only called one at a * time. * @param port_id port to discover on * @param callback the RDMDiscoveryCallback to run when discovery completes */ void RunFullDiscovery(uint8_t port_id, ola::rdm::RDMDiscoveryCallback *callback); /** * @brief Run an 'incremental' discovery. This just involves fetching the TOD from * all nodes. * * The DiscoverableQueueingRDMController ensures only one discovery process * is running per port at any time. * @param port_id port to send on * @param callback the RDMDiscoveryCallback to run when discovery completes */ void RunIncrementalDiscovery(uint8_t port_id, ola::rdm::RDMDiscoveryCallback *callback); /** * @brief Send an RDMRequest on this port * * This may defer the sending if there are * other outstanding messages in the queue. * @param port_id the id of the port to send the request on * @param request the RDMRequest object * @param on_complete the RDMCallback to run * * Because this is wrapped in the QueueingRDMController this will only be * called one-at-a-time (per port) */ void SendRDMRequest(uint8_t port_id, ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *on_complete); /** * @brief Set the RDM handlers for an Input port * @param port_id the id of the port to set the handlers for * @param on_tod the callback to be invoked when a ArtTod message is * received, and the RDM process isn't running. */ bool SetUnsolicitedUIDSetHandler( uint8_t port_id, ola::Callback1 *on_tod); /** * @brief Get the nodes listening to the universe a port is sending * * Populate the vector with a list of IP addresses that are known to be * listening for the universe that this port is sending * @param port_id the id of the port to fetch nodes for * @param[out] node_addresses a vector of nodes listening to the port */ void GetSubscribedNodes( uint8_t port_id, std::vector *node_addresses); // The following apply to Output Ports (those which receive data); /** * @brief Set the closure to be called when we receive data for this universe. * @param port_id the id of the port to register the handler for * @param buffer a pointer to the DmxBuffer * @param handler the Callback0 to call when there is data for this universe. * Ownership of the closure is transferred to the node. */ bool SetDMXHandler(uint8_t port_id, DmxBuffer *buffer, ola::Callback0 *handler); /** * @brief Send an set of UIDs in one of more ArtTod packets * @param port_id the id of the port to send on * @param uid_set the UIDSet to send */ bool SendTod(uint8_t port_id, const ola::rdm::UIDSet &uid_set); /** * @brief Set the RDM handlers for an Output port */ bool SetOutputPortRDMHandlers( uint8_t port_id, ola::Callback0 *on_discover, ola::Callback0 *on_flush, ola::Callback2 *on_rdm_request); /** * @brief Send a timecode packet */ bool SendTimeCode(const ola::timecode::TimeCode &timecode); private: class InputPort; typedef std::vector InputPorts; // map a uid to a IP address and the number of times we've missed a // response. typedef std::map > uid_map; enum { MAX_MERGE_SOURCES = 2 }; struct DMXSource { DmxBuffer buffer; TimeStamp timestamp; ola::network::IPV4Address address; }; // Output Ports receive ArtNet data struct OutputPort { uint8_t universe_address; uint8_t sequence_number; bool enabled; artnet_merge_mode merge_mode; bool is_merging; DMXSource sources[MAX_MERGE_SOURCES]; DmxBuffer *buffer; std::map uid_map; Callback0 *on_data; Callback0 *on_discover; Callback0 *on_flush; ola::Callback2 *on_rdm_request; }; bool m_running; uint8_t m_net_address; // this is the 'net' portion of the Artnet address bool m_send_reply_on_change; std::string m_short_name; std::string m_long_name; unsigned int m_broadcast_threshold; unsigned int m_unsolicited_replies; ola::io::SelectServerInterface *m_ss; bool m_always_broadcast; bool m_use_limited_broadcast_address; // The following keep track of "Configuration mode" bool m_in_configuration_mode; bool m_artpoll_required; bool m_artpollreply_required; InputPorts m_input_ports; OutputPort m_output_ports[ARTNET_MAX_PORTS]; ola::network::Interface m_interface; std::auto_ptr m_socket; /** * @brief Called when there is data on this socket */ void SocketReady(); /** * @brief Send an ArtPoll if we're both running and not in configuration mode. * * If we're in configuration mode this sets m_artpoll_required instead. */ bool SendPollIfAllowed(); /** * @brief Send an ArtPollReply if we're both running and m_send_reply_on_change is * true. * * If we're in configuration mode, this sets m_artpollreply_required * instead of sending. */ bool SendPollReplyIfRequired(); /** * @brief Send an ArtPollReply message */ bool SendPollReply(const ola::network::IPV4Address &destination); /** * @brief Send an IPProgReply */ bool SendIPReply(const ola::network::IPV4Address &destination); /** * @brief Handle an ArtNet packet */ void HandlePacket(const ola::network::IPV4Address &source_address, const artnet_packet &packet, unsigned int packet_size); /** * @brief Handle an ArtPoll packet */ void HandlePollPacket(const ola::network::IPV4Address &source_address, const artnet_poll_t &packet, unsigned int packet_size); /** * @brief Handle an ArtPollReply packet */ void HandleReplyPacket(const ola::network::IPV4Address &source_address, const artnet_reply_t &packet, unsigned int packet_size); /** * @brief Handle a DMX Data packet, this takes care of the merging */ void HandleDataPacket(const ola::network::IPV4Address &source_address, const artnet_dmx_t &packet, unsigned int packet_size); /** * @brief Handle a TOD Request packet */ void HandleTodRequest(const ola::network::IPV4Address &source_address, const artnet_todrequest_t &packet, unsigned int packet_size); /** * @brief Handle a TOD Data packet */ void HandleTodData(const ola::network::IPV4Address &source_address, const artnet_toddata_t &packet, unsigned int packet_size); /** * @brief Handle a TOD Control packet */ void HandleTodControl(const ola::network::IPV4Address &source_address, const artnet_todcontrol_t &packet, unsigned int packet_size); /** * @brief Handle an RDM packet */ void HandleRdm(const ola::network::IPV4Address &source_address, const artnet_rdm_t &packet, unsigned int packet_size); /** * @brief Handle the completion of a request for an Output port */ void RDMRequestCompletion(ola::network::IPV4Address destination, uint8_t port_id, uint8_t universe_address, ola::rdm::RDMReply *reply); /** * @brief Handle an RDM response. * * * ArtNet as a protocol is broken, the nodes don't buffer ACK_OVERFLOW messages * so if another GET/SET message arrives from *any* controller the ACK_OVERFLOW * session will be reset, possibly causing the controller to spin in a loop. * */ void HandleRDMResponse(InputPort *port, const ola::rdm::RDMFrame &rdm_data, const ola::network::IPV4Address &source_address); /** * @brief Handle an IP Program message. */ void HandleIPProgram(const ola::network::IPV4Address &source_address, const artnet_ip_prog_t &packet, unsigned int packet_size); /** * @brief Fill in the header for a packet */ void PopulatePacketHeader(artnet_packet *packet, uint16_t op_code); /** * @brief Send an ArtNet packet * @param packet the packet to send * @param size the size of the packet, excluding the header portion * @param destination where to send the packet to */ bool SendPacket(const artnet_packet &packet, unsigned int size, const ola::network::IPV4Address &destination); /** * @brief Timeout a pending RDM request * @param port the id of the port to timeout. */ void TimeoutRDMRequest(InputPort *port); /** * @brief Send a generic ArtRdm message */ bool SendRDMCommand(const ola::rdm::RDMCommand &command, const ola::network::IPV4Address &destination, uint8_t universe); /** * @brief Update a port from a source, merging if necessary */ void UpdatePortFromSource(OutputPort *port, const DMXSource &source); /** * @brief Check the version number of a incoming packet */ bool CheckPacketVersion(const ola::network::IPV4Address &source_address, const std::string &packet_type, uint16_t version); /** * @brief Check the size of an incoming packet */ bool CheckPacketSize(const ola::network::IPV4Address &source_address, const std::string &packet_type, unsigned int actual_size, unsigned int expected_size); // methods for accessing Input & Output ports /** * @brief Lookup an InputPort by id, if the id is invalid, we return NULL. */ InputPort *GetInputPort(uint8_t port_id, bool warn = true); /** * @brief A const version of GetInputPort(); */ const InputPort *GetInputPort(uint8_t port_id) const; /** * @brief Similar to GetInputPort, but this also confirms the port is enabled. */ InputPort *GetEnabledInputPort(uint8_t port_id, const std::string &action); /** * @brief Lookup an OutputPort by id, if the id is invalid, we return NULL. */ OutputPort *GetOutputPort(uint8_t port_id); /** * @brief A const version of GetOutputPort(); */ const OutputPort *GetOutputPort(uint8_t port_id) const; /** * @brief Similar to GetOutputPort, but this also confirms the port is enabled. */ OutputPort *GetEnabledOutputPort(uint8_t port_id, const std::string &action); /** * @brief Update a port with a new TOD list */ void UpdatePortFromTodPacket(InputPort *port, const ola::network::IPV4Address &source_address, const artnet_toddata_t &packet, unsigned int packet_size); /** * @brief Called when the discovery process times out. */ void ReleaseDiscoveryLock(InputPort *port); /** * @brief Start the discovery process, this puts the port into discovery mode and * sets up the callback. * @param port the InputPort to discover devices one * @param callback the RDMDiscoveryCallback to run */ bool StartDiscoveryProcess(InputPort *port, ola::rdm::RDMDiscoveryCallback *callback); /** * @brief Setup the networking components. */ bool InitNetwork(); static const char ARTNET_ID[]; static const uint16_t ARTNET_PORT = 6454; static const uint16_t OEM_CODE = 0x0431; static const uint16_t ARTNET_VERSION = 14; // after not receiving a PollReply after this many seconds we declare the // node as dead. This is set to 3x the POLL_INTERVAL in ArtNetDevice. static const uint8_t NODE_CODE = 0x00; static const uint16_t MAX_UIDS_PER_UNIVERSE = 0xffff; static const uint8_t RDM_VERSION = 0x01; // v1.0 standard baby! static const uint8_t TOD_FLUSH_COMMAND = 0x01; static const unsigned int MERGE_TIMEOUT = 10; // As per the spec // seconds after which a node is marked as inactive for the dmx merging static const unsigned int NODE_TIMEOUT = 31; // mseconds we wait for a TodData packet before declaring a node missing static const unsigned int RDM_TOD_TIMEOUT_MS = 4000; // Number of missed TODs before we decide a UID has gone static const unsigned int RDM_MISSED_TODDATA_LIMIT = 3; // The maximum number of requests we'll allow in the queue. This is a per // port (universe) limit. static const unsigned int RDM_REQUEST_QUEUE_LIMIT = 100; // How long to wait for a response to an RDM Request static const unsigned int RDM_REQUEST_TIMEOUT_MS = 2000; DISALLOW_COPY_AND_ASSIGN(ArtNetNodeImpl); }; /** * This glues the ArtNetNodeImpl together with the QueueingRDMController. * The ArtNetNodeImpl takes a port id so we need this extra layer. */ class ArtNetNodeImplRDMWrapper : public ola::rdm::DiscoverableRDMControllerInterface { public: ArtNetNodeImplRDMWrapper(ArtNetNodeImpl *impl, uint8_t port_id): m_impl(impl), m_port_id(port_id) { } ~ArtNetNodeImplRDMWrapper() {} void SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *on_complete) { m_impl->SendRDMRequest(m_port_id, request, on_complete); } void RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { m_impl->RunFullDiscovery(m_port_id, callback); } void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback) { m_impl->RunIncrementalDiscovery(m_port_id, callback); } private: ArtNetNodeImpl *m_impl; uint8_t m_port_id; DISALLOW_COPY_AND_ASSIGN(ArtNetNodeImplRDMWrapper); }; /** * @brief The actual ArtNet Node */ class ArtNetNode { public: ArtNetNode(const ola::network::Interface &iface, ola::io::SelectServerInterface *ss, const ArtNetNodeOptions &options, ola::network::UDPSocketInterface *socket = NULL); virtual ~ArtNetNode(); bool Start() { return m_impl.Start(); } bool Stop() { return m_impl.Stop(); } bool EnterConfigurationMode() { return m_impl.EnterConfigurationMode(); } bool ExitConfigurationMode() { return m_impl.ExitConfigurationMode(); } // Various parameters to control the behaviour bool SetShortName(const std::string &name) { return m_impl.SetShortName(name); } std::string ShortName() const { return m_impl.ShortName(); } bool SetLongName(const std::string &name) { return m_impl.SetLongName(name); } std::string LongName() const { return m_impl.LongName(); } uint8_t NetAddress() const { return m_impl.NetAddress(); } bool SetNetAddress(uint8_t net_address) { return m_impl.SetNetAddress(net_address); } bool SetSubnetAddress(uint8_t subnet_address) { return m_impl.SetSubnetAddress(subnet_address); } uint8_t SubnetAddress() const { return m_impl.SubnetAddress(); } uint8_t InputPortCount() const { return m_impl.InputPortCount(); } bool SetInputPortUniverse(uint8_t port_id, uint8_t universe_id) { return m_impl.SetInputPortUniverse(port_id, universe_id); } uint8_t GetInputPortUniverse(uint8_t port_id) const { return m_impl.GetInputPortUniverse(port_id); } void DisableInputPort(uint8_t port_id) { m_impl.DisableInputPort(port_id); } bool InputPortState(uint8_t port_id) const { return m_impl.InputPortState(port_id); } bool SetOutputPortUniverse(uint8_t port_id, uint8_t universe_id) { return m_impl.SetOutputPortUniverse(port_id, universe_id); } uint8_t GetOutputPortUniverse(uint8_t port_id) { return m_impl.GetOutputPortUniverse(port_id); } void DisableOutputPort(uint8_t port_id) { m_impl.DisableOutputPort(port_id); } bool OutputPortState(uint8_t port_id) const { return m_impl.OutputPortState(port_id); } void SetBroadcastThreshold(unsigned int threshold) { m_impl.SetBroadcastThreshold(threshold); } bool SetMergeMode(uint8_t port_id, artnet_merge_mode merge_mode) { return m_impl.SetMergeMode(port_id, merge_mode); } // Poll, this should be called periodically if we're sending data. bool SendPoll() { return m_impl.SendPoll(); } // The following apply to Input Ports (those which send data) bool SendDMX(uint8_t port_id, const ola::DmxBuffer &buffer) { return m_impl.SendDMX(port_id, buffer); } /** * @brief Trigger full discovery for a port */ void RunFullDiscovery(uint8_t port_id, ola::rdm::RDMDiscoveryCallback *callback); /** * @brief Trigger incremental discovery for a port. */ void RunIncrementalDiscovery(uint8_t port_id, ola::rdm::RDMDiscoveryCallback *callback); /** * @brief Send a RDM request by passing it though the Queuing Controller */ void SendRDMRequest(uint8_t port_id, ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *on_complete); /* * @brief This handler is called if we receive ArtTod packets and a discovery * process isn't running. */ bool SetUnsolicitedUIDSetHandler( uint8_t port_id, ola::Callback1 *on_tod) { return m_impl.SetUnsolicitedUIDSetHandler(port_id, on_tod); } void GetSubscribedNodes( uint8_t port_id, std::vector *node_addresses) { m_impl.GetSubscribedNodes(port_id, node_addresses); } // The following apply to Output Ports (those which receive data); bool SetDMXHandler(uint8_t port_id, DmxBuffer *buffer, ola::Callback0 *handler) { return m_impl.SetDMXHandler(port_id, buffer, handler); } bool SendTod(uint8_t port_id, const ola::rdm::UIDSet &uid_set) { return m_impl.SendTod(port_id, uid_set); } bool SetOutputPortRDMHandlers( uint8_t port_id, ola::Callback0 *on_discover, ola::Callback0 *on_flush, ola::Callback2 *on_rdm_request) { return m_impl.SetOutputPortRDMHandlers(port_id, on_discover, on_flush, on_rdm_request); } // Time Code methods bool SendTimeCode(const ola::timecode::TimeCode &timecode) { return m_impl.SendTimeCode(timecode); } private: ArtNetNodeImpl m_impl; std::vector m_wrappers; std::vector m_controllers; /** * @brief Check that the port_id is a valid input port. * @return true if the port id is valid, false otherwise */ bool CheckInputPortId(uint8_t port_id); DISALLOW_COPY_AND_ASSIGN(ArtNetNode); }; } // namespace artnet } // namespace plugin } // namespace ola #endif // PLUGINS_ARTNET_ARTNETNODE_H_ ola-0.10.5.nojsmin/plugins/artnet/ArtNetPackets.h0000644000175000017500000001426313023355232021323 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ArtNetPackets.h * Datagram definitions for ArtNet * Copyright (C) 2004 Simon Newton */ #ifndef PLUGINS_ARTNET_ARTNETPACKETS_H_ #define PLUGINS_ARTNET_ARTNETPACKETS_H_ #include "ola/Constants.h" #include "ola/rdm/UID.h" #include "ola/network/IPV4Address.h" #include "ola/network/MACAddress.h" #include "ola/network/Interface.h" #ifndef ARTNET_PORT_COUNT #define ARTNET_PORT_COUNT 4 #endif // ARTNET_PORT_COUNT namespace ola { namespace plugin { namespace artnet { // various length enums enum { ARTNET_LONG_NAME_LENGTH = 64 }; enum { ARTNET_MAX_PORTS = ARTNET_PORT_COUNT }; enum { ARTNET_MAX_RDM_ADDRESS_COUNT = 32 }; // According to the RDM spec, this should be 256 bytes // We'll set to 512 here just to be safe enum { ARTNET_MAX_RDM_DATA = 512 }; enum { ARTNET_MAX_UID_COUNT = 200 }; enum { ARTNET_REPORT_LENGTH = 64 }; enum { ARTNET_SHORT_NAME_LENGTH = 18 }; /* * The subset of packets we're interested in */ typedef enum artnet_packet_type_e { ARTNET_POLL = 0x2000, ARTNET_REPLY = 0x2100, ARTNET_DMX = 0x5000, ARTNET_TODREQUEST = 0x8000, ARTNET_TODDATA = 0x8100, ARTNET_TODCONTROL = 0x8200, ARTNET_RDM = 0x8300, ARTNET_RDM_SUB = 0x8400, ARTNET_TIME_CODE = 0x9700, ARTNET_IP_PROGRAM = 0xf800, ARTNET_IP_PROGRAM_REPLY = 0xf900, } artnet_packet_type; PACK( struct artnet_poll_s { uint16_t version; uint8_t talk_to_me; uint8_t priority; }); typedef struct artnet_poll_s artnet_poll_t; PACK( struct artnet_reply_s { uint8_t ip[ola::network::IPV4Address::LENGTH]; uint16_t port; uint16_t version; uint8_t net_address; uint8_t subnet_address; uint16_t oem; uint8_t ubea; uint8_t status1; uint16_t esta_id; char short_name[ARTNET_SHORT_NAME_LENGTH]; char long_name[ARTNET_LONG_NAME_LENGTH]; char node_report[ARTNET_REPORT_LENGTH]; uint8_t number_ports[2]; uint8_t port_types[ARTNET_MAX_PORTS]; uint8_t good_input[ARTNET_MAX_PORTS]; uint8_t good_output[ARTNET_MAX_PORTS]; uint8_t sw_in[ARTNET_MAX_PORTS]; uint8_t sw_out[ARTNET_MAX_PORTS]; uint8_t sw_video; uint8_t sw_macro; uint8_t sw_remote; uint8_t spare1; uint8_t spare2; uint8_t spare3; uint8_t style; uint8_t mac[ola::network::MACAddress::LENGTH]; uint8_t bind_ip[ola::network::IPV4Address::LENGTH]; uint8_t bind_index; uint8_t status2; uint8_t filler[26]; }); typedef struct artnet_reply_s artnet_reply_t; PACK( struct artnet_timecode_s { uint16_t version; uint8_t filler; uint8_t filler2; uint8_t frames; uint8_t seconds; uint8_t minutes; uint8_t hours; uint8_t type; }); typedef struct artnet_timecode_s artnet_timecode_t; PACK( struct artnet_dmx_s { uint16_t version; uint8_t sequence; uint8_t physical; uint8_t universe; uint8_t net; uint8_t length[2]; uint8_t data[DMX_UNIVERSE_SIZE]; }); typedef struct artnet_dmx_s artnet_dmx_t; PACK( struct artnet_todrequest_s { uint16_t version; uint8_t filler1; uint8_t filler2; uint8_t spare1; uint8_t spare2; uint8_t spare3; uint8_t spare4; uint8_t spare5; uint8_t spare6; uint8_t spare7; uint8_t net; uint8_t command; uint8_t address_count; uint8_t addresses[ARTNET_MAX_RDM_ADDRESS_COUNT]; }); typedef struct artnet_todrequest_s artnet_todrequest_t; PACK( struct artnet_toddata_s { uint16_t version; uint8_t rdm_version; uint8_t port; uint8_t spare1; uint8_t spare2; uint8_t spare3; uint8_t spare4; uint8_t spare5; uint8_t spare6; uint8_t spare7; uint8_t net; uint8_t command_response; uint8_t address; uint16_t uid_total; uint8_t block_count; uint8_t uid_count; uint8_t tod[ARTNET_MAX_UID_COUNT][ola::rdm::UID::UID_SIZE]; }); typedef struct artnet_toddata_s artnet_toddata_t; PACK( struct artnet_todcontrol_s { uint16_t version; uint8_t filler1; uint8_t filler2; uint8_t spare1; uint8_t spare2; uint8_t spare3; uint8_t spare4; uint8_t spare5; uint8_t spare6; uint8_t spare7; uint8_t net; uint8_t command; uint8_t address; }); typedef struct artnet_todcontrol_s artnet_todcontrol_t; PACK( struct artnet_rdm_s { uint16_t version; uint8_t rdm_version; uint8_t filler2; uint8_t spare1; uint8_t spare2; uint8_t spare3; uint8_t spare4; uint8_t spare5; uint8_t spare6; uint8_t spare7; uint8_t net; uint8_t command; uint8_t address; uint8_t data[ARTNET_MAX_RDM_DATA]; }); typedef struct artnet_rdm_s artnet_rdm_t; PACK( struct artnet_ip_prog_s { uint16_t version; uint16_t filler; uint8_t command; uint8_t filler1; uint8_t ip[ola::network::IPV4Address::LENGTH]; uint8_t subnet[ola::network::IPV4Address::LENGTH]; uint16_t port; uint8_t spare[8]; }); typedef struct artnet_ip_prog_s artnet_ip_prog_t; PACK( struct artnet_ip_reply_s { uint16_t version; uint16_t filler; uint8_t command; uint8_t filler1; uint8_t ip[ola::network::IPV4Address::LENGTH]; uint8_t subnet[ola::network::IPV4Address::LENGTH]; uint16_t port; uint8_t spare[8]; }); typedef struct artnet_ip_reply_s artnet_ip_reply_t; // union of all artnet packets typedef struct { uint8_t id[8]; uint16_t op_code; union { artnet_poll_t poll; artnet_reply_t reply; artnet_timecode_t timecode; artnet_dmx_t dmx; artnet_todrequest_t tod_request; artnet_toddata_t tod_data; artnet_todcontrol_t tod_control; artnet_rdm_t rdm; artnet_ip_prog_t ip_program; artnet_ip_reply_t ip_reply; } data; } artnet_packet; } // namespace artnet } // namespace plugin } // namespace ola #endif // PLUGINS_ARTNET_ARTNETPACKETS_H_ ola-0.10.5.nojsmin/plugins/artnet/artnet_loadtest.cpp0000644000175000017500000000563313023355232022343 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * artnet_loadtest.cpp * A simple ArtNet load tester * Copyright (C) 2013 Simon Newton */ #include #include #include #include #include "ola/Callback.h" #include "ola/DmxBuffer.h" #include "ola/Logging.h" #include "ola/base/Flags.h" #include "ola/base/Init.h" #include "ola/io/SelectServer.h" #include "ola/network/InterfacePicker.h" #include "plugins/artnet/ArtNetNode.h" using ola::DmxBuffer; using ola::NewCallback; using ola::io::SelectServer; using ola::network::Interface; using ola::network::InterfacePicker; using ola::plugin::artnet::ArtNetNode; using ola::plugin::artnet::ArtNetNodeOptions; using std::auto_ptr; using std::cout; using std::endl; using std::min; DEFINE_s_uint32(fps, f, 10, "Frames per second per universe [1 - 1000]"); DEFINE_s_uint16(universes, u, 1, "Number of universes to send"); DEFINE_string(iface, "", "The interface to send from"); /** * Send N DMX frames using ArtNet, where N is given by number_of_universes. */ bool SendFrames(ArtNetNode *node, DmxBuffer *buffer, uint16_t number_of_universes) { for (uint16_t i = 0; i < number_of_universes; i++) { node->SendDMX(i, *buffer); } return true; } int main(int argc, char* argv[]) { ola::AppInit(&argc, argv, "", "Run the E1.31 load test."); if (FLAGS_universes == 0 || FLAGS_fps == 0) { return -1; } unsigned int fps = min(1000u, static_cast(FLAGS_fps)); uint16_t universes = FLAGS_universes; DmxBuffer output; output.Blackout(); Interface iface; { auto_ptr picker(InterfacePicker::NewPicker()); if (!picker->ChooseInterface(&iface, FLAGS_iface.str())) { return -1; } } ArtNetNodeOptions options; options.always_broadcast = true; SelectServer ss; ArtNetNode node(iface, &ss, options); for (uint16_t i = 0; i < universes; i++) { if (!node.SetInputPortUniverse(i, i)) { OLA_WARN << "Failed to set port"; } } if (!node.Start()) { return -1; } ss.RegisterRepeatingTimeout( 1000 / fps, NewCallback(&SendFrames, &node, &output, universes)); cout << "Starting loadtester: " << universes << " universe(s), " << fps << " fps" << endl; ss.Run(); } ola-0.10.5.nojsmin/plugins/artnet/ArtNetDevice.h0000644000175000017500000000727213023355232021132 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ArtNetDevice.h * Interface for the ArtNet device * Copyright (C) 2005 Simon Newton */ /** * @namespace ola::plugin::artnet * An Art-Net device is an instance of libartnet bound to a single IP address * Art-Net is limited to four ports per direction per IP, so in this case * our device has 8 ports : * * IDs 0-3 : Input ports (recv DMX) * IDs 4-7 : Output ports (send DMX) */ #ifndef PLUGINS_ARTNET_ARTNETDEVICE_H_ #define PLUGINS_ARTNET_ARTNETDEVICE_H_ #include #include "olad/Device.h" #include "plugins/artnet/messages/ArtNetConfigMessages.pb.h" #include "plugins/artnet/ArtNetNode.h" namespace ola { class Preferences; namespace plugin { namespace artnet { class ArtNetDevice: public Device { public: /** * Create a new Artnet Device */ ArtNetDevice(AbstractPlugin *owner, class Preferences *preferences, class PluginAdaptor *plugin_adaptor); // only one ArtNet device std::string DeviceId() const { return "1"; } void EnterConfigurationMode() { m_node->EnterConfigurationMode(); } void ExitConfigurationMode() { m_node->ExitConfigurationMode(); } /** * Handle device config messages * @param controller An RpcController * @param request the request data * @param response the response to return * @param done the closure to call once the request is complete */ void Configure(ola::rpc::RpcController *controller, const std::string &request, std::string *response, ConfigureCallback *done); static const char K_ALWAYS_BROADCAST_KEY[]; static const char K_DEVICE_NAME[]; static const char K_IP_KEY[]; static const char K_LIMITED_BROADCAST_KEY[]; static const char K_LONG_NAME_KEY[]; static const char K_LOOPBACK_KEY[]; static const char K_NET_KEY[]; static const char K_OUTPUT_PORT_KEY[]; static const char K_SHORT_NAME_KEY[]; static const char K_SUBNET_KEY[]; static const unsigned int K_ARTNET_NET; static const unsigned int K_ARTNET_SUBNET; static const unsigned int K_DEFAULT_OUTPUT_PORT_COUNT; // 10s between polls when we're sending data, DMX-workshop uses 8s; static const unsigned int POLL_INTERVAL = 10000; protected: /** * Start this device * @return true on success, false on failure */ bool StartHook(); /** * Stop this device. This is called before the ports are deleted */ void PrePortStop(); /** * Stop this device */ void PostPortStop(); private: class Preferences *m_preferences; ArtNetNode *m_node; class PluginAdaptor *m_plugin_adaptor; ola::thread::timeout_id m_timeout_id; /** * Handle an options request */ void HandleOptions(Request *request, std::string *response); /** * Handle a node list request */ void HandleNodeList(Request *request, std::string *response, ola::rpc::RpcController *controller); }; } // namespace artnet } // namespace plugin } // namespace ola #endif // PLUGINS_ARTNET_ARTNETDEVICE_H_ ola-0.10.5.nojsmin/README.rpm0000644000175000017500000000233213023355232015133 0ustar wouterwouterInstructions on how to build RPM's for Fedora, this may work with other RPM based distros like CentOS. 1. Install RPM build tools: $ sudo dnf install rpmdevtools 2. Create the build environment as the user you want to build as (NOT root): $ rpmdev-setuptree 3. Clone the ola git repository to /tmp: $ sudo dnf install git # install git if you haven't already $ cd /tmp $ git clone https://github.com/OpenLightingProject/ola.git $ cd ola $ git checkout X.Y.Z # If you want a specific version $ autoreconf -i && ./configure && make dist $ cp ola-X.Y.Z.tar.gz ~/rpmbuild/SOURCES/ 4. Install requires build dependencies of ola: $ sudo dnf install libmicrohttpd-devel cppunit-devel protobuf-devel \ protobuf-compiler protobuf-python libftdi-devel \ openslp-devel uuid-devel libtool bison flex \ pkgconfig gcc gcc-c++ python2-devel avahi-devel 5. Build ola from the spec file: $ cd ~/rpmbuild/SPECS/ $ cp /tmp/ola/ola.spec ./ $ rpmbuild -ba ./ola.spec 6. Et voila ! Your RPM's are in ~/rpmbuild/RPMS/noarch/ and ~/rpmbuild/RPMS// ! 7. (OPTIONAL) Further reading: https://fedoraproject.org/wiki/How_to_create_an_RPM_package ola-0.10.5.nojsmin/GPL0000644000175000017500000004313713023355232014033 0ustar wouterwouter GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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. ola-0.10.5.nojsmin/AUTHORS0000644000175000017500000000174413023355232014534 0ustar wouterwouterPlease do not email the author directly, instead use open-lighting@googlegroups.com Primary author: Simon Newton Contributors: Bastien Andrès, contributed to the dmx4linux plugin Carsten Presser, Karate USB plugin Dave Olsthoorn, working on a new web-ui Hakan Lindestaf, Renard plugin Harry F, for the Eurolite USB Pro code Heikki Junnila, bug fixes for the debian packaging files Laurent (Renzo), Debian packages, FreeBSD & RDM testing. Lukas Erlinghagen, win32 port. Johan Nilsson, Philips Hue trigger config Joshua Moyerman, ArtNet fixes. Masaki Muranaka, various patches Nicolas, for the win32 port of libartnet Peter Newman, MilInst Plugin, Scanlime Fadecandy support and numerous fixes Ravindra Nath Kakarla, RDM Test Server (Google Summer of Code 2012) Rowan Maclachlan (hippy) for various changes Rui Barreiros, ftdidmx plugin Sean Sill, various fixes. Stefan Krüger, added APA102 support to the SPI Plugin Tobi Schäfer, for the MacPort files ola-0.10.5.nojsmin/README0000644000175000017500000000621413134123277014346 0ustar wouterwouter# Open Lighting Architecture - OLA [www.openlighting.org/ola](https://www.openlighting.org/ola) [![Build Status](https://travis-ci.org/OpenLightingProject/ola.svg?branch=master)](https://travis-ci.org/OpenLightingProject/ola) [![Coverity Scan Status](https://scan.coverity.com/projects/3514/badge.svg)](https://scan.coverity.com/projects/3514) [![Coverage Status](https://coveralls.io/repos/OpenLightingProject/ola/badge.png?branch=master)](https://coveralls.io/r/OpenLightingProject/ola?branch=master) The Open Lighting Architecture (OLA) is a framework for controlling entertainment lighting equipment. Within the entertainment lighting industry, the [Digital Multiplex protocol](https://en.wikipedia.org/wiki/DMX512) (DMX-512) and IP variants such as [Streaming ACN](https://en.wikipedia.org/wiki/Architecture_for_Control_Networks#External_Extensions) (sACN) are used to control lighting fixtures. OLA provides the distribution layer that abstracts away the various protocols used. This allows authors of lighting control software to focus on generating the control information, rather than having to implement support for different hardware devices & network protocols. OLA runs on Linux & Mac OS X, some features will also work on Windows. OLA can also be used to convert between different network protocols. With the use of a USB to DMX512 device, OLA can act as a DMX-over-IP to DMX512 gateway. OLA consists of three parts, the daemon olad, the olad plugins and the client library, libola. Documentation on OLA, including examples on how to get started, are provided on the [Open Lighting Architecture Docs](https://docs.openlighting.org/ola/doc/latest/) site. The pages are automatically updated from the git repository. ## Downloading OLA OLA is distributed in a number of formats, including [Debian](https://www.debian.org/) / [Ubuntu](http://www.ubuntu.com/) Packages and [MacPorts](https://www.macports.org/). The [OLA Downloads](https://www.openlighting.org/ola/getting-started/downloads/) page has more information. Tagged releases in the git repository are signed. To import the public key, run: $ git cat-file blob simon-pubkey | gpg --import and then to verify the release: $ git tag -v 0.9.6 ## Support Support for OLA is provided via the mailing list and IRC channel. The [Getting Help](https://www.openlighting.org/ola/get-help/) page has more details. ## Components ### Plugins The OLA plugins are located in ./plugins. For a walkthrough of an example see plugins/osc/README. ### C++ Library The C++ Client is in ./ola. The [C++ DMX Client API Tutorial](https://docs.openlighting.org/ola/doc/latest/dmx_cpp_client_tutorial.html) has various examples on how one can use the client. ### Python Module The Python module can be built by running configure with --enable-python-libs. There are examples on how to use the Python API in python/examples. ### Java Library There is an experimental Java library which can be built by running configure with --enable-java-libs. ## Credits The AUTHORS files contains a list of code contributors. A [full list of supporters](https://www.openlighting.org/openlightingproject/about/supporters/) is published on the website. ola-0.10.5.nojsmin/examples/0000755000175000017500000000000013155164170015301 5ustar wouterwouterola-0.10.5.nojsmin/examples/Makefile.mk0000644000175000017500000001324513134123277017354 0ustar wouterwouter# Note: gcc 4.6.1 is pretty strict about library ordering. Libraries need to be # specified in the order they are used. i.e. a library should depend on things # to the right, not the left. # See http://www.network-theory.co.uk/docs/gccintro/gccintro_18.html if BUILD_EXAMPLES # The following should match what pkg-config --libs libola returns EXAMPLE_COMMON_LIBS = common/libolacommon.la \ ola/libola.la # LIBRARIES ################################################## noinst_LTLIBRARIES += examples/libolaconfig.la examples_libolaconfig_la_SOURCES = \ examples/OlaConfigurator.h \ examples/OlaConfigurator.cpp examples_libolaconfig_la_CXXFLAGS = $(COMMON_PROTOBUF_CXXFLAGS) # PROGRAMS ################################################## bin_PROGRAMS += \ examples/ola_dev_info \ examples/ola_rdm_discover \ examples/ola_rdm_get \ examples/ola_recorder \ examples/ola_streaming_client \ examples/ola_timecode \ examples/ola_uni_stats if USE_E131 bin_PROGRAMS += examples/ola_e131 examples_ola_e131_SOURCES = examples/ola-e131.cpp examples_ola_e131_CXXFLAGS = $(COMMON_PROTOBUF_CXXFLAGS) examples_ola_e131_LDADD = examples/libolaconfig.la \ $(EXAMPLE_COMMON_LIBS) \ plugins/e131/messages/libolae131conf.la \ $(libprotobuf_LIBS) endif if USE_USBPRO bin_PROGRAMS += examples/ola_usbpro examples_ola_usbpro_SOURCES = examples/ola-usbpro.cpp examples_ola_usbpro_CXXFLAGS = $(COMMON_PROTOBUF_CXXFLAGS) examples_ola_usbpro_LDADD = examples/libolaconfig.la \ $(EXAMPLE_COMMON_LIBS) \ plugins/usbpro/messages/libolausbproconf.la \ $(libprotobuf_LIBS) endif if USE_ARTNET bin_PROGRAMS += examples/ola_artnet examples_ola_artnet_SOURCES = examples/ola-artnet.cpp examples_ola_artnet_CXXFLAGS = $(COMMON_PROTOBUF_CXXFLAGS) examples_ola_artnet_LDADD = examples/libolaconfig.la \ $(EXAMPLE_COMMON_LIBS) \ plugins/artnet/messages/libolaartnetconf.la \ $(libprotobuf_LIBS) endif examples_ola_dev_info_SOURCES = examples/ola-client.cpp examples_ola_dev_info_LDADD = $(EXAMPLE_COMMON_LIBS) examples_ola_streaming_client_SOURCES = examples/ola-streaming-client.cpp examples_ola_streaming_client_LDADD = $(EXAMPLE_COMMON_LIBS) examples_ola_rdm_get_SOURCES = examples/ola-rdm.cpp examples_ola_rdm_get_LDADD = $(EXAMPLE_COMMON_LIBS) examples_ola_rdm_discover_SOURCES = examples/ola-rdm-discover.cpp examples_ola_rdm_discover_LDADD = $(EXAMPLE_COMMON_LIBS) examples_ola_recorder_SOURCES = \ examples/ola-recorder.cpp \ examples/ShowLoader.h \ examples/ShowLoader.cpp \ examples/ShowPlayer.h \ examples/ShowPlayer.cpp \ examples/ShowRecorder.h \ examples/ShowRecorder.cpp \ examples/ShowSaver.h \ examples/ShowSaver.cpp examples_ola_recorder_LDADD = $(EXAMPLE_COMMON_LIBS) examples_ola_timecode_SOURCES = examples/ola-timecode.cpp examples_ola_timecode_LDADD = $(EXAMPLE_COMMON_LIBS) examples_ola_uni_stats_SOURCES = examples/ola-uni-stats.cpp examples_ola_uni_stats_LDADD = $(EXAMPLE_COMMON_LIBS) if HAVE_NCURSES bin_PROGRAMS += examples/ola_dmxconsole examples/ola_dmxmonitor examples_ola_dmxconsole_SOURCES = examples/ola-dmxconsole.cpp examples_ola_dmxconsole_LDADD = $(EXAMPLE_COMMON_LIBS) -lncurses examples_ola_dmxmonitor_SOURCES = examples/ola-dmxmonitor.cpp examples_ola_dmxmonitor_LDADD = $(EXAMPLE_COMMON_LIBS) -lncurses endif noinst_PROGRAMS += examples/ola_throughput examples/ola_latency examples_ola_throughput_SOURCES = examples/ola-throughput.cpp examples_ola_throughput_LDADD = $(EXAMPLE_COMMON_LIBS) examples_ola_latency_SOURCES = examples/ola-latency.cpp examples_ola_latency_LDADD = $(EXAMPLE_COMMON_LIBS) if USING_WIN32 # rename this program, otherwise UAC will block it OLA_PATCH_NAME = ola_ptch else OLA_PATCH_NAME = ola_patch endif # Many of the example programs are just symlinks to ola_dev_info install-exec-hook-examples: $(LN_S) -f $(bindir)/ola_dev_info $(DESTDIR)$(bindir)/$(OLA_PATCH_NAME) $(LN_S) -f $(bindir)/ola_dev_info $(DESTDIR)$(bindir)/ola_plugin_info $(LN_S) -f $(bindir)/ola_dev_info $(DESTDIR)$(bindir)/ola_set_dmx $(LN_S) -f $(bindir)/ola_dev_info $(DESTDIR)$(bindir)/ola_set_priority $(LN_S) -f $(bindir)/ola_dev_info $(DESTDIR)$(bindir)/ola_uni_info $(LN_S) -f $(bindir)/ola_dev_info $(DESTDIR)$(bindir)/ola_uni_merge $(LN_S) -f $(bindir)/ola_dev_info $(DESTDIR)$(bindir)/ola_uni_name $(LN_S) -f $(bindir)/ola_dev_info $(DESTDIR)$(bindir)/ola_plugin_state $(LN_S) -f $(bindir)/ola_rdm_get $(DESTDIR)$(bindir)/ola_rdm_set INSTALL_EXEC_HOOKS += install-exec-hook-examples # TESTS_DATA ################################################## EXTRA_DIST += \ examples/testdata/dos_line_endings \ examples/testdata/multiple_unis \ examples/testdata/partial_frames \ examples/testdata/single_uni \ examples/testdata/trailing_timeout # TESTS ################################################## test_scripts += examples/RecorderVerifyTest.sh examples/RecorderVerifyTest.sh: examples/Makefile.mk echo "for FILE in ${srcdir}/examples/testdata/dos_line_endings ${srcdir}/examples/testdata/multiple_unis ${srcdir}/examples/testdata/partial_frames ${srcdir}/examples/testdata/single_uni ${srcdir}/examples/testdata/trailing_timeout; do echo \"Checking \$$FILE\"; ${top_builddir}/examples/ola_recorder${EXEEXT} --verify \$$FILE; STATUS=\$$?; if [ \$$STATUS -ne 0 ]; then echo \"FAIL: \$$FILE caused ola_recorder to exit with status \$$STATUS\"; exit \$$STATUS; fi; done; exit 0" > examples/RecorderVerifyTest.sh chmod +x examples/RecorderVerifyTest.sh CLEANFILES += examples/RecorderVerifyTest.sh endif ola-0.10.5.nojsmin/examples/ola-rdm-discover.cpp0000644000175000017500000000751013023355232021152 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ola-rdm-discover.cpp * Print the list of UIDs and force RDM discovery * Copyright (C) 2010 Simon Newton */ #include #include #include #include #include #include #include #include #include #include #include #include #include using std::cout; using std::cerr; using std::endl; using std::setw; using std::string; using std::vector; using ola::OlaCallbackClient; using ola::OlaCallbackClientWrapper; using ola::io::SelectServer; using ola::rdm::UID; using ola::rdm::UIDSet; DEFINE_s_uint32(universe, u, 1, "The universe to do RDM discovery on"); DEFINE_s_default_bool(full, f, false, "Force full RDM Discovery for this universe"); DEFINE_s_default_bool(incremental, i, false, "Force incremental RDM Discovery for this universe"); DEFINE_default_bool(include_broadcast, false, "Include broadcast UID for this universe"); DEFINE_default_bool(include_vendorcast, false, "Include vendorcast UID for this universe"); SelectServer *ss; /* * This is called when we receive uids for a universe * @param universes a vector of OlaUniverses */ void UIDList(const ola::rdm::UIDSet &uids, const string &error) { UIDSet vendorcast; if (error.empty()) { UIDSet::Iterator iter = uids.Begin(); for (; iter != uids.End(); ++iter) { cout << *iter << endl; vendorcast.AddUID(UID::VendorcastAddress(*iter)); } if (FLAGS_include_vendorcast) { iter = vendorcast.Begin(); for (; iter != vendorcast.End(); ++iter) { cout << *iter << endl; } } if (FLAGS_include_broadcast) { cout << UID::AllDevices().ToString() << endl; } } else { cerr << error << endl; } ss->Terminate(); } /* * Send a fetch uid list request * @param client the ola client */ bool FetchUIDs(OlaCallbackClient *client) { if (FLAGS_full) { return client->RunDiscovery( FLAGS_universe, true, ola::NewSingleCallback(&UIDList)); } else if (FLAGS_incremental) { return client->RunDiscovery( FLAGS_universe, false, ola::NewSingleCallback(&UIDList)); } else { return client->FetchUIDList( FLAGS_universe, ola::NewSingleCallback(&UIDList)); } } /* * Main */ int main(int argc, char *argv[]) { ola::AppInit( &argc, argv, "--universe [--full|--incremental]", "Fetch the UID list for a universe."); OlaCallbackClientWrapper ola_client; if (!FLAGS_universe.present()) { ola::DisplayUsageAndExit(); } if (FLAGS_full && FLAGS_incremental) { cerr << "Only one of -i and -f can be specified" << endl; exit(ola::EXIT_USAGE); } if (!ola_client.Setup()) { OLA_FATAL << "Setup failed"; exit(ola::EXIT_UNAVAILABLE); } OlaCallbackClient *client = ola_client.GetClient(); ss = ola_client.GetSelectServer(); if (FetchUIDs(client)) { ss->Run(); } return ola::EXIT_OK; } ola-0.10.5.nojsmin/examples/ShowLoader.cpp0000644000175000017500000000657613023355232020065 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ShowLoader.cpp * A class that reads OLA show files * Copyright (C) 2011 Simon Newton * * The data file is in the form: * universe-number channel1,channel2,channel3 * delay-in-ms * universe-number channel1,channel2,channel3 */ #include #include #include #include #include #include #include #include #include #include #include #include "examples/ShowLoader.h" using std::vector; using std::string; using ola::DmxBuffer; const char ShowLoader::OLA_SHOW_HEADER[] = "OLA Show"; ShowLoader::ShowLoader(const string &filename) : m_filename(filename), m_line(0) { } ShowLoader::~ShowLoader() { if (m_show_file.is_open()) { m_show_file.close(); } } /** * Load the show file. * @returns true if we could open the file, false otherwise. */ bool ShowLoader::Load() { m_show_file.open(m_filename.data()); if (!m_show_file.is_open()) { OLA_FATAL << "Can't open " << m_filename << ": " << strerror(errno); return false; } string line; ReadLine(&line); if (line != OLA_SHOW_HEADER) { OLA_WARN << "Invalid show file, expecting " << OLA_SHOW_HEADER << " got " << line; return false; } return true; } /** * Reset to the start of the show */ void ShowLoader::Reset() { m_show_file.clear(); m_show_file.seekg(0, std::ios::beg); // skip over the first line string line; ReadLine(&line); } /** * Get the next time offset * @param timeout a pointer to the timeout in ms */ ShowLoader::State ShowLoader::NextTimeout(unsigned int *timeout) { string line; ReadLine(&line); if (line.empty()) { return END_OF_FILE; } if (!ola::StringToInt(line, timeout, true)) { OLA_WARN << "Line " << m_line << ": Invalid timeout: " << line; return INVALID_LINE; } return OK; } /** * Read the next DMX frame. * @param universe the universe to send on * @param data the DMX data */ ShowLoader::State ShowLoader::NextFrame(unsigned int *universe, DmxBuffer *data) { string line; ReadLine(&line); if (line.empty()) { return END_OF_FILE; } vector inputs; ola::StringSplit(line, &inputs); if (inputs.size() != 2) { OLA_WARN << "Line " << m_line << " invalid: " << line; return INVALID_LINE; } if (!ola::StringToInt(inputs[0], universe, true)) { OLA_WARN << "Line " << m_line << " invalid: " << line; return INVALID_LINE; } return (data->SetFromString(inputs[1]) ? OK : INVALID_LINE); } void ShowLoader::ReadLine(string *line) { getline(m_show_file, *line); ola::StripSuffix(line, "\r"); m_line++; } ola-0.10.5.nojsmin/examples/ShowLoader.h0000644000175000017500000000276313023355232017524 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ShowLoader.h * A simple show playback system. * Copyright (C) 2011 Simon Newton */ #include #include #include #ifndef EXAMPLES_SHOWLOADER_H_ #define EXAMPLES_SHOWLOADER_H_ /** * Loads a show file and reads the DMX data. */ class ShowLoader { public: explicit ShowLoader(const std::string &filename); ~ShowLoader(); typedef enum { OK, INVALID_LINE, END_OF_FILE, } State; bool Load(); void Reset(); State NextTimeout(unsigned int *timeout); State NextFrame(unsigned int *universe, ola::DmxBuffer *data); private: const std::string m_filename; std::ifstream m_show_file; unsigned int m_line; static const char OLA_SHOW_HEADER[]; void ReadLine(std::string *line); }; #endif // EXAMPLES_SHOWLOADER_H_ ola-0.10.5.nojsmin/examples/ola-streaming-client.cpp0000644000175000017500000000532413134123277022027 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ola-streaming-client.cpp * The streaming client example program. * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include #include #include #include #include #include using std::cout; using std::endl; using std::string; using ola::client::StreamingClient; DEFINE_s_string(dmx, d, "", "Comma separated DMX values to send, e.g. " "0,255,128 sets first channel to 0, second " "channel to 255 and third channel to 128."); DEFINE_s_uint32(universe, u, 1, "The universe to send data for"); DEFINE_uint8(priority, ola::dmx::SOURCE_PRIORITY_DEFAULT, "The source priority to send data at"); bool terminate = false; bool SendDataFromString(StreamingClient *client, unsigned int universe, const string &data) { StreamingClient::SendArgs args; args.priority = FLAGS_priority; ola::DmxBuffer buffer; bool status = buffer.SetFromString(data); if (!status || buffer.Size() == 0) { return false; } if (!client->SendDMX(universe, buffer, args)) { cout << "Send DMX failed" << endl; terminate = true; return false; } return true; } int main(int argc, char *argv[]) { ola::AppInit(&argc, argv, "--dmx --universe ", "Send DMX512 data to OLA. If DMX512 data isn't provided, it " "will read from STDIN."); StreamingClient ola_client; if (!ola_client.Setup()) { OLA_FATAL << "Setup failed"; exit(1); } if (FLAGS_dmx.str().empty()) { string input; while (!terminate && std::cin >> input) { ola::StringTrim(&input); SendDataFromString(&ola_client, FLAGS_universe, input); } } else { SendDataFromString(&ola_client, FLAGS_universe, FLAGS_dmx.str()); } ola_client.Stop(); return 0; } ola-0.10.5.nojsmin/examples/ola-throughput.cpp0000644000175000017500000000340713134123277020773 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ola-throughput.cpp * Send a bunch of frames quickly to load test the server. * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include #include #include #include #include #include #include using std::cout; using std::endl; using std::string; using ola::StreamingClient; DEFINE_s_uint32(universe, u, 1, "The universe to send data on"); DEFINE_s_uint32(sleep, s, 40000, "Time between DMX updates in micro-seconds"); /* * Main */ int main(int argc, char *argv[]) { ola::AppInit(&argc, argv, "[options]", "Send DMX512 data to OLA."); StreamingClient ola_client; if (!ola_client.Setup()) { OLA_FATAL << "Setup failed"; exit(1); } ola::DmxBuffer buffer; buffer.Blackout(); while (1) { usleep(FLAGS_sleep); if (!ola_client.SendDmx(FLAGS_universe, buffer)) { cout << "Send DMX failed" << endl; exit(1); } } return 0; } ola-0.10.5.nojsmin/examples/ola-usbpro.cpp0000644000175000017500000001527613023355232020076 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ola-usbpro.cpp * Configure Enttec USB Pro Devices managed by OLA * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include #include #include #include #include "examples/OlaConfigurator.h" using std::cerr; using std::cout; using std::endl; using std::string; DECLARE_int32(device); DEFINE_s_default_bool(assignments, a, false, "Get the port assignments."); DEFINE_s_int32(brk, b, -1, "Set the break time (9 - 127)."); DEFINE_s_default_bool(get_params, g, false, "Get the current parameters."); DEFINE_s_int32(mab, m, -1, "Set the make after-break-time (1 - 127)."); DEFINE_s_int32(port, p, -1, "The port to configure."); DEFINE_s_int32(rate, r, -1, "Set the transmission rate (1 - 40)."); DEFINE_s_default_bool(serial, s, false, "Get the serial number."); /* * A class which configures UsbPro devices. */ class UsbProConfigurator: public OlaConfigurator { public: UsbProConfigurator() : OlaConfigurator(FLAGS_device, ola::OLA_PLUGIN_USBPRO) {} void HandleConfigResponse(const string &reply, const string &error); void SendConfigRequest(); bool SendParametersRequest(); bool SendSerialRequest(); bool SendPortAssignmentRequest(); private: void DisplayParameters(const ola::plugin::usbpro::ParameterReply &reply); void DisplaySerial(const ola::plugin::usbpro::SerialNumberReply &reply); void DisplayPortAssignment( const ola::plugin::usbpro::PortAssignmentReply &reply); }; /* * Handle the device config reply */ void UsbProConfigurator::HandleConfigResponse(const string &reply, const string &error) { Terminate(); if (!error.empty()) { cerr << error << endl; return; } ola::plugin::usbpro::Reply reply_pb; if (!reply_pb.ParseFromString(reply)) { cout << "Protobuf parsing failed" << endl; return; } if (reply_pb.type() == ola::plugin::usbpro::Reply::USBPRO_PARAMETER_REPLY && reply_pb.has_parameters()) { DisplayParameters(reply_pb.parameters()); return; } else if (reply_pb.type() == ola::plugin::usbpro::Reply::USBPRO_SERIAL_REPLY && reply_pb.has_serial_number()) { DisplaySerial(reply_pb.serial_number()); return; } else if (reply_pb.type() == ola::plugin::usbpro::Reply::USBPRO_PORT_ASSIGNMENT_REPLY && reply_pb.has_port_assignment()) { DisplayPortAssignment(reply_pb.port_assignment()); return; } cout << "Invalid response type or missing options field" << endl; } /* * Send the appropriate ConfigRequest */ void UsbProConfigurator::SendConfigRequest() { if (FLAGS_serial) { SendSerialRequest(); } else if (FLAGS_assignments) { SendPortAssignmentRequest(); } else { // Also FLAGS_get_params SendParametersRequest(); } } /* * Send a get parameters request */ bool UsbProConfigurator::SendParametersRequest() { ola::plugin::usbpro::Request request; request.set_type(ola::plugin::usbpro::Request::USBPRO_PARAMETER_REQUEST); ola::plugin::usbpro::ParameterRequest *parameter_request = request.mutable_parameters(); parameter_request->set_port_id(FLAGS_port); if (FLAGS_brk.present()) { parameter_request->set_break_time(FLAGS_brk); } if (FLAGS_mab.present()) { parameter_request->set_mab_time(FLAGS_mab); } if (FLAGS_rate.present()) { parameter_request->set_rate(FLAGS_rate); } return SendMessage(request); } /* * Send a get serial request */ bool UsbProConfigurator::SendSerialRequest() { ola::plugin::usbpro::Request request; request.set_type(ola::plugin::usbpro::Request::USBPRO_SERIAL_REQUEST); return SendMessage(request); } /* * Send a get port assignment request */ bool UsbProConfigurator::SendPortAssignmentRequest() { ola::plugin::usbpro::Request request; request.set_type( ola::plugin::usbpro::Request::USBPRO_PORT_ASSIGNMENT_REQUEST); return SendMessage(request); } /* * Display the widget parameters */ void UsbProConfigurator::DisplayParameters( const ola::plugin::usbpro::ParameterReply &reply) { cout << "Device: " << m_alias << endl; cout << "Firmware: " << reply.firmware_high() << "." << reply.firmware() << endl; cout << "Break Time: " << reply.break_time() * 10.67 << "us" << endl; cout << "MAB Time: " << reply.mab_time() * 10.67 << "us" << endl; cout << "Packet Rate: " << reply.rate() << " packets/sec" << endl; } /* * Display the serial number */ void UsbProConfigurator::DisplaySerial( const ola::plugin::usbpro::SerialNumberReply &reply) { string serial_number = reply.serial(); cout << "Device: " << m_alias << endl; cout << "Serial: " << reply.serial() << endl; } /* * Display the port assignments */ void UsbProConfigurator::DisplayPortAssignment( const ola::plugin::usbpro::PortAssignmentReply &reply) { cout << "Device: " << m_alias << endl; cout << "Port 1: " << reply.port_assignment1() << endl; cout << "Port 2: " << reply.port_assignment2() << endl; } /* * The main function */ int main(int argc, char *argv[]) { ola::AppInit( &argc, argv, "-d [--serial | -p --g | -p -b -m -r " "]", "Configure Enttec USB Pro Devices managed by OLA."); if (FLAGS_device < 0) { ola::DisplayUsageAndExit(); } // check for valid parameters if (FLAGS_brk.present() && (FLAGS_brk < 9 || FLAGS_brk > 127)) { ola::DisplayUsageAndExit(); } if (FLAGS_mab.present() && (FLAGS_mab < 1 || FLAGS_mab > 127)) { ola::DisplayUsageAndExit(); } if (FLAGS_rate.present() && (FLAGS_rate < 1 || FLAGS_rate > 40)) { ola::DisplayUsageAndExit(); } if ((FLAGS_get_params || (!FLAGS_assignments && !FLAGS_serial)) && (FLAGS_port < 0)) { ola::DisplayUsageAndExit(); } UsbProConfigurator configurator; if (!configurator.Setup()) { cerr << "Error: " << strerror(errno) << endl; exit(1); } configurator.Run(); return 0; } ola-0.10.5.nojsmin/examples/OlaConfigurator.h0000644000175000017500000000564413023355232020554 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OlaConfigurator.h * Makes configuring devices easy * Copyright (C) 2005 Simon Newton * * The Configurator makes it easy to use the device specific ConfigureDevice() * rpc. For each device type you want to manage, subclass the Configurator and * implement the SendConfigRequest() and HandleConfigResponse() methods. * Upon calling Setup() the Configurator will send a DeviceInfo * request to check that the device type matches the plugin_id given in the * constructor. On successfull match, it will call SendConfigRequest() which * the subclass uses to send the desired request. * * Once the response is returned, HandleConfigResponse() is called in the * subclass. */ #include #include #include #include #include #include #include #ifndef EXAMPLES_OLACONFIGURATOR_H_ #define EXAMPLES_OLACONFIGURATOR_H_ class OlaConfigurator; /** * Inherit from this and implement HandleResponse() */ class OlaConfigurator { public: /** * @param device_id the device id to configure * @param plugin_id the expected plugin id for this device */ OlaConfigurator(unsigned int device_id, ola::ola_plugin_id plugin_id) : m_alias(device_id), m_plugin_id(plugin_id), m_client_wrapper(NULL), m_client(NULL), m_ss(NULL) {} virtual ~OlaConfigurator(); /** * Setup the configurator */ bool Setup(); void Run() { m_ss->Run(); } void Terminate() { m_ss->Terminate(); } void HandleDevices(const std::vector &devices, const std::string &error); bool SendMessage(const google::protobuf::Message &message); // Subclasses implement this virtual void HandleConfigResponse(const std::string &reply, const std::string &error) = 0; virtual void SendConfigRequest() = 0; protected: unsigned int m_alias; ola::ola_plugin_id m_plugin_id; private: ola::OlaCallbackClientWrapper *m_client_wrapper; ola::OlaCallbackClient *m_client; ola::io::SelectServer *m_ss; }; #endif // EXAMPLES_OLACONFIGURATOR_H_ ola-0.10.5.nojsmin/examples/ola-artnet.cpp0000644000175000017500000001235013023355232020047 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ola-artnet.cpp * Configure an ArtNet device * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include #include #include #include #include #include "examples/OlaConfigurator.h" using std::cerr; using std::cout; using std::endl; using std::string; DECLARE_int32(device); DEFINE_s_string(name, n, "", "Set the name of the ArtNet device."); DEFINE_string(long_name, "", "Set the long name of the ArtNet device."); DEFINE_int32(net, -1, "Set the net parameter of the ArtNet device."); DEFINE_s_int32(subnet, s, -1, "Set the subnet parameter of the ArtNet device."); DEFINE_s_uint32(universe, u, 0, "List the IPs of ArtNet devices for this universe."); /* * A class that configures Artnet devices */ class ArtnetConfigurator: public OlaConfigurator { public: ArtnetConfigurator() : OlaConfigurator(FLAGS_device, ola::OLA_PLUGIN_ARTNET) {} void HandleConfigResponse(const string &reply, const string &error); void SendConfigRequest(); private: void SendOptionRequest(); void SendNodeListRequest(); void DisplayOptions(const ola::plugin::artnet::OptionsReply &reply); void DisplayNodeList(const ola::plugin::artnet::NodeListReply &reply); }; /* * Handle the device config reply */ void ArtnetConfigurator::HandleConfigResponse(const string &reply, const string &error) { Terminate(); if (!error.empty()) { cerr << error << endl; return; } ola::plugin::artnet::Reply reply_pb; if (!reply_pb.ParseFromString(reply)) { cout << "Protobuf parsing failed" << endl; return; } if (reply_pb.type() == ola::plugin::artnet::Reply::ARTNET_OPTIONS_REPLY && reply_pb.has_options()) { DisplayOptions(reply_pb.options()); return; } else if (reply_pb.type() == ola::plugin::artnet::Reply::ARTNET_NODE_LIST_REPLY && reply_pb.has_node_list()) { DisplayNodeList(reply_pb.node_list()); } else { cout << "Invalid response type or missing options field" << endl; } } /* * Send a request */ void ArtnetConfigurator::SendConfigRequest() { if (FLAGS_universe.present()) { SendNodeListRequest(); } else { SendOptionRequest(); } } /** * Send an options request, which may involve setting options */ void ArtnetConfigurator::SendOptionRequest() { ola::plugin::artnet::Request request; request.set_type(ola::plugin::artnet::Request::ARTNET_OPTIONS_REQUEST); ola::plugin::artnet::OptionsRequest *options = request.mutable_options(); if (FLAGS_name.present()) options->set_short_name(FLAGS_name.str()); if (FLAGS_long_name.present()) options->set_long_name(FLAGS_long_name.str()); if (FLAGS_subnet.present()) options->set_subnet(FLAGS_subnet); if (FLAGS_net.present()) options->set_net(FLAGS_net); SendMessage(request); } /** * Send a request for the node list */ void ArtnetConfigurator::SendNodeListRequest() { ola::plugin::artnet::Request request; request.set_type(ola::plugin::artnet::Request::ARTNET_NODE_LIST_REQUEST); ola::plugin::artnet::NodeListRequest *node_list_request = request.mutable_node_list(); node_list_request->set_universe(FLAGS_universe); SendMessage(request); } /** * Display the widget parameters */ void ArtnetConfigurator::DisplayOptions( const ola::plugin::artnet::OptionsReply &reply) { cout << "Name: " << reply.short_name() << endl; cout << "Long Name: " << reply.long_name() << endl; cout << "Subnet: " << reply.subnet() << endl; cout << "Net: " << reply.net() << endl; } /** * Display the list of discovered nodes */ void ArtnetConfigurator::DisplayNodeList( const ola::plugin::artnet::NodeListReply &reply) { unsigned int nodes = reply.node_size(); for (unsigned int i = 0; i < nodes; i++) { const ola::plugin::artnet::OutputNode &node = reply.node(i); ola::network::IPV4Address address(node.ip_address()); cout << address << endl; } } /* * The main function */ int main(int argc, char*argv[]) { ola::AppInit(&argc, argv, "-d -n -l -s ", "Configure ArtNet devices managed by OLA."); if (FLAGS_device < 0) ola::DisplayUsageAndExit(); ArtnetConfigurator configurator; if (!configurator.Setup()) { cerr << "Error: " << strerror(errno) << endl; exit(1); } configurator.Run(); return 0; } ola-0.10.5.nojsmin/examples/ShowPlayer.h0000644000175000017500000000415313023355232017545 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ShowPlayer.h * A simple show playback system. * Copyright (C) 2011 Simon Newton */ #include #include #include #include #include "examples/ShowLoader.h" #ifndef EXAMPLES_SHOWPLAYER_H_ #define EXAMPLES_SHOWPLAYER_H_ /** * @brief A class which plays back recorded show files. */ class ShowPlayer { public: /** * @brief Create a new ShowPlayer * @param filename the show file to play */ explicit ShowPlayer(const std::string &filename); ~ShowPlayer(); /** * @brief Initialize the show player. * @return EXIT_OK if successfull. */ int Init(); /** * @brief Playback the show * @param iterations the number of iterations of the show to play. * @param duration the duration in seconds after which playback is stopped. * @param delay the hold time at the end of a show before playback starts * from the beginning again. */ int Playback(unsigned int iterations, unsigned int duration, unsigned int delay); private: ola::client::OlaClientWrapper m_client; ShowLoader m_loader; bool m_infinite_loop; unsigned int m_iteration_remaining; unsigned int m_loop_delay; void SendNextFrame(); ShowLoader::State RegisterNextTimeout(); bool ReadNextFrame(unsigned int *universe, ola::DmxBuffer *data); void HandleEndOfFile(); }; #endif // EXAMPLES_SHOWPLAYER_H_ ola-0.10.5.nojsmin/examples/ola-timecode.cpp0000644000175000017500000000753413023355232020353 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ola-timecode.cpp * Send timecode data with OLA * Copyright (C) 2011 Simon Newton */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include using ola::client::OlaClientWrapper; using ola::StringToInt; using ola::io::SelectServer; using ola::timecode::TimeCode; using std::cerr; using std::endl; using std::string; using std::vector; DEFINE_s_string(format, f, "SMPTE", "One of FILM, EBU, DF, SMPTE (default)."); /** * Called on when we return from sending timecode data. */ void TimeCodeDone(ola::io::SelectServer *ss, const ola::client::Result &result) { if (!result.Success()) { OLA_WARN << result.Error(); } ss->Terminate(); } /* * Main */ int main(int argc, char *argv[]) { ola::AppInit( &argc, argv, "[options] ", "Send TimeCode data to OLA. time_code is in the form: \n" "Hours:Minutes:Seconds:Frames"); ola::client::OlaClientWrapper ola_client; if (argc != 2) ola::DisplayUsageAndExit(); ola::timecode::TimeCodeType time_code_type = ola::timecode::TIMECODE_SMPTE; if (!FLAGS_format.str().empty()) { string type = FLAGS_format; ola::ToLower(&type); if (type == "film") { time_code_type = ola::timecode::TIMECODE_FILM; } else if (type == "ebu") { time_code_type = ola::timecode::TIMECODE_EBU; } else if (type == "df") { time_code_type = ola::timecode::TIMECODE_DF; } else if (type == "smpte") { time_code_type = ola::timecode::TIMECODE_SMPTE; } else { cerr << "Invalid TimeCode format " << type << endl; exit(ola::EXIT_USAGE); } } vector tokens; ola::StringSplit(argv[1], &tokens, ":"); if (tokens.size() != 4) { cerr << "Invalid TimeCode value " << argv[1] << endl; exit(ola::EXIT_USAGE); } uint8_t hours, minutes, seconds, frames; if (!StringToInt(tokens[0], &hours, true)) { cerr << "Invalid TimeCode hours " << tokens[0] << endl; exit(ola::EXIT_USAGE); } if (!StringToInt(tokens[1], &minutes, true)) { cerr << "Invalid TimeCode minutes " << tokens[1] << endl; exit(ola::EXIT_USAGE); } if (!StringToInt(tokens[2], &seconds, true)) { cerr << "Invalid TimeCode seconds " << tokens[2] << endl; exit(ola::EXIT_USAGE); } if (!StringToInt(tokens[3], &frames, true)) { cerr << "Invalid TimeCode frames " << tokens[3] << endl; exit(ola::EXIT_USAGE); } TimeCode timecode(time_code_type, hours, minutes, seconds, frames); if (!timecode.IsValid()) { OLA_FATAL << "Invalid TimeCode value"; exit(ola::EXIT_USAGE); } if (!ola_client.Setup()) { OLA_FATAL << "Setup failed"; exit(ola::EXIT_UNAVAILABLE); } ola_client.GetClient()->SendTimeCode( timecode, ola::NewSingleCallback(&TimeCodeDone, ola_client.GetSelectServer())); ola_client.GetSelectServer()->Run(); return ola::EXIT_OK; } ola-0.10.5.nojsmin/examples/ola-rdm.cpp0000644000175000017500000004462713134123277017355 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ola-rdm.cpp * The command line tool for controlling RDM devices * Copyright (C) 2010 Simon Newton */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using ola::network::NetworkToHost; using ola::rdm::PidStoreHelper; using ola::rdm::UID; using std::auto_ptr; using std::cerr; using std::cout; using std::endl; using std::string; using std::vector; typedef struct { bool set_mode; bool help; // show the help string pid_location; // alt pid store bool list_pids; // show the pid list int universe; // universe id UID *uid; // uid uint16_t sub_device; // the sub device string pid; // pid to get/set vector args; // extra args string cmd; // argv[0] bool display_frames; // print raw frames. } options; /* * Parse our cmd line options */ void ParseOptions(int argc, char *argv[], options *opts) { const int FRAME_OPTION_VALUE = 256; opts->cmd = argv[0]; string cmd_name = ola::file::FilenameFromPathOrPath(opts->cmd); // To skip the lt prefix during development ola::StripPrefix(&cmd_name, "lt-"); #ifdef _WIN32 // Strip the extension size_t extension = cmd_name.find("."); if (extension != string::npos) { cmd_name = cmd_name.substr(0, extension); } #endif // _WIN32 opts->set_mode = false; opts->pid_location = ""; opts->list_pids = false; opts->help = false; opts->universe = 1; opts->uid = NULL; opts->sub_device = 0; opts->display_frames = false; if (cmd_name == "ola_rdm_set") { opts->set_mode = true; } int uid_set = 0; static struct option long_options[] = { {"sub-device", required_argument, 0, 'd'}, {"help", no_argument, 0, 'h'}, {"pid-location", required_argument, 0, 'p'}, {"list-pids", no_argument, 0, 'l'}, {"universe", required_argument, 0, 'u'}, {"frames", no_argument, 0, FRAME_OPTION_VALUE}, {"uid", required_argument, &uid_set, 1}, {0, 0, 0, 0} }; int option_index = 0; while (1) { int c = getopt_long(argc, argv, "d:hlp:u:", long_options, &option_index); if (c == -1) break; switch (c) { case 0: if (uid_set) opts->uid = UID::FromString(optarg); break; case 'd': opts->sub_device = atoi(optarg); break; case 'h': opts->help = true; break; case 'l': opts->list_pids = true; break; case 'p': opts->pid_location = optarg; break; case 'u': opts->universe = atoi(optarg); break; case FRAME_OPTION_VALUE: opts->display_frames = true; break; default: break; } } int index = optind; for (; index < argc; index++) opts->args.push_back(argv[index]); } /* * Display the help for get_pid */ void DisplayGetPidHelp(const options &opts) { cout << "Usage: " << opts.cmd << " --universe --uid \n" "\n" "Get the value of a PID for a device.\n" "Use '" << opts.cmd << " --list-pids' to get a list of PIDs.\n" "\n" " --frames display the raw RDM frames if available.\n" " --uid the UID of the device to control.\n" " -d, --sub-device target a particular sub device (default is 0)\n" " -h, --help display this help message and exit.\n" " -l, --list-pids display a list of PIDs\n" " -p, --pid-location the directory to read PID definitions from\n" " -u, --universe universe number.\n" << endl; } /* * Display the help for set_pid */ void DisplaySetPidHelp(const options &opts) { cout << "Usage: " << opts.cmd << " --universe --uid \n" "\n" "Set the value of a PID for a device.\n" "Use '" << opts.cmd << " --list-pids' to get a list of PIDs.\n" "\n" " --frames display the raw RDM frames if available.\n" " --uid the UID of the device to control.\n" " -d, --sub-device target a particular sub device (default is 0)\n" " -h, --help display this help message and exit.\n" " -l, --list-pids display a list of PIDs\n" " -p, --pid-location the directory to read PID definitions from\n" " -u, --universe universe number.\n" << endl; } /* * Display the help message */ void DisplayHelpAndExit(const options &opts) { if (opts.set_mode) { DisplaySetPidHelp(opts); } else { DisplayGetPidHelp(opts); } exit(ola::EXIT_USAGE); } /* * Dump the list of known pids */ void DisplayPIDsAndExit(uint16_t manufacturer_id, const PidStoreHelper &pid_helper) { vector pid_names; pid_helper.SupportedPids(manufacturer_id, &pid_names); sort(pid_names.begin(), pid_names.end()); vector::const_iterator iter = pid_names.begin(); for (; iter != pid_names.end(); ++iter) { cout << *iter << endl; } exit(ola::EXIT_OK); } class RDMController { public: RDMController(string pid_location, bool show_frames); bool InitPidHelper(); bool Setup(); const PidStoreHelper& PidHelper() const { return m_pid_helper; } int PerformRequestAndWait(unsigned int universe, const UID &uid, uint16_t sub_device, const string &pid_name, bool is_set, const vector &inputs); void HandleResponse(const ola::client::Result &result, const ola::client::RDMMetadata &metadata, const ola::rdm::RDMResponse *response); void ShowFrames(const ola::client::RDMMetadata &metadata); private: struct PendingRequest { public: PendingRequest() : universe(0), uid(NULL), sub_device(0), pid_value(0) { } unsigned int universe; const UID *uid; uint16_t sub_device; uint16_t pid_value; }; const bool m_show_frames; ola::client::OlaClientWrapper m_ola_client; PidStoreHelper m_pid_helper; PendingRequest m_pending_request; void FetchQueuedMessage(); void PrintRemainingMessages(uint8_t message_count); void HandleAckResponse(uint16_t manufacturer_id, bool is_set, uint16_t pid, const uint8_t *data, unsigned int length); }; RDMController::RDMController(string pid_location, bool show_frames) : m_show_frames(show_frames), m_pid_helper(pid_location) { } bool RDMController::InitPidHelper() { return m_pid_helper.Init(); } bool RDMController::Setup() { return m_ola_client.Setup(); } /** * Handle the RDM response */ void RDMController::HandleResponse(const ola::client::Result &result, const ola::client::RDMMetadata &metadata, const ola::rdm::RDMResponse *response) { if (!result.Success()) { cerr << "Error: " << result.Error() << endl; ShowFrames(metadata); m_ola_client.GetSelectServer()->Terminate(); return; } if (metadata.response_code == ola::rdm::RDM_WAS_BROADCAST) { m_ola_client.GetSelectServer()->Terminate(); // Broadcast, there shouldn't be any frames return; } else if (metadata.response_code != ola::rdm::RDM_COMPLETED_OK) { cerr << "Error: " << ola::rdm::StatusCodeToString(metadata.response_code) << endl; ShowFrames(metadata); m_ola_client.GetSelectServer()->Terminate(); return; } if (!response) { cerr << "Error: Missing RDM Response but response_code was " "RDM_COMPLETED_OK, this is a bug, please report it!" << endl; ShowFrames(metadata); return; } if (response->ResponseType() == ola::rdm::RDM_ACK_TIMER) { uint16_t backoff_time; if (response->ParamDataSize() != sizeof(backoff_time)) { cerr << "Invalid ACK_TIMER param size of " << response->ParamDataSize(); } else { memcpy(reinterpret_cast(&backoff_time), response->ParamData(), sizeof(backoff_time)); unsigned int timeout = 100 * NetworkToHost(backoff_time); m_ola_client.GetSelectServer()->RegisterSingleTimeout( timeout, ola::NewSingleCallback(this, &RDMController::FetchQueuedMessage)); } } else if (response->ResponseType() == ola::rdm::RDM_ACK) { if (response->ParamId() == m_pending_request.pid_value || m_pending_request.pid_value == ola::rdm::PID_QUEUED_MESSAGE) { HandleAckResponse( m_pending_request.uid->ManufacturerId(), response->CommandClass() == ola::rdm::RDMCommand::SET_COMMAND_RESPONSE, response->ParamId(), response->ParamData(), response->ParamDataSize()); } else { // we got something other than an empty status message, this means there // there are probably more messages to fetch if (response->ParamId() != ola::rdm::PID_STATUS_MESSAGES || response->ParamDataSize() != 0) { FetchQueuedMessage(); return; } // this is just an empty status message, the device probably doesn't // support queued messages. cout << "Empty STATUS_MESSAGES returned." << endl; } } else if (response->ResponseType() == ola::rdm::RDM_NACK_REASON) { uint16_t nack_reason; if (response->ParamDataSize() != sizeof(nack_reason)) { cerr << "Invalid NACK reason size of " << response->ParamDataSize(); } else { memcpy(reinterpret_cast(&nack_reason), response->ParamData(), sizeof(nack_reason)); nack_reason = NetworkToHost(nack_reason); cout << "Request NACKed: " << ola::rdm::NackReasonToString(nack_reason) << endl; } } else { cout << "Unknown RDM response type " << ola::strings::ToHex(response->ResponseType()) << endl; } PrintRemainingMessages(response->MessageCount()); ShowFrames(metadata); m_ola_client.GetSelectServer()->Terminate(); } /** * Show frames if asked for */ void RDMController::ShowFrames(const ola::client::RDMMetadata &metadata) { if (m_show_frames && !metadata.frames.empty()) { cout << "------- Frame Information --------" << endl; ola::rdm::RDMFrames::const_iterator iter = metadata.frames.begin(); for (; iter != metadata.frames.end(); ++iter) { std::ios::fmtflags f(cout.flags()); cout << std::fixed << std::setprecision(1); if (iter->timing.response_time) { cout << "Response Time: " << iter->timing.response_time / 1000.0 << "uS" << endl; } if (iter->timing.break_time) { cout << "Break Time: " << iter->timing.break_time / 1000.0 << "uS" << endl; } if (iter->timing.mark_time) { cout << "Mark Time: " << iter->timing.mark_time / 1000.0 << "uS" << endl; } if (iter->timing.data_time) { cout << "Data Time: " << iter->timing.data_time / 1000.0 << "uS" << endl; } cout.flags(f); ola::strings::FormatData(&cout, iter->data.data(), iter->data.size()); } } } /** * Build a RDM Request from the options provided and send it to the daemon. */ int RDMController::PerformRequestAndWait(unsigned int universe, const UID &uid, uint16_t sub_device, const string &pid_name, bool is_set, const vector &inputs) { // get the pid descriptor const ola::rdm::PidDescriptor *pid_descriptor = m_pid_helper.GetDescriptor( pid_name, uid.ManufacturerId()); uint16_t pid_value; if (!pid_descriptor && (ola::PrefixedHexStringToInt(pid_name, &pid_value) || ola::StringToInt(pid_name, &pid_value))) { pid_descriptor = m_pid_helper.GetDescriptor( pid_value, uid.ManufacturerId()); } if (!pid_descriptor) { cout << "Unknown PID: " << pid_name << endl; cout << "Use --list-pids to list the available PIDs." << endl; return ola::EXIT_USAGE; } const ola::messaging::Descriptor *descriptor = NULL; if (is_set) descriptor = pid_descriptor->SetRequest(); else descriptor = pid_descriptor->GetRequest(); if (!descriptor) { cout << (is_set ? "SET" : "GET") << " command not supported for " << pid_name << endl; exit(ola::EXIT_USAGE); } // attempt to build the message auto_ptr message(m_pid_helper.BuildMessage( descriptor, inputs)); if (!message.get()) { cout << m_pid_helper.SchemaAsString(descriptor); return ola::EXIT_USAGE; } m_pending_request.universe = universe; m_pending_request.uid = &uid; m_pending_request.sub_device = sub_device; m_pending_request.pid_value = pid_descriptor->Value(); unsigned int param_data_length; const uint8_t *param_data = m_pid_helper.SerializeMessage( message.get(), ¶m_data_length); ola::client::SendRDMArgs args( ola::NewSingleCallback(this, &RDMController::HandleResponse)); if (m_show_frames) { args.include_raw_frames = true; } if (is_set) { m_ola_client.GetClient()->RDMSet( m_pending_request.universe, *m_pending_request.uid, m_pending_request.sub_device, pid_descriptor->Value(), param_data, param_data_length, args); } else { m_ola_client.GetClient()->RDMGet( m_pending_request.universe, *m_pending_request.uid, m_pending_request.sub_device, pid_descriptor->Value(), param_data, param_data_length, args); } m_ola_client.GetSelectServer()->Run(); return ola::EXIT_OK; } /** * Called after the ack timer expires. This resends the request. */ void RDMController::FetchQueuedMessage() { uint8_t status_type = 4; ola::client::SendRDMArgs args( ola::NewSingleCallback(this, &RDMController::HandleResponse)); m_ola_client.GetClient()->RDMGet( m_pending_request.universe, *m_pending_request.uid, m_pending_request.sub_device, ola::rdm::PID_QUEUED_MESSAGE, &status_type, sizeof(status_type), args); } /** * Print the number of messages remaining if it is non-0. */ void RDMController::PrintRemainingMessages(uint8_t message_count) { if (!message_count) return; cout << "-----------------------------------------------------" << endl; cout << "Messages remaining: " << static_cast(message_count) << endl; } /** * Handle an ACK response */ void RDMController::HandleAckResponse(uint16_t manufacturer_id, bool is_set, uint16_t pid, const uint8_t *data, unsigned int length) { const ola::rdm::PidDescriptor *pid_descriptor = m_pid_helper.GetDescriptor( pid, m_pending_request.uid->ManufacturerId()); if (!pid_descriptor) { OLA_WARN << "Unknown PID: " << pid << "."; return; } const ola::messaging::Descriptor *descriptor = NULL; if (is_set) descriptor = pid_descriptor->SetResponse(); else descriptor = pid_descriptor->GetResponse(); if (!descriptor) { OLA_WARN << "Unknown response message: " << (is_set ? "SET" : "GET") << " " << pid_descriptor->Name(); return; } auto_ptr message( m_pid_helper.DeserializeMessage(descriptor, data, length)); if (!message.get()) { OLA_WARN << "Unable to inflate RDM response"; return; } cout << m_pid_helper.PrettyPrintMessage(manufacturer_id, is_set, pid, message.get()); } /* * Main */ int main(int argc, char *argv[]) { ola::InitLogging(ola::OLA_LOG_WARN, ola::OLA_LOG_STDERR); if (!ola::NetworkInit()) { OLA_WARN << "Network initialization failed." << endl; exit(ola::EXIT_UNAVAILABLE); } options opts; ParseOptions(argc, argv, &opts); RDMController controller(opts.pid_location, opts.display_frames); if (opts.help) DisplayHelpAndExit(opts); // Make sure we can load our PIDs if (!controller.InitPidHelper()) exit(ola::EXIT_OSFILE); if (!opts.uid) { if (opts.list_pids) { DisplayPIDsAndExit(0, controller.PidHelper()); } else { OLA_FATAL << "Invalid or missing UID, try xxxx:yyyyyyyy"; DisplayHelpAndExit(opts); } } UID dest_uid(*opts.uid); delete opts.uid; if (opts.list_pids) DisplayPIDsAndExit(dest_uid.ManufacturerId(), controller.PidHelper()); if (opts.args.empty()) DisplayHelpAndExit(opts); if (!controller.Setup()) { OLA_FATAL << "Setup failed"; exit(ola::EXIT_UNAVAILABLE); } // split out rdm message params from the pid name vector inputs(opts.args.size() - 1); vector::iterator args_iter = opts.args.begin(); copy(++args_iter, opts.args.end(), inputs.begin()); return controller.PerformRequestAndWait(opts.universe, dest_uid, opts.sub_device, opts.args[0], opts.set_mode, inputs); } ola-0.10.5.nojsmin/examples/ShowSaver.h0000644000175000017500000000264713023355232017377 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ShowSaver.h * Writes show data to a file. * Copyright (C) 2011 Simon Newton */ #include #include #include #include #ifndef EXAMPLES_SHOWSAVER_H_ #define EXAMPLES_SHOWSAVER_H_ /** * Write show data to a file. */ class ShowSaver { public: explicit ShowSaver(const std::string &filename); ~ShowSaver(); bool Open(); void Close(); bool NewFrame(const ola::TimeStamp &arrival_time, unsigned int universe, const ola::DmxBuffer &data); private: const std::string m_filename; std::ofstream m_show_file; ola::TimeStamp m_last_frame; static const char OLA_SHOW_HEADER[]; }; #endif // EXAMPLES_SHOWSAVER_H_ ola-0.10.5.nojsmin/examples/ShowPlayer.cpp0000644000175000017500000000762313023355232020105 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ShowPlayer.cpp * A simple show playback system. * Copyright (C) 2011 Simon Newton * * The data file is in the form: * universe-number channel1,channel2,channel3 * delay-in-ms * universe-number channel1,channel2,channel3 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "examples/ShowPlayer.h" using std::vector; using std::string; using ola::DmxBuffer; ShowPlayer::ShowPlayer(const string &filename) : m_loader(filename), m_infinite_loop(false), m_iteration_remaining(0), m_loop_delay(0) { } ShowPlayer::~ShowPlayer() {} int ShowPlayer::Init() { if (!m_client.Setup()) { OLA_FATAL << "Client Setup failed"; return ola::EXIT_UNAVAILABLE; } if (!m_loader.Load()) { return ola::EXIT_NOINPUT; } return ola::EXIT_OK; } int ShowPlayer::Playback(unsigned int iterations, unsigned int duration, unsigned int delay) { m_infinite_loop = iterations == 0 || duration != 0; m_iteration_remaining = iterations; m_loop_delay = delay; SendNextFrame(); ola::io::SelectServer *ss = m_client.GetSelectServer(); if (duration != 0) { ss->RegisterSingleTimeout( duration * 1000, ola::NewSingleCallback(ss, &ola::io::SelectServer::Terminate)); } ss->Run(); return ola::EXIT_OK; } void ShowPlayer::SendNextFrame() { DmxBuffer buffer; unsigned int universe; ShowLoader::State state = m_loader.NextFrame(&universe, &buffer); switch (state) { case ShowLoader::END_OF_FILE: HandleEndOfFile(); return; case ShowLoader::INVALID_LINE: m_client.GetSelectServer()->Terminate(); return; default: {} } state = RegisterNextTimeout(); OLA_INFO << "Universe: " << universe << ": " << buffer.ToString(); ola::client::SendDMXArgs args; m_client.GetClient()->SendDMX(universe, buffer, args); switch (state) { case ShowLoader::END_OF_FILE: HandleEndOfFile(); return; case ShowLoader::INVALID_LINE: m_client.GetSelectServer()->Terminate(); return; default: {} } } /** * Get the next time offset */ ShowLoader::State ShowPlayer::RegisterNextTimeout() { unsigned int timeout; ShowLoader::State state = m_loader.NextTimeout(&timeout); if (state != ShowLoader::OK) { return state; } OLA_INFO << "Registering timeout for " << timeout << "ms"; m_client.GetSelectServer()->RegisterSingleTimeout( timeout, ola::NewSingleCallback(this, &ShowPlayer::SendNextFrame)); return state; } /** * Handle the case where we reach the end of file */ void ShowPlayer::HandleEndOfFile() { m_iteration_remaining--; if (m_infinite_loop || m_iteration_remaining > 0) { m_loader.Reset(); m_client.GetSelectServer()->RegisterSingleTimeout( m_loop_delay, ola::NewSingleCallback(this, &ShowPlayer::SendNextFrame)); return; } else { // stop the show m_client.GetSelectServer()->Terminate(); } } ola-0.10.5.nojsmin/examples/testdata/0000755000175000017500000000000013134123611017102 5ustar wouterwouterola-0.10.5.nojsmin/examples/testdata/single_uni0000644000175000017500000006041713023355232021174 0ustar wouterwouterOLA Show 1 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 463 1 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 553 1 208,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 1004 1 208,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 143 1 208,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 76 1 208,0,175,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 789 1 208,0,228,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 353 1 208,0,228,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 639 1 208,0,228,0,0,238,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 999 1 208,0,228,0,0,238,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 1050 1 208,0,228,0,0,238,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 968 1 208,0,228,0,0,238,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 983 1 208,0,228,0,0,238,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 1004 1 208,0,228,0,0,238,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 1019 1 208,0,228,0,0,238,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 982 1 208,0,228,0,0,238,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 1018 1 208,0,228,0,0,238,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 988 1 208,0,228,0,0,238,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 1025 1 208,0,228,0,0,238,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 994 1 208,0,228,0,0,238,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 1021 1 208,0,228,0,0,238,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 993 1 208,0,228,0,0,238,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 992 1 208,0,228,0,0,238,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 1006 1 208,0,228,0,0,238,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ola-0.10.5.nojsmin/examples/testdata/partial_frames0000644000175000017500000000024013023355232022015 0ustar wouterwouterOLA Show 1 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 463 1 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 553 1 208,0,228,0,0,238,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ola-0.10.5.nojsmin/examples/testdata/multiple_unis0000644000175000017500000004426113023355232021730 0ustar wouterwouterOLA Show 1 208,0,228,0,0,238,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 0 3 10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 360 1 160,0,154,0,0,171,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 248 3 20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 174 3 30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 185 3 40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 318 3 40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 737 3 40,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 205 3 40,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 342 3 40,40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 145 3 40,50,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 591 3 40,50,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 3326 1 180,0,154,0,0,171,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 189 1 190,0,154,0,0,171,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 564 1 190,0,154,0,0,171,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 1018 1 190,0,154,0,0,171,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 993 1 190,0,154,0,0,171,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 1015 1 190,0,154,0,0,171,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ola-0.10.5.nojsmin/examples/testdata/dos_line_endings0000644000175000017500000000603713023355232022341 0ustar wouterwouterOLA Show 1 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 463 1 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 553 1 208,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ola-0.10.5.nojsmin/examples/testdata/trailing_timeout0000644000175000017500000000403413023355232022410 0ustar wouterwouterOLA Show 1 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 463 1 208,0,228,0,0,238,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 1006 ola-0.10.5.nojsmin/examples/ola-latency.cpp0000644000175000017500000001022213023355232020205 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ola-latency.cpp * Call FetchDmx and track the latency for each call. * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include #include #include #include #include #include #include using ola::DmxBuffer; using ola::NewSingleCallback; using ola::OlaCallbackClientWrapper; using ola::TimeStamp; using ola::TimeInterval; using std::cout; using std::endl; using std::string; DEFINE_s_uint32(universe, u, 1, "The universe to receive data for"); DEFINE_default_bool(send_dmx, false, "Use SendDmx messages, default is GetDmx"); DEFINE_s_uint32(count, c, 0, "Exit after this many RPCs, default: infinite (0)"); class Tracker { public: Tracker() : m_count(0), m_sum(0) { m_buffer.Blackout(); } bool Setup(); void Start(); void GotDmx(const DmxBuffer &data, const string &error); void SendComplete(const string &error); private: uint32_t m_count; uint64_t m_sum; TimeInterval m_max; ola::DmxBuffer m_buffer; OlaCallbackClientWrapper m_wrapper; ola::Clock m_clock; ola::thread::SignalThread m_signal_thread; TimeStamp m_send_time; void SendRequest(); void LogTime(); void StartSignalThread(); }; bool Tracker::Setup() { return m_wrapper.Setup(); } void Tracker::Start() { ola::io::SelectServer *ss = m_wrapper.GetSelectServer(); m_signal_thread.InstallSignalHandler( SIGINT, ola::NewCallback(ss, &ola::io::SelectServer::Terminate)); m_signal_thread.InstallSignalHandler( SIGTERM, ola::NewCallback(ss, &ola::io::SelectServer::Terminate)); SendRequest(); ss->Execute(ola::NewSingleCallback(this, &Tracker::StartSignalThread)); ss->Run(); // Print this via cout to ensure we actually get some output by default // It also means you can just see the stats and not each individual request // if you want. cout << "--------------" << endl; cout << "Sent " << m_count << " RPCs" << endl; cout << "Max was " << m_max.MicroSeconds() << " microseconds" << endl; cout << "Mean " << m_sum / m_count << " microseconds" << endl; } void Tracker::GotDmx(const DmxBuffer &, const string &) { LogTime(); } void Tracker::SendComplete(const string &) { LogTime(); } void Tracker::SendRequest() { m_clock.CurrentTime(&m_send_time); if (FLAGS_send_dmx) { m_wrapper.GetClient()->SendDmx( FLAGS_universe, m_buffer, NewSingleCallback(this, &Tracker::SendComplete)); } else { m_wrapper.GetClient()->FetchDmx( FLAGS_universe, NewSingleCallback(this, &Tracker::GotDmx)); } } void Tracker::LogTime() { TimeStamp now; m_clock.CurrentTime(&now); TimeInterval delta = now - m_send_time; if (delta > m_max) { m_max = delta; } m_sum += delta.MicroSeconds(); OLA_INFO << "RPC took " << delta; if (FLAGS_count == ++m_count) { m_wrapper.GetSelectServer()->Terminate(); } else { SendRequest(); } } void Tracker::StartSignalThread() { if (!m_signal_thread.Start()) { m_wrapper.GetSelectServer()->Terminate(); } } int main(int argc, char *argv[]) { ola::AppInit(&argc, argv, "[options]", "Measure the latency of RPCs to olad."); Tracker tracker; if (!tracker.Setup()) { OLA_FATAL << "Setup failed"; exit(1); } tracker.Start(); return 0; } ola-0.10.5.nojsmin/examples/ola-client.cpp0000644000175000017500000006257313023355232020044 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ola-client.cpp * The multi purpose ola client. * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using ola::NewSingleCallback; using ola::client::OlaClient; using ola::client::OlaClientWrapper; using ola::client::OlaDevice; using ola::client::OlaInputPort; using ola::client::OlaOutputPort; using ola::client::OlaPlugin; using ola::client::OlaUniverse; using ola::client::Result; using ola::io::SelectServer; using std::cerr; using std::cout; using std::endl; using std::setw; using std::string; using std::vector; static const int INVALID_VALUE = -1; /* * The mode is determined by the name in which we were called */ typedef enum { DEVICE_INFO, DEVICE_PATCH, PLUGIN_INFO, PLUGIN_STATE, UNIVERSE_INFO, UNIVERSE_NAME, UNI_MERGE, SET_DMX, SET_PORT_PRIORITY, } mode; typedef struct { mode m; // mode int uni; // universe id unsigned int plugin_id; // plugin id bool help; // show the help int device_id; // device id int port_id; // port id ola::client::PortDirection port_direction; // input or output ola::client::PatchAction patch_action; // patch or unpatch OlaUniverse::merge_mode merge_mode; // the merge mode string cmd; // argv[0] string uni_name; // universe name string dmx; // DMX string ola::port_priority_mode priority_mode; // port priority mode uint8_t priority_value; // port priority value bool list_plugin_ids; bool list_universe_ids; string state; // plugin enable/disable state } options; /** * A Helper function to display a list of ports */ template void ListPorts(const vector &ports, bool input) { typename vector::const_iterator port_iter; for (port_iter = ports.begin(); port_iter != ports.end(); ++port_iter) { cout << " port " << port_iter->Id() << ", "; if (input) { cout << "IN"; } else { cout << "OUT"; } if (!port_iter->Description().empty()) { cout << " " << port_iter->Description(); } switch (port_iter->PriorityCapability()) { case ola::CAPABILITY_STATIC: cout << ", priority " << static_cast(port_iter->Priority()); break; case ola::CAPABILITY_FULL: cout << ", priority "; if (port_iter->PriorityMode() == ola::PRIORITY_MODE_INHERIT) { cout << "inherited"; } else { cout << "overide " << static_cast(port_iter->Priority()); } break; default: break; } if (port_iter->IsActive()) { cout << ", patched to universe " << port_iter->Universe(); } if (port_iter->SupportsRDM()) { cout << ", RDM supported"; } cout << endl; } } /* * This is called when we receive universe results from the client * @param list_ids_only show ids only * @param universes a vector of OlaUniverses */ void DisplayUniverses(SelectServer *ss, bool list_ids_only, const Result &result, const vector &universes) { vector::const_iterator iter; if (!result.Success()) { cerr << result.Error() << endl; ss->Terminate(); return; } if (list_ids_only) { for (iter = universes.begin(); iter != universes.end(); ++iter) { cout << iter->Id() << endl; } } else { cout << setw(5) << "Id" << "\t" << setw(30) << "Name" << "\t\tMerge Mode" << endl; cout << "----------------------------------------------------------" << endl; for (iter = universes.begin(); iter != universes.end(); ++iter) { cout << setw(5) << iter->Id() << "\t" << setw(30) << iter->Name() << "\t\t" << (iter->MergeMode() == OlaUniverse::MERGE_HTP ? "HTP" : "LTP") << endl; } cout << "----------------------------------------------------------" << endl; } ss->Terminate(); } /* * @param list_ids_only show ids only * @params plugins a vector of OlaPlugins */ void DisplayPlugins(SelectServer *ss, bool list_ids_only, const Result &result, const vector &plugins) { vector::const_iterator iter; if (!result.Success()) { cerr << result.Error() << endl; ss->Terminate(); return; } if (list_ids_only) { for (iter = plugins.begin(); iter != plugins.end(); ++iter) { cout << iter->Id() << endl; } } else { cout << setw(5) << "Id" << "\tPlugin Name" << endl; cout << "--------------------------------------" << endl; for (iter = plugins.begin(); iter != plugins.end(); ++iter) { cout << setw(5) << iter->Id() << "\t" << iter->Name() << endl; } cout << "--------------------------------------" << endl; } ss->Terminate(); } /* * Print a plugin description */ void DisplayPluginDescription(SelectServer *ss, const Result &result, const string &description) { if (!result.Success()) { cerr << result.Error() << endl; } else { cout << description << endl; } ss->Terminate(); return; } /* * Print a plugin state */ void DisplayPluginState(SelectServer *ss, const Result &result, const ola::client::PluginState &state) { if (!result.Success()) { cerr << result.Error() << endl; } else { cout << state.name << endl; cout << "Enabled: " << (state.enabled ? "True" : "False") << endl; cout << "Active: " << (state.active ? "True" : "False") << endl; vector::const_iterator iter = state.conflicting_plugins.begin(); cout << "Conflicts with:" << endl; for (; iter != state.conflicting_plugins.end(); ++iter) { cout << " " << iter->Name() << "(" << iter->Id() << ")" << endl; } } ss->Terminate(); return; } /* * @param devices a vector of OlaDevices */ void DisplayDevices(SelectServer *ss, const Result &result, const vector &devices) { vector::const_iterator iter; if (!result.Success()) { cerr << result.Error() << endl; ss->Terminate(); return; } for (iter = devices.begin(); iter != devices.end(); ++iter) { cout << "Device " << iter->Alias() << ": " << iter->Name() << endl; vector input_ports = iter->InputPorts(); ListPorts(input_ports, true); vector output_ports = iter->OutputPorts(); ListPorts(output_ports, false); } ss->Terminate(); } /* * Called when a generic set command completes */ void HandleAck(SelectServer *ss, const Result &result) { if (!result.Success()) { cerr << result.Error() << endl; } ss->Terminate(); } /* * Init options */ void InitOptions(options *opts) { opts->m = DEVICE_INFO; opts->uni = INVALID_VALUE; opts->plugin_id = ola::OLA_PLUGIN_ALL; opts->help = false; opts->list_plugin_ids = false; opts->list_universe_ids = false; opts->patch_action = ola::client::PATCH; opts->port_id = INVALID_VALUE; opts->port_direction = ola::client::OUTPUT_PORT; opts->device_id = INVALID_VALUE; opts->merge_mode = OlaUniverse::MERGE_HTP; opts->priority_mode = ola::PRIORITY_MODE_INHERIT; opts->priority_value = 0; } /* * Decide what mode we're running in */ void SetMode(options *opts) { string cmd_name = ola::file::FilenameFromPathOrPath(opts->cmd); // To skip the lt prefix during development ola::StripPrefix(&cmd_name, "lt-"); #ifdef _WIN32 // Strip the extension size_t extension = cmd_name.find("."); if (extension != string::npos) { cmd_name = cmd_name.substr(0, extension); } #endif // _WIN32 if (cmd_name == "ola_plugin_info") { opts->m = PLUGIN_INFO; } else if (cmd_name == "ola_plugin_state") { opts->m = PLUGIN_STATE; } else if (cmd_name == "ola_patch") { opts->m = DEVICE_PATCH; } else if (cmd_name == "ola_ptch") { // Working around Windows UAC opts->m = DEVICE_PATCH; } else if (cmd_name == "ola_uni_info") { opts->m = UNIVERSE_INFO; } else if (cmd_name == "ola_uni_name") { opts->m = UNIVERSE_NAME; } else if (cmd_name == "ola_uni_merge") { opts->m = UNI_MERGE; } else if (cmd_name == "ola_set_dmx") { opts->m = SET_DMX; } else if (cmd_name == "ola_set_priority") { opts->m = SET_PORT_PRIORITY; } } /* * parse our cmd line options */ void ParseOptions(int argc, char *argv[], options *opts) { enum { LIST_PLUGIN_IDS_OPTION = 256, LIST_UNIVERSE_IDS_OPTION, }; static struct option long_options[] = { {"dmx", required_argument, 0, 'd'}, {"help", no_argument, 0, 'h'}, {"ltp", no_argument, 0, 'l'}, {"name", required_argument, 0, 'n'}, {"plugin-id", required_argument, 0, 'p'}, {"state", required_argument, 0, 's'}, {"list-plugin-ids", no_argument, 0, LIST_PLUGIN_IDS_OPTION}, {"list-universe-ids", no_argument, 0, LIST_UNIVERSE_IDS_OPTION}, {"universe", required_argument, 0, 'u'}, {0, 0, 0, 0} }; int c; int option_index = 0; while (1) { c = getopt_long(argc, argv, "ld:n:u:p:s:hv", long_options, &option_index); if (c == -1) break; switch (c) { case 0: break; case 'd': opts->dmx = optarg; break; case 'h': opts->help = true; break; case 'l': opts->merge_mode = OlaUniverse::MERGE_LTP; break; case 'n': opts->uni_name = optarg; break; case 'p': opts->plugin_id = atoi(optarg); break; case 's': opts->state = optarg; break; case 'u': opts->uni = atoi(optarg); break; case LIST_PLUGIN_IDS_OPTION: opts->list_plugin_ids = true; break; case LIST_UNIVERSE_IDS_OPTION: opts->list_universe_ids = true; break; case '?': break; default: break; } } } /* * parse our cmd line options for the patch command */ int ParsePatchOptions(int argc, char *argv[], options *opts) { static struct option long_options[] = { {"device", required_argument, 0, 'd'}, {"help", no_argument, 0, 'h'}, {"input", no_argument, 0, 'i'}, {"patch", no_argument, 0, 'a'}, {"port", required_argument, 0, 'p'}, {"universe", required_argument, 0, 'u'}, {"unpatch", no_argument, 0, 'r'}, {0, 0, 0, 0} }; int c; int option_index = 0; while (1) { c = getopt_long(argc, argv, "ard:p:u:hi", long_options, &option_index); if (c == -1) { break; } switch (c) { case 0: break; case 'a': opts->patch_action = ola::client::PATCH; break; case 'd': opts->device_id = atoi(optarg); break; case 'p': opts->port_id = atoi(optarg); break; case 'r': opts->patch_action = ola::client::UNPATCH; break; case 'u': opts->uni = atoi(optarg); break; case 'h': opts->help = true; break; case 'i': opts->port_direction = ola::client::INPUT_PORT; break; case '?': break; default: break; } } return 0; } /* * parse our cmd line options for the set priority command */ int ParseSetPriorityOptions(int argc, char *argv[], options *opts) { static struct option long_options[] = { {"device", required_argument, 0, 'd'}, {"help", no_argument, 0, 'h'}, {"input", no_argument, 0, 'i'}, {"port", required_argument, 0, 'p'}, {"override", required_argument, 0, 'o'}, {0, 0, 0, 0} }; int c; int option_index = 0; while (1) { c = getopt_long(argc, argv, "d:p:o:hi", long_options, &option_index); if (c == -1) { break; } switch (c) { case 0: break; case 'd': opts->device_id = atoi(optarg); break; case 'h': opts->help = true; break; case 'i': opts->port_direction = ola::client::INPUT_PORT; break; case 'o': opts->priority_mode = ola::PRIORITY_MODE_STATIC; opts->priority_value = atoi(optarg); break; case 'p': opts->port_id = atoi(optarg); break; case '?': break; default: break; } } return 0; } /* * help message for device info */ void DisplayDeviceInfoHelp(const options &opts) { cout << "Usage: " << opts.cmd << " [--plugin-id ]\n" "\n" "Show information on the devices loaded by olad.\n" "\n" " -h, --help Display this help message and exit.\n" " -p, --plugin-id Show only devices owned by this " "plugin.\n" << endl; } /* * Display the Patch help */ void DisplayPatchHelp(const options &opts) { cout << "Usage: " << opts.cmd << " [--patch | --unpatch] --device --port " "[--universe ]\n" "\n" "Control ola port <-> universe mappings.\n" "\n" " -a, --patch Patch this port (default).\n" " -d, --device Id of device to patch.\n" " -h, --help Display this help message and exit.\n" " -p, --port Id of the port to patch.\n" " -r, --unpatch Unpatch this port.\n" " -i, --input Patch the input port (default is " "output).\n" " -u, --universe Id of the universe to patch to (default " "0).\n" << endl; } /* * help message for plugin info */ void DisplayPluginInfoHelp(const options &opts) { cout << "Usage: " << opts.cmd << " [--plugin-id ]\n" "\n" "Get info on the plugins loaded by olad. Called without arguments" " this will\n" "display the plugins loaded by olad. When used with --plugin-id this" " will\n" "display the specified plugin's description.\n" "\n" " -h, --help Display this help message and exit.\n" " -p, --plugin-id Id of the plugin to fetch the " "description of\n" " --list-plugin-ids List plugin Ids only.\n" << endl; } /* * help message for plugin state */ void DisplayPluginStateHelp(const options &opts) { cout << "Usage: " << opts.cmd << " --plugin-id [--state ]\n" "\n" "Displays the enabled/disabled state for a plugin and the list of " "plugins\n" "this plugin will conflict with.\n" "\n" " -h, --help Display this help message and exit.\n" " -p, --plugin-id Id of the plugin to fetch the state " "of\n" " -s, --state State to set a plugin to\n" << endl; } /* * help message for uni info */ void DisplayUniverseInfoHelp(const options &opts) { cout << "Usage: " << opts.cmd << "\n" "Shows info on the active universes in use.\n" "\n" " -h, --help Display this help message and exit.\n" " --list-universe-ids List universe Ids only.\n" << endl; } /* * Help message for set uni name */ void DisplayUniverseNameHelp(const options &opts) { cout << "Usage: " << opts.cmd << " --name --universe \n" "\n" "Set a name for the specified universe\n" "\n" " -h, --help Display this help message and exit.\n" " -n, --name Name for the universe.\n" " -u, --universe Id of the universe to name.\n" << endl; } /* * Help message for set uni merge mode */ void DisplayUniverseMergeHelp(const options &opts) { cout << "Usage: " << opts.cmd << " --universe [--ltp]\n" "\n" "Change the merge mode for the specified universe. Without --ltp " "it will\n" "revert to HTP mode.\n" "\n" " -h, --help Display this help message and exit.\n" " -l, --ltp Change to LTP mode.\n" " -u, --universe Id of the universe to change.\n" << endl; } /* * Help message for set dmx */ void DisplaySetDmxHelp(const options &opts) { cout << "Usage: " << opts.cmd << " --universe --dmx \n" "\n" "Sets the DMX values for a universe.\n" "\n" " -h, --help Display this help message and exit.\n" " -u, --universe Universe number, e.g. 0.\n" " -d, --dmx Comma separated DMX values, e.g. " "0,255,128 sets first channel to 0, second channel to 255" " and third channel to 128.\n" << endl; } /* * Display the Patch help */ void DisplaySetPriorityHelp(const options &opts) { cout << "Usage: " << opts.cmd << " --device --port [--override ]\n" "\n" "Set a port's priority, without the --override flag this will set " "the port\n" " to inherit mode.\n" "\n" " -d, --device Id of device to set priority for.\n" " -h, --help Display this help message and exit.\n" " -i, --input Set an input port\n" " -o, --override Set the port priority to a static " "value.\n" " -p, --port Id of the port to set priority for.\n" << endl; } /* * Display the help message */ void DisplayHelpAndExit(const options &opts) { switch (opts.m) { case DEVICE_INFO: DisplayDeviceInfoHelp(opts); break; case DEVICE_PATCH: DisplayPatchHelp(opts); break; case PLUGIN_INFO: DisplayPluginInfoHelp(opts); break; case PLUGIN_STATE: DisplayPluginStateHelp(opts); break; case UNIVERSE_INFO: DisplayUniverseInfoHelp(opts); break; case UNIVERSE_NAME: DisplayUniverseNameHelp(opts); break; case UNI_MERGE: DisplayUniverseMergeHelp(opts); break; case SET_DMX: DisplaySetDmxHelp(opts); break; case SET_PORT_PRIORITY: DisplaySetPriorityHelp(opts); } exit(0); } /* * Send a fetch device info request * @param client the ola client * @param opts the const options */ int FetchDeviceInfo(OlaClientWrapper *wrapper, const options &opts) { SelectServer *ss = wrapper->GetSelectServer(); OlaClient *client = wrapper->GetClient(); client->FetchDeviceInfo((ola::ola_plugin_id) opts.plugin_id, NewSingleCallback(&DisplayDevices, ss)); return 0; } void Patch(OlaClientWrapper *wrapper, const options &opts) { SelectServer *ss = wrapper->GetSelectServer(); OlaClient *client = wrapper->GetClient(); if (opts.device_id == INVALID_VALUE || opts.port_id == INVALID_VALUE) { DisplayPatchHelp(opts); exit(1); } if (opts.patch_action == ola::client::PATCH && opts.uni == INVALID_VALUE) { DisplayPatchHelp(opts); exit(1); } client->Patch(opts.device_id, opts.port_id, opts.port_direction, opts.patch_action, opts.uni, NewSingleCallback(&HandleAck, ss)); } /* * Fetch information on plugins. */ int FetchPluginInfo(OlaClientWrapper *wrapper, const options &opts) { SelectServer *ss = wrapper->GetSelectServer(); OlaClient *client = wrapper->GetClient(); if (opts.plugin_id > 0) { client->FetchPluginDescription( (ola::ola_plugin_id) opts.plugin_id, NewSingleCallback(&DisplayPluginDescription, ss)); } else { client->FetchPluginList( NewSingleCallback(&DisplayPlugins, ss, opts.list_plugin_ids)); } return 0; } /* * Fetch the state of a plugin. */ int FetchPluginState(OlaClientWrapper *wrapper, const options &opts) { SelectServer *ss = wrapper->GetSelectServer(); OlaClient *client = wrapper->GetClient(); if (opts.plugin_id == 0) { DisplayPluginStateHelp(opts); exit(1); } if (!opts.state.empty()) { bool state; if (ola::StringToBoolTolerant(opts.state, &state)) { cout << "Setting state to " << (state ? "enabled" : "disabled") << endl; client->SetPluginState( (ola::ola_plugin_id) opts.plugin_id, state, NewSingleCallback(&HandleAck, ss)); } else { cerr << "Invalid state: " << opts.state << endl; DisplayPluginStateHelp(opts); exit(1); } } else { client->FetchPluginState((ola::ola_plugin_id) opts.plugin_id, NewSingleCallback(&DisplayPluginState, ss)); } return 0; } /* * send a set name request * @param client the ola client * @param opts the const options */ int SetUniverseName(OlaClientWrapper *wrapper, const options &opts) { SelectServer *ss = wrapper->GetSelectServer(); OlaClient *client = wrapper->GetClient(); if (opts.uni == INVALID_VALUE) { DisplayUniverseNameHelp(opts); exit(1); } client->SetUniverseName(opts.uni, opts.uni_name, NewSingleCallback(&HandleAck, ss)); return 0; } /* * send a set name request * @param client the ola client * @param opts the const options */ int SetUniverseMergeMode(OlaClientWrapper *wrapper, const options &opts) { SelectServer *ss = wrapper->GetSelectServer(); OlaClient *client = wrapper->GetClient(); if (opts.uni == INVALID_VALUE) { DisplayUniverseMergeHelp(opts); exit(1); } client->SetUniverseMergeMode( opts.uni, opts.merge_mode, NewSingleCallback(&HandleAck, ss)); return 0; } /* * Send a DMX message * @param client the ola client * @param opts the options */ int SendDmx(OlaClientWrapper *wrapper, const options &opts) { SelectServer *ss = wrapper->GetSelectServer(); OlaClient *client = wrapper->GetClient(); ola::DmxBuffer buffer; bool status = buffer.SetFromString(opts.dmx); if (opts.uni < 0 || !status || buffer.Size() == 0) { DisplaySetDmxHelp(opts); exit(1); } ola::client::SendDMXArgs args(NewSingleCallback(&HandleAck, ss)); client->SendDMX(opts.uni, buffer, args); return 0; } /* * Set the priority of a port */ void SetPortPriority(OlaClientWrapper *wrapper, const options &opts) { SelectServer *ss = wrapper->GetSelectServer(); OlaClient *client = wrapper->GetClient(); if (opts.device_id == INVALID_VALUE || opts.port_id == INVALID_VALUE) { DisplaySetPriorityHelp(opts); exit(1); } if (opts.priority_mode == ola::PRIORITY_MODE_INHERIT) { client->SetPortPriorityInherit( opts.device_id, opts.port_id, opts.port_direction, NewSingleCallback(&HandleAck, ss)); } else if (opts.priority_mode == ola::PRIORITY_MODE_STATIC) { client->SetPortPriorityOverride( opts.device_id, opts.port_id, opts.port_direction, opts.priority_value, NewSingleCallback(&HandleAck, ss)); } else { DisplaySetPriorityHelp(opts); } } /* * Main */ int main(int argc, char *argv[]) { ola::InitLogging(ola::OLA_LOG_WARN, ola::OLA_LOG_STDERR); if (!ola::NetworkInit()) { OLA_WARN << "Network initialization failed." << endl; exit(ola::EXIT_UNAVAILABLE); } OlaClientWrapper ola_client; options opts; InitOptions(&opts); opts.cmd = argv[0]; // decide how we should behave SetMode(&opts); if (opts.m == DEVICE_PATCH) { ParsePatchOptions(argc, argv, &opts); } else if (opts.m == SET_PORT_PRIORITY) { ParseSetPriorityOptions(argc, argv, &opts); } else { ParseOptions(argc, argv, &opts); } if (opts.help) { DisplayHelpAndExit(opts); } if (!ola_client.Setup()) { OLA_FATAL << "Setup failed"; exit(1); } switch (opts.m) { case DEVICE_INFO: FetchDeviceInfo(&ola_client, opts); break; case DEVICE_PATCH: Patch(&ola_client, opts); break; case PLUGIN_INFO: FetchPluginInfo(&ola_client, opts); break; case PLUGIN_STATE: FetchPluginState(&ola_client, opts); break; case UNIVERSE_INFO: ola_client.GetClient()->FetchUniverseList( NewSingleCallback(&DisplayUniverses, ola_client.GetSelectServer(), opts.list_universe_ids)); break; case UNIVERSE_NAME: SetUniverseName(&ola_client, opts); break; case UNI_MERGE: SetUniverseMergeMode(&ola_client, opts); break; case SET_DMX: SendDmx(&ola_client, opts); break; case SET_PORT_PRIORITY: SetPortPriority(&ola_client, opts); } ola_client.GetSelectServer()->Run(); return 0; } ola-0.10.5.nojsmin/examples/ola-dmxmonitor.cpp0000644000175000017500000004217013134123277020762 0ustar wouterwouter/* * Copyright (C) 2001 Dirk Jagdmann * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Modified by Simon Newton (nomis52gmail.com) to use ola * * The (void) before attrset is due to a bug in curses. See * http://www.mail-archive.com/debian-bugs-dist@lists.debian.org/msg682294.html */ #ifdef HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_FTIME #include #endif // HAVE_FTIME #include #include #include #include #include #include #include #include #include #include #include #include using ola::Clock; using ola::DmxBuffer; using ola::client::OlaClient; using ola::client::OlaClientWrapper; using ola::client::Result; using ola::TimeInterval; using ola::TimeStamp; using ola::io::SelectServer; using std::string; static const unsigned int DEFAULT_UNIVERSE = 0; static const unsigned char CHANNEL_DISPLAY_WIDTH = 4; static const unsigned char ROWS_PER_CHANNEL_ROW = 2; /* color names used */ enum { CHANNEL = 1, ZERO, NORM, FULL, HEADLINE, HEADEMPH, HEADERROR, MAXCOLOR }; /* display modes */ enum { DISP_MODE_DMX = 0, DISP_MODE_HEX, DISP_MODE_DEC, DISP_MODE_MAX, }; typedef struct { unsigned int universe; bool help; // help } options; class DmxMonitor *dmx_monitor; static unsigned int display_mode = DISP_MODE_DMX; static int current_channel = 0; /* channel cursor is positioned on */ static int first_channel = 0; /* channel in upper left corner */ static unsigned int channels_per_line = 80 / CHANNEL_DISPLAY_WIDTH; // Default chans/screen is 80x24, less a row for the header, // and one at the bottom to get an even number of rows static unsigned int channels_per_screen = (80 / CHANNEL_DISPLAY_WIDTH) * ((24 - 2) / ROWS_PER_CHANNEL_ROW); static int palette[MAXCOLOR]; /* * The observer class which responds to events */ class DmxMonitor { public: explicit DmxMonitor(unsigned int universe) : m_universe(universe), m_counter(0), m_palette_number(0), m_stdin_descriptor(STDIN_FILENO), m_window(NULL), m_data_loss_window(NULL), m_channels_offset(true) { } ~DmxMonitor() { if (m_window) { resetty(); endwin(); } } bool Init(); void Run() { m_client.GetSelectServer()->Run(); } void NewDmx(const ola::client::DMXMetadata &meta, const DmxBuffer &buffer); void RegisterComplete(const Result &result); void StdinReady(); bool CheckDataLoss(); void DrawDataLossWindow(); void TerminalResized(); private: unsigned int m_universe; unsigned int m_counter; int m_palette_number; ola::io::UnmanagedFileDescriptor m_stdin_descriptor; TimeStamp m_last_data; WINDOW *m_window; WINDOW *m_data_loss_window; bool m_channels_offset; // start from channel 1 rather than 0; OlaClientWrapper m_client; DmxBuffer m_buffer; void DrawScreen(bool include_values = true); void Mask(); void Values(); void ChangePalette(int p); void CalcScreenGeometry(); }; /* * Setup the monitoring console */ bool DmxMonitor::Init() { /* set up ola connection */ if (!m_client.Setup()) { printf("error: %s", strerror(errno)); return false; } OlaClient *client = m_client.GetClient(); client->SetDMXCallback(ola::NewCallback(this, &DmxMonitor::NewDmx)); client->RegisterUniverse( m_universe, ola::client::REGISTER, ola::NewSingleCallback(this, &DmxMonitor::RegisterComplete)); /* init curses */ m_window = initscr(); if (!m_window) { printf("unable to open main-screen\n"); return false; } savetty(); start_color(); noecho(); raw(); keypad(m_window, TRUE); m_client.GetSelectServer()->AddReadDescriptor(&m_stdin_descriptor); m_stdin_descriptor.SetOnData( ola::NewCallback(this, &DmxMonitor::StdinReady)); m_client.GetSelectServer()->RegisterRepeatingTimeout( 500, ola::NewCallback(this, &DmxMonitor::CheckDataLoss)); CalcScreenGeometry(); ChangePalette(m_palette_number); m_buffer.Blackout(); DrawScreen(); return true; } /* * Called when there is new DMX data */ void DmxMonitor::NewDmx(OLA_UNUSED const ola::client::DMXMetadata &meta, const DmxBuffer &buffer) { m_buffer.Set(buffer); if (m_data_loss_window) { // delete the window wborder(m_data_loss_window, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '); wrefresh(m_data_loss_window); delwin(m_data_loss_window); m_data_loss_window = NULL; Mask(); } move(0, COLS - 1); // NOLINT(build/include_what_you_use) This is ncurses.h's switch (m_counter % 4) { case 0: printw("/"); break; case 1: printw("-"); break; case 2: printw("\\"); break; default: printw("|"); break; } m_counter++; Clock clock; clock.CurrentTime(&m_last_data); Values(); refresh(); } void DmxMonitor::RegisterComplete(const Result &result) { if (!result.Success()) { std::cerr << "Register command failed with " << result.Error() << std::endl; m_client.GetSelectServer()->Terminate(); } } /* * Called when there is input from the keyboard */ void DmxMonitor::StdinReady() { int c = wgetch(m_window); switch (c) { case KEY_HOME: current_channel = 0; first_channel = 0; DrawScreen(); break; case KEY_END: current_channel = ola::DMX_UNIVERSE_SIZE - 1; if (channels_per_screen >= ola::DMX_UNIVERSE_SIZE) { first_channel = 0; } else { first_channel = current_channel - (channels_per_screen - 1); } DrawScreen(); break; case 'l': case 'L': case KEY_RIGHT: if (current_channel < ola::DMX_UNIVERSE_SIZE - 1) { current_channel++; if (current_channel >= static_cast(first_channel + channels_per_screen)) { first_channel += channels_per_line; } DrawScreen(); } break; case 'h': case 'H': case KEY_LEFT: if (current_channel > 0) { current_channel--; if (current_channel < first_channel) { first_channel -= channels_per_line; if (first_channel < 0) first_channel = 0; } DrawScreen(); } break; case 'j': case 'J': case KEY_DOWN: current_channel += channels_per_line; if (current_channel >= ola::DMX_UNIVERSE_SIZE) current_channel = ola::DMX_UNIVERSE_SIZE - 1; if (current_channel >= static_cast(first_channel + channels_per_screen)) { first_channel += channels_per_line; } DrawScreen(); break; case 'k': case 'K': case KEY_UP: current_channel -= channels_per_line; if (current_channel < 0) current_channel = 0; if (current_channel < first_channel) { first_channel -= channels_per_line; if (first_channel < 0) first_channel = 0; } DrawScreen(); break; case 'M': case 'm': if (++display_mode >= DISP_MODE_MAX) display_mode = 0; DrawScreen(); break; case 'N': case 'n': m_channels_offset = !m_channels_offset; DrawScreen(false); break; case 'P': case 'p': ChangePalette(++m_palette_number); DrawScreen(); break; case 'Q': case 'q': m_client.GetSelectServer()->Terminate(); break; default: break; } } /* * Check for data loss. * TODO(simon): move to the ola server */ bool DmxMonitor::CheckDataLoss() { if (m_last_data.IsSet()) { TimeStamp now; Clock clock; clock.CurrentTime(&now); TimeInterval diff = now - m_last_data; if (diff > TimeInterval(2, 5000000)) { // loss of data DrawDataLossWindow(); } } return true; } void DmxMonitor::DrawDataLossWindow() { if (!m_data_loss_window) { m_data_loss_window = newwin(3, 14, (LINES - 3) / 2, (COLS - 14) / 2); } mvwprintw(m_data_loss_window, 1, 2, "Data Loss!"); wborder(m_data_loss_window, '|', '|', '-', '-', '+', '+', '+', '+'); wrefresh(m_data_loss_window); } /* * Called when the terminal is resized */ void DmxMonitor::TerminalResized() { struct winsize size; if (ioctl(0, TIOCGWINSZ, &size) < 0) return; resizeterm(size.ws_row, size.ws_col); CalcScreenGeometry(); DrawScreen(); } void DmxMonitor::DrawScreen(bool include_values) { if (include_values) erase(); Mask(); if (include_values) Values(); refresh(); if (m_data_loss_window) DrawDataLossWindow(); } /* display the channels numbers */ void DmxMonitor::Mask() { unsigned int i = 0, x, y; unsigned int channel = first_channel; /* clear headline */ (void) attrset(palette[HEADLINE]); move(0, 0); // NOLINT(build/include_what_you_use) This is ncurses.h's move for (x = 0; static_cast(x) < COLS; x++) addch(' '); if (COLS > 15) { mvprintw(0 , 0, "Universe: "); printw("%u", m_universe); } /* write channel numbers */ (void) attrset(palette[CHANNEL]); for (y = 1; static_cast(y) < LINES && static_cast(channel) < ola::DMX_UNIVERSE_SIZE && i < channels_per_screen; y += ROWS_PER_CHANNEL_ROW) { move(y, 0); // NOLINT(build/include_what_you_use) This is ncurses.h's move for (x = 0; static_cast(x) < static_cast(channels_per_line) && static_cast(channel) < ola::DMX_UNIVERSE_SIZE && static_cast(i < channels_per_screen); x++, i++, channel++) { switch (display_mode) { case DISP_MODE_HEX: printw("%03X ", channel + (m_channels_offset ? 1 : 0)); break; case DISP_MODE_DMX: case DISP_MODE_DEC: default: printw("%03d ", channel + (m_channels_offset ? 1 : 0)); break; } } } } /* * Update the screen with new values */ void DmxMonitor::Values() { int i = 0, x, y, z = first_channel; /* values */ for (y = ROWS_PER_CHANNEL_ROW; y < LINES && z < ola::DMX_UNIVERSE_SIZE && i < static_cast(channels_per_screen); y += ROWS_PER_CHANNEL_ROW) { move(y, 0); // NOLINT(build/include_what_you_use) This is ncurses.h's move for (x = 0; x < static_cast(channels_per_line) && z < ola::DMX_UNIVERSE_SIZE && i < static_cast(channels_per_screen); x++, z++, i++) { const int d = m_buffer.Get(z); switch (d) { case ola::DMX_MIN_SLOT_VALUE: (void) attrset(palette[ZERO]); break; case ola::DMX_MAX_SLOT_VALUE: (void) attrset(palette[FULL]); break; default: (void) attrset(palette[NORM]); } if (static_cast(z) == current_channel) attron(A_REVERSE); switch (display_mode) { case DISP_MODE_HEX: if (d == 0) { if (static_cast(m_buffer.Size()) <= z) { addstr("--- "); } else { addstr(" "); } } else { printw(" %02x ", d); } break; case DISP_MODE_DEC: if (d == 0) { if (static_cast(m_buffer.Size()) <= z) { addstr("--- "); } else { addstr(" "); } } else if (d < 100) { printw(" %02d ", d); } else { printw("%03d ", d); } break; case DISP_MODE_DMX: default: switch (d) { case ola::DMX_MIN_SLOT_VALUE: if (static_cast(m_buffer.Size()) <= z) { addstr("--- "); } else { addstr(" "); } break; case ola::DMX_MAX_SLOT_VALUE: addstr(" FL "); break; default: printw(" %02d ", (d * 100) / ola::DMX_MAX_SLOT_VALUE); } } } } } /* change palette to "p". If p is invalid new palette is number "0". */ void DmxMonitor::ChangePalette(int p) { /* COLOR_BLACK COLOR_RED COLOR_GREEN COLOR_YELLOW COLOR_BLUE COLOR_MAGENTA COLOR_CYAN COLOR_WHITE A_NORMAL A_ATTRIBUTES A_CHARTEXT A_COLOR A_STANDOUT A_UNDERLINE A_REVERSE A_BLINK A_DIM A_BOLD A_ALTCHARSET A_INVIS */ switch (p) { default: m_palette_number = 0; // fall through, use 0 as default palette OLA_FALLTHROUGH case 0: init_pair(CHANNEL, COLOR_BLACK, COLOR_CYAN); init_pair(ZERO, COLOR_BLACK, COLOR_WHITE); init_pair(NORM, COLOR_BLUE, COLOR_WHITE); init_pair(FULL, COLOR_RED, COLOR_WHITE); init_pair(HEADLINE, COLOR_WHITE, COLOR_BLUE); init_pair(HEADEMPH, COLOR_YELLOW, COLOR_BLUE); init_pair(HEADERROR, COLOR_RED, COLOR_BLUE); goto color; case 2: init_pair(CHANNEL, COLOR_BLACK, COLOR_WHITE); init_pair(ZERO, COLOR_BLUE, COLOR_BLACK); init_pair(NORM, COLOR_GREEN, COLOR_BLACK); init_pair(FULL, COLOR_RED, COLOR_BLACK); init_pair(HEADLINE, COLOR_WHITE, COLOR_BLACK); init_pair(HEADEMPH, COLOR_CYAN, COLOR_BLACK); init_pair(HEADERROR, COLOR_RED, COLOR_BLACK); goto color; color: palette[CHANNEL] = COLOR_PAIR(CHANNEL); palette[ZERO] = COLOR_PAIR(ZERO); palette[NORM] = COLOR_PAIR(NORM); palette[FULL] = COLOR_PAIR(FULL); palette[HEADLINE] = COLOR_PAIR(HEADLINE); palette[HEADEMPH] = COLOR_PAIR(HEADEMPH); palette[HEADERROR] = COLOR_PAIR(HEADERROR); break; case 1: palette[CHANNEL] = A_REVERSE; palette[ZERO] = A_NORMAL; palette[NORM] = A_NORMAL; palette[FULL] = A_BOLD; palette[HEADLINE] = A_NORMAL; palette[HEADEMPH] = A_NORMAL; palette[HEADERROR] = A_BOLD; break; } } /* calculate channels_per_line and channels_per_screen from LINES and COLS */ void DmxMonitor::CalcScreenGeometry() { int c = LINES; if (c < 3) { std::cerr << "Terminal must be more than 3 lines" << std::endl; exit(1); } c--; // one line for headline if (c % ROWS_PER_CHANNEL_ROW == 1) c--; // Need an even number of lines for data channels_per_line = COLS / CHANNEL_DISPLAY_WIDTH; channels_per_screen = channels_per_line * (c / ROWS_PER_CHANNEL_ROW); } /* signal handler for SIGWINCH */ void terminalresize(int sig) { dmx_monitor->TerminalResized(); (void) sig; } /* cleanup handler for program exit. */ void cleanup() { if (dmx_monitor) delete dmx_monitor; } /* * parse our cmd line options */ void ParseOptions(int argc, char *argv[], options *opts) { static struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"universe", required_argument, 0, 'u'}, {0, 0, 0, 0} }; opts->universe = DEFAULT_UNIVERSE; opts->help = false; int c; int option_index = 0; while (1) { c = getopt_long(argc, argv, "hu:", long_options, &option_index); if (c == -1) break; switch (c) { case 0: break; case 'h': opts->help = true; break; case 'u': opts->universe = strtoul(optarg, NULL, 0); break; case '?': break; default: break; } } } /* * Display the help message */ void DisplayHelpAndExit(char arg[]) { std::cout << "Usage: " << arg << " [--universe ]\n" "\n" "Monitor the values on a DMX512 universe.\n" "\n" " -h, --help Display this help message and exit.\n" " -u, --universe Id of universe to monitor (defaults to " << DEFAULT_UNIVERSE << ").\n" << std::endl; exit(ola::EXIT_OK); } int main(int argc, char *argv[]) { signal(SIGWINCH, terminalresize); atexit(cleanup); if (!ola::NetworkInit()) { std::cerr << "Network initialization failed." << std::endl; exit(ola::EXIT_UNAVAILABLE); } options opts; ParseOptions(argc, argv, &opts); if (opts.help) { DisplayHelpAndExit(argv[0]); } dmx_monitor = new DmxMonitor(opts.universe); if (!dmx_monitor->Init()) return 1; dmx_monitor->Run(); delete dmx_monitor; dmx_monitor = NULL; return 0; } ola-0.10.5.nojsmin/examples/ola-uni-stats.cpp0000644000175000017500000001633313023355232020506 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ola-uni-stats.cpp * Display some simple universe stats. * Copyright (C) 2012 Simon Newton */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using ola::DmxBuffer; using ola::OlaCallbackClientWrapper; using ola::StringToInt; using ola::TimeInterval; using ola::TimeStamp; using ola::io::SelectServer; using std::cerr; using std::cout; using std::endl; using std::setw; using std::string; using std::vector; class UniverseTracker { public: UniverseTracker(OlaCallbackClientWrapper *wrapper, const vector &universes); ~UniverseTracker() {} bool Run(); void Stop() { m_wrapper->GetSelectServer()->Terminate(); } void PrintStats(); void ResetStats(); protected: void Input(int c); private: struct UniverseStats { public: uint16_t shortest_frame; uint16_t longest_frame; uint64_t frame_count; uint64_t frame_changes; DmxBuffer frame_data; UniverseStats() { Reset(); } void Reset() { shortest_frame = ola::DMX_UNIVERSE_SIZE + 1, longest_frame = 0; frame_count = 0; frame_changes = 0; } }; typedef std::map UniverseStatsMap; UniverseStatsMap m_stats; ola::TimeStamp m_start_time; OlaCallbackClientWrapper *m_wrapper; ola::io::StdinHandler m_stdin_handler; ola::Clock m_clock; void UniverseData(unsigned int universe, const DmxBuffer &dmx, const string &error); void RegisterComplete(const string &error); }; UniverseTracker::UniverseTracker(OlaCallbackClientWrapper *wrapper, const vector &universes) : m_wrapper(wrapper), m_stdin_handler(wrapper->GetSelectServer(), ola::NewCallback(this, &UniverseTracker::Input)) { // set callback m_wrapper->GetClient()->SetDmxCallback( ola::NewCallback(this, &UniverseTracker::UniverseData)); vector::const_iterator iter = universes.begin(); for (; iter != universes.end(); ++iter) { struct UniverseStats stats; m_stats[*iter] = stats; // register here m_wrapper->GetClient()->RegisterUniverse( *iter, ola::REGISTER, ola::NewSingleCallback(this, &UniverseTracker::RegisterComplete)); } } bool UniverseTracker::Run() { m_clock.CurrentTime(&m_start_time); m_wrapper->GetSelectServer()->Run(); return true; } void UniverseTracker::PrintStats() { UniverseStatsMap::iterator iter = m_stats.begin(); TimeStamp now; m_clock.CurrentTime(&now); TimeInterval interval = now - m_start_time; OLA_INFO << "Time delta was " << interval; for (; iter != m_stats.end(); ++iter) { const UniverseStats stats = iter->second; float fps = 0.0; if (interval.Seconds() > 0) fps = static_cast(stats.frame_count) / interval.Seconds(); cout << "Universe " << iter->first << endl; cout << " Frames Received: " << stats.frame_count << ", Frames/sec: " << fps << endl; cout << " Frame changes: " << stats.frame_changes << endl; cout << " Smallest Frame: "; if (stats.shortest_frame == ola::DMX_UNIVERSE_SIZE + 1) cout << "N/A"; else cout << stats.shortest_frame; cout << ", Largest Frame: "; if (stats.longest_frame == 0) cout << "N/A"; else cout << stats.longest_frame; cout << endl; cout << "------------------------------" << endl; } } void UniverseTracker::ResetStats() { m_clock.CurrentTime(&m_start_time); UniverseStatsMap::iterator iter = m_stats.begin(); for (; iter != m_stats.end(); ++iter) { iter->second.Reset(); } cout << "Reset counters" << endl; } void UniverseTracker::Input(int c) { switch (c) { case 'q': m_wrapper->GetSelectServer()->Terminate(); break; case 'p': PrintStats(); break; case 'r': ResetStats(); break; default: break; } } void UniverseTracker::UniverseData(unsigned int universe, const DmxBuffer &dmx, const string &error) { if (!error.empty()) { OLA_WARN << error; return; } UniverseStatsMap::iterator iter = m_stats.find(universe); if (iter == m_stats.end()) { OLA_WARN << "Received data for unknown universe " << universe; return; } if (dmx.Size() < iter->second.shortest_frame) iter->second.shortest_frame = dmx.Size(); if (dmx.Size() > iter->second.longest_frame) iter->second.longest_frame = dmx.Size(); iter->second.frame_count++; DmxBuffer &last_dmx = iter->second.frame_data; if (last_dmx.Size() == 0) { // this is the first frame last_dmx.Set(dmx); } else { if (last_dmx.Size() != dmx.Size() || last_dmx != dmx) { // the frame changed iter->second.frame_changes++; last_dmx.Set(dmx); } } } void UniverseTracker::RegisterComplete(const string &error) { if (!error.empty()) OLA_WARN << "Register command failed with " << errno; } SelectServer *ss = NULL; static void InteruptSignal(OLA_UNUSED int signo) { int old_errno = errno; if (ss) { ss->Terminate(); } errno = old_errno; } /* * Main */ int main(int argc, char *argv[]) { ola::AppInit( &argc, argv, "[options] ...", "Watch one or more universes and produce stats on DMX frame rates."); vector universes; for (int i = 1; i < argc; i++) { unsigned int universe; if (!StringToInt(argv[i], &universe, true)) { cerr << "Invalid Universe " << argv[i] << endl; exit(ola::EXIT_USAGE); } universes.push_back(universe); } if (universes.size() <= 0) { ola::DisplayUsageAndExit(); } ola::OlaCallbackClientWrapper ola_client; if (!ola_client.Setup()) { OLA_FATAL << "Setup failed"; exit(ola::EXIT_UNAVAILABLE); } ss = ola_client.GetSelectServer(); UniverseTracker tracker(&ola_client, universes); ola::InstallSignal(SIGINT, InteruptSignal); cout << "Actions:" << endl; cout << " p - Print stats" << endl; cout << " q - Quit" << endl; cout << " r - Reset stats" << endl; bool r = tracker.Run(); if (r) tracker.PrintStats(); return r; } ola-0.10.5.nojsmin/examples/ola-e131.cpp0000644000175000017500000001302513023355232017223 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ola-e131.cpp * Configure an E1.31 device * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include #include #include #include #include "examples/OlaConfigurator.h" using std::cerr; using std::cout; using std::endl; using std::string; DECLARE_int32(device); DEFINE_s_uint32(port_id, p, 0, "Id of the port to control"); DEFINE_s_default_bool(input, i, false, "Set an input port, otherwise set an output port."); DEFINE_bool(preview_mode, false, "Set the preview mode bit on|off"); DEFINE_default_bool(discovery, false, "Get the discovery state"); /* * A class that configures E131 devices */ class E131Configurator: public OlaConfigurator { public: E131Configurator() : OlaConfigurator(FLAGS_device, ola::OLA_PLUGIN_E131) {} void HandleConfigResponse(const string &reply, const string &error); void SendConfigRequest(); private: void DisplayOptions(const ola::plugin::e131::PortInfoReply &reply); void DisplaySourceList(const ola::plugin::e131::SourceListReply &reply); }; /* * Handle the device config reply */ void E131Configurator::HandleConfigResponse(const string &reply, const string &error) { Terminate(); if (!error.empty()) { cerr << error << endl; return; } ola::plugin::e131::Reply reply_pb; if (!reply_pb.ParseFromString(reply)) { cout << "Protobuf parsing failed" << endl; return; } switch (reply_pb.type()) { case ola::plugin::e131::Reply::E131_PORT_INFO: if (reply_pb.has_port_info()) { DisplayOptions(reply_pb.port_info()); } else { cout << "Missing port_info field in reply" << endl; } break; case ola::plugin::e131::Reply::E131_SOURCES_LIST: if (reply_pb.has_source_list()) { DisplaySourceList(reply_pb.source_list()); } else { cout << "Missing source_list field in reply" << endl; } break; default: cout << "Invalid response type" << endl; } } /* * Send a get parameters request * @param device_id the device to send the request to * @param client the OLAClient */ void E131Configurator::SendConfigRequest() { ola::plugin::e131::Request request; if (FLAGS_preview_mode.present()) { if (FLAGS_port_id.present()) { request.set_type(ola::plugin::e131::Request::E131_PREVIEW_MODE); ola::plugin::e131::PreviewModeRequest *preview_request = request.mutable_preview_mode(); preview_request->set_port_id(FLAGS_port_id); preview_request->set_preview_mode(FLAGS_preview_mode); preview_request->set_input_port(FLAGS_input); } else { cout << "Please specify a port number" << endl; request.set_type(ola::plugin::e131::Request::E131_PORT_INFO); } } else if (FLAGS_discovery) { request.set_type(ola::plugin::e131::Request::E131_SOURCES_LIST); ola::plugin::e131::SourceListRequest *source_list_request = request.mutable_source_list(); (void) source_list_request; // no options for now. } else { request.set_type(ola::plugin::e131::Request::E131_PORT_INFO); } SendMessage(request); } /* * Display the widget parameters */ void E131Configurator::DisplayOptions( const ola::plugin::e131::PortInfoReply &reply) { for (int i = 0; i < reply.input_port_size(); i++) { cout << "Input Port " << reply.input_port(i).port_id() << ", ignore preview mode " << (reply.input_port(i).preview_mode() ? "on" : "off") << endl; } for (int i = 0; i < reply.output_port_size(); i++) { cout << "Output Port " << reply.output_port(i).port_id() << ", preview mode " << (reply.output_port(i).preview_mode() ? "on" : "off") << endl; } } void E131Configurator::DisplaySourceList( const ola::plugin::e131::SourceListReply &reply) { if (reply.unsupported()) { cout << "Discovery mode isn't enabled" << endl; return; } for (int i = 0; i < reply.source_size(); i++) { const ola::plugin::e131::SourceEntry &entry = reply.source(i); cout << entry.cid() << " (" << entry.ip_address() << ")"; if (entry.has_source_name()) { cout << ", " << entry.source_name(); } cout << endl; for (int j = 0; j < entry.universe_size(); j++) { cout << " " << entry.universe(j) << endl; } } } /* * The main function */ int main(int argc, char*argv[]) { ola::AppInit( &argc, argv, "-d -p [--input] --preview-mode ", "Configure E1.31 devices managed by OLA."); if (FLAGS_device < 0) ola::DisplayUsageAndExit(); E131Configurator configurator; if (!configurator.Setup()) { cerr << "Error: " << strerror(errno) << endl; exit(1); } configurator.Run(); return 0; } ola-0.10.5.nojsmin/examples/ola-recorder.cpp0000644000175000017500000001254013023355232020360 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ola-recorder.cpp * A simple tool to record & playback shows. * Copyright (C) 2011 Simon Newton */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "examples/ShowPlayer.h" #include "examples/ShowLoader.h" #include "examples/ShowRecorder.h" using std::auto_ptr; using std::cout; using std::endl; using std::map; using std::vector; using std::string; DEFINE_s_string(playback, p, "", "The show file to playback."); DEFINE_s_string(record, r, "", "The show file to record data to."); DEFINE_string(verify, "", "The show file to verify."); DEFINE_s_string(universes, u, "", "A comma separated list of universes to record"); DEFINE_s_uint32(delay, d, 0, "The delay in ms between successive iterations."); DEFINE_uint32(duration, 0, "The length of time (seconds) to run for."); // 0 means infinite looping DEFINE_s_uint32(iterations, i, 1, "The number of times to repeat the show, 0 means unlimited."); void TerminateRecorder(ShowRecorder *recorder) { recorder->Stop(); } /** * Record a show */ int RecordShow() { if (FLAGS_universes.str().empty()) { OLA_FATAL << "No universes specified, use -u"; exit(ola::EXIT_USAGE); } vector universe_strs; vector universes; ola::StringSplit(FLAGS_universes.str(), &universe_strs, ","); vector::const_iterator iter = universe_strs.begin(); for (; iter != universe_strs.end(); ++iter) { unsigned int universe; if (!ola::StringToInt(*iter, &universe)) { OLA_FATAL << *iter << " isn't a valid universe number"; exit(ola::EXIT_USAGE); } universes.push_back(universe); } ShowRecorder show_recorder(FLAGS_record.str(), universes); int status = show_recorder.Init(); if (status) return status; { ola::thread::SignalThread signal_thread; cout << "Recording, hit Control-C to end" << endl; signal_thread.InstallSignalHandler( SIGINT, ola::NewCallback(TerminateRecorder, &show_recorder)); signal_thread.InstallSignalHandler( SIGTERM, ola::NewCallback(TerminateRecorder, &show_recorder)); if (!signal_thread.Start()) { show_recorder.Stop(); } show_recorder.Record(); } cout << "Saved " << show_recorder.FrameCount() << " frames" << endl; return ola::EXIT_OK; } /** * Verify a show file is valid */ int VerifyShow(const string &filename) { ShowLoader loader(filename); if (!loader.Load()) return ola::EXIT_NOINPUT; map frames_by_universe; uint64_t total_time = 0; unsigned int universe; ola::DmxBuffer buffer; unsigned int timeout; ShowLoader::State state; while (true) { state = loader.NextFrame(&universe, &buffer); if (state != ShowLoader::OK) break; frames_by_universe[universe]++; state = loader.NextTimeout(&timeout); if (state != ShowLoader::OK) break; total_time += timeout; } map::const_iterator iter; unsigned int total = 0; cout << "------------ Summary ----------" << endl; for (iter = frames_by_universe.begin(); iter != frames_by_universe.end(); ++iter) { cout << "Universe " << iter->first << ": " << iter->second << " frames" << endl; total += iter->second; } cout << "Total frames: " << total << endl; cout << "Playback time: " << total_time / 1000 << "." << total_time % 10 << " seconds" << endl; if ((state == ShowLoader::OK) || (state == ShowLoader::END_OF_FILE)) { return ola::EXIT_OK; } else { OLA_FATAL << "Error loading show, got state " << state; return ola::EXIT_DATAERR; } } /* * Main */ int main(int argc, char *argv[]) { ola::AppInit(&argc, argv, "[--record --universes ] [--playback " "] [--verify ]", "Record a series of universes, or playback a previously " "recorded show."); if (!FLAGS_playback.str().empty()) { ShowPlayer player(FLAGS_playback.str()); int status = player.Init(); if (!status) status = player.Playback(FLAGS_iterations, FLAGS_duration, FLAGS_delay); return status; } else if (!FLAGS_record.str().empty()) { return RecordShow(); } else if (!FLAGS_verify.str().empty()) { return VerifyShow(FLAGS_verify.str()); } else { OLA_FATAL << "One of --record or --playback or --verify must be provided"; ola::DisplayUsage(); } return ola::EXIT_OK; } ola-0.10.5.nojsmin/examples/OlaConfigurator.cpp0000644000175000017500000000601513023355232021100 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OlaConfigurator.cpp * Makes configuring devices easy * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include #include #include #include "examples/OlaConfigurator.h" using ola::NewSingleCallback; using ola::OlaCallbackClient; using ola::OlaDevice; using ola::io::SelectServer; using std::cerr; using std::cout; using std::endl; using std::string; using std::vector; DEFINE_s_int32(device, d, -1, "Id of the device to control."); /* * Clean up */ OlaConfigurator::~OlaConfigurator() { delete m_client_wrapper; } /* * Setup the configurator * @return true on success, false on failure */ bool OlaConfigurator::Setup() { m_client_wrapper = new ola::OlaCallbackClientWrapper(); if (!m_client_wrapper->Setup()) { delete m_client_wrapper; m_client_wrapper = NULL; return false; } m_client = m_client_wrapper->GetClient(); m_ss = m_client_wrapper->GetSelectServer(); // fire off a DeviceInfo request m_client->FetchDeviceInfo( m_plugin_id, NewSingleCallback(this, &OlaConfigurator::HandleDevices)); return true; } /* * Send a ConfigureDevice() request * @param message the request to send */ bool OlaConfigurator::SendMessage(const google::protobuf::Message &message) { string request_string; message.SerializeToString(&request_string); return m_client->ConfigureDevice( m_alias, request_string, NewSingleCallback(this, &OlaConfigurator::HandleConfigResponse)); } /* * Handle the DeviceInfo response. We do this to ensure that the plugin this * device corresponds to is the one we expect. * * @param devices a vector of OlaDevice objects * @param error an error string */ void OlaConfigurator::HandleDevices(const vector &devices, const string &error) { if (!error.empty()) { cerr << "Error: " << error << endl; m_ss->Terminate(); return; } vector ::const_iterator iter; for (iter = devices.begin(); iter != devices.end(); ++iter) { if (iter->Alias() == m_alias && iter->PluginId() == m_plugin_id) { SendConfigRequest(); return; } } cout << "Device " << m_alias << " is of the wrong type or missing." << endl; m_ss->Terminate(); } ola-0.10.5.nojsmin/examples/ShowRecorder.h0000644000175000017500000000334213023355232020055 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ShowRecorder.h * Create recordings for the simple show playback system. * Copyright (C) 2011 Simon Newton */ #include #include #include #include #include #include #include #include "examples/ShowSaver.h" #ifndef EXAMPLES_SHOWRECORDER_H_ #define EXAMPLES_SHOWRECORDER_H_ /** * The show player class */ class ShowRecorder { public: ShowRecorder(const std::string &filename, const std::vector &universes); ~ShowRecorder(); int Init(); int Record(); void Stop(); uint64_t FrameCount() const { return m_frame_count; } private: ola::client::OlaClientWrapper m_client; ShowSaver m_saver; std::vector m_universes; ola::Clock m_clock; uint64_t m_frame_count; void NewFrame(const ola::client::DMXMetadata &meta, const ola::DmxBuffer &data); void RegisterComplete(const ola::client::Result &result); }; #endif // EXAMPLES_SHOWRECORDER_H_ ola-0.10.5.nojsmin/examples/ShowRecorder.cpp0000644000175000017500000000573113023355232020414 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ShowRecorder.cpp * Create recordings for the simple show playback system. * Copyright (C) 2011 Simon Newton * * The data file is in the form: * universe-number channel1,channel2,channel3 * delay-in-ms * universe-number channel1,channel2,channel3 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "examples/ShowRecorder.h" using ola::DmxBuffer; using ola::client::Result; using std::string; using std::vector; ShowRecorder::ShowRecorder(const string &filename, const vector &universes) : m_saver(filename), m_universes(universes), m_frame_count(0) { } ShowRecorder::~ShowRecorder() { } /** * Init the ShowRecorder */ int ShowRecorder::Init() { if (!m_client.Setup()) { OLA_FATAL << "Client Setup failed"; return ola::EXIT_UNAVAILABLE; } if (!m_saver.Open()) { return ola::EXIT_CANTCREAT; } m_client.GetClient()->SetDMXCallback( ola::NewCallback(this, &ShowRecorder::NewFrame)); vector::const_iterator iter = m_universes.begin(); for (; iter != m_universes.end(); ++iter) { m_client.GetClient()->RegisterUniverse( *iter, ola::client::REGISTER, ola::NewSingleCallback(this, &ShowRecorder::RegisterComplete)); } return ola::EXIT_OK; } /** * Record the show. */ int ShowRecorder::Record() { m_client.GetSelectServer()->Run(); return ola::EXIT_OK; } /** * Stop recording */ void ShowRecorder::Stop() { m_client.GetSelectServer()->Terminate(); } /** * Record the new frame */ void ShowRecorder::NewFrame(const ola::client::DMXMetadata &meta, const ola::DmxBuffer &data) { ola::TimeStamp now; m_clock.CurrentTime(&now); m_saver.NewFrame(now, meta.universe, data); m_frame_count++; } void ShowRecorder::RegisterComplete(const Result &result) { if (!result.Success()) { OLA_WARN << "Register failed: " << result.Error(); } else { OLA_INFO << "Register completed"; } } ola-0.10.5.nojsmin/examples/ShowSaver.cpp0000644000175000017500000000457013023355232017727 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ShowSaver.cpp * Writes show data to a file. * Copyright (C) 2011 Simon Newton * * The data file is in the form: * universe-number channel1,channel2,channel3 * delay-in-ms * universe-number channel1,channel2,channel3 */ #include #include #include #include #include #include #include #include "examples/ShowSaver.h" using std::string; using ola::DmxBuffer; using std::endl; const char ShowSaver::OLA_SHOW_HEADER[] = "OLA Show"; ShowSaver::ShowSaver(const string &filename) : m_filename(filename) { } ShowSaver::~ShowSaver() { Close(); } /** * Open the show file for writing. * @returns true if we could open the file, false otherwise. */ bool ShowSaver::Open() { m_show_file.open(m_filename.data()); if (!m_show_file.is_open()) { OLA_FATAL << "Can't open " << m_filename << ": " << strerror(errno); return false; } m_show_file << OLA_SHOW_HEADER << endl; return true; } /** * Close the show file */ void ShowSaver::Close() { if (m_show_file.is_open()) { m_show_file.close(); } } /** * Write a new frame */ bool ShowSaver::NewFrame(const ola::TimeStamp &arrival_time, unsigned int universe, const ola::DmxBuffer &data) { // TODO(simon): add much better error handling here if (m_last_frame.IsSet()) { // this is not the first frame so write the delay in ms const ola::TimeInterval delta = arrival_time - m_last_frame; m_show_file << delta.InMilliSeconds() << endl; } m_last_frame = arrival_time; m_show_file << universe << " " << data.ToString() << endl; return true; } ola-0.10.5.nojsmin/examples/ola-dmxconsole.cpp0000644000175000017500000004752613134123277020747 0ustar wouterwouter/* * Copyright (C) 2001 Dirk Jagdmann * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Modified by Simon Newton (nomis52gmail.com) to use ola * * The (void) before attrset is due to a bug in curses. See * http://www.mail-archive.com/debian-bugs-dist@lists.debian.org/msg682294.html */ #ifdef HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_FTIME #include #endif // HAVE_FTIME #include #include #include #include #include #include #include #include #include #include #include #include using ola::client::OlaClient; using ola::client::OlaClientWrapper; using ola::io::SelectServer; using std::string; static const unsigned int DEFAULT_UNIVERSE = 0; static const unsigned char CHANNEL_NUDGE_VALUE = 0x10; static const unsigned char CHANNEL_DISPLAY_WIDTH = 4; static const unsigned char ROWS_PER_CHANNEL_ROW = 2; /* color names used */ enum { CHANNEL = 1, ZERO, NORM, FULL, HEADLINE, HEADEMPH, HEADERROR, MAXCOLOR }; /* display modes */ enum { DISP_MODE_DMX = 0, DISP_MODE_HEX, DISP_MODE_DEC, DISP_MODE_MAX, }; typedef struct { unsigned int universe; bool help; // help } options; unsigned int MAXFKEY = 12; unsigned int universe = 0; typedef unsigned char dmx_t; static dmx_t *dmx; static dmx_t *dmxsave; static dmx_t *dmxundo; static int display_mode = DISP_MODE_DMX; static int current_channel = 0; // channel cursor is positioned on static int first_channel = 0; // channel in upper left corner static int channels_per_line = 80 / CHANNEL_DISPLAY_WIDTH; // Default chans/screen is 80x24, less a row for the header, // and one at the bottom to get an even number of rows static int channels_per_screen = (80 / CHANNEL_DISPLAY_WIDTH) * ((24 - 2) / ROWS_PER_CHANNEL_ROW); static int undo_possible = 0; static int current_cue = 0; // select with F keys static float fadetime = 1.0f; static int fading = 0; // percentage counter of fade process static int palette_number = 0; static int palette[MAXCOLOR]; static bool screen_to_small = false; static int channels_offset = 1; OlaClient *client; SelectServer *ss; void DMXsleep(int usec) { struct timeval tv; tv.tv_sec = usec / 1000000; tv.tv_usec = usec % 1000000; if (select(1, NULL, NULL, NULL, &tv) < 0) perror("could not select"); } // returns the time in milliseconds uint64_t timeGetTime() { #ifdef HAVE_GETTIMEOFDAY struct timeval tv; gettimeofday(&tv, NULL); return (static_cast(tv.tv_sec) * 1000UL + static_cast(tv.tv_usec / 1000)); #else # ifdef HAVE_FTIME struct timeb t; ftime(&t); return (static_cast(t.time) * 1000UL + static_cast(t.millitm); # else # endif // HAVE_FTIME #endif // HAVE_GETTIMEOFDAY } /* set all DMX channels */ void setall() { ola::DmxBuffer buffer(dmx, ola::DMX_UNIVERSE_SIZE); client->SendDMX(universe, buffer, ola::client::SendDMXArgs()); } /* set current DMX channel */ void set() { setall(); } /* display the channels numbers */ void mask() { int i = 0; int x, y; int z = first_channel; erase(); /* clear headline */ (void) attrset(palette[HEADLINE]); move(0, 0); // NOLINT(build/include_what_you_use) This is ncurses.h's move for (x = 0; x < COLS; x++) addch(' '); /* write channel numbers */ (void) attrset(palette[CHANNEL]); for (y = 1; y < LINES && z < ola::DMX_UNIVERSE_SIZE && i < channels_per_screen; y += ROWS_PER_CHANNEL_ROW) { move(y, 0); // NOLINT(build/include_what_you_use) This is ncurses.h's move for (x = 0; x < channels_per_line && z < ola::DMX_UNIVERSE_SIZE && i < channels_per_screen; x++, i++, z++) { switch (display_mode) { case DISP_MODE_DMX: case DISP_MODE_DEC: default: printw("%03d ", z + channels_offset); break; case DISP_MODE_HEX: printw("%03X ", z + channels_offset); break; } } } } /* update the screen */ void values() { int i = 0; int x, y; int z = first_channel; int universe_length = 0; int width_total = 0; if (universe > 0) { universe_length = floor(log10(universe)) + 1; } else { universe_length = 1; } /* headline */ width_total += 25; if (COLS >= width_total) { time_t t = time(NULL); struct tm tt; localtime_r(&t, &tt); char s[32]; asctime_r(&tt, s); s[strlen(s) - 1] = 0; /* strip newline at end of string */ attrset(palette[HEADLINE]); mvprintw(0, 1, "%s", s); } width_total += (5 + universe_length); if (COLS >= width_total) { /* Max universe 4294967295 - see MAX_UNIVERSE in include/ola/Constants.h */ attrset(palette[HEADLINE]); printw(" uni:"); attrset(palette[HEADEMPH]); printw("%u", universe); } width_total += (5 + 2); if (COLS >= width_total) { attrset(palette[HEADLINE]); printw(" cue:"); attrset(palette[HEADEMPH]); printw("%02i", current_cue + 1); } width_total += (10 + 3); if (COLS >= width_total) { attrset(palette[HEADLINE]); printw(" fadetime:"); attrset(palette[HEADEMPH]); printw("%1.1f", fadetime); } width_total += (8 + 3); if (COLS >= width_total) { if (fading) { attrset(palette[HEADLINE]); printw(" fading:"); attrset(palette[HEADEMPH]); printw("%02i%%", (fading < 100) ? fading: 99); } else { attrset(palette[HEADLINE]); printw(" "); } } /* Use 10 as error string length, rather than error_str.length(), as a safety feature to ensure it's shown */ width_total += (6 + 10); if (COLS >= width_total && screen_to_small) { attrset(palette[HEADERROR]); printw("ERROR: screen too small, we need at least 3 lines"); } /* values */ for (y = ROWS_PER_CHANNEL_ROW; y < LINES && z < ola::DMX_UNIVERSE_SIZE && i < channels_per_screen; y += ROWS_PER_CHANNEL_ROW) { move(y, 0); // NOLINT(build/include_what_you_use) This is ncurses.h's move for (x = 0; x < channels_per_line && z < ola::DMX_UNIVERSE_SIZE && i < channels_per_screen; x++, z++, i++) { const int d = dmx[z]; switch (d) { case ola::DMX_MIN_SLOT_VALUE: attrset(palette[ZERO]); break; case ola::DMX_MAX_SLOT_VALUE: attrset(palette[FULL]); break; default: attrset(palette[NORM]); } if (z == current_channel) attron(A_REVERSE); switch (display_mode) { case DISP_MODE_HEX: if (d == 0) addstr(" "); else printw(" %02x ", d); break; case DISP_MODE_DEC: if (d == 0) addstr(" "); else if (d < 100) printw(" %02d ", d); else printw("%03d ", d); break; case DISP_MODE_DMX: default: switch (d) { case ola::DMX_MIN_SLOT_VALUE: addstr(" "); break; case ola::DMX_MAX_SLOT_VALUE: addstr(" FL "); break; default: printw(" %02d ", (d * 100) / ola::DMX_MAX_SLOT_VALUE); } } } } } /* save current cue into cuebuffer */ void savecue() { memcpy(&dmxsave[current_cue * ola::DMX_UNIVERSE_SIZE], dmx, ola::DMX_UNIVERSE_SIZE); } /* get new cue from cuebuffer */ void loadcue() { memcpy(dmx, &dmxsave[current_cue * ola::DMX_UNIVERSE_SIZE], ola::DMX_UNIVERSE_SIZE); } /* fade cue "new_cue" into current cue */ void crossfade(unsigned int new_cue) { dmx_t *dmxold; dmx_t *dmxnew; int i; int max = ola::DMX_UNIVERSE_SIZE; /* check parameter */ if (new_cue > MAXFKEY) return; undo_possible = 0; /* don't crossfade for small fadetimes */ if (fadetime < 0.1f) { savecue(); current_cue = new_cue; loadcue(); setall(); return; } savecue(); dmxold = &dmxsave[current_cue * ola::DMX_UNIVERSE_SIZE]; dmxnew = &dmxsave[new_cue * ola::DMX_UNIVERSE_SIZE]; /* try to find the last channel value > 0, so we don't have to crossfade large blocks of 0s */ for (i = ola::DMX_UNIVERSE_SIZE - 1; i >= 0; max = i, i--) if (dmxold[i] || dmxnew[i]) break; { const uint64_t tstart = timeGetTime(); const uint64_t tend = tstart + static_cast(fadetime * 1000.0); uint64_t t = tstart; while (t <= tend) { /* calculate new cue */ t = timeGetTime(); { const float p = static_cast(t - tstart) / 1000.0f / fadetime; const float q = 1.0f - p; for (i = 0; i < max; i++) if (dmxold[i] || dmxnew[i]) /* avoid calculating with only 0 */ dmx[i] = static_cast(static_cast(dmxold[i]) * q + static_cast(dmxnew[i]) * p); setall(); /* update screen */ fading = static_cast(p * 100.0f); values(); refresh(); DMXsleep(100000); // get current time, because the last time is too old (due to the sleep) t = timeGetTime(); } } fading = 0; /* set the new cue */ current_cue = new_cue; loadcue(); setall(); } } void undo() { if (undo_possible) { memcpy(dmx, dmxundo, ola::DMX_UNIVERSE_SIZE); undo_possible = 0; } } void undoprep() { memcpy(dmxundo, dmx, ola::DMX_UNIVERSE_SIZE); undo_possible = 1; } /* change palette to "p". If p is invalid new palette is number "0". */ void changepalette(int p) { /* COLOR_BLACK COLOR_RED COLOR_GREEN COLOR_YELLOW COLOR_BLUE COLOR_MAGENTA COLOR_CYAN COLOR_WHITE A_NORMAL A_ATTRIBUTES A_CHARTEXT A_COLOR A_STANDOUT A_UNDERLINE A_REVERSE A_BLINK A_DIM A_BOLD A_ALTCHARSET A_INVIS */ switch (p) { default: palette_number = 0; // fall through, use 0 as default palette OLA_FALLTHROUGH case 0: init_pair(CHANNEL, COLOR_BLACK, COLOR_CYAN); init_pair(ZERO, COLOR_BLACK, COLOR_WHITE); init_pair(NORM, COLOR_BLUE, COLOR_WHITE); init_pair(FULL, COLOR_RED, COLOR_WHITE); init_pair(HEADLINE, COLOR_WHITE, COLOR_BLUE); init_pair(HEADEMPH, COLOR_YELLOW, COLOR_BLUE); init_pair(HEADERROR, COLOR_RED, COLOR_BLUE); break; case 2: init_pair(CHANNEL, COLOR_BLACK, COLOR_WHITE); init_pair(ZERO, COLOR_BLUE, COLOR_BLACK); init_pair(NORM, COLOR_GREEN, COLOR_BLACK); init_pair(FULL, COLOR_RED, COLOR_BLACK); init_pair(HEADLINE, COLOR_WHITE, COLOR_BLACK); init_pair(HEADEMPH, COLOR_CYAN, COLOR_BLACK); init_pair(HEADERROR, COLOR_RED, COLOR_BLACK); break; case 1: palette[CHANNEL] = A_REVERSE; palette[ZERO] = A_NORMAL; palette[NORM] = A_NORMAL; palette[FULL] = A_BOLD; palette[HEADLINE] = A_NORMAL; palette[HEADEMPH] = A_NORMAL; palette[HEADERROR] = A_BOLD; break; } if (p == 0 || p == 2) { palette[CHANNEL] = COLOR_PAIR(CHANNEL); palette[ZERO] = COLOR_PAIR(ZERO); palette[NORM] = COLOR_PAIR(NORM); palette[FULL] = COLOR_PAIR(FULL); palette[HEADLINE] = COLOR_PAIR(HEADLINE); palette[HEADEMPH] = COLOR_PAIR(HEADEMPH); palette[HEADERROR] = COLOR_PAIR(HEADERROR); } mask(); } void CHECK(void *p) { if (p == NULL) { fprintf(stderr, "could not alloc\n"); exit(1); } } /* calculate channels_per_line and channels_per_screen from LINES and COLS */ void calcscreengeometry() { int c = LINES; if (c < 3) { screen_to_small = true; exit(1); } c--; // One line for headline if (c % ROWS_PER_CHANNEL_ROW == 1) c--; // Need an even number of lines for data channels_per_line = COLS / CHANNEL_DISPLAY_WIDTH; channels_per_screen = channels_per_line * (c / ROWS_PER_CHANNEL_ROW); } /* signal handler for SIGWINCH */ void terminalresize(int sig) { struct winsize size; if (ioctl(0, TIOCGWINSZ, &size) < 0) return; resizeterm(size.ws_row, size.ws_col); calcscreengeometry(); mask(); (void) sig; } WINDOW *w = NULL; /* cleanup handler for program exit. */ void cleanup() { if (w) { resetty(); endwin(); } if (screen_to_small) puts("screen too small, we need at least 3 lines"); } void stdin_ready() { int n; int c = wgetch(w); switch (c) { case KEY_PPAGE: undoprep(); if (dmx[current_channel] < ola::DMX_MAX_SLOT_VALUE - CHANNEL_NUDGE_VALUE) dmx[current_channel] += CHANNEL_NUDGE_VALUE; else dmx[current_channel] = ola::DMX_MAX_SLOT_VALUE; set(); break; case '+': if (dmx[current_channel] < ola::DMX_MAX_SLOT_VALUE) { undoprep(); dmx[current_channel]++; } set(); break; case KEY_NPAGE: undoprep(); if (dmx[current_channel] == ola::DMX_MAX_SLOT_VALUE) { // Smooth out the fade down dmx[current_channel] = (ola::DMX_MAX_SLOT_VALUE + 1) - CHANNEL_NUDGE_VALUE; } else if (dmx[current_channel] > CHANNEL_NUDGE_VALUE) { dmx[current_channel] -= CHANNEL_NUDGE_VALUE; } else { dmx[current_channel] = ola::DMX_MIN_SLOT_VALUE; } set(); break; case '-': if (dmx[current_channel] > ola::DMX_MIN_SLOT_VALUE) { undoprep(); dmx[current_channel]--; } set(); break; case ' ': undoprep(); if (dmx[current_channel] < ((ola::DMX_MAX_SLOT_VALUE + 1) / 2)) dmx[current_channel] = ola::DMX_MAX_SLOT_VALUE; else dmx[current_channel] = ola::DMX_MIN_SLOT_VALUE; set(); break; case '0' ... '9': fadetime = c -'0'; break; case KEY_HOME: current_channel = 0; first_channel = 0; mask(); break; case KEY_END: current_channel = ola::DMX_UNIVERSE_SIZE - 1; if (channels_per_screen >= ola::DMX_UNIVERSE_SIZE) { first_channel = 0; } else { first_channel = current_channel - (channels_per_screen - 1); } mask(); break; case KEY_RIGHT: if (current_channel < ola::DMX_UNIVERSE_SIZE - 1) { current_channel++; if (current_channel >= first_channel + channels_per_screen) { first_channel += channels_per_line; mask(); } } break; case KEY_LEFT: if (current_channel > 0) { current_channel--; if (current_channel < first_channel) { first_channel -= channels_per_line; if (first_channel < 0) first_channel = 0; mask(); } } break; case KEY_DOWN: current_channel += channels_per_line; if (current_channel >= ola::DMX_UNIVERSE_SIZE) current_channel = ola::DMX_UNIVERSE_SIZE - 1; if (current_channel >= first_channel + channels_per_screen) { first_channel += channels_per_line; mask(); } break; case KEY_UP: current_channel -= channels_per_line; if (current_channel < 0) current_channel = 0; if (current_channel < first_channel) { first_channel -= channels_per_line; if (first_channel < 0) first_channel = 0; mask(); } break; case KEY_IC: undoprep(); for (n = ola::DMX_UNIVERSE_SIZE - 1; n > current_channel && n > 0; n--) dmx[n] = dmx[n - 1]; setall(); break; case KEY_DC: undoprep(); for (n = current_channel; n < ola::DMX_UNIVERSE_SIZE - 1; n++) dmx[n] = dmx[n + 1]; setall(); break; case 'B': case 'b': undoprep(); memset(dmx, ola::DMX_MIN_SLOT_VALUE, ola::DMX_UNIVERSE_SIZE); setall(); break; case 'F': case 'f': undoprep(); memset(dmx, ola::DMX_MAX_SLOT_VALUE, ola::DMX_UNIVERSE_SIZE); setall(); break; case 'M': case 'm': if (++display_mode >= DISP_MODE_MAX) display_mode = 0; mask(); break; case 'N': case 'n': if (++channels_offset > 1) channels_offset = 0; mask(); break; case 'P': case 'p': changepalette(++palette_number); break; case 'U': case 'u': undo(); break; case 'Q': case 'q': ss->Terminate(); break; default: if (c >= static_cast(KEY_F(1)) && c <= static_cast(KEY_F(MAXFKEY))) crossfade(c - KEY_F(1)); break; } values(); refresh(); } /* * parse our cmd line options */ void ParseOptions(int argc, char *argv[], options *opts) { static struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"universe", required_argument, 0, 'u'}, {0, 0, 0, 0} }; opts->universe = DEFAULT_UNIVERSE; opts->help = false; int c; int option_index = 0; while (1) { c = getopt_long(argc, argv, "hu:", long_options, &option_index); if (c == -1) break; switch (c) { case 0: break; case 'h': opts->help = true; break; case 'u': opts->universe = strtoul(optarg, NULL, 0); break; case '?': break; default: break; } } } /* * Display the help message */ void DisplayHelpAndExit(char arg[]) { std::cout << "Usage: " << arg << " [--universe ]\n" "\n" "Send data to a DMX512 universe.\n" "\n" " -h, --help Display this help message and exit.\n" " -u, --universe Id of universe to control (defaults to " << DEFAULT_UNIVERSE << ").\n" << std::endl; exit(ola::EXIT_OK); } int main(int argc, char *argv[]) { signal(SIGWINCH, terminalresize); atexit(cleanup); if (!ola::NetworkInit()) { std::cerr << "Network initialization failed." << std::endl; exit(ola::EXIT_UNAVAILABLE); } // 10 bytes security, for file IO routines, will be optimized and checked // later dmx = reinterpret_cast(calloc(ola::DMX_UNIVERSE_SIZE + 10, sizeof(dmx_t))); CHECK(dmx); dmxsave = reinterpret_cast( calloc(ola::DMX_UNIVERSE_SIZE * MAXFKEY, sizeof(dmx_t))); CHECK(dmxsave); dmxundo = reinterpret_cast( calloc(ola::DMX_UNIVERSE_SIZE, sizeof(dmx_t))); CHECK(dmxundo); options opts; ParseOptions(argc, argv, &opts); if (opts.help) { DisplayHelpAndExit(argv[0]); } universe = opts.universe; /* set up ola connection */ OlaClientWrapper ola_client; ola::io::UnmanagedFileDescriptor stdin_descriptor(0); stdin_descriptor.SetOnData(ola::NewCallback(&stdin_ready)); if (!ola_client.Setup()) { printf("error: %s", strerror(errno)); exit(1); } client = ola_client.GetClient(); ss = ola_client.GetSelectServer(); ss->AddReadDescriptor(&stdin_descriptor); /* init curses */ w = initscr(); if (!w) { printf("unable to open main-screen\n"); return 1; } savetty(); start_color(); noecho(); raw(); keypad(w, TRUE); calcscreengeometry(); changepalette(palette_number); values(); refresh(); ss->Run(); return 0; } ola-0.10.5.nojsmin/doxygen/0000755000175000017500000000000013155164170015140 5ustar wouterwouterola-0.10.5.nojsmin/doxygen/overview.dox0000644000175000017500000000341713023355232017522 0ustar wouterwouter/** * @mainpage Open Lighting Architecture Developer Documentation * * [TOC] * * @section sec_Overview Overview * The Open Lighting Architecture is a flexible framework for working with * lighting control protocols such as * [DMX512](http://en.wikipedia.org/wiki/DMX512) and * [RDM](http://en.wikipedia.org/wiki/RDM_(lighting%29). It contains a framework * library (libola), a C++ API (libolaclient) and the main * program (olad). * * @section sec_Features Features * * OLA can act as a gateway, where it converts between different protocols. It * can also be used by client applications to communicate with DMX devices. * * OLA supports the following: * - Various DMX512 over IP Protocols, including: * - ArtNet 1, 2 & 3 * - Streaming ACN (E1.31) * - Pathway Pathport * - Strand ShowNet * - Enttec ESP * - Other network protocols, including: * - KiNet * - OSC (Open Sound Control) * - More than 20 USB DMX widgets, including those from the * following manufacturers: * - Enttec * - DMXKing * - JESE * - Robe * * Other features include: * - Built in web based control panel * - Support for acting as an RDM controller or RDM gateway. * - C++, Python and Java APIs. * * @section sec_Platforms Supported Platforms * OLA runs on Linux, Mac OS X and FreeBSD. It's been tested to run on x86, * x86_64 & arm platforms. * * @section sec_GettingStarted Getting Started * * As a developer, the easiest way to get started using OLA is with the * @ref dmx_cpp_client_tutorial. * * @section sec_Licensing Licensing * The OLA framework and C++ client library is licensed under the * [LGPL](http://www.gnu.org/licenses/lgpl.html). The * OLA Daemon (olad) is licenced under the * [GPL](http://www.gnu.org/licenses/gpl.html). */ ola-0.10.5.nojsmin/doxygen/Makefile.mk0000644000175000017500000000067213023355232017206 0ustar wouterwouterinclude doxygen/examples/Makefile.mk EXTRA_DIST += \ doxygen/copy-doc.sh \ doxygen/cpp-client.dox \ doxygen/dmx-cpp-client.dox \ doxygen/event-driven.dox \ doxygen/http.dox \ doxygen/json.dox \ doxygen/namespaces.dox \ doxygen/olad.dox \ doxygen/OLALayout.xml \ doxygen/OLA.png \ doxygen/overview.dox \ doxygen/rdm.dox \ doxygen/rpc.dox \ doxygen/rpc-message.png \ doxygen/rpc.png ola-0.10.5.nojsmin/doxygen/http.dox0000644000175000017500000000032113023355232016622 0ustar wouterwouter/** * @defgroup http HTTP * @brief HTTP related functionality for the web server * * @addtogroup http * @{ * * @defgroup http_server HTTP Server * @brief The HTTP server. * * @} //End http group */ ola-0.10.5.nojsmin/doxygen/namespaces.dox0000644000175000017500000000577413023355232020003 0ustar wouterwouter/** * @namespace ola * @brief The namespace containing all OLA symbols. * * @namespace ola::acn * @brief ACN related code. * * @namespace ola::client * @brief OLA C++ API * * @namespace ola::dmx * @brief DMX512 related code. * * @namespace ola::e133 * @brief E1.33 (RDMNet) * * @namespace ola::io * @brief Classes for general I/O and event handling. * * @namespace ola::http * @brief The embedded HTTP server. * * @namespace ola::math * @brief Math helper functions. * * @namespace ola::messaging * @brief A framework for serializing simple message structures. * * @namespace ola::network * @brief Code for network communication. * * @namespace ola::plugin * @brief Code for supported devices and protocols. * * @namespace ola::plugin::artnet * @brief The ArtNet plugin. * * @namespace ola::plugin::dmx4linux * @brief Code for DMX4Linux devices. * * @namespace ola::plugin::dummy * @brief The Dummy plugin. * * @namespace ola::plugin::e131 * @brief The E1.31 (sACN) plugin. * * @namespace ola::plugin::espnet * @brief Code for the ESPNet protocol. * * @namespace ola::plugin::ftdidmx * @brief Code for FTDI devices. * * @namespace ola::plugin::gpio * @brief The General Purpose digital I/O Plugin. * * @namespace ola::plugin::karate * @brief Code for Karate devices. * * @namespace ola::plugin::kinet * @brief Code for the Kinet protocol. * * @namespace ola::plugin::milinst * @brief Code for Milford Instruments devices. * * @namespace ola::plugin::opendmx * @brief Code for the Enttec OpenDMX. * * @namespace ola::plugin::openpixelcontrol * @brief The Open Pixel Control (OPC) plugin. * * @namespace ola::plugin::osc * @brief Code for the OSC protocol. * * @namespace ola::plugin::pathport * @brief Code for the Pathport protocol. * * @namespace ola::plugin::renard * @brief Code for Renard devices. * * @namespace ola::plugin::sandnet * @brief Code for the SandNet protocol. * * @namespace ola::plugin::shownet * @brief Code for the Strand ShowNet protocol. * * @namespace ola::plugin::spi * @brief Code for SPI devices. * * @namespace ola::plugin::stageprofi * @brief Code for Stageprofi devices. * * @namespace ola::plugin::uartdmx * @brief Code for UART DMX devices. * * @namespace ola::plugin::usbdmx * @brief The plugin for hardware using libusb. * * @namespace ola::plugin::usbdmx::jarule * @brief Ja Rule code. * * @namespace ola::plugin::usbpro * @brief Code for Enttec USB Pro devices and others using the same protocol. * * @namespace ola::rdm * @brief PLASA E1.20 Remote %Device Management * * @namespace ola::rpc * @brief The RPC (Remote Procedure Call) system * * @namespace ola::stl * @brief STL Helper functions. * * @namespace ola::testing * @brief Code used for unit testing. * * @namespace ola::thread * @brief Threads and syncronization mechanisms. * * @namespace ola::timecode * @brief Timecode * * @namespace ola::web * @brief Classes to deal with web services. * * @namespace ola::usb * @brief USB Device drivers. */ ola-0.10.5.nojsmin/doxygen/cpp-client.dox0000644000175000017500000000540613023355232017712 0ustar wouterwouter/** * @page cpp_client_tutorial Advanced C++ Client API * @brief Advanced C++ Client API Tutorial * * [TOC] * * @section cpp_client_Overview Overview * This page covers some of the more advanced aspects of the OLA C++ Client * API including using callbacks, handling a server-side shutdown and running * the client in a separate thread. For an introduction on using the OLA C++ * Client see @ref dmx_cpp_client_tutorial. * * @section cpp_client_Fetch_Plugins Using Callbacks * * Almost all of the ola::client::OlaClient methods take a \ref callbacks * "Callback" object. Each callback is executed when the server responds with * the results of the method invocation. * * Lets look at the ola::client::OlaClient::FetchPluginList method. This method * is used to fetch a list of available plugins from the olad server. The * client may choose to present the list of plugins to the user so they know * what Devices / Protocols are supported. * * The code below calls FetchPluginList() and then waits for the results from * the olad server. When the list of plugins is received, the name of each * plugin is printed to stdout and the program exits. * * @snippet fetch_plugins.cpp Client Fetch Plugins * * @section cpp_client_Disconnects Handling Server Shutdown. * * To write a robust program, you'll need to handle the case of olad * shutting down. This can be done by setting a callback to be executed when the * connection to the olad server is closed. * * The following example builds on the @ref dmx_cpp_client_OLAClient_TX * "OlaClient TX" example. Instead of exiting after 100 DMX frames have been * sent, the program runs until the connection to olad is closed. * * @snippet client_disconnect.cpp Client Disconnect Example * * Instead of exiting, a better approach would be to try and reconnect to the * olad server. Clients that do this should use a ola::BackOffPolicy to avoid * spinning in a loop trying to reconnect. * * @section cpp_client_Thread Running the OlaClient within a thread. * * Sometimes it can be difficult to integrate OLA's @ref event_driven * "Event Driven" programming model with the main event loop of your program. * The OlaClient is not thread safe, so a workaround is to run a separate * thread for the OlaClient. * * We can use ola::io::SelectServer::Execute to run a callback on a * SelectServer running in a different thread. This allows us to schedule the * calls to OlaClient on the thread where the SelectServer is running. * * @snippet client_thread.cpp Client Thread * * It's important to realize that the ShowPluginList function will be run from * the OLA thread. If this function uses any variables from the main program * (such as UI widgets), you must use locking, or some other thread * syncronization technique. */ ola-0.10.5.nojsmin/doxygen/examples/0000755000175000017500000000000013155164170016756 5ustar wouterwouterola-0.10.5.nojsmin/doxygen/examples/callback_client_transmit.cpp0000644000175000017500000000351113023355232024470 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Copyright (C) 2010 Simon Newton */ //! [Tutorial Example] NOLINT(whitespace/comments) #include #include #include #include #include using std::cout; using std::endl; bool SendData(ola::client::OlaClientWrapper *wrapper) { static unsigned int universe = 1; static unsigned int i = 0; ola::DmxBuffer buffer; buffer.Blackout(); buffer.SetChannel(0, i); wrapper->GetClient()->SendDMX(universe, buffer, ola::client::SendDMXArgs()); if (++i == 100) { wrapper->GetSelectServer()->Terminate(); } return true; } int main(int, char *[]) { ola::InitLogging(ola::OLA_LOG_WARN, ola::OLA_LOG_STDERR); ola::client::OlaClientWrapper wrapper; if (!wrapper.Setup()) { std::cerr << "Setup failed" << endl; exit(1); } // Create a timeout and register it with the SelectServer ola::io::SelectServer *ss = wrapper.GetSelectServer(); ss->RegisterRepeatingTimeout(25, ola::NewCallback(&SendData, &wrapper)); // Start the main loop ss->Run(); } //! [Tutorial Example] NOLINT(whitespace/comments) ola-0.10.5.nojsmin/doxygen/examples/Makefile.mk0000644000175000017500000000537013023355232021024 0ustar wouterwouter# The following should match what pkg-config --libs libola returns DOXYGEN_EXAMPLES_LDADD = common/libolacommon.la \ ola/libola.la if BUILD_EXAMPLES noinst_PROGRAMS += \ doxygen/examples/callback_client_transmit \ doxygen/examples/client_disconnect \ doxygen/examples/client_thread \ doxygen/examples/fetch_plugins \ doxygen/examples/flags \ doxygen/examples/legacy_callback_client_transmit \ doxygen/examples/legacy_receiver \ doxygen/examples/legacy_streaming_client \ doxygen/examples/receiver \ doxygen/examples/stdin_handler \ doxygen/examples/streaming_client \ doxygen/examples/udp_server if HAVE_DLOPEN noinst_PROGRAMS += doxygen/examples/streaming_client_plugin endif endif doxygen_examples_callback_client_transmit_SOURCES = \ doxygen/examples/callback_client_transmit.cpp doxygen_examples_callback_client_transmit_LDADD = $(DOXYGEN_EXAMPLES_LDADD) doxygen_examples_client_disconnect_SOURCES = \ doxygen/examples/client_disconnect.cpp doxygen_examples_client_disconnect_LDADD = $(DOXYGEN_EXAMPLES_LDADD) doxygen_examples_client_thread_SOURCES = \ doxygen/examples/client_thread.cpp doxygen_examples_client_thread_LDADD = $(DOXYGEN_EXAMPLES_LDADD) doxygen_examples_fetch_plugins_SOURCES = \ doxygen/examples/fetch_plugins.cpp doxygen_examples_fetch_plugins_LDADD = $(DOXYGEN_EXAMPLES_LDADD) doxygen_examples_legacy_callback_client_transmit_SOURCES = \ doxygen/examples/legacy_callback_client_transmit.cpp doxygen_examples_legacy_callback_client_transmit_LDADD = $(DOXYGEN_EXAMPLES_LDADD) doxygen_examples_flags_SOURCES = \ doxygen/examples/flags.cpp doxygen_examples_flags_LDADD = $(DOXYGEN_EXAMPLES_LDADD) doxygen_examples_streaming_client_SOURCES = \ doxygen/examples/streaming_client.cpp doxygen_examples_streaming_client_LDADD = $(DOXYGEN_EXAMPLES_LDADD) doxygen_examples_legacy_streaming_client_SOURCES = \ doxygen/examples/legacy_streaming_client.cpp doxygen_examples_legacy_streaming_client_LDADD = $(DOXYGEN_EXAMPLES_LDADD) doxygen_examples_streaming_client_plugin_SOURCES = \ doxygen/examples/streaming_client_plugin.cpp doxygen_examples_streaming_client_plugin_LDADD = $(DOXYGEN_EXAMPLES_LDADD) doxygen_examples_legacy_receiver_SOURCES = \ doxygen/examples/legacy_receiver.cpp doxygen_examples_legacy_receiver_LDADD = $(DOXYGEN_EXAMPLES_LDADD) doxygen_examples_receiver_SOURCES = \ doxygen/examples/receiver.cpp doxygen_examples_receiver_LDADD = $(DOXYGEN_EXAMPLES_LDADD) doxygen_examples_stdin_handler_SOURCES = \ doxygen/examples/stdin_handler.cpp doxygen_examples_stdin_handler_LDADD = $(DOXYGEN_EXAMPLES_LDADD) doxygen_examples_udp_server_SOURCES = \ doxygen/examples/udp_server.cpp doxygen_examples_udp_server_LDADD = $(DOXYGEN_EXAMPLES_LDADD) ola-0.10.5.nojsmin/doxygen/examples/legacy_streaming_client.cpp0000644000175000017500000000360713023355232024336 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Copyright (C) 2010 Simon Newton */ //! [Tutorial Example] NOLINT(whitespace/comments) #include #include #include #include #include #include using std::cout; using std::endl; int main(int, char *[]) { unsigned int universe = 1; // universe to use for sending data // turn on OLA logging ola::InitLogging(ola::OLA_LOG_WARN, ola::OLA_LOG_STDERR); ola::DmxBuffer buffer; // A DmxBuffer to hold the data. buffer.Blackout(); // Set all channels to 0 // Create a new client. ola::StreamingClient ola_client((ola::StreamingClient::Options())); // Setup the client, this connects to the server if (!ola_client.Setup()) { std::cerr << "Setup failed" << endl; exit(1); } // Send 100 frames to the server. Increment slot (channel) 0 each time a // frame is sent. for (unsigned int i = 0; i < 100; i++) { buffer.SetChannel(0, i); if (!ola_client.SendDmx(universe, buffer)) { cout << "Send DMX failed" << endl; exit(1); } usleep(20000); // sleep for 25ms between frames. } return 0; } //! [Tutorial Example] NOLINT(whitespace/comments) ola-0.10.5.nojsmin/doxygen/examples/legacy_callback_client_transmit.cpp0000644000175000017500000000345013023355232026016 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Copyright (C) 2010 Simon Newton */ //! [Tutorial Example] NOLINT(whitespace/comments) #include #include #include #include #include using std::cout; using std::endl; bool SendData(ola::OlaCallbackClientWrapper *wrapper) { static unsigned int universe = 1; static unsigned int i = 0; ola::DmxBuffer buffer; buffer.Blackout(); buffer.SetChannel(0, i); wrapper->GetClient()->SendDmx(universe, buffer); if (++i == 100) { wrapper->GetSelectServer()->Terminate(); } return true; } int main(int, char *[]) { ola::InitLogging(ola::OLA_LOG_WARN, ola::OLA_LOG_STDERR); ola::OlaCallbackClientWrapper wrapper; if (!wrapper.Setup()) { std::cerr << "Setup failed" << endl; exit(1); } // Create a timeout and register it with the SelectServer ola::io::SelectServer *ss = wrapper.GetSelectServer(); ss->RegisterRepeatingTimeout(25, ola::NewCallback(&SendData, &wrapper)); // Start the main loop ss->Run(); } //! [Tutorial Example] NOLINT(whitespace/comments) ola-0.10.5.nojsmin/doxygen/examples/legacy_receiver.cpp0000644000175000017500000000404613023355232022611 0ustar wouterwouter/* * 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 Library 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. * * Copyright (C) 2010 Simon Newton */ //! [Tutorial Example] NOLINT(whitespace/comments) #include #include #include #include static const unsigned int UNIVERSE = 1; // Called when universe registration completes. void RegisterComplete(const std::string& error) { if (!error.empty()) { OLA_WARN << "Failed to register universe"; } } // Called when new DMX data arrives. void NewDmx(unsigned int universe, uint8_t priority, const ola::DmxBuffer &data, const std::string &error) { if (error.empty()) { OLA_INFO << "Received " << data.Size() << " channels for universe " << universe << ", priority " << static_cast(priority); } else { OLA_WARN << "Receive failed: " << error; } } int main() { ola::InitLogging(ola::OLA_LOG_INFO, ola::OLA_LOG_STDERR); ola::OlaCallbackClientWrapper wrapper; if (!wrapper.Setup()) exit(1); ola::OlaCallbackClient *client = wrapper.GetClient(); // Set the callback and register our interest in this universe client->SetDmxCallback(ola::NewCallback(&NewDmx)); client->RegisterUniverse( UNIVERSE, ola::REGISTER, ola::NewSingleCallback(&RegisterComplete)); wrapper.GetSelectServer()->Run(); } //! [Tutorial Example] NOLINT(whitespace/comments) ola-0.10.5.nojsmin/doxygen/examples/client_thread.cpp0000644000175000017500000000644313023355232022271 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Copyright (C) 2015 Simon Newton */ //! [Client Thread] NOLINT(whitespace/comments) #include #include #include #include #include #include #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #define VC_EXTRALEAN #include #endif // _WIN32 using ola::io::SelectServer; using ola::NewSingleCallback; using std::cout; using std::endl; using std::vector; class OlaThread : public ola::thread::Thread { public: bool Start() { if (!m_wrapper.Setup()) { return false; } return ola::thread::Thread::Start(); } void Stop() { m_wrapper.GetSelectServer()->Terminate(); } void FetchPluginList(ola::client::PluginListCallback *callback) { m_wrapper.GetSelectServer()->Execute( NewSingleCallback(this, &OlaThread::InternalFetchPluginList, callback)); } ola::io::SelectServer* GetSelectServer() { return m_wrapper.GetSelectServer(); } protected: void *Run() { m_wrapper.GetSelectServer()->Run(); return NULL; } private: ola::client::OlaClientWrapper m_wrapper; void InternalFetchPluginList(ola::client::PluginListCallback *callback) { m_wrapper.GetClient()->FetchPluginList(callback); } }; // Called when plugin information is available. // This function is run from the OLA Thread, if you use variables in the main // program then you'll need to add locking. void ShowPluginList(ola::io::SelectServer *ss, const ola::client::Result &result, const vector &plugins) { if (!result.Success()) { std::cerr << result.Error() << endl; } else { vector::const_iterator iter = plugins.begin(); for (; iter != plugins.end(); ++iter) { cout << "Plugin: " << iter->Name() << endl; } } ss->Terminate(); // terminate the program. } int main(int, char *[]) { ola::InitLogging(ola::OLA_LOG_WARN, ola::OLA_LOG_STDERR); OlaThread ola_thread; if (!ola_thread.Start()) { std::cerr << "Failed to start OLA thread" << endl; exit(1); } // Control is returned to the main program here. // To fetch a list of plugins ola::io::SelectServer *ss = ola_thread.GetSelectServer(); ola_thread.FetchPluginList( ola::NewSingleCallback(ShowPluginList, ss)); // The main program continues... #ifdef _WIN32 Sleep(1000); #else sleep(1); #endif // _WIN32 // When it's time to exit, Stop the OLA thread. ola_thread.Stop(); ola_thread.Join(); } //! [Client Thread] NOLINT(whitespace/comments) ola-0.10.5.nojsmin/doxygen/examples/udp_server.cpp0000644000175000017500000000366313023355232021643 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Copyright (C) 2014 Simon Newton */ //! [UDP Server] NOLINT(whitespace/comments) #include #include #include #include #include using ola::network::IPV4Address; using ola::network::IPV4SocketAddress; using ola::network::UDPSocket; // The port to listen on. static const unsigned int PORT = 12345; // Called when a UDP datagram arrives. void ReceiveMessage(UDPSocket *socket) { ola::network::IPV4SocketAddress client; uint8_t data[1500]; ssize_t data_size = arraysize(data); if (socket->RecvFrom(data, &data_size, &client)) { OLA_INFO << "Received " << data_size << " bytes from " << client; } else { OLA_WARN << "Recv failure"; } } int main() { ola::InitLogging(ola::OLA_LOG_INFO, ola::OLA_LOG_STDERR); IPV4SocketAddress listen_address(IPV4Address::WildCard(), PORT); UDPSocket udp_socket; if (!udp_socket.Init()) { return -1; } if (!udp_socket.Bind(listen_address)) { return -1; } udp_socket.SetOnData(ola::NewCallback(&ReceiveMessage, &udp_socket)); ola::io::SelectServer ss; ss.AddReadDescriptor(&udp_socket); ss.Run(); } //! [UDP Server] NOLINT(whitespace/comments) ola-0.10.5.nojsmin/doxygen/examples/receiver.cpp0000644000175000017500000000377713023355232021277 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Copyright (C) 2010 Simon Newton */ //! [Tutorial Example] NOLINT(whitespace/comments) #include #include #include #include static const unsigned int UNIVERSE = 1; // Called when universe registration completes. void RegisterComplete(const ola::client::Result& result) { if (!result.Success()) { OLA_WARN << "Failed to register universe: " << result.Error(); } } // Called when new DMX data arrives. void NewDmx(const ola::client::DMXMetadata &metadata, const ola::DmxBuffer &data) { std::cout << "Received " << data.Size() << " channels for universe " << metadata.universe << ", priority " << static_cast(metadata.priority) << std::endl; } int main() { ola::InitLogging(ola::OLA_LOG_INFO, ola::OLA_LOG_STDERR); ola::client::OlaClientWrapper wrapper; if (!wrapper.Setup()) exit(1); ola::client::OlaClient *client = wrapper.GetClient(); // Set the callback and register our interest in this universe client->SetDMXCallback(ola::NewCallback(&NewDmx)); client->RegisterUniverse( UNIVERSE, ola::client::REGISTER, ola::NewSingleCallback(&RegisterComplete)); wrapper.GetSelectServer()->Run(); } //! [Tutorial Example] NOLINT(whitespace/comments) ola-0.10.5.nojsmin/doxygen/examples/fetch_plugins.cpp0000644000175000017500000000413413023355232022311 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Copyright (C) 2015 Simon Newton */ //! [Client Fetch Plugins] NOLINT(whitespace/comments) #include #include #include #include #include using std::cout; using std::endl; using std::vector; // Called when plugin information is available. void ShowPluginList(ola::io::SelectServer *ss, const ola::client::Result &result, const vector &plugins) { if (!result.Success()) { std::cerr << result.Error() << endl; } else { vector::const_iterator iter = plugins.begin(); for (; iter != plugins.end(); ++iter) { cout << "Plugin: " << iter->Name() << endl; } } ss->Terminate(); // terminate the program. } int main(int, char *[]) { ola::InitLogging(ola::OLA_LOG_WARN, ola::OLA_LOG_STDERR); ola::client::OlaClientWrapper wrapper; if (!wrapper.Setup()) { std::cerr << "Setup failed" << endl; exit(1); } // Fetch the list of plugins, a pointer to the SelectServer is passed to the // callback so we can use it to terminate the program. ola::io::SelectServer *ss = wrapper.GetSelectServer(); wrapper.GetClient()->FetchPluginList( ola::NewSingleCallback(ShowPluginList, ss)); // Start the main loop ss->Run(); } //! [Client Fetch Plugins] NOLINT(whitespace/comments) ola-0.10.5.nojsmin/doxygen/examples/flags.cpp0000644000175000017500000000322013023355232020546 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Copyright (C) 2010 Simon Newton */ //! [Example] NOLINT(whitespace/comments) #include #include using std::cout; using std::endl; // These options are --foo and --no-bar. DEFINE_default_bool(foo, false, "Enable feature foo"); DEFINE_default_bool(bar, true, "Disable feature bar"); // FLAGS_name defaults to "simon" and can be changed with --name bob DEFINE_string(name, "simon", "Specify the name"); // Short options can also be specified: // FLAGS_baz can be set with --baz or -b DEFINE_s_int8(baz, b, 0, "Sets the value of baz"); int main(int argc, char* argv[]) { ola::SetHelpString("[options]", "Description of binary"); ola::ParseFlags(&argc, argv); cout << "--foo is " << FLAGS_foo << endl; cout << "--bar is " << FLAGS_bar << endl; cout << "--name is " << FLAGS_name.str() << endl; cout << "--baz (-b) is " << static_cast(FLAGS_baz) << endl; } //! [Example] NOLINT(whitespace/comments) ola-0.10.5.nojsmin/doxygen/examples/streaming_client_plugin.cpp0000644000175000017500000000561513023355232024371 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Copyright (C) 2014 Simon Newton */ //! [Streaming Client Plugin] NOLINT(whitespace/comments) #include #include #include #include #include using std::cout; using std::endl; /** * @brief Load a symbol. */ template FunctionType LoadSymbol(void *module, const char *symbol) { FunctionType ptr = reinterpret_cast(dlsym(module, symbol)); if (!ptr) { cout << "Failed to find " << symbol << " " << dlerror() << endl; } return ptr; } int main() { ola::client::StreamingClientInterface *client = NULL; // Adjust to suit. void *module = dlopen("/usr/local/lib/libola.dylib", RTLD_NOW); // void *module = dlopen("/usr/local/lib/libola.so", RTLD_NOW); if (!module) { cout << "Failed to load" << dlerror() << endl; return -1; } ola_new_streaming_client_t *new_client_ptr = LoadSymbol(module, OLA_NEW_STREAMING_CLIENT); ola_delete_streaming_client_t *delete_client_ptr = LoadSymbol( module, OLA_DELETE_STREAMING_CLIENT); ola_new_dmxbuffer_t *new_buffer_ptr = LoadSymbol(module, OLA_NEW_DMXBUFFER); ola_delete_dmxbuffer_t *delete_buffer_ptr = LoadSymbol(module, OLA_DELETE_DMXBUFFER); ola_set_dmxbuffer_t *set_buffer_ptr = LoadSymbol(module, OLA_SET_DMXBUFFER); if (!(new_client_ptr && delete_client_ptr && new_buffer_ptr && delete_buffer_ptr && set_buffer_ptr)) { return -1; } ola::client::StreamingClient::Options options; client = new_client_ptr(options); cout << "Setup() returned: " << client->Setup() << endl; ola::DmxBuffer *buffer = new_buffer_ptr(); // Now actually send the DMX uint8_t data[] = {1, 2, 3}; set_buffer_ptr(buffer, data, sizeof(data)); const unsigned int universe = 1; client->SendDMX(universe, *buffer, ola::client::StreamingClient::SendArgs()); client->Stop(); delete_buffer_ptr(buffer); delete_client_ptr(client); if (module) { dlclose(module); } } //! [Streaming Client Plugin] NOLINT(whitespace/comments) ola-0.10.5.nojsmin/doxygen/examples/client_disconnect.cpp0000644000175000017500000000416413023355232023151 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Copyright (C) 2015 Simon Newton */ //! [Client Disconnect Example] NOLINT(whitespace/comments) #include #include #include #include #include #include using std::cout; using std::endl; // Called when the connection to olad is closed. void ConnectionClosed(ola::io::SelectServer *ss) { std::cerr << "Connection to olad was closed" << endl; ss->Terminate(); // terminate the program. } bool SendData(ola::client::OlaClientWrapper *wrapper) { static unsigned int universe = 1; static uint8_t i = 0; ola::DmxBuffer buffer; buffer.Blackout(); buffer.SetChannel(0, i++); wrapper->GetClient()->SendDMX(universe, buffer, ola::client::SendDMXArgs()); return true; } int main(int, char *[]) { ola::InitLogging(ola::OLA_LOG_WARN, ola::OLA_LOG_STDERR); ola::client::OlaClientWrapper wrapper; if (!wrapper.Setup()) { std::cerr << "Setup failed" << endl; exit(1); } // Create a timeout and register it with the SelectServer ola::io::SelectServer *ss = wrapper.GetSelectServer(); ss->RegisterRepeatingTimeout(25, ola::NewCallback(&SendData, &wrapper)); // Register the on-close handler wrapper.GetClient()->SetCloseHandler( ola::NewSingleCallback(ConnectionClosed, ss)); // Start the main loop ss->Run(); } //! [Client Disconnect Example] NOLINT(whitespace/comments) ola-0.10.5.nojsmin/doxygen/examples/stdin_handler.cpp0000644000175000017500000000314713023355232022300 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Copyright (C) 2015 Simon Newton */ //! [Example] NOLINT(whitespace/comments) #include #include #include #include class ExampleStdinHandler { public: ExampleStdinHandler() : m_stdin_handler(&m_ss, ola::NewCallback(this, &ExampleStdinHandler::Input)) { } void Run() { m_ss.Run(); } private: ola::io::SelectServer m_ss; ola::io::StdinHandler m_stdin_handler; void Input(int c); }; void ExampleStdinHandler::Input(int c) { switch (c) { case 'q': m_ss.Terminate(); break; default: std::cout << "Got " << static_cast(c) << " - " << c << std::endl; break; } } int main(int argc, char* argv[]) { ola::AppInit(&argc, argv, "", "Example Stdin Handler"); ExampleStdinHandler handler; handler.Run(); } //! [Example] NOLINT(whitespace/comments) ola-0.10.5.nojsmin/doxygen/examples/streaming_client.cpp0000644000175000017500000000364513023355232023014 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Copyright (C) 2010 Simon Newton */ //! [Tutorial Example] NOLINT(whitespace/comments) #include #include #include #include #include #include using std::cout; using std::endl; int main(int, char *[]) { unsigned int universe = 1; // universe to use for sending data // turn on OLA logging ola::InitLogging(ola::OLA_LOG_WARN, ola::OLA_LOG_STDERR); ola::DmxBuffer buffer; // A DmxBuffer to hold the data. buffer.Blackout(); // Set all channels to 0 // Create a new client. ola::client::StreamingClient ola_client( (ola::client::StreamingClient::Options())); // Setup the client, this connects to the server if (!ola_client.Setup()) { std::cerr << "Setup failed" << endl; exit(1); } // Send 100 frames to the server. Increment slot (channel) 0 each time a // frame is sent. for (unsigned int i = 0; i < 100; i++) { buffer.SetChannel(0, i); if (!ola_client.SendDmx(universe, buffer)) { cout << "Send DMX failed" << endl; exit(1); } usleep(25000); // sleep for 25ms between frames. } return 0; } //! [Tutorial Example] NOLINT(whitespace/comments) ola-0.10.5.nojsmin/doxygen/event-driven.dox0000644000175000017500000001163613023355232020264 0ustar wouterwouter/** * @page event_driven OLA & Event Driven Programming * * [TOC] * * @section event_Overview Overview * * This page describes event driven programming and how OLA uses it. It also * provides pointers on how OLA's event driven model can be used with other * event driven frameworks. * * @section event_Background Background * * [Event Driven * Programming](http://en.wikipedia.org/wiki/Event-driven_programming) is a * programming style where actions within the program are triggered by various * events. Event driven programs typically have a main event loop which then * executes the required handlers when events occur. * * The simplest event loop may look something like: ~~~~~~~~~~~~~~~~~~~~~ while ((c = getchar()) != EOF) { switch (c) { case 'q': printf("'q' was pressed\n"); break; default: printf("Something other than 'q' was pressed\n"); } } ~~~~~~~~~~~~~~~~~~~~~ * * While this works for key-presses, it doesn't support any other type of I/O * event. To support more generic types of events, the * [select()](http://linux.die.net/man/2/select) call (or a variant thereof) is * often used. * * Event driven frameworks allow the programmer to register to * receive notifications of certain events. Notifications are usually delivered * by executing a callback function. For example, for a timer event, the code * may look like: ~~~~~~~~~~~~~~~~~~~~~ app.RunAfter(1000, TimerFunction); ~~~~~~~~~~~~~~~~~~~~~ * * Usually after any initialization is performed, the application gives up * control to the main event loop. This is usually done with a call to Run(): ~~~~~~~~~~~~~~~~~~~~~ app.Run(); ~~~~~~~~~~~~~~~~~~~~~ * * The Run() call will only return when the application shuts down. * * While this appears limiting at first, the method is in fact very powerful. * Event driven programming allows the programmer to focus on writing code to * handle the events, rather than determining what action to take next. * * A caveat however that is that callbacks triggered by events can't block. * Doing so prevents control returning to the main event loop and will starve * other event notifications. Typical approaches are to either use * non-blocking I/O or perform blocking I/O in a separate thread. * * @section event_OLA OLA Event Management * * In OLA, there are two main types of events: * - Timer events, which trigger after a certain time interval. * - I/O events, which trigger when a network packet arrives, a device has new * data or some other I/O occurs. * * @subsection event_CPlusPlus C++ * * The ola::io::SelectServer is the core of OLA's event driven system. It * invokes \ref callbacks when events occur. * * For the OLA Client, the ola::OlaClientWrapper class encapsulates the * SelectServer behind an easy to use interface. This is described in the @ref * dmx_cpp_client_tutorial. * * @subsection event_Python Python * * The Python classes are similar to the C++ ones. The ola.ClientWrapper module * provides a basic SelectServer class. * * As the in C++ clase, the ola.ClientWrapper.ClientWrapper class encapsulates * this all so in the basic case you can just call: ~~~~~~~~~~~~~~~~~~~~~ from ola.ClientWrapper import ClientWrapper wrapper = ClientWrapper() wrapper.Run() # event loop is running ~~~~~~~~~~~~~~~~~~~~~ * * @section event_Integration Integration with other frameworks * * This section is for those who want to use the OLA client within another * event management framework. The OLA client code does not use timers so the * only events you need to handle are socket I/O. * * There are two main approaches. For frameworks that allow file descriptors to * be added to the main event loop, one can simply add the file descriptor for * the OLA server and call the appropriate read/write methods when the event * triggers. * * For frameworks that do not support raw file descriptor access the best * solution is to run the OLA client in a \ref cpp_client_Thread * "separate thread" and use a callback queue to pass control between the * threads. * * The OLA clients are not thread safe, and must only be accessed from the * thread in which the event loop is running. * * @subsection event_GLib Integration with GLib * * [GLib](https://developer.gnome.org/glib/stable/) has a * [g_source_add_unix_fd](https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#g-source-add-unix-fd) * function. * * @subsection event_QT Integration with QT * * [Qt](http://qt-project.org/) provides a * [QSocketNotifier](http://qt-project.org/doc/qt-4.8/qsocketnotifier.html) * which allows the OLA socket to be added to Qt's main loop. * * @subsection event_kivy Integration with Kivy * * See https://github.com/jesseanderson/ola-rpiui for an example. * * @subsection event_pygame Integration with PyGame * * See [Example](https://groups.google.com/d/msg/open-lighting/hBq00uYXioA/zpG88fjJFDAJ) */ ola-0.10.5.nojsmin/doxygen/rpc-message.png0000644000175000017500000003426613023355232020062 0ustar wouterwouter‰PNG  IHDRôb¦ž!` AiCCPICC ProfileH –wTSهϽ7½Ð" %ôz Ò;HQ‰I€P†„&vDF)VdTÀG‡"cE ƒ‚b× òPÆÁQDEåÝŒk ï­5óÞšýÇYßÙç·×Ùgï}׺Pü‚ÂtX€4¡XîëÁ\ËÄ÷XÀáffGøDÔü½=™™¨HƳöî.€d»Û,¿P&sÖÿ‘"7C$ EÕ6<~&å”S³Å2ÿÊô•)2†12¡ ¢¬"ãįlö§æ+»É˜—&ä¡Yμ4žŒ»PÞš%ᣌ¡\˜%àg£|e½TIšå÷(ÓÓøœL0™_Ìç&¡l‰2Eî‰ò”Ä9¼r‹ù9hžx¦g䊉Ib¦טiåèÈfúñ³Sùb1+”ÃMáˆxLÏô´ Ž0€¯o–E%Ym™h‘í­ííYÖæhù¿Ùß~Sý=ÈzûUñ&ìÏžAŒžYßlì¬/½ö$Z›³¾•U´m@åá¬Oï ò´Þœó†l^’Äâ ' ‹ììlsŸk.+è7ûŸ‚oÊ¿†9÷™ËîûV;¦?#I3eE妧¦KDÌÌ —Ïdý÷ÿãÀ9iÍÉÃ,œŸÀñ…èUQè” „‰h»…Ø A1ØvƒjpÔzÐN‚6p\WÀ p €G@ †ÁK0Þi‚ð¢Aª¤™BÖZyCAP8ÅC‰’@ùÐ&¨*ƒª¡CP=ô#tº]ƒú Ð 4ý}„˜Óa ض€Ù°;GÂËàDxœÀÛáJ¸>·Âáð,…_“@ÈÑFXñDBX$!k‘"¤©Eš¤¹H‘q䇡a˜Æã‡YŒábVaÖbJ0Õ˜c˜VLæ6f3ù‚¥bÕ±¦X'¬?v 6›-ÄV``[°—±Øaì;ÇÀâp~¸\2n5®·׌»€ëà á&ñx¼*Þï‚Ásðb|!¾ ߯¿' Zk‚!– $l$Tçý„Â4Q¨Ot"†yÄ\b)±ŽØA¼I&N“I†$R$)™´TIj"]&=&½!“É:dGrY@^O®$Ÿ _%’?P”(&OJEBÙN9J¹@y@yC¥R ¨nÔXª˜ºZO½D}J}/G“3—ó—ãÉ­“«‘k•ë—{%O”×—w—_.Ÿ'_!Jþ¦ü¸QÁ@ÁS£°V¡Fá´Â=…IEš¢•bˆbšb‰bƒâ5ÅQ%¼’’·O©@é°Ò%¥!BÓ¥yÒ¸´M´:ÚeÚ0G7¤ûÓ“éÅôè½ô e%e[å(ååå³ÊRÂ0`ø3R¥Œ“Œ»Œó4æ¹ÏãÏÛ6¯i^ÿ¼)•ù*n*|•"•f••ªLUoÕÕªmªOÔ0j&jajÙjûÕ.«Ï§ÏwžÏ_4ÿäü‡ê°º‰z¸újõÃê=ꓚ¾U—4Æ5šnšÉšåšç4Ç´hZ µZåZçµ^0•™îÌTf%³‹9¡­®í§-Ñ>¤Ý«=­c¨³Xg£N³Î]’.[7A·\·SwBOK/X/_¯Qï¡>QŸ­Ÿ¤¿G¿[ÊÀÐ Ú`‹A›Á¨¡Š¡¿aža£ác#ª‘«Ñ*£Z£;Æ8c¶qŠñ>ã[&°‰I’IÉMSØÔÞT`ºÏ´Ï kæh&4«5»Ç¢°ÜYY¬FÖ 9Ã<È|£y›ù+ =‹X‹Ý_,í,S-ë,Y)YXm´ê°úÃÚÄšk]c}džjãc³Î¦Ýæµ­©-ßv¿í};š]°Ý»N»Ïöö"û&û1=‡x‡½÷Øtv(»„}Õëèá¸ÎñŒã'{'±ÓI§ßYÎ)ΠΣ ðÔ-rÑqá¸r‘.d.Œ_xp¡ÔUÛ•ãZëúÌM×çvÄmÄÝØ=Ùý¸û+K‘G‹Ç”§“çÏ ^ˆ—¯W‘W¯·’÷bïjï§>:>‰>>¾v¾«}/øaýývúÝó×ðçú×ûO8¬ è ¤FV> 2 uÃÁÁ»‚/Ò_$\ÔBüCv…< 5 ]ús.,4¬&ìy¸Ux~xw-bEDCÄ»HÈÒÈG‹KwFÉGÅEÕGME{E—EK—X,Y³äFŒZŒ ¦={$vr©÷ÒÝK‡ãìâ ãî.3\–³ìÚrµå©ËÏ®_ÁYq*ßÿ‰©åL®ô_¹wåד»‡û’çÆ+çñ]øeü‘—„²„ÑD—Ä]‰cI®IIãOAµàu²_òä©””£)3©Ñ©Íi„´ø´ÓB%aа+]3='½/Ã4£0CºÊiÕîU¢@Ñ‘L(sYf»˜ŽþLõHŒ$›%ƒY ³j²ÞgGeŸÊQÌæôäšänËÉóÉû~5f5wug¾vþ†üÁ5îk­…Ö®\Û¹Nw]Áºáõ¾ëm mHÙðËFËeßnŠÞÔQ Q°¾`h³ïæÆB¹BQá½-Î[lÅllíÝf³­jÛ—"^ÑõbËâŠâO%Ü’ëßY}WùÝÌö„í½¥ö¥ûwàvwÜÝéºóX™bY^ÙЮà]­åÌò¢ò·»Wì¾Va[q`id´2¨²½J¯jGÕ§ê¤êšæ½ê{·íÚÇÛ׿ßmÓÅ>¼È÷Pk­AmÅaÜá¬ÃÏë¢êº¿g_DíHñ‘ÏG…G¥ÇÂuÕ;Ô×7¨7”6’ƱãqÇoýàõC{«éP3£¹ø8!9ñâÇøïž <ÙyŠ}ªé'ýŸö¶ÐZŠZ¡ÖÜÖ‰¶¤6i{L{ßé€ÓÎ-?›ÿ|ôŒö™š³ÊgKϑΜ›9Ÿw~òBÆ…ñ‹‰‡:Wt>º´äÒ®°®ÞË—¯^ñ¹r©Û½ûüU—«g®9];}}½í†ýÖ»ž–_ì~iéµïm½ép³ý–ã­Ž¾}çú]û/Þöº}åŽÿ‹úî.¾{ÿ^Ü=é}ÞýÑ©^?Ìz8ýhýcìã¢' O*žª?­ýÕø×f©½ôì ×`ϳˆg†¸C/ÿ•ù¯OÃÏ©Ï+F´FêG­GÏŒùŒÝz±ôÅðËŒ—Óã…¿)þ¶÷•Ñ«Ÿ~wû½gbÉÄðkÑë™?JÞ¨¾9úÖömçdèäÓwi獵ŠÞ«¾?öý¡ûcôÇ‘éìOøO•Ÿ?w| üòx&mfæß÷„óû2:Y~ pHYs  šœ7iTXtXML:com.adobe.xmp 72 72 1 1 2 ˆbù +ØIDATxí] œNÕûŒcìŒ%²+•BöŸ}'k²¤”$)%[¤¤ìQD‰Z„)[%)ÉZT$Y²ïÆ2ûŒ™ÿ÷ûÜ÷μ¦Qó×ÌxñœÏ¼ó¾÷žsÏò=˳œçKç.õLºÝ÷Oã’´¡Õš5˶~Ù²rmîë’±Å=sfô÷—ø8à’!­ù‰4neeˆŽ¥°ÐPy¡ï£R¡J éØå1É(q.Øøº²½c¥×žõfëeò¸‘e —¼õ†ƒ{v\W];ôö‚eã×˲¨¢ÅKJõº cýü ³÷ÚíéßšxL°€€9{&D‰xÁ‹HµZu%0stHëÆ0¦§X‰†À5Š×›ÀÀLqgNŸÂ¶±Dg;¸Ç·›Öº§µ'ù*ѨˆÒó qÐ3Ø‚ë[£á*« 'ØHâQ‘‘°ÒÀoŒ¯Hþ†Œ÷m|]ejÕ5|®7Xg2ÄÄİ–~1ѾWÙt"èNùÀº??ªÛMåî{CâꪑŽ'?I†×ørÇÙÕÕ«­!`ø2¾¾®˜qš/«›!`†€!BŒ §(Kf†€!`ø2FÐ}¹w¬n†€!`†@ 0‚žB ,™!`†€!àËA÷åÞ±º†€!`)DÀz ²d†€!`†€/#`Ý—{Çêf†€!`¤#è)Ê’†€!`¾Œ€ô4ïËy±\<¥ì¹”¦KófZ†€!`WtõwE[šî…ÇÃ+žŸøet^DCW·É¼òÓã¢Ôã5_ åqðuÏÏ¿yÓ£/sº95žºvÏ0 ë#èiÒ×1gÖŸ~8SråÉ+[´‘¨¨È‹ý‹ÃUéÄÿ±í}k)yxX˜”«XUš¶l+Ùsæ”ØXú v\æºU%ñ¦ B~ÿ±ýWÉœWòå/¨iq÷Ý”x’7,†€!`\ó˜Ê= º˜ïç–Ÿ7þ(ÞyRŽ> Ôw½Wa ´$¶ß,ÿ\NŸ<.•«×–;ÊW’ŠUkȈ=å£YS”Èè!ö‰Ïâí6’9sDGEIûFU%L@@¦L ä|áŸdÂ3™3‹?¤w †€!`×&¡§r?Sj&A=|pŸ¼ÿÎ$Í=sP–dTâŽO•{Ëv¤MÇöv¯çË(ÅJÞ$]Ú4”fwwÀkA3C¥+ Þ˜PS2aaç%äÔ)½·ëí’'_~É–-»ÄDGËï¿n‘Ó'åæ[o×ç¨î7•||öÃ0 k#è©Ø­$šx5¬DD„ËôIc¥EÛûå¶²wJèù³É«¾‘žRú¹sg@€Ã$"<Œ:r9zè ÔlÐT²çÈ)›7¬•Åó?—Þ˜†ë\ªVÿ`ú›’%k6•ÊYý_|*¥n¹MâA¸ß;RN;"%o¾UÆ Nú ~Ij7lšŠ­´¬ CÀ0|#è©Ø+$ÎPµ¯X¼@Ξ ‘wµ”=þã6¯Mí„òœ=ðà|dÞ¬©rà¯=ú>oãÅ 3?ýJ .,7Ÿ-#«VP-Brå–cGÉ{o½&._+7-.ãG –®Oô“b%n’YSÞ#Pï|}ªä/PPjÔk¤’þòõHa¤ŽŽJž±H¨“ý0 CÀ¸Z°=ôTê9JçܳþsÇv%Ðý’9³IdD„î§sOýâàyªÓ )‚[ ¼ˆÜR¦¬ªà¿ûzöÞKÁ‹Èƒö’oV|‰Ü_6¬]-ÍÚ? ¥‘Ž{é 9ræ’óçÎÊë#I¹ Ueçï¿Éw߬€fàœÆoݼNÕöf §p\7ÿ8&“~þkãÝüRšOÒô¼N«´¬äÊqÓ¸ßz¤$¹„—y/1ß¿gðOqOmw ÿ?I©Ìÿ?{BÍŒ Øá¡¡òÆ+/JŽ\y`}þë6Ù·w—…T½jÅ)_¹ša?ÇÌH\iÀvêÄqðûåî{”°Ðóºÿ~üèaiX±¤Tþ_miܲT©YGÞ›ú†´ «ìÚ±Mó¡ÊDœ!ùÅÄÐ^$4ôœlZ·F÷Ò¹—ÿÌð±ŒýõK›Ó‡ìßµ…‰&Æ™Hna¤I &9NøÍc‘—”1EÞbcÿ5 ŽñL0Ö¤†Š§52øù‰?˜Ð 8ŽÉí¡Ô e%—7ëC›žáŸXµ/a]Rç4ˆ{ •sáQRp'O;öWN0üô‘åý×úÚóצrO…þäbA'0°H¿çþ.òHÏþÒsÀ‹Ò{Ð)_©š4¼«µt{j€5s¥s“°€PŠ>zø ìß³OîÛ+{vî…óÞò÷·ã×̼8c^¬äÍ2{Ê•Îó`Œ‡Ôã.û±ÿî‡EjÐKãåÕ!åÀÞ=rþìùeóéÖ¾©ªÞ)©¹éS¡É–…"À±H[‰/>+­jÝ¡v æÌ”çzv•*¥ò€ÁÛˆ“^,‘ˆ¹Ä'±i^*{Œ·€€Lšï¤W‡+“ʲ’Ž)^óÃñHÂ6{Êxß\ mA€ìݽSÚÔ« û÷I€JÓ‰eýýWry{§rÊrîð÷LØ–lÛú³wýMbM¦÷àþ½Ò¸òÍòê°2êù¾òØý-epŸî²§DØ–ÄàÎ-÷ÚMqñ5ËÖ5Rùœ“¥Q¥Rò3ŒYuΡl¶¶14RíÒ¦ì`*c•œ¤îÝf§}nBB <8{_»¿ïÄçTÔ@zïà]Ž®E,¼ƒŸxïâôÞ)í·/!`z*÷FFx†ó÷w:ª'så –¬FÜýîÄâœ44V;ôý¸qÍîé(ï/þVÞb¡J§´U¯IsÿÒ`©ëwžA§”D¢ë“O+Ñž2g±´îð€JAÍk”‘¼ùòÉÉ'dâ¬R¸X U‘^´f¹…Ù÷5ƒ]2ˆß­\.Ï÷zD&ÍþDn½½$Ð9sú”l\ûž¤p‰—ªä1¶t­÷Ð3ªÒIh(]rÜ1O~“³¤ºž[@u7“Œû y%ì TíƒÔéXã7CB…¡=Ê"±°)Z¼”|´l3®qMÆ‚Ï0hz”ŧ\u>¥XÍ79vYÇ+¢£"g<#X?¿Ø šofø_H˜'óq·¥º>ÙO·¾Îž9#ËÍ—gztÆ|[%Ù²çÐüI€Ù^'ÖŠ˜pË‚¾€¿§îN;ùŸš¸Ó§Nhš% çA+Q9As¶uóF5ve$5&l7óO®Ì‡me¨”¯9:mHìÄ¡.Šs¼KRã }†<øŸL÷6€[®&@]XžãÒÙ qÆ„€„œ~a: ¾‹€ôTîªò0w4PÅ×öþ‡uâFEF$,‰‰Á©Ai¾Ëã}œÅ“wðGõyvº‘˜sÒeÉ¢ª÷Šÿ«%… åZ£ Çtï=PîïúT‡Yq=‡ty¬·îÇsñá‚™^ê˜G¢fÀ©›ý¿6ðÃ"¿çÏ?°-ó¸4mÕVÇI4|¸¡Ž2Þ¢Fš—\ôybâóO>’“Ça|ÄJ¥j5¥~“–’5{vÙñÛ/²võ×8zyŸlþñ{ùñûo¤Ó#O“áy0§õ8&mF¾\ñ©jrÌF„‡«V©IË{tÜq0;Ø!öÏlûUUðTwÏxs¬2 dvyÍPªô­Ò°YkeVwÀƒâç æhd`Ùž;+W×ñÌúoÿågY¬ñ±:ö™¶zÝFJœ’ë]Ï‚2nÓô$Ê4( 'Nç ÑÊ™;JÒ_~±P5bôà¸[ô Ѻ}'­õ´'N¾Ó´†«dl(ý“™æQQbÛsàÙMÁ¦uß ±8t`Ÿ|òá Ó'ÔX(QDe8/¹%¶LÚÓÜQ¡²ü0Œ£FƒíÍ‚u ]§G”A§]βEóäðýj›3W.iqÏ}Z×该 çëü¶†>,Ø… Ó~&Þ›fÅçŸ*LyòæSmBMœŠ¹­lhW2`l–Ïæ¿m›S*ÛSÚÜûâ ©ÁógžY‘¶P‘¢Z½ñ‚…Šè1µ¼ùop8ow·>©Þ\ËЧàVL.¦y³§bÿúK%‘ ´ ´Õ á%qàB=b`/ ©"X¡JuøÄC²rÙb+´ß7üYÜë,Û@8ó( 5V¶lZ/ß~½Ò¡¿.ôô¡pëå¥l…*Rµf=™8zˆ,–‘¾‡€cÜ-Ç) îéð„‡ú™`¡"Å•pòy2§SÇ¿¬>ƒÀPl•îíš(1ª^§ÜvÇòH»¦òÛ–MºïMçIïª!9AYwgOLIéTâ|æÌiņƪœ#áÀjÌ2mâÌÃìR½v}¤NPÿ¡0B%±[ºðcyòÁ6rÓ-e¤BÕêJ ×­ùV%tÚ­/YZê5m!+—~¦ "ÅK*´ă„q+¶Ä:µ¨­ùT¯ÓPÓ<вŽìÛó§n›Ì†!ì–Íë…v1wVþŸ ÚçpKåMl{ðšqÜÖ;qô¨ìÚù»÷3!§”°—cP­V=œ¼Ù&Ü&aŸR£²éÇï¤+°%f«ÕÐã°oŽæà€dBüñ£GdÔ >Jü‰=ñ:þ%YõåÅŠØYðMLBOã~¡úŒáRÕUþ­˜4\4à uïÐP{z¨ÔÇ"qªEï@Ü/ï”Ì£ñqƒ–kÐ…ãšÿæx¢JüGŸÒ­˜œ9²IË] Õ•”2åîÔ÷€¢È«WªÚ˜¶9à°ˆ‹4%¹®mK£æw«„L°z=7\Ê€˜RmαDI=E޳@lýÜÛùQeHHù®‚“ÇÈWptD‰•^™N‰:$ÃB…ЍôIíQÛûÒí¦™3ómH€-äÜ#½ùöxyü™!ªq¢.‹Dxßž]òÓúµjôöáô·¤ÇӃ屾ϩvŠZn)ÄКõL–öÌý$ÓLß,gèØÉ’ Nœ¨M Š›¡7ÚMF‡» dVZ×)/vJnÄÓÁ}ºÉŒ—ëö5rš·Ñ- –K ~æS·Q3útiÖæ^Õ2Üßµ‡Ã1oZþŸ#ôî›ãdô›3¡Që BœAµ'Ôš¬ýökäÝDÞ…MÀ;s—¨dÌçø>¶“Æu ?š% Wm†Z¿"»SîjÝNµ ôÙ i+%Üämˆ-·üztj­þ*¨ y´Ã]ª-h×éaÕ.pYñùô…£b_‡>¦ÆæÑ^[b’#gn0€OJýÆ-ô¶Q×VÌ‚Ï `ÝÓÉ.ž8ï{©tÞiœÇ° yI |îïi ½ÆóAϢß”¸óæÏ/«~=ª‹/÷GÉ xçãüN䘽ã˜Ç?…KÕ韞±8ßE€}OɘF“}@¸`oÛú“]nøá[Hžýeò‹ô½?møA%¼±0£ñ öY´J¢Ä=c†r f\Ð#!ÉÓ"œ÷¹˜“èRʦ¤LI’ûÑ´¤§tÉc›îó‰SÀ£!'Ži¾Ô$У"ÇôÊ¥‹eÔs½eéÛ‘Ç *ÉÇ`Ÿ™î~äG ¬ßü÷¦Igl)………*c1æ­Yú<ãYžnQiîÉüCEܹñí—KÁ(Ÿƒ¤=Oú­L 3ëäjÖ8ÿˆ Uí $–Gí×ßE`@u6q!ã6¦Õtx.Op>yiâ yì¾rßÃ=ÀLUÔ-ÆÓXŽ/aúnå2¨ùsËFH̬;$¶±ãC©ê½{Ÿgõù‡á8ªRµZð=qüR@í¦¥íý]åžú•°e7@*a+Žqd´xÂáè¡2ÿýé²Úú±ˆŒt444T$Nl%Oð;ôüyÕÒ„Á›%µa¸¦+é8nKM58ì÷ßýYÛ©ÇÙ >‰€tO·pqò&¦noQe¨RKN–ŒdÙ“Fª#u•Ã^S]NŽWÕ{zϳ&yÖ½dùšÊóœdêÏ„<)1÷Nw9¿™7 ˵p !€þ ‚MUÂ¥J—Ñq¢7eüh™›AQò­~î¸ã˜¥#ªŸ9Öü3:ó4¾Tbè'$~$b»ölWµ÷³#Æ) 'ÃõkVÉòÅ'ÏäQ¥Ì:eUz¿î÷ÉŒ+to˜’eS‚­^·¡úbˆÕ¹×u-X¨°ªçCïJÓ¬¥GÂL¾D2 º÷‹è'úV Õà+—/–梹•¥ÛžÇI`‰ ÛíòؼŽòmêö8¨ ÀÜöJb¨Øa{ƒ6 uÝ¥nœc/Áamô'´)Í•‰áÞ;ËjÚª½ãѶÎÐP;ðû/[dh¿îr:ä´L›·T¨žï3h¸æûûo[¤gç6š ûèjú¹§ºJ™²¥ç3/ªQîqHý_Á.€˜»e³,Ö•Ì·bh8Év’àŸƒ j­Ò´u{•ÔÙî8©CWÔìw§öß—0‚ŽÞà%—Ï滑óA÷µ¹•4èÞ$¸kå~‘Ž„’Ž4èÃý4^ Â…‡; ×XFÒr¸Ð„Â;÷6¹xzÇ““çBãª<“–}¹×,ƒ‹&Ëcý½Ë¼Ü<í¹+é#ШR¦A$oÚZÜPèF%Œ Ø·aßšêsJw¹òdƒÔÇy \Ã0œ7÷åÎ ‰«¼ðÓ!TKÇco}³,X/êŒýðüPΔ~Õ±ï’-2ÀNÎÜÊ‚z°ZYïݵS=õ°ŒŸ>WjB½Íùã‚á— „åRâ¬Y¯ž¦g5bbâ 1rFÂâ>FùÈdgÍ–M%Þè¨h=.çV÷RßdXrƒyyJ ë^ì÷¸Œ™÷ôƒ‚%syﮚŸË“×Á”NŠ— A„Ô …ójdžÿw,Óc¢c4¿o¶ü¥{ñ”öYW†8@C:¾M±f½†xN/!õÇI$¶.¢¢"ôÝ ÍÛ´ƒ ½%Ôý=…~(ÁP­L¹ zνEÛ{Ah[é‘XîyoÙ´N‰.̽8z41™àøª×ºæéOu- ã@õƒÝÀYì»SóÂ5ªAëqÿ=KV8‚B†}ž°Æ9µµÿ¾†ÀuMÐIÄÈqR%5ò¹>j5š; Ò°`pA ’.=ú€Sîµ[1ùå§ òέ†ž qÃõ—sçÃÀɶÓsçEáOD™G„ü¡Õnx—ƒç·?a1;sá×j`âO~S2GRÒ§ŠÚ9v‡µóŒL ç,ËfûØN.ŽŸ6Wútí€É5_Û àäWýA¡ èEsßÓöÐúžyP…ÞÞ"Y÷™oOÀ‰„ØÞÈ­R÷.¸{¦%:ë0О ªÐi¤È@ÍOÌŒÿŽ–;õçÉÆÜ¿OëHf®VýÆÂ­˜ÛÊ–W[zú;~ôúµ úŸÌŽí¡+¤>÷ïº&èÚ©cå’Odä„w¤RÕšº·G¢wRû« ´ÜÛê;h¤.dûÿÚ-“ß_¤©\Ü(=¿?íMÔ« X¾Ðhâè¡ò×î?åã¯Ö«•;³kWËÃ÷4’Ù‹VBXËKuçÒpÂp‘ìr,ƒ±ÀRZà1!rÏîþž{ö–q\¹Pp¢2P@ZÜ.ŽÚŸR;ùø,¯ÉÄd Pç\(˜%uJ\Üùqóe¥ –Éû,“ùXð=ØguÀDRÍÚ¹uý„ Þr{y™2çsU“ÀòøãÂo6Ë ^M|eˆ…|°×è·óÑ…*57-p„Ê Žª–ýÎY`XE£)JŠœ3½»¶×díì&­:t‚ä ›ÌŽGžÅæé ŒjÕ2Ý ižÚw…ƒ87nqLÀ †¨j9uªÞ†ÒûÙa0Hk(S1Ÿ&kðuš?÷‰¯LKaã™oñ1ô}~¤JÜÌÛ£dGPu5s Ý­%ý Â_ôíÏòô£å'H¶%n*-7€páÜYòÚðgä4Žè= 'QíxDëÏqßkàPg¯Vönà–O˜gkÖicb¨Ñs"jû¨R'A$‘¬Ù ±Ú4ð »þø]³¢Õú3Ã^U5ƒ´zÎ+§N„š}„°Ý”ª©Á`\>Ø-œÀ±ÃpñLC¼ÜÐN›¿LºßÛLó«P¥†´†[éûÀ„°_¹جMUó/œ;[FžÀúC- ™‘â¥J˧ßlÂÍËúò'fD6祷ßKÐæ±}|´îŠ’q<òHöwß}wQÏg†4èÖ³ˆŽŸÃ­¦uñÿ 8(rÑÑàxéEëƒÏWcª¾•LÀ)ÊgóæÉÛØ‹°ø­[óŒØS&ø¹ž—%§Ìɹ÷ÏÒ´Ú-²jë_ròØ1éФš,ùá7}¥)..l4¨™«Ö7Ý¢çl9ÙY>Õó§ QíÇ3ë-Ûß§8%bô¬ywïÜ.O¿ð²Zâ†`boÙ¸®d·êbÉã,”Â(M쀤Ãã0,óN7¹ ¯UåâÌòè#ž®89qËW¬*}»u„áÎt=örþÜ9ù\þÆWc1ɨÕ3™¢‘Ðáƒt&OkY—Qøg”Ó.VñÂ3ÄíTÂ)€ÖÒï…QI<ò¥]ù¾š3ûžccŽŒ‰eá8qΆ“I#óÇ#mT3ðšN‹È¼ÅâÕÆê¨Å³xs§tÉqIÉÙ%ZúÚ_d:ÁzÒÚ›G«8/I´¸åDæD‘'ë§Ïàù ›dø<™nG2¦ÛQg³Mn`2¯Ä„iyí–ï§gèÉðòH]óêe䣥k ¸C™{ÎWGÓàr^°lVšx»yòÛÆ6$ œƒÄy)þHÇŽí6µÓAy6žó•õSmðc{X—é&–t­ëÄe@\nc¸s’¸±ŸÈ¼fÔñ@ï|Ä•80»ÝF?õÊÕ6ó}Ä~’Ž ­ÈuúXƒ)Š[öÙ¿?p°Lù*wmߺqàP:ç °˜„îÕ ”¶1ÎAü.è´ïµDå±Ϋ˜Øh%Ž”‚9A)8qTãIàkÍ:à”óá<9¯‹ÉÉ Ju%>ç8]9QØ«oJã¤ç„ç:rè€~S‚c6}@„¹ÇEui,[´RË8]$'¾2T~Xµ\úBÊâ9ãNÍkÉ„ó”«ç¹Þ¶ *Ë€actaÜ./qn5SªXuY9goGL˜.öíQ™‹Vÿ,%À­Ïy÷m}%lMrÚpÒsO–‹‚ßC€”ÌfBÀXbqLq,ò›Ši2C «÷86éc]1Ax½ûX4Ožšé9Né‰äѽçÕC D·‰ÈD0Ž„/̧›Ž{ßÉÆ“ÀÅ£žÜÓE…d(Ï­ãIœè†ó‡×œ[ |>i`Ý“kƱo[þæQ6½‡Ìˆ•ËpN³-4Óà©óᶘÛ^'2ñ?Ÿa›Ýö³-Ì3+rO™‡¶ß,›ÄŸ­wÛH¦…Ï$Çz¹}ëh*¸f9Ø+Žx2S<—þΣõ¸ë0úÅþꈈt” Dþd&Ȥüml ? ¾‹€tô ÷ÔªÔ¬‹sŸ¯ÃÔ påa˜x9Ôk%î~/¼¤…Óêà¾ý²~²¹7ÆÉBg“à”aÀÐÑØ¢‡­­újS·Ë9ÁøaàâçNb7^§*òáÞÖëØÇ[ š{”TqÁ¢G§.=úbA‰VÇäªûBõV `AUyÖ/_*µT9}B¦CõWªt ¨éÃQ×=Bo[tø1oö4éÿâ+ò`·žºHPâî…=tJ=|#Ü„—__oP«ZJ\´,¦J®GßAj)ÛªÂC^Ñ=;:Ÿð^àÛb¿|Çi ÛEÕñ‹ŒàµH¯tÎXõ|ðÎDÓ{žå}ÎWrå5‡z\¬³5Ãk2:ú¡i½ò$J.x×3i§~NÝ•ð{ˆ7Ë wËJ.ߤå{§qµ$ì<ÊÆ³ùÔ.¸DÒ-—Ïð7·Ÿb½7Þ»½ÞùówÒòÝg.ÕFv~ÜÀ¶¹Ïü-‘nÓ»[iüÍûq¬Y?¾,‡Îh¾^²Hµ1ÏB]_ër7Å$±ø„ûÌÓ‚o"`ýBâIiº ÜÞtküŽ!p Ác'¯MûHÏ׺›ÝH#7|.dtÚ0æ­Ù0$i¢Ü, ¤«úóîrNfªôT% µ¯ 3QÕ[}ñu:… „îXÄÆÃÄlHÜo$qÏ–#‡úŸfùäøƒp^w‘Û=7žAýöË=z>˜î&z¼Ÿ2ô6wÙª %Î}üàà<Ê‘óÜ)úïW©sJ2|+Ö‚fH‡ºiÜÿ`DÅ3­¬¶³øémû磸‹ò¿UïŸÒ%—’{$ênHšÞûÚû·›>é÷?¥IçUlÒl®“>ãFPíNÍ å|´§Þæ<&žl@#“+ïRù»y$ŸÜ=¦¿Ôý‹K.ÞÍ‹m¢!! }]M×obž\šÈþù4FÐÑ=ì¿ÀÅ"9ÕêujƒÆK•êu¤öÒøò†»éž1'@ÑâÅ¥3&| ßæ +Mg¿Rð\móâx±z^‰r¯ö©2'A>ƒŸªöv #ñ"EKÀ¨¦œ³‡Ž=OÂ,\ŽA)@·wà lyadDf‚ÌÁ«ï8Ú»›>i¬¼ÿÎDUŸÕ¨×HZÁëìNf~“‘ ”޵\ÁT•Gã¿rØS§ñUyäþëÀò™-¤ùõðÆýr–ï½Oê>g߆€!`¾ƒ€tSÏÕ8*jg?-sæ,úò ¾½è¯Ýp€Ëu¾‚ûæôöäÝÄÎ$a¦Í—(0íG3§ÂÇõ)Ý“¯Ý°ŒÊ^vŽ‚A ç³LO&‚–Æ-ÚvÔ×:¾’82 ôæDÇL{ó­·ë9öfN‘åŸ}¬j{:«¹Ęw4|[8ã-Õ T‚êâ6ü°Zª8ß:aÆ|™‹—`ðHM+¼’¯{¤Õ+½Ñ~Á‡ïÊ”×_c-ÃÆ½×1v0uñBîŸ'mobËí—!`†À•F€ZÔ´ >}Ý»á$˜ ÞD‹÷hC"ïþæ·wï<ø›ñ$êLCÉ\Óã>÷»ùIÎ`Î}.¹|ù<ãøa}4_Ô‰†sTÿ“)pÓк•ÏpÏž/c úÞ}Ž ‚kýJ©{gÈ’¹kyMõ¾^#žf?î>¿›?¿}%8í´sè¾ÒVCàZF€ëC¿Jz˜„Ò%žn•Iyϵtu'Mç¦ç7Ÿq¥C|=“”^¥hÆ'’+Ÿé¼Ë¦£ˆ œúdsÀzxká5-ÔÈ„àT½jMG ƒãH‡5p· ܶI`YÞÏ»Z·ÎnZ-Àþ†€!`ø¦r÷t‰%%Óä‚w\JˆZ"DžŽðLJ¯Ä>¹üyïRù^|ß©ëC¡Üá .®3™ §dHœv%Ô ñ*óãaï¼ÏkWÚ÷®¯w:ÍÜþ†€!`øFкäb˜p[üSÜÅ)/¾Âs—ûèÅ%¹r ç’ÜÔK—p'Æ%©€Ã$F'ýõoñIÓÛµ!`†€O p ¯ >Q7«„!`†€!`¤#è)Ê’†€!`¾Œ€t_î«›!`†€!BŒ §(Kf†€!`ø2FÐ}¹w¬n†€!`†@ 0‚žB ,™!`†€!àˤë±5=ç̳Ξ/cuó}ô|<Æ”§²Îo_¾ßwVCCàjC a]IXo|¯éJÐé•/&á«;ÕŨyö½q5Õ‹ã‰nlyàßÏÏ_ôUïçëzÞ¹šZdu5 _EÀ³ÞÐÝ6ƒã“Ó·*›.ýHT”z7ákIÏ„œŽ#aw=˜ùV›« rÌ èçΞÁËrâôõ·|ß|æÌŽK\c¯¦î´º¾×›Lq¡çÏq«:>:Þ¡k¾Té´&èª ýéë¯éÔï›_Ⱦ=»ýýð~p`cÁøàE9ð?ÏWÑž?{VÖ¯Y%gAÐaü°Úㆀ! ú ¿Ã‡0.ðàÞ½PúVHâ4M*Ç2â³diÞ¿£ñIrÓ¤1–©Ï!À±tD<;üØ“M Å'#>Æ2 †€!ªp]Á¯³lŠŒ ŸŽßîÛ:RµËÌ0 CÀ0ÒëV8½nž¾ãËJ3 CÀHcHÏ|ަ¥w…Ò»¼4îSËÞ0 Cà:DÀ¶ô®ÃN·&†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`†€!`¤ÿ„„?øNê‡IEND®B`‚ola-0.10.5.nojsmin/doxygen/OLA.png0000644000175000017500000000305313023355232016255 0ustar wouterwouter‰PNG  IHDRo0$BòIDATxÚíÜylTUÆagÚŽ-[ T‘h""J\ˆaQ0j(ˆAÀ­)£‰…Ó ¨,j `ÀE²7\E[D@YLYìýü…@Ò|ùêÜ™¹[Ißäù‹éÜKß™;çž3§‰ÈY ©?9ßYCy åM6ò1ëQ†Ã¨FÊñ#Ö q .ä4BfXË‹bV ’ Ó؈‘ˆ!Ùˆ†D°ëÂV^ùØ qÉŒEúR^_È9ÃR^[¬‡xd'º\å•@ÎY†òîÇß:œÄ ¢7:"÷œŽ¸ ã±ÿ@êP…Âz\ÞMê|ªÑ.ÈòžG ÄðB8Mˆsé]€´zXÞ{eNPåM‡Ž`4ÒSü`„½Ã2¤Õ£ò:à D9Ž~—÷$İ­àVšáuˆan})Oý´gý,¯NC”©ˆÀ‹ŒBD)¨嵎sËtY~”× ¿A”gàu/š \òòfBâxÔò^2?týËãå+DCZ^ŽªóøÛŒÁ]ÔËòòŒK×7È€Ÿy¢Œ iyOA”.QzYÞkÆ}Ê ð;¹8¤Î¥ Ñ•ÃêJjM!–ªûÒ«òZá”:Ø|•q¥_ÈÊ{¢ôÁù< QzxQ^¡9;\²ð§:§wCT^eêøÛŒwæ}«åEyŸ©ƒ|„ ó‚:§SÈ Iyùet&ªÇÔ “›åeCôÑ:7B”ž!)ïkuìRD¡Óåê±o¹Y^ˆr‚Nĸt>‚òzAx±OU­Dk·Ê+2ÖØ¬DÐQ— j„º²J¿jCPÞZuÜ}q•sÁà,·Ê›ïàó®%¶BðKïÌö(Å,GtŠÕ¹m¸¼ÎÆ*K!âeŽú™£Èv£¼÷Õ¿éàƒwRÍbõœC 3A/Ú\ÞR½ÂâpI¬ªÕϹQÞZoéIê1Ó=øE s0]öK€å]n0N³Hýì~ÄR-o£ƒòšáS¾E.RÍÕµf(Jé ¼Ÿ,ïUc­®%œ¦“qÉ‘jy&°Ž–7‹3òšŠË¦=è(F¢Ñ¿ë]ˆ¤RÞBõ„Ë–ÌVç¶) ò¦Ãý6H4·@”»S)oб’–¬Òƒ)?ËÓ7ÚÙœJyCyÍÆø¿4…׉« “(¯â±.É–—Qî„•ŒZ×íÝIN^wÄTâÅx_¥Sºú\^ {![–ÊÄôž¸÷zö»t.¾¯ì+3ÔãNàbŸË{âƒ3¸"ÙòfÃàèŒP[ˆD³A=ÇÐÉ4:—ø¼$Á.uŒµ.nF9¢ž{^²å] qpš‰-À•°ÒMa¥'ŽÕšŠKsø]–¾>—×¢Ü ·2ÅXòÊu\žJ‰ñîk +yˆÁJªñ/†ÃJ:!lcó{D|.ïsõü[=¸w<®§“-¯»1°8MSµ6øÍkÞÓÇòºA”ûàv^6æJ;-Og D™ §ÉQóåH$ùÆ èD|.o¥ñÕ½4¸{Âz\²åµÂAcé~œ¦•8¡pš®8iì@ºÊ×/ÝÚsð*zueÒ–§s;NCÙ'à4Y nDéSu}_Óçò—²,x•kŒËT6š@ \ÞoçêØ13€&íPe|lxÕê˜Û/ÏžŒÕv£—Kƒ‚ÃBD(o¶11 ¯Ó¢ôNusej † ¸+ÁòîÁ&H^QÅùU^ pŸÆzBÀm̓q,ΦŃžhKÑÐaqœÙù Œ…Óˆ öךr›lLÐçÁ¯Ük ¯O±Remote * procedure call has some good background reading. * * On the client side there is a stub, usually a class. Each stub method takes * some request data and some sort of callback function that is run when the * remote call completes. The stub class is auto-generated from the protocol * specification. The stub class is responsible for serializing the request * data, sending it to the remote end, waiting for the response, deserializing * the response and finally invoking the callback function. * * On the server side there is a usually a 'Service' class that has to be * provided. Usually an abstract base class is generated from the protocol * specification and the programmer subclasses this and provides an * implementation for each method that can be called. * * Because the client stub is autogenerated their can be a lot of duplicated * code which constructs the request message, sets up the completion callbacks * and invokes the method. Rather than forcing the users of the client library * to do duplicate all this work, there is usually a layer in between that * provides a friendly API and calls into the stub. This layer can be thin * (all it does is wrap the stub functions) or thick (a single API call may * invoke multiple RPCs). * * These client APIs can be blocking or asyncronous. Blocking clients force the * caller to wait for the RPC to complete before the function call returns. * Asyncronous APIs take a callback, in much the same way as the stub itself * does. * * @section rpc_Proto Use of Protocol Buffers * * OLA uses Protocol Buffers * as the data serialization format. Protocol buffers allow us to wrap the * request and response data up into a message (similar to a C struct) and then * serialize the message to binary data in a platform independent way. It's * worth reading the * * Protocol Buffers documentation before going further. You don't need to * understand the binary format, but you should be familiar with the Protocol * Buffer definition format. * * As well as data serialization, protobufs also provide a basic framework for * building RPC services. Early versions of protobufs came with a * service generator. The generic service generator has been deprecated * since the 2.4.0 release since code generated was rather inflexible (in * trying to be all things to all people it left many needs un-addressed). * * Let's look at a simple example for a dictionary service, Dictionary.proto. * The client sends the word its looking for and the server replies with the * definition and maybe some extra information like the pronunciation and a * list of similar words. * ~~~~~~~~~~~~~~~~~~~~~ message WordQuery { required string word = 1; } message WordDefinition { required string definition = 1; optional string pronunciation = 2; repeated string similar_words = 3; } service DictionaryLookup { rpc Lookup(WordQuery) returns(WordDefinition); } ~~~~~~~~~~~~~~~~~~~~~ * * We can generate the C++ code by running: * * protoc --plugin=protoc-gen-cppservice=protoc/ola_protoc_plugin \ * --cppservice_out ./ Dictionary.proto * * The generated C++ stub class definition in Dictionary.pb.h looks something * like: ~~~~~~~~~~~~~~~~~~~~~ class DictionaryLookup_Stub { public: DictionaryLookup_Stub(::google::protobuf::RpcChannel* channel); void Lookup(\::google::protobuf::RpcController* controller, const \::WordQuery* request, \::WordDefinition* response, \::google::protobuf::Closure* done); }; ~~~~~~~~~~~~~~~~~~~~~ * * As you can see the 2nd and 3rd arguments are the request and response * messages (WordQuery and WordDefinition respectively). The 4th argument is * the completion callback and the 1st argument keeps track of the outstanding * RPC. * * An implementation of DictionaryLookup_Stub::Lookup(...) is generated in * Dictionary.pb.cc. Since the only thing that differs between methods is the * request / response types and the method name, the implementation just calls * through to the RpcChannel class: * ~~~~~~~~~~~~~~~~~~~~~ void DictionaryLookup_Stub::Lookup(\::google::protobuf::RpcController* controller, const \::WordQuery* request, \::WordDefinition* response, \::google::protobuf::Closure* done) { channel_->CallMethod(descriptor()->method(0), controller, request, response, done); } ~~~~~~~~~~~~~~~~~~~~~ * * Protocol buffers doesn't provide an implementation of RpcChannel, since it's * implementation specific. Most of the time the RpcChannel uses a TCP * connection but you can imagine other data passing mechanisms. * * As part of writing a new client you'll need to write an implementation of * an RpcChannel. The C++ implementation is ola::rpc::RpcChannel. * * Putting it all together produces the flow shown in the diagram below. The * yellow code is auto-generated, the blue code has to be written. * * \image html rpc.png "The control flow from the Client to the Server" * * * @section rpc_OLA_RPC OLA's Model * * By default, olad listens on localhost:9010 . Clients open a TCP connection * to this ip:port and write serialized protobufs (see \ref rpc_RPCLayer) to * the connection. * * Why TCP and not UDP? Mostly because the original developer was lazy and * didn't want to deal with chunking data into packets, when TCP handles this * for us. However TCP has it's own problems, with [Head of line * blocking](http://en.wikipedia.org/wiki/Head-of-line_blocking). For this * reason RPC traffic should only be used on localhost, where packet loss is * unlikely. If you want cross-host RPC you should probably be using E1.31 * (sACN) or the Web APIs. * * The OLA client libraries follow the thin, asyncronous client model. * There is usually a 1:1 mapping between API methods and the underlying RPC * calls. The clients take the arguments supplied to the API method, construct * a request protobuf and invoke the stub method. * * The exception is the Java library, which could do with some love. * * The Python client continues to use the service generator that comes with * Protocol Buffers. The C++ client and olad (the server component) has * switched to our own generator, which can be found in protoc/ . If you're * writing a client in a new language we suggest you build your own generator, * protoc/CppGenerator.h is a good starting point. * * If you don't know C++ don't worry, we're happy to help. Once you know what * your generated code needs to look like we can build the generator for you. * * @section rpc_RPCLayer RPC Layer * * To make the RPC system message-agnostic we wrap the serialized request / * response protobufs in an outer layer protobuf. This outer layer also * contains the RPC control information, like what method to invoke, the * sequence number etc. * * The outer layer is defined in common/rpc/Rpc.proto and looks like: ~~~~~~~~~~~~~~~~~~~~~ enum Type { REQUEST = 1; RESPONSE = 2; ... }; message RpcMessage { required Type type = 1; optional uint32 id = 2; optional string name = 3; optional string name = 3; optional bytes buffer = 4; } ~~~~~~~~~~~~~~~~~~~~~ * * The fields are as follows: *
type
*
The type of this RPC message, usually REQUEST or RESPONSE
*
id
*
the sequence number of the message. The sequence number of response messages * must match the number used in the request.
*
name
*
the name of the remote method to call
*
buffer
*
the serialized inner protocol buffer.
*
* * So putting it all together, the RpcChannel::CallMethod() should look * something like: ~~~~~~~~~~~~~~~~~~~~~ void RpcChannel::CallMethod(const MethodDescriptor *method, RpcController *controller, const Message *request, Message *reply, SingleUseCallback0 *done) { RpcMessage message; message.set_type(REQUEST); message.set_id(m_sequence.Next()); message.set_name(method->name()); string output; request->SerializeToString(&output); message.set_buffer(output); // Send the message over the TCP connection. return SendMsg(&message); } ~~~~~~~~~~~~~~~~~~~~~ * * That's it on the sender side at a high level, although there is a bit of * detail that was skipped over. For instance you'll need to store the sequence * number, the reply message, the RpcController and the callback so you can do * the right thing when the response arrives. * * @section rpc_RPCHeader RPC Header * * Finally, since protobufs don't contain length information, we prepend a * 4 byte header to each message. The first 4 bits of the header is a version * number (currently 1) while the remaining 28 bits is the length of the * serialized RpcMessage. * * \image html rpc-message.png "The wire format of a single RPC message" * * When writing the code that sends a message, it's very important to enable * TCP_NODELAY on the socket and write the 4 byte header and the serialized * RpcMessage in a single call to write(). Otherwise, the write-write-read * pattern can introduce delays of up to 500ms to the RPCs, Nagle's algorithm * has a detailed analysis of why this is so. Fixing this in the C++ & Python * clients led to a 1000x improvement in the RPC latency and a 4x speedup in * the RDM Responder Tests, see commit * a80ce0ee1e714ffa3c036b14dc30cc0141c13363. * * @section rpc_OLAServices OLA Methods * * The methods exported by olad are defined in common/protocol/Ola.proto . If * you compare the RPC methods to those provided by the ola::client::OlaClient * class (the C++ API) you'll notice they are very similar. * * @section rpc_NewClient Writing a new Client * * To write a client in a new language you'll need the following: * - An implementation of Protocol Buffers for your language. Luckily there * are * many implementations available. It doesn't have to have a service * generator (see the first point below). * - A sockets library. * - If you're writing an asyncronous client (and we recommend you do) you'll * either need non-blocking I/O or a threading library. * * I'd tackle the problem in the following steps: * - Write (or ask us to help write) the service generator for your language. * This will allow you to generate the OlaServerService_Stub. * - Write an implementation of RpcChannel and RpcController. * - Write the code to establish a connection to localhost:9010 and read from * the network socket when new data arrives. * * Once that's complete you should have a working RPC implementation. However * it'll still require the callers to deal with protobufs, stub objects and the * network code. The final step is to write the thin layer on top that presents * a clean, programmer friendly API, and handles the protobuf creation * internally. * * The last part is the least technically challenging, but it does require good * API design so that new methods and arguments can be added later. * * @section rpc_SimpleExample A Very Simple Example * * A quick example in Python style pseudo code. This constructs a DmxData * message, sends it to the server and the extracts the Ack response. ~~~~~~~~~~~~~~~~~~~~~ # connect to socket server = socket.connect("127.0.0.1", 9010) # Build the request Ola_pb2.DmxData dmx_data dmx_data.universe = 1 dmx_data.data = ..... # Wrap in the outer layer Rpc_pb2.RpcMessage rpc_message rpc_message.type = RpcMessage::REQUEST rpc_message.id = 1 rpc_message.name = 'UpdateDmxData' rpc_message.buffer = dmx_data.Serialize() server.write(rpc_message.Serialize()) # wait for response on socket response_data = server.recv(1000) header = struct.unpack('> 28, header & 0x0ffffff) if version != 1: # Bad reply! return response = Rpc_pb2.RpcMessage() response.ParseFromString(response_data[4:size]) if message.type != RpcMessage::RESPONSE: # not a response return if message.id != 1: # not the response we're looking for return Ola_pb2.Ack ack ack.ParseFromString(response.buffer) ~~~~~~~~~~~~~~~~~~~~~ * */ ola-0.10.5.nojsmin/doxygen/rdm.dox0000644000175000017500000000231613023355232016433 0ustar wouterwouter/** * See [PLASA Standards] * (http://tsp.plasa.org/tsp/documents/published_docs.php) to download a * copy of E1.20. * * @defgroup rdm RDM * @brief E1.20 (Remote Device Management) * * Remote Device Management or RDM is a protocol enhancement to DMX512 * that allows bi-directional communication between a lighting or system * controller and attached RDM compliant devices over a standard DMX line. See * [RDM](http://en.wikipedia.org/wiki/RDM_(lighting%29). * * @addtogroup rdm * @{ * * @defgroup rdm_command RDM Messages * @brief Construct and dissect RDM messages. * * @defgroup rdm_resp Responders * @brief Code related to RDM responders. * * @defgroup rdm_controller Controllers * @brief Code related to RDM controllers. * * @defgroup rdm_helpers Helpers and Constants * @brief RDM Helper functions, constants and enumerations. * * @defgroup rdm_pids Parameter IDs * @brief A flexible system to handle RDM parameter data. * * @defgroup rdm_uid UID * @brief RDM UID Storage and allocation * * @defgroup rdm_api RDM API * @brief Old interface for RDM mesage handling. * @deprecated This is only used by the Web Server. New code should * use ola::rdm::PidStore. * * @} //End rdm group */ ola-0.10.5.nojsmin/doxygen/OLALayout.xml0000644000175000017500000001310013023355232017461 0ustar wouterwouter ola-0.10.5.nojsmin/doxygen/copy-doc.sh0000755000175000017500000000062313023355232017210 0ustar wouterwouter#!/bin/sh if [ $# != 1 ]; then echo "Usage: $0 " exit 1; fi output_dir=$1 if [ ! -d $output_dir ]; then echo $output_dir is not a directory exit 1; fi echo "Output dir: $output_dir"; if [ ! -d ./html/ ]; then echo ./html/ doesn\'t exist, make doxygen-doc failed somehow exit 1; fi cp -a -v ./html/* $output_dir chmod -c -R a+r $output_dir chmod -c a+rx $output_dir/search ola-0.10.5.nojsmin/doxygen/rpc.png0000644000175000017500000011227313023355232016433 0ustar wouterwouter‰PNG  IHDRôo¼w9 AiCCPICC ProfileH –wTSهϽ7½Ð" %ôz Ò;HQ‰I€P†„&vDF)VdTÀG‡"cE ƒ‚b× òPÆÁQDEåÝŒk ï­5óÞšýÇYßÙç·×Ùgï}׺Pü‚ÂtX€4¡XîëÁ\ËÄ÷XÀáffGøDÔü½=™™¨HƳöî.€d»Û,¿P&sÖÿ‘"7C$ EÕ6<~&å”S³Å2ÿÊô•)2†12¡ ¢¬"ãįlö§æ+»É˜—&ä¡Yμ4žŒ»PÞš%ᣌ¡\˜%àg£|e½TIšå÷(ÓÓøœL0™_Ìç&¡l‰2Eî‰ò”Ä9¼r‹ù9hžx¦g䊉Ib¦טiåèÈfúñ³Sùb1+”ÃMáˆxLÏô´ Ž0€¯o–E%Ym™h‘í­ííYÖæhù¿Ùß~Sý=ÈzûUñ&ìÏžAŒžYßlì¬/½ö$Z›³¾•U´m@åá¬Oï ò´Þœó†l^’Äâ ' ‹ììlsŸk.+è7ûŸ‚oÊ¿†9÷™ËîûV;¦?#I3eE妧¦KDÌÌ —Ïdý÷ÿãÀ9iÍÉÃ,œŸÀñ…èUQè” „‰h»…Ø A1ØvƒjpÔzÐN‚6p\WÀ p €G@ †ÁK0Þi‚ð¢Aª¤™BÖZyCAP8ÅC‰’@ùÐ&¨*ƒª¡CP=ô#tº]ƒú Ð 4ý}„˜Óa ض€Ù°;GÂËàDxœÀÛáJ¸>·Âáð,…_“@ÈÑFXñDBX$!k‘"¤©Eš¤¹H‘q䇡a˜Æã‡YŒábVaÖbJ0Õ˜c˜VLæ6f3ù‚¥bÕ±¦X'¬?v 6›-ÄV``[°—±Øaì;ÇÀâp~¸\2n5®·׌»€ëà á&ñx¼*Þï‚Ásðb|!¾ ߯¿' Zk‚!– $l$Tçý„Â4Q¨Ot"†yÄ\b)±ŽØA¼I&N“I†$R$)™´TIj"]&=&½!“É:dGrY@^O®$Ÿ _%’?P”(&OJEBÙN9J¹@y@yC¥R ¨nÔXª˜ºZO½D}J}/G“3—ó—ãÉ­“«‘k•ë—{%O”×—w—_.Ÿ'_!Jþ¦ü¸QÁ@ÁS£°V¡Fá´Â=…IEš¢•bˆbšb‰bƒâ5ÅQ%¼’’·O©@é°Ò%¥!BÓ¥yÒ¸´M´:ÚeÚ0G7¤ûÓ“éÅôè½ô e%e[å(ååå³ÊRÂ0`ø3R¥Œ“Œ»Œó4æ¹ÏãÏÛ6¯i^ÿ¼)•ù*n*|•"•f••ªLUoÕÕªmªOÔ0j&jajÙjûÕ.«Ï§ÏwžÏ_4ÿäü‡ê°º‰z¸újõÃê=ꓚ¾U—4Æ5šnšÉšåšç4Ç´hZ µZåZçµ^0•™îÌTf%³‹9¡­®í§-Ñ>¤Ý«=­c¨³Xg£N³Î]’.[7A·\·SwBOK/X/_¯Qï¡>QŸ­Ÿ¤¿G¿[ÊÀÐ Ú`‹A›Á¨¡Š¡¿aža£ác#ª‘«Ñ*£Z£;Æ8c¶qŠñ>ã[&°‰I’IÉMSØÔÞT`ºÏ´Ï kæh&4«5»Ç¢°ÜYY¬FÖ 9Ã<È|£y›ù+ =‹X‹Ý_,í,S-ë,Y)YXm´ê°úÃÚÄšk]c}džjãc³Î¦Ýæµ­©-ßv¿í};š]°Ý»N»Ïöö"û&û1=‡x‡½÷Øtv(»„}Õëèá¸ÎñŒã'{'±ÓI§ßYÎ)ΠΣ ðÔ-rÑqá¸r‘.d.Œ_xp¡ÔUÛ•ãZëúÌM×çvÄmÄÝØ=Ùý¸û+K‘G‹Ç”§“çÏ ^ˆ—¯W‘W¯·’÷bïjï§>:>‰>>¾v¾«}/øaýývúÝó×ðçú×ûO8¬ è ¤FV> 2 uÃÁÁ»‚/Ò_$\ÔBüCv…< 5 ]ús.,4¬&ìy¸Ux~xw-bEDCÄ»HÈÒÈG‹KwFÉGÅEÕGME{E—EK—X,Y³äFŒZŒ ¦={$vr©÷ÒÝK‡ãìâ ãî.3\–³ìÚrµå©ËÏ®_ÁYq*ßÿ‰©åL®ô_¹wåד»‡û’çÆ+çñ]øeü‘—„²„ÑD—Ä]‰cI®IIãOAµàu²_òä©””£)3©Ñ©Íi„´ø´ÓB%aа+]3='½/Ã4£0CºÊiÕîU¢@Ñ‘L(sYf»˜ŽþLõHŒ$›%ƒY ³j²ÞgGeŸÊQÌæôäšänËÉóÉû~5f5wug¾vþ†üÁ5îk­…Ö®\Û¹Nw]Áºáõ¾ëm mHÙðËFËeßnŠÞÔQ Q°¾`h³ïæÆB¹BQá½-Î[lÅllíÝf³­jÛ—"^ÑõbËâŠâO%Ü’ëßY}WùÝÌö„í½¥ö¥ûwàvwÜÝéºóX™bY^ÙЮà]­åÌò¢ò·»Wì¾Va[q`id´2¨²½J¯jGÕ§ê¤êšæ½ê{·íÚÇÛ׿ßmÓÅ>¼È÷Pk­AmÅaÜá¬ÃÏë¢êº¿g_DíHñ‘ÏG…G¥ÇÂuÕ;Ô×7¨7”6’ƱãqÇoýàõC{«éP3£¹ø8!9ñâÇøïž <ÙyŠ}ªé'ýŸö¶ÐZŠZ¡ÖÜÖ‰¶¤6i{L{ßé€ÓÎ-?›ÿ|ôŒö™š³ÊgKϑΜ›9Ÿw~òBÆ…ñ‹‰‡:Wt>º´äÒ®°®ÞË—¯^ñ¹r©Û½ûüU—«g®9];}}½í†ýÖ»ž–_ì~iéµïm½ép³ý–ã­Ž¾}çú]û/Þöº}åŽÿ‹úî.¾{ÿ^Ü=é}ÞýÑ©^?Ìz8ýhýcìã¢' O*žª?­ýÕø×f©½ôì ×`ϳˆg†¸C/ÿ•ù¯OÃÏ©Ï+F´FêG­GÏŒùŒÝz±ôÅðËŒ—Óã…¿)þ¶÷•Ñ«Ÿ~wû½gbÉÄðkÑë™?JÞ¨¾9úÖömçdèäÓwi獵ŠÞ«¾?öý¡ûcôÇ‘éìOøO•Ÿ?w| üòx&mfæß÷„óû2:Y~ pHYs  šœ7iTXtXML:com.adobe.xmp 72 72 1 1 2 ˆbù @IDATxì`Å÷ÇßÝåÒJè½ R¥Š‚‚Š(»±¬Š?`A±÷^P@À†‚té½—!½ÞÝÿû» G @ á.y›Û2õ3;óæ½™ÝQ§”€PJ@ (% ”€PJ@ (% ”€PJ@ (% ”€PJ@ (% ”€PJ@ (% ”€PJ PØŠ˜†/jEÌ‚W&à.p  ”€PJ@ (% ”€8Ù «]3œ'66¶qRRÒÕØwðødgVãWE ÀûÓ9?33mJâÑ J@ (€$Pn„¹¯4ïÖ¨]÷®z ‹Ýî€D÷¨ý= «¹lgÊQn·ÛeüY¹|ñ–ˆˆˆ.éééÛAÅŽMÍïeûöÐÒ+RC ¤°%ñx<6¸è®={Ëí÷ Îq††:ÜnzaÆ…Í…†SÇ'€{UBÃÃݳ~ŸæxìÞ›7Z¶ìßãTJ@ ( "PhaN¦+2"J*V®bs:6·Ë-6•çATýe#«èaá¶ØrX`="Rµò²QõZJ%P¦Z û(Ù\Ðʳ³2w»\Xó®½LÝAAPX t‡Ã!®œ“[Ç­7iÔ›fQ (‚(ª@‡ü†‘Ý·Q˜s_4æ¾Ô[3ЪEó£”@1ࢠuJ@ (% ”@Pä¨ÙWJ@ (%@*Ðõ>PJ@ (%P ¨@/•¨EPJ@ (% ]ï% ”€P¥€€ ôRP‰Z% ”€P*ÐõPJ@ (%P ¨@/•¨EPJ@ (% ]ï% ”€P¥€€ ôRP‰Z% ”€P*ÐõPJ@ (%P ¨@/•¨EPJ@ (% ]ï% ”€P¥€@‘¿¶V ³üô¦¿óÿš¯YÇþûþþ ¶Ï´ŽýI°cå§ iYñXù/HXõ«”€PG@z>uBg·Û%$$¿ãËív‹Ë•#ü¥ t:CÍ1/:NÉÁ÷¶-A™O´ÇaÎK;¶n–ËKNv¶4oÝVjÕ­/‡ÃïÕÿ-•µëÁ¾~5i&aááø^!IåÞûyø#…­%´- ™¿®ÎGÞjÁàiâ¢ìضE˜VVV¦4oÕVj×k€4ì‡ $òÆ}¨ˆF!6»M¶oÝdÂU¯Y;7lþáÅ {J@ (%˜t=O½P¨Ù <³!0¿ùä]éÕétùoÉ¿²ê¿%rI—–òÃןø¯GnºølÙ³k§¤¥¦ÈõŸ#éF›w»iŠ·ÁŸWØZœƒn&=sj÷¿ý\¶mÞh´}K¸RÓB‰¸¿ÿòcéufSY¾ø_Y½b™ô9§•ŒûâC–ñZa¬¸1È=ç½f3´ùi?~/þ2%÷:ý DZÃáS y0é¡PJ@ ¼ª`€e¯ä³CÚSû÷ß}%_ü¶Lüs´rjÁ6é}ùÕrõ…gI…¸ÊÒã¢K%4"J²³³p\Éø‹ˆŒ4&xgh¨Ñèsr²!@‡™ã)(©sÀ@S=·ýñ{åÙÇî—q¿Ì;L˜R¬R;Ÿ:ñ;ùôWeÂŒEÐÊ뛃ÉÏ$::F.íw£I›ñgef-<44LÜ8vC󧉀ÌÌ AúL“ŽþyÍ„ËÊâ ƒ•ç=ÆÒp¤uÁÔ?J@ (%PTC÷«#l!€wíØ&Ï y@ž|ñuiÖªM®æÚ²My÷ëI[®œŽ‘Q1F8RCÿcÚ$hÑ™ a¸eÃ:ñÌ£rÍ…dô³ÿ“Í8­›6ÈO(ü>í'¹¯ÿ•òÀ­WË’çáÿë” &'¯ {LV._Œx Œ!P9O¿kû6:èytøH_~BLžZžÑ^>þáä§‚p$'%Êøo>•[úö”Gî¼AþùûOɦÀNNJ’/?|Kúž×V>~{´1Ý;pžë2ÒÓå—Éäö~½ä®kûȯØwa0âÓWMÝïÑ]% ”@ÀPî_5ÔV¡½nÛ²Ihº¨ùòŒŒ hªn³.==M:wë)gÛfîlqAàR{NOK“×_zBÖ.Û·l”Ëa oÓñ,yìÏÒ¢M{xçõ²kçvc6§`^»j¹<úÌésÕ ÒÿŠ®›¥í™Í²¶+®ë/ÕjÔ†@ÍAlâqHüÞ]&—Mšµ4qpž ó˜Ÿg+Ý.¼ØìðúcŽ6ú]éÏÃrÇÕ½eþœ¿Œ°ïµÍ@cÌ'?H£¦ÍåÛOß3‚žOýñ; 4¾”a£Þ•'_#Ó&}/SÆ‹´Õ€cÀë% ”@Pž·’`a¦0­Û¸)¸EÐ&mV¶Ysßf•;Lל‡6×`¢æ"3: ÀKI«ŽgË™»IDd”t<»«ÄÄVÅóçHxD¤ñ×§ïuÒº};¹°O_©Q«Ž$'&JC¤× ñéÒ¢u;©R­ºÉƒeìö`NžŽùñî!uÎ Àq`A-{ݪÿdÜ'oËm÷="- ¹w:ç|ñÎ2éû¯dãº5òÕcäæ»”VmÛJ×ÉwÜHˆìÛ»Gž‡©ÿªn“ÊU«Iuä§GïËåÝQ/˜|qþž– uJ@ (%ØTó¯#£=Ä‘²yÝjIMI–*ÕkÁM‘ÆEc ö™Ej‘QQT ³ä]&´yjÍÞO>t‡™§Ü°z™DFE›9n§àOOË2&uÎÇS8gbN=óñ Ÿõ8é0 aë³”ä$©X©2bð®V§@N8o Ì{\,•*W3ùæµÓšµOÞ­}œÓãáœzZjºмæq¹Í\~ü¿9Òä%+õ;vé*‰Htl,ŸmóTÿ*% ”@ÀP~XÕ`µ9„iýFM¤Áé-dãú5Ò¤y+sŽB—qòcå`Â~¹ýþÁR¾B%£1û亼nÉ«n¼]6æú4o§ÄïÞ ¿q²{×)N×ÒêÍ3äˆÛÎø1ÿÎuÔ¸Ã9jà5j×…fÝ«-’Æ0—Ó‚`òƒyvÎw'&4°Ä`# ‹Þ"££Í¾Ą…sÕjÔ’}ñ{0=Àçê&Ïi©© ‚8 ±û}Æø£‚«õ“”¸JUÌ‚:Ëp*=PJ@ (€" &w¿ê àâJp ß;xL¢µ¿gübæ«yž ׸hælšÓ×­^Ae9×Qó®×°/ûPöBˆW«QSR°PíªóÛÉæëŒÀß·?>×?w’!Œ)Ô©å¯[³BöíÙ ­9Ël懳ÅU®"·Ü;P½çÿdÖÓfÏüüöóDyþI+,ÖkÕ¶ƒìزAfþ6Õ„M†6ÿÑ›¯È¹=/2×8øgöŸf0±Ú½ôä@wù ¥ïu·˜…z´L”¯ggûںΡVUz ”€hª¡ç©ÈP£w½ ·èÇ©##!àŽæÌ5ßÿ}žÊ/ÜQýåF~ø€!÷´ßN~ñZ^Žuý¸×Ì(ÀŠI•€PJ ˜è*÷`ª-Í«PJ@ (|¨@ÏŒžVJ@ (%LT Smi^•€PJ@ äC@z>`ô´PJ@ (`" =˜jK󪔀PJ *Ðó£§•€PJ@ èÁT[šW% ”€PùPž=­”€PJ ˜¨@¦ÚÒ¼*% ”€ȇ€ ô|Àèi% ”€PÁD@z0Õ–æU (% ”@>T çFO+% ”€&Eþ8 ¾2j¾ÐÅÏ{rÇüÍk©'À{ÓÜŸ¼EÕ)% J)" t;¾ î ‘l.7>×YJAi±‚—…yHˆSì‡)>+«¢=x«Ss®”@>Š,г23$%9Ù*n|Ï;ïçAóIWO‡€Ûã±cpäO>Çau¼ËèÙYÙîô´N1á0CÇǃ¦×•€:Eè¶¹ý.‰„؈JííÅrPqƒ07®X"-Ñ¥Ãá°ïܾ•Â6¯Yã*Ã8´èJ@ ”R…ÕTÎÛ1=)éFìçøø6¾RŠ·ÀÅ"¿,lõ±]„ílë°…aSMŠàܹ0#-íì+Ï"ÀÔ J@ (%p6iÞ¹|ÅJ;ë48­Ç xW/J@ (% ¤È&wCÕvŠçfâª-×– kœŒ.%é U?æ|ñ$Qæc±¬HzÏ–ù[A(ÒEÀ…-•vŠ…%§áN½gOyMW (“J@_,sRñ8òü„M~ç œ€PJ@ (ÒI@zé¬W-•PJ@ ”1*ÐËX…kq•€PJ tP^:ëUK¥”€PeŒ€ ô2VáZ\% ”€(T —ÎzÕR)% ”@# ½ŒU¸W (% J'襳^µTJ@ (%Pƨ@/c®ÅUJ@ (ÒI@zé¬W-•PJ@ ”1*ÐËX…kq•€PJ t(ê»ÜK'• /¾ÿm}€$ÈK"ü&¼¾ö6èkQ  ”@IP^”K8 ‚% \“SJ@ èP Å™ŸvŠ8ƒ_K_¿Þ#eé¥8ïK (ÒJ@z)©Y rŸà«Ÿ“ãbÅÙlö,¸ ¼Nq‰à¿Í^´1£üA¾NxxÁ´=ndÚn‹°Õ¯¿‚ ±$ú•¯”Ô˜C (%P¼T /ÏS¥¯'-;»\xˆ³dq”73‰Aê²sÜUû0_öMù‚´(šm% ”ÀI' ý¤#.Ù"NwrJjjFFFTÅŠs Ù ÝhÝÈŠÝn·Ûm2EÍ™ç3<ït†H|ü>ILL” ˜sÖõüJ⇕ŽÃá”ädÙºm›‰',,ì¸q1o;v쬬Lwà B`!HEšº(.?ðz^ (%àG ÀæX¿°º öìÙcÿéÇ™;Ö¯B²Ònw†8Ì>!ps÷y BÛaN#»}ñâEögŸnÂÒ/¯YqpŸqò×Úèÿ‰Ý‚^GDöoÆ~cŸ1ã{hh¨7 ŒøVžòþšø&==Ý>xÐ û„ƒ‚ÜØSRRàUPJ@ ;Xu¥Œ-%®Ñ¾Y4ˆZÉÉÉ‘¿ÿž#/<ÿ¼üýôSyãõ×eݺõ†µéÊ•+ D¹¬Å¹?ÿüS ñËÌ™JJJª‰oîܹ’m>^~ûýwùþ‡dä+#dË–­/«V¯‘Å‹Ëí·ß!”ñÆ*@£y>ŽyÎÎvÉiÉ­·Þ&ßg|FGGçBO+% ”€?èþ4JÓ>$MàÌÿ.X c¿ýVúöí+óæÎ“I“~2×_~é%‰‘víÚÉÀ‡–Ĥdz§DEEÉfçÁƒ‘š5k³üˆ#$99É„ûyòd9Nùm·Ü*UªT•fÍšËC> YÙ9²gÏnisF‰“ìW®YßÎïOà·lÕÒ 2³²óó©ç•€PJ CϤ´Rs…¹Ýî ÆiÓ¦ÉwÜ!-Z4—˜˜ÛdâeÑ¢ÅR£f ¹êÊ+M±7oÞ,K–,jÅ&N/>ûL¦N›.M›œ& ¥V­Ú^ÁŒ¨c0à<95ï[o»MÎ=§‹ddfÉŸf„qVV–´iÛö0œÔÂM¾pÖßòÄs9.7µ¤Zµj²k×.©W·ŽuY•€PJàT N0_¼µ1©³ öP§yfw:„° ÿhЧàuC@sò<;;Ú¼×<^¯n=éСƒ¬\µRš6mbü¦¤$ Íñð±¥²ÐÄt4Ëc=žñËs._zæ"þ.Ä‘£€·Â[û̧wžÓ ª¿J@ (%pjr? `¼ AíùsÚ0±{>ûü ÏÜ9s=}úôñ¼òÊHÏŠ•«<ï½÷®§jµªž6g´öì‹ßçÁ|µgÖìÙž¯¾úÊ­ÚƒÕé˜Ù=>â™Ǹqßeòé§„Ívûå‹ärÓÍÊÊÎÝgXUï¹çž{Üû$0ΘG¯LØ?.ƒ ¬oͲPJ Øèz±¡<åó4Lã›aÖ¾5#++‹Ö\pЈ˜O‘ÌLï:sÊc» æ2]8ò?–{.$Ä»ïrå`îüððˆW"##=QÑQQ‘8ÞÁÒ C܆…§W¯ C† ©Ø£{÷µjÕÊÆ£r6ÎÁSOKËÄ¢º_¾2M\óL™<©BÏž=Ý+”OÆœ|"¬‰æ"dºïW”€PJ@ ŠZaœé +–+wÁÄÄ¥A6¾Âä¡4†± yÖŶ ›u®4–·¤ÊD†ÜÂË•‹œ™˜˜ööiQ¡¥Ô™º-W®â‰‰´*¥•\ŠŠ•ÛGEFÇþ•–’ô"ÊVà>ª0Ø¿üªkç6×_Øý,q:CÄíažÔ•“¥ÿj÷¢ÆY¦Ãã¶ qÈŠUäã/'í«]»J§mÛön®M°£eQ)+¼õeÛ3;ßpv׸œü>B)+ª§tðˆÃ"Ö­’¿ýbåʵ:ÅÇo_²¨*ªÉÝÕ©CKüÐÍÙ!¡N‡Çå†*xOu)Ðí¥ö>ÅPÙÃÃÜ?OšžV·nuz1ĬQWË6¤ÿÝe;CCn”í¤‚ ÚÊV9Ð wϘ69=µzݺôC(ª@›ÝHpŒ—vÓN´±¸ŽÀ7.ÒáÑÑàðœyD÷¥Ã{¯Úìv›” È0˜½Ûm¸Pýäv sµ|sm–Þ¼ó¾DçÄâ–-\UdNÒ˜±0Âà¯J Ò{ÃkÉÜnhèæþô–Çz›ke<ßè½}û'ÓW< ¡N*Û+G‹’%oXöÚG£Æp2xF¸?õ=xƒ&N­þ ©ª²—QjçÅPêbèÅB (% ”€(4è…F§•€PJ@ èSš% ”€P…& ½Ðè4 PJ@ (À! =pêBs¢”€PJ ÐT TJ@ (%8T N]hN”€PJ@ š€ ôB£Ó€J@ (% ‡€ ôÀ© ͉PJ@ (BP^htP (% ”@àP8u¡9QJ@ (%Ph*Ð N*% ”€*Ч.‚6'øˆ¾´Ù׌+%”´ÓÉ[mA#ÐÝ…üô¡ùdbÞRëq±°>G‰o÷â;¾6#Ôý?Oi]/–Ä4%@¼÷¶»À9Ò6Q`dG Cóíp~çŽÇ꼊þ=ô“AÒû½K|î’”Ceáׂ¬æ¸Ä““c*S¼‚ÁwdålN„Ã÷°=.—د×ã„9V|ÅvÍ*cqÞŒ'#Î| lë„‚<+Ûs{¨¾Á:Û[G†7¯gƒý±¾ h],Nùä[O+‚ ð°÷)>BЗp?;+ G0vs|³µT«Y/;7¿>¯¹i0OVüy¯åÍ÷´_ÿ–fMHµŒ5þOPZñx½£\ÿ|´²Ziæý¥°NOI“¹ó—Éo3þ‘ltPÝÎi/çœÕFb+Ĉ¸Ü’žš.éR±bù܆aåñ±#ã `릲jí&9ïœâ _:=‹ZÞ”õX ” ¶ ŒÄƒ 2oÖ ÉĽìvspj“*ÕkJÝz ¥jš(NI8/ógÏ”Vm;HõÚu%'WÀx;†á–™ž.©)ÉR¹juÙ¼q­lX³Zº]ÐÛ´w«¿á¯é‘ØváüÛhÞkÆC®ŸÃÊÏòåýõoƒetÊ¢昲µ=³sžô¬°Þ¾ðDÒgˆÐÐPY¾ø_IMM‘3;wƒÀõö·¼ÆôY¦ÃóÁcsõˆô-üuC¬Y³Jfÿù‹ìزYš¶l-z Ä…k–ó2;œÇá½>½IâÌ4²²2åŸÙJíº ¤ÁiMZ—V:^ÆL‡Î[ÇÞýSó7 Lî8ЪÕå–{†ÉÆÍ;dæí2»m—äšþCdÏ®xÜ-ÛvËò•ëQù‡a {D<Šå°K„ö ·?)“EÂÂe ÛvìViÇÍ‹(£eøg8¯ÉØ[1Ôêé˜øàϺø›Ži!¿Ö5Ž#w„³1NŒ$­›‘ÕköqžC+o|TvíÙÇ¡~nxëð¦âMþé¬4ü¯™|{ïES¦‘c>—õ·¡ì^K„ Š,˜G“O_6nuG œ"£ý%A ¾ûF™õÇ4Ù¾u“lÙ¸N>ï5éÕ©©éøíèk(ìÌûK’““`´ò ,j’aá¸ÅÑæqC‡àø—Éãåï?•pô‰ ²rÙ"¿>ÂA&aaf aµCj –&ÊkN´kËY~¬pü¥ãy»ÝŽaCÃÂL8î›ÓçÇaÎ0LŸ$3~ýÙ„óﳬ¸h`LŸù±Òå/ýç^3ý¡[ïÂþ–™ˆÓáëã8p ú' ÿtxÌüÒqŸi0NntÞòØeþß3åÊøÃO—î¢.6È%[ÈKšòYÖÃìY^+¯Gˆ9füŒ—¬0)xûgÃ}Ïêÿ–b¶/·.ËΊå¼e'—ð#¸X~Jú7 4tSx(‚ºùºÞòôÿî2‚ƒ&ª'ß.÷<ü¼Œ~óKyùù‡ä¼sÛ!b49Þ00ó—M±JåŠY©¼l]³Y¦ÿ6Wöî; Õ«U–«¯¼@œ¼¡!èá¡’–˜"{㠒溂ĕ#IûJ4ÒÁ} ’”œŠø*HtlŒ×Üa–”b¬Ì`1(W±œ™8ˆpaˆ7))ÕŒCá766ã/f´ÖÄÝûPùNiÕ¢ÆÖxÊ’ÊÞê§ NÚPö8h¬ Õ«W67ž™6@œ) I댿&®m·V*ØEœˆ— ÷lß-11QfTËL9jθY3Ò3%- šs…Xh ©H”VƒÙ‡8y®øAå>ú½ˆx9 Zºh¥<7òcÙ°ìGiд™ú8·s[©Ò §Üú‹ä’‹ºÊ3H‡¶Í$ùÍ -=CâÀŠ(ñHH”*È3ùœ~Z}s=~ífçjõ*Þ馧N œ"¼ûØÿÐÝpÛiÝ®£Ñà(|(¬î¾¾üúï:©R­†Üvï#hcqÆÇŽÿÀ¾xô%2*Zªâz „ýÂy³¥QÓæ¿g4<ít„«n,U`F;·o‘¬ÌL)_1qU4¦ù´ÔT£=ÓÏþø½fP©JU“'æÃ«ÁÎí[M¾˜.µú¹thÇl×ì h °¢ ‹‰-g,fŒïàþ}&å‘V–™>0ÑæþaX @N-ìÞ¹Ýä§bå*èWÊÁúN§IcÇÖÍÆì]1®’DÇÄš4Ã#"$*ý& R LØ¿Ù[®¼¤Ø>µœ9Ï4À* þ™?kÿ ü0pe° —äõÃ7Fʨ÷¿–^—^…>VÁž½%Üo>~GŸÞܰát†Å±ò[¾‚ÉwjJf_=âÆuZ8Ðb^(Ü™òß·wúŸ0é{] º"LÙÈ”Væ‡ù`]Ó?ùÑÔ¿kÇ6S?•«TC^¢Ì9ÿÁJ.Ìر$J $uâI˜pôŽ› =…vù•åÑo–¯}.)ijæ,–w?þžÃ*IÅñK£>‘ž—Ý'Ï¿MyâUÙ»e§L™>Ë$zçýÏËÚõ[dÒÏÉ/Ô#Ãe¬÷=ò’ñß©ûí2ê/L¼l£0hxõ­¯äÁ#¥a«Ë䮞ÇͼWl0ݯúo<üØ(9·÷ÝR¿Å¥rÛ€á²jÅz£i¿õáwòäð·å‚ËÈà§Æ xRBð µl”eÁ¢ò܈0DxSáÐy,[¼J®¿í épÞ­ˆë>ùà“ñ’ž–í5L–-Y-ýï*]/ºKš´½FÞ|ï[ÉHM3BœÓÉÁâýbìÏrÿà¹ûã'ýA;˜Éç’ekdØ‹ï›|Ì›¿\?ùª<ùìÛrvÏ;¥ÏÕË’…+L|GäÍ:ø™º ´ddšMe .¶¬œ,gul- þýútyøñWÍôùoN7p@°)òÉ‚Y>\ÿE™_Džßç^©}ú2S˜¨S§š€ÕJÙS€q ‡ö×¹[iÖ²,]8‚v¼ñòPÙ¶e§Sþ&ùØ€[äîë.‘žmÈâse´È‰ß~.¯ {Lfþ6U6mX#_|ð&CˆÑðÇ}ñ¡ôëÑNnïw<~ÿ­Æ?5ü5+—Ëèçž Ì.†6Ú£]Cù{Ư¦ÿHKM– c?—›ûv—Û®ì!t8M~žð­6ë׬”מR^{á)¹¾÷Ù2ðökdüן'¬eh[™8¼?æeY¹|‰ê¶þÎ-ô[I°$|ðúù¿ËºÉM}ºÈó?„é‚uF+¥ ûæ“wåÖ¾=äÆ^å9\Û¸n5y(º¡˜F£ÿ;¯é-Û6o”½»wÊ«È'ô,|üö«°V,6ezcÄ0yóåáòÔÃwÊ][Ë„o>ƒ’fQ,¬]õŸ$%&¿¬“o¿On»º ‡d¤¥™2Þxñ¹rI—–ˆã.Y¿z…ÎKþýG^xüAöè¹óÚÞòÒSåÏ_¦K;{v퟈ÁÖnÔÓ&?àÔþ‡?v¿Üsã¥raûÆòˤñ& Ëþñ[£ä¢N§ËÅg·×_&;¶m1Öƒ£öíþpOÒ~Àö˜FL\”`Ì(Ð袢" †­Û÷Íy'ÌïœSùòÛŸåo̹ÿ5í=ÙºâGø÷È·?ü*W]ÖÃøÿäg¤I‹Æê›!ÄÒE ^zÍ@9fâ-+&Ê¢YŸM~Üø_ ¼gËæ-;äï¹Kåõ‘ƒåÀ–?0Í–±?L7šý{—V-#ÜOâN\ -›5’o¾›fö6hÄ£ß+_}ø¬Œyy´ÓÓeÆ_ÿŠ‚–SSù[Ô«)•«Äɼù+39™òBÇïÝ/­Ï¾Vn½éRÙ½vŠüôíh¹Š¿þ^$ûwÆË…}ï“K{w• K'Èš…cå÷ÆÉ¸ ¿Âtm-qÉôÉ3dä˜/dô %ªjœlÇ4ƒ}û ü[‘WÎ{³¼ï|ø,"—ÈÎ5“eðƒ7ILo$À:À8óÞ˜fä ¡Ü¤q]!W8ÎêÞ_žö¦Ì‚F^¹R‰ƒ`oß¶¹Ü÷5òö½êB#ÈgÎö6X.¤ËF}þöç|S?lü 1PiߦÊôÌùí]¹¤ßC²d1CèóæÁÒ?J „ °²6Î sÛY]{<…ãäñcFGíö~½Œ™4û?yýÓM—ž'+U‘»>!ƒžyY.º¬Ÿ$'ÄúBaŠŸ ¯<ù°Œ>_&ÏY)—\y\{QgÙ­˜ò_},g#­7&È›Ÿ—ÿw4ù YùäW†–¯&Í”ßo–¯¦ü%O8C¦-Ü"m:ž%Þrµ$'%a)[7o’aƒÈ-Áú¥Î’íx˦u°Òa^i¸1ÏQ:,Ðßù¬åeÌ'ßÉC züY0g–”‡õ㮇†ÈOã¾ÎM«Êð!È”ñPh2Ò¥QhçЬçþõ»Lýñ;÷ë?²lGš\~íÿÉ÷]kâfY~ž8N®½åùù½äª0yÇ»°°8"3ZFÈ(|©•?|Û5rÞËÄ‹ï||ÏM²ƒ, vZFæ®Ý+K·§JÍ:õäÛÏÞ7á¼VÆV²îP –lº'–×tá•D¨{ã¸PÎ !“ößÿdLò·IeËp˜Ê_xf€\vIWsâ°(KBÃM\Q³fÝÕk·Èå—t“˜˜«Ô®.£_(C_üÀ ÊÁ¼~ËM}¤R­jR¡Z%˜ê{ÊÒåë`âqË£ýŸ\}EOYyß…Ð*wîÚ›«­&b®~ÜgÏI ³JµªÂô|¹<Í7„ƒÔÍY$ÝÏëh´füñÆüõíãgÑÒÕÒ±]séÕ³³8Q–úMëË”ïÇÈøŸþÀš‚í‚q¹…rÍ&õeäsÈ䩳% fþ:Hóѧ^—^WÜ/ßñ²Ô>­®6§Lcõ%CS8ÎÙÑ€]ÎÞs­´9£©8b£¤{·3Í\7×.äç8ȲC«îóå²rÁ÷òÌãw6çöºCÚv¾AÖÀŠa‹‰”ä?qJX •{Ôòa™¤ø›‰)+/;uÖM˜Cov[yèÞëdâñ®1ðÓ¿JàT0÷¬é“¼¹€žkYûû¸nƒÐFCåß¹³äÚþwKûN]Œ9·ãÙ]eüÿJõšµŒvO3o4*Û$ÍßÙX„5gæ¯òüÛŸÃ ßÔ˜{ö¾Ü$B­‘¡y«¶fÁ]lùòÒ¼u;s-Zk£¦Íä{ÄÍ…¤+—.Â"»U™è˜·Ù]6kÝVÚŸuÒ®-ÌG,⣃'OVý·DÎíÑÛ 4(¼¸nˆÎ@3]jÆï¿ú<¬‚A`Õ5&ê>l,ž?Bo­h<õâR ™·]›Š9è%ÆÔýûÏ?Êýý¯’s»÷2ƒï ÁfLñVÀ49¨á‰iÇU®ŠÏÕ‡ó=lÔ»2}Ò$$¢,]䋟f`4UŸÖ Ã0éѶ¡ü‹ ´@´hÓÎX–-Z`Lí´l…e€ÊßÅW^/gŸÛ]ªÕ¨%­Úpn(¬µÿ“ù¯½$×õ¿ fóHcÎŒŠ2Ö‹: O§‹$ç›4o%SæÀ‚‰úžùûT,œ«ÁÎjc¥a]~òöhÙ¾e“‰—uRÒÎ;¹[Ò©žhz¨\V°¹ÁŒ‰(Û„ä¼ñ0s\ø‰0ÝpÞ7æß8ÌÇÁ<-”Ž6–]›}JÎÝö»ü|ÓøZ8—½bÕiŠÁì?¦L&ÿøÒ³n6ˆê`àbŽÁŽþÂ®í±¶ Áø%/gò Ö»Á–å8VˆÓa±8¿kGyä›äù‘É»}/¯ŽyÂÄIMöxE·öLô(Õ¯[S"ÐÉåÀz‚2s©SBÀôC¦ý @Dm}ó†µr„ÛoFºw= Kú q‡!CÁØ´yk£‰¦§±ºÐv`}Ä?j¤\PÇÁ9]šŸ9‡Î¸;s>Ú}št\UÏöÆ9[Ë4NáÈsÆ~a¬R\Àǹi6\˜[¯^£6ÒÍ0}Ø•×ß"¿ÿ<ƒƒŽ÷™ ‡°¤czt,#ûSVSs¯Û¨©)oÞ¼Ð/ I°0ì†5‚ërpž+ûiMhÑæLÌ9ÄXÜiý]zõÈßzcj¯†üx9z{Óß2·ÞÐ\kظ©É ¹0½Šq•¦Ì5{wí4‹Z¤ma ¸ìÚ›ÌÂÄ{oº\~ük‰D—+m?¦ôŸÁ>ÙÌç?ðøp3(b\Tfø¤µú*ÕkHKpX»j…T@4¡×kÐi{ב/çÝë7ll xBÊL£&ÍÌ hHÆÆ–7sû´€Vˆ‹“ÖÌ£ž¦L¦(%ö' {LŠ.ø¢¹•+£θ‹±bzŽ\racÒå\·YÏÙBéœÇ…‰8ZáFhÏßù“™#&I—·zoÔª0y7ñwsÝa´@š ¹øóõ‡nhD+ãڦۥ˷Ëu0!¿=úqþÒòðÍÞUô¸Q¸š“æ#†a£ ƒ€º÷ö«dГ¯Ãdÿ‹<1èS&Vv Ò EÙXF‡¯œÈ¨l?Mžen;¬ tÌ[,⢛…„` &aa^ŒT‚ÐßyþáXHøÑ›OÉU7=&+Wn`ᡤû‹Cþ&Ô;@àz:»¬ß´ÍÛ °¸„埆…„ò8@Šìj9Ó!l'LšEŠ/Š –´B E^ãêÖ£kíÌmÂŒøÃXâ3›#*o½b4nâfÓál…ÃX¸H‘õÇø°Žƒ(uJàT°îB®¬¦ÐåÆÅ[[6­7«ÖÛv<÷3猽JCl¹ Ðì£I1‚€š'Mß4¯[ ÁBBikƒà€¡Fè@ø´´T£Ùq~žm`Þ¬?ŒïÄœ½ÿsëV~(@§Â„L³ùcÃGÊS/½*wÂ$M–Æï”ÞvFÕ¼U3Ÿ?ÿï?¥1çUÅ@Áâ¦lè/¬_ çÌYïܶ٠2¸xŒsÊt´BT¬TÙ,ð#Î…GbA…0 \´ÇÍí<&ÏŒxK`Å8µgoZ˜½„E€}Wûó11c‰'æwÑüY¦ ‡²Bæ|¼¯UÛö’ázI—ж7˜A…uP©reiÓá,“'òà‰V‚ÇŸ%Ͼúž ü´¹^ š¾I›ýÒ°úø .¾Úõ¼v½è²°˜jŸT;w•Éß-3¦OÁt[~'ËÓï2Œ êæ"üÎm;Lœ‰˜é=z_&ÿÃB¸eX`ÇÕà\ ÇUð¸Ô&in†”ÇvH{¦€¢0äªöÌUoÙ¸&ðOL¼^MÚe´NöC`Ì#ç‡ÿ‚‡óìç]ØGÊ•¯hÎS¸.üg¶)«›óço0cOƒ†ž*ƒ‡Ž”g±(l4Ùø=»äó÷1­“x=h®W^+˜],kV,—½¸öÝ—ÊÙÝzJ“f­Œ¦p,‡'>ñœY4È@å*ÕÍ€€<÷îÞ >“°ÈïôÏ^qä 3Â×ömfAÚ¨ácý@O©Q«.æÐ—[a]¥¾‹×ÍŸg¸õ¿g žEo(—ö»A¼µŸü‹AW¬sAÝ-}{áL^|ÒÀrT¬X>>8凱æ >ÀóœjHKIÁ”E³ú~Êøo°®h¿,˜;ñ_z©i„‹äŽ«/‚ïDAÙßý‚|€E†Ö Ê{×X©•Ì/T¶;ÿÇ]Î:£õyçvð@;å–[˜ÇŠnž‰>A¶ ÞÖ¬Û"ÿ`ÅõÚõ[¥E³†òÊsK ,n£Û‹ëŽ»têØZã¥3åËÅÈÐÞ—1o+7]{‘ôÇŠÄrxd¬S¿ÿb’ÑŒNM·i«&Ò /—Y„…X<ñšü9k¡¼8ô>¹ìânf€ÀEd§ãQ¬Z˜“¦Û½‡[¸ä¢^]¤ÌÙƒŸ#ïA •/…Åd#ß9ù;­²aƒÚRæc¾ÕΆóå°(mÛæÒBò2,fÃÐÓŒÞöïO”—¬2yX²|­YµŸ ssnåÜ€\‘ÿ££0ß¿ÉÌïwëÒN"Ð0º´o!ó,—…€‹eÄðåŠ>çóû–­;¥9òQ½f5i\§†,YºÆhï=Ïë$ÊEKï«4†õ†•£6^hÓ”q•zyçUl£ÐþªÉÂ<¿«ÂiI;£C'£=SÀSuíy‘Ð<ÍUö/<~¿ì„ù»Ó9ݥ⭔ef¦Këög‹-|ŒŒBšæöƒž’ò0ÓŒÌEi×­2¦d>¿vå23¯V×îX p,N¬tY¾ýü}¬ìo+·Þ7&æJx¤¬ºÉ÷;¯ï9óœóäSÌ7ùá›Òá¬s¥,ÀÄá‘8>kÎAÊ㾔ߦLá£ß“Vx\SMš·Ä‹{êË7Ÿ¾+cžÁý7æÅ¯Ãcf7càP{5˜ÑÏ„•r¤|á+Ͻö¾ÔªSϬ@AäÍû€µ|®i¨Šõ ½.íg”*e ÔiÐHê7jA&ù,ñÌ 3ÅòÌÈ·Í9.‚«º~ýå§eì§ï  íäŽ5Ö Z-Á~¢÷/¬žÍÖÙð”BRµšu>ß³ckû(ÿÿDÓe«ü&盆?y¯Û洛礋ªN!<çj¨i €ÎÑcµ[¾áæ$úáüo$Ì2»žr0¦˜p³¸‹s4a8°‘0ÿHã<>víUÈù½Î74}"JÁ¯çbn.¤ÉÅj|) ç:p ѹr\Ô‡|™8Ѱr``¾ÃÐ)”çB3_¾¹zçhÂfùÓSÒqÉ-Qظ¡UÇã9yZ¢ñ´@:©Hüþ€òÿb5ùãÜŠügcmÜñMo,knM¾?„Èëȯö#Ÿ¬ ÆE†ÔªÉ-Ì(p,\<·uD³~”) oš£É ˆóè|¼…s÷|€©oÆS ÎpwO›2Ã~Qß¶uéÒºÇìÙK×"jÞ8(ˆºRF€whnÕÿž‡o0ø)7ÌävN…´£e»£@÷¶Wï­ÍÕÛ4ÁRCæynœc¥Yš‚š8µAn*®4 s€ÀÕáÌãàJušqig¸ƒ ŒÙº\… æ:Ø ‚ÏEÓ1?ê4 ‡ÂòÅgÌ©ÁSK§MN„6ì¿8ÏtL8ô`ÓúAæÏ™)O<ÿªÑFyþ²aIDFLÉæË<ÒÄÎéóE+4ý3 ÆMŸB–þ¨½2Ÿ|ž/Zá V;ž`ØÞºc—îKçÏ.px‹âP°PµPHÓ$­¦ Aíöä³9ï.ㇷ*ÙHT¬‚¢ÐÁ¯asaU´d Dœ0—M8ÎyW©-ññÅ4LAAgî`œgÂ8h 3iáe2X@g„ÂPƒŒ¦°Â5<N|ûÚ¯˜2xaÔÇrZúxÍëæymÆÏºŽa«lŒÛì#1„uc° ¡^­6æ±™&nTz`X¾7 uˆ@IDATÏæWå7¹_¾ù( Ï™ò ü\G?œÇ« ­œñ‘…É+âã óm˜vàÀ(–/”AÃ&¿%0£/ÃçÀy³ù;šê{žß £è8“§JxÀ y7.ŽïÝ7/Ýá>òÀü›º`t¸‰•ð,/ߊ0HÇÊ#ËIÿê”À©&ÀNŸó¢þΘe3ø¨ïQoÛŒŠÁKTØ^q³SŒŽ6á¸8‚‰~Ýn´ ˜¹q³cŸ6Ö=Î×fc¡…MÏœ[·Âp%6 ôOÇüðyl¦E?äÑшÇœÃæŽùˆŒ EsÏ1B‰«¯§ÀjðÖÈáòõ”YFðYøRæËß1NKÛŒƒ`exÌÅy„XáùB™C×¼e5kÀ†–ï+fCŒ6Ì8ž/Ï1a°OAÈÁ+ç¬é‡«Ý9ð¦åeìÍ -CXN¡²kâàÁ’‡8ò:óAîcÏgúYWÖZ–“/å¡Ð&c>,ÇîägêáÉ¿ZÚ&¬U/VÙã*UE9˜r)¸0·Ò,ŽßÀè(•Ç…ZBEø;V¼ÿ")ãÊÏs££0ÎÿkœçéÆÛøxˆ›Â•EçÃ+–q˜+ÌÃy…=Ïy,/2m£"½ñyã7'qo‘»áêÞÒç¢s%< ‹,`- :†9šc<æFe|7˜7o^ß¹é@Óy¯y#å ÆòküqPãó“·¬¦`°Ãñ­1A­ÙÃçåéç©ÉW«Š‘8&¼©½XXÜä80/°AÍ5‹;ÃZôí{‡Î[udåÏøgœhÀÎaõaRÕ?Jà”`g×Q ù;káÏñ¾æ1Ö³/‡Ú¢·Ÿâ9¾µÌ{ÍÛ—P󳜆mŒÎ:æu+-ž£`áFg{›¡wÁóŒƒæv I>öÕüŒv¹‚’×½á½qðØrŒÏJ—‚•Žq[ç¬ßÜk溷?òÏB˜¯ç=>Z˜¼þò†ñ?¶ö)i¿òúþÆ,Í)2gùó?—wÿX~Žvíxçü¯sŸƒjé­Ûv0“ǴFÍù‡=ñë^a"þóÆŸ÷Ø?Žc]ó÷Wû)ÐK¢à%’†Ñì½£ã@ªtÿ²Ój@©7–fíïןþ}Ã$ÿÓº¯”@€ðjÁ^m*Ѓ¯Î4ÇJ@ (% Ž  ý$zB (% ”@ðP|u¦9VJ@ (%pèG ÑJ@ (% ‚€ ôà«3ͱPJ@ (#¨@?‰žPJ@ (%|ŠüêW¾@ŸŸ¬Ãórý£}Ë#ø°hŽK~iÎ{”÷ªº2HÕîí§¼}T$ Ep”¡nŸ -JV‹*Ð=!ø¼&¾MîÁ‡³=v~ŒD¿–U”ú8Öãá§T"Rø=~&7,Ìãýä«xð©XåZxšÁÒãp  ÷„…†áKÈø,¦~V(Øê°Ôç—=r4ÄédY Ý?Z cÄ‹wèÛœûö'ÊêÕ›ìa¡N› §Êób¸÷PÐ%ØñhßS81ò u:[·íflÎÔ„4G1D«Qƒ ûeÓºÕvgh¨Í ¥C?þW–rI ’}ÔîÛYlgzzb¡¦ÃüÌÖñ)2ŒA„„„¼f·ÛÌÊÊÉÁ©BeàøÉ•Idlq.ôh­L’˷з#Äâ°Ëʬ¬ì àm6Þ³ü~¬ºÒEÀj;‚>êUôQ¹ÐI¡!iU<õlñÍFtT)­ã≽ìÆâÆýâ±ÛVege÷†÷Q¬ˆÂ8S‘‘‘ÕÓÒÒºù" à)l|…ÉCi C~éØÚ`»Û{Øæa‹Ä¦‚ é,v;Wã{Ë ¹‡ Ÿ |¦~£¢¢ª¥¦¦žçË®öQÅSo‡aë‹m"¶4ljõ„"8ÿ>j ú¨ùˆ«Dû(&¦î$¨_¿ZÇØ˜¨õjUëz¢×(•@Y! }ÔIªéÚµtˆŠ)·©Vƒ-ORm!ziY£]m4…ŸOŽr³·mÛ…_[jZéhÖr™=ýSÖˆWÍìE¡”¯`,Í67ÞV¥+n ssh% ÐO± ¤×Åu¿¢=@nìâÌ…¹OØY¯c,Îè&._gà6¬Â3Þb =ôÍù€)—fD ”è§øA—€rãÆyýú™Ïe ÁN¸Äèu+=3–0ÏÈÈh`w:{"FÞ”yn¬£+î|Õ“ËÜÇ|í“]\.´5œ4û¾ó‡+ýV[ôÇîWØ­°ïIKÏpïÞ³×ÅcZ  Oe!šw*ÐKyÉ$HËÏÖ­ÛlW\~™´lÕÚv÷Ý÷Øî¼ó.[ƒ† lëÖ­ãýkKLL´­Z½Æ–””dCáHÒ–’’bËÉÎfK°¡‘±­Ø233m3füi»îÚklÛ'¬Õ¶åË–Ù>ü°mÖ_³lè4–ñËK¶õ6Úâ÷ÆÛÐØlqÿú믶6˜¸y¼k×.øµÙRÓÒmÛ¶m·AH›kü¥Û¸i³->~Ÿ-$Ä{žç àmÛwì´íرƒy‘Œô f×®Ý2dÈ{rR’^Øð~ÎwC¡íÈ«}ذ¡öU«V™+>>Þô9ôÂþVJókõ1HÜ3<÷­>jÃÆ¶ôô Aš´hÚ““Säÿ{ܾ{÷.öJÇìW¬>iØ¡ÜØÿž=ÛôhóL£ÄÝ!A‰'­ žlcÇŽ•;î¸Sn¸þºÜ¤N?½©dgçÈâ%Kåã>’ºõêÊîÝ»¥W¯‹¤G÷óé w½ñ%óJ°uîÜYÎÇõiÓ¦Ém·Ý&sæÎ‘7ß|S/^B¸ìÙã7$2"ñí’+¯ºJ5j, Ì—x˜Ùÿ[ñŸ\qE_iÞ¼¹¼<âeiÑ¢…,\¸P®½öZé¿Ë»ï¼#iii‚†œwþùr9#©©i&Ÿ7n¸J•dΜ¹ÒåÜsLþ>ÿì3¾fÍ —`jÏkòu†„½¼…¾è‘AƒeõêÕ’•%öºÓ~"o¼þºôèÑý^=>|˜DFFÉÁƒÄíòÈC=$ Ô7}ÜY:I«–-÷qû(*Š~ñv² ­Z·– åËYÅ)Ñ_è%Š»dƒF+={ö0‰ffe›“‚7}­š5å±!C¤råÊòÅ_ȧŸ|"ݺu3£N†‚Ü;ä0Ì‘>=ûÈäɓ姟~Ä  [οðB™=ûoÖ+_~ù…´nÕZ®ºêJY3ÿ¥—ö‘)?O•óÎ;OêÔ®c^ÒÝ¿¿´o×^úßr‹lذ^ž~êiéÖµ›üòë/ë€ >æ·ÝÒ¿ܦ²eË™÷Ïã uO~ÿýwÁ4 Œ|åÙ´q£4nÜÈ(a¡aΑK¬vÉ€÷IÍÕeÊ”)йmÆI½|öìÙr&„5×1Bfþ5KÚµk'/¿ü’Lœ8ÁvÿÚ~F˜§žzÊd‰ÂÊ·•½£þe‚¿nÝ:PbÉVôYÊ·:ªß“}RúÉ&| ã‡yŠsB¹ÎkiòžJ×&Ô ÓüV)W®œÌÞ›×/B3ܾýû¤~ýúÒÂfü•«VKxx8Ÿ!ƒÞ'3fÌÎgw–×^#™aBLL¬T¨PA*V,/TP ßvûmR±By‰Â QãÆF8/Z´ƒ€ËŒÙ‹ƒ ZÖ­]+›Ñ8.¿ür)ƒx³¤víZˆ×fFÞ+V”,س´sk Âüúï€ul5Ðê5j`džËFw”€8UµW.NK8˜ˆÁþXï0bõ<2sæLY´h¡Q`V—:uëÊSO?-Û·m“,sŸ6}šŒýv¬|õÕ×PÎ5+Þ#aedœìÑØTª\É,^ã~ÿ[n•30PˆB_uå•WÉ7ß|mç4cKhæãâLø¼}‰Õäö¥€ ¿a¿s½Q`8ðhÝúÔôc=NUýjºÅB b…вB‘.,Ôi„%ç‰8_ôØ£BÈÆÉý< wÞu—ÝÒºeþÂüÎ`X‹–fuŽj)h¿úúiذ¡ÑÚCÃÂŒÿlk^» Â÷ò˯€?ÉhÿšN¤MÇ? þ™>iÈD ÅùÏgÓ@Ó?‚䮇y~ñ°*4ô Œê]yæ¿Y6nlt4ÛYûŒŸûÞÁŠ71ÑÑðg²¡”€8…ÂÂÃL¿À,P(RQ Æ»4rs•š–jü8!Æ:È ìORSS0ç1÷ÝwÝ-³gͬÑ%·ÃzȾ»P>ðØkˆ·/¢®ÇaDGó=âö𠚈ˆpÓßY›}ãÈÛ¯0}«_±úšðÓ1mxªœ ôSE¾Ò½ñ¦›äõ×ÇÈGb´`>†öæ½ÿ™77²KjÕªiÍÔ©?ËÌ5Y „€nûöæ†ÇâÙ¿Ï4€Ê•âäšk®1f{ÎM1.ší9NsµñªU«Ê¿ þ…àN—ºuêʯ¿ü*XÀbŽ©¡s``9ŽfÙx»c^ë›o¾1sdË–ÿ'óæÎ•V­ZsýÌw3<çã}t0‚z¤zµj& .Wg¾)¬Ç~û­,]¶Ü4²%X#0~ÂD³Q·|öÙç‚E€h´Þ[~ËÖ-f¤n"³2£¿J@ ”(,"—?Ðo,[ºÊÇ:hà‹a9; ·µ|öég’‚54\kóÞ»ïK·nݤK—Îòê«£ñ˜Z²,_¾LF%uêÔ1}KË-åO<5?.yþ¹ç$ k…êB‹ÿúë¯Mÿ1ûï9òƯ›þ‚}ÆìÙ³„Ó’»07räH˜ÞÛzйW¯YkÖñpÀ~eâ?™µBÞËÑ7Q¡á>cƼŽ'möBaò»×­[+UÐÿ*§&÷SEþ$§ ™é©_¯nÎÔ©Óìœè4h-ZiƤ´ë§ž*#F¼$S&O‘fÍ›É5×^cnt.Z£?*¯×]w­p´ê„9ëÒK/•HÒüÚ½¿ÿþÀÿ|~ûyýãÑ4Ï]wßãÁóãGÁÂ:¼¯cˆýÌ׎ubê´éžO?ûÜxÉÎvñÅ2%Þ¯¨†^úZ¥b:i;dët¼ó€Ïˆ{0‡nQ&´kK-ubNšf¥,œÃó–FûæE;þ!œ™ƒ"jå\YÎsþA3g}“H\QJÇ81Ë…Íû&âG~rãeœþiáÈ8ÎõóRVòéK€?|,áy‰KVù®åm°6Ä~ðþûa+V®ÌjÞ¬Úß›¦¼I›8­?N¼¸Ïœ†Ìü믰«ú]|»ááÛ|×·:% JˆÀB´?,ûíºº—Tt¾AZ¯·ÿ‰@»gÃä-vÞÅêëƒØ˜~çÙ·x_?á͸ÕwÙ°Þ†V9N³ùú„wqÕ»/£r@ò†feefD„‡yÐ/²›ÉÂúœXŸU¡B\äô_¦».éÝ;+3›Ï³[ 阺÷¾+áÙ»o¿}üãÃñäM„žq£xÆi¿âQ¬Ño¡5ô²­¨eFöZiQ£ÒðJ ´°ú¨BkèíþÐ ¹“©Sѯœ°™ä$”W£T…&€ÆÂ78á3‡ý8Ò.ІWØúûÇT~Éæ°Ð×€J@  ´{ïĸ_lV¿’§ðï/òÝÏæ”ô+jr÷«ÌÒ¶‹›³Ôjžh-¹öì—¶ªÓò(2A Ðú(ÿ~%+@z0ÖÚ æ7§Îßœ +õ¦”@ÉÐ>ªx™«É½xy56³B‘•“æ_„ª‚•¬†WJ@ ”r–À(åÅ øâYÛÌé`ÔÊW ñ3¥Ö+‡ø&ËOÀF3¨”€P%O@Mî%ÏU7°†0oˆŒðÝ«èñ¥âüõøUꔀPJàèÔä~t.%y–«µíxï9_p2:Y‘ÌöØðr„Ù<†ÓEn^úW (% òPžÈ©<„ðþºõMOß Øª8º™ë-»ì‹½äYaa‘Ÿåädõ Œœ”š˜Èøé2uÅG@×#Ë`ˆIû¨â«%Ã2"66#+-Í–é룎x/zñ%Y&c*TUXn%f+Wµj½zuëb5v¸j=E¼ïð…r[„=$ë`ÊÁ-û÷í™W©jjl“Øú™øÊ'>ë§|‹È7)~¯mãÆÕ;M 6ë.b¬<@ Xõëë£k*†Šr»\ö¨Ø°”›·6Hr„8£¢cëµj×®fjRf´ÝáÐSµâM_gKdtô€´””§A¶ÂÆU˜ôK{6Œ0l|]¹Om“idDdô_éi)·`_Ÿ(®‹ÕGÝ‹>êdRû¨â«)*|OF¶ØÒ±i?EtV5 }TÄUà>ª0ºi(Ì8Ê9=.¾¢Ê%}¯gh˜xÜÈV+ÑÞ±©X„•eá9ú…ÄZ qʲEóåQÏu­_¿IM›Ö¬ñ#íç[wK«yû¨Þ—W¹äÊë´*ŽŠõõO|‡ý½Ín«lžÊ±ú­âH£ ÆaõQË/·_yöÜÂöQ…èþ¸3ëÖo$çõê“jw³‚ý¯ê~¡  }ðá56uE$ÀÆêOÞ况•+{d幺2@ ³Nnf‡ÉØ4¬2Pî“ZD4)vOØlx"Gû©¢ÂÎí£¼/K+lUTns¹r$3#ÝŽÑšo4ãÛÍŠZ6 ˆ€Â<Ä¢Ð{X›`Âf瘵…ºâ¹Ð$ƒ2 B\û¨“Vw죴Ÿ*"^«ÊÉ1k ÝGU N!l\ 3»ïþ,æh5º` €Î‰æ.í£‚¡²Ên}}TÇF… ”]ðZr% ”€PG@zàÕ‰æH (% ”@ ¨@/02  ”€PJ ð¨@¼:Ñ)% ”€(0èF¦”€PJ@ èW'š#% ”€P& ½ÀÈ4€PJ@ (À# =ðêDs¤”€PJ ÀT ™PJ@ (%xT ^hŽ”€PJ@ ˜€ ô#ÓJ@ (% € ôÀ«Í‘PJ@ (P^`d@ (% ”@à(ò×Ö¯HEÌ>ô›÷#äÅÿIX¤áK$oÜü.nÞsE,Q¡ƒR^ ] ¨Jí£rkTû¨\fGúá<Äf·‹ý°oºÛÄíq ¾÷A[tƒã±;âz4Ì|£Ûÿ¦ä5ú Ǽ0ÌŸ:% ƒ€öQ‡êAû¨C,¸§ýp’••)ÿßÞyÀYQ¤[ü›ÈY’DE² ¢¢È‚J0¬ŠWT|‚oQ k@×gxV¦5¯ ºˆ>sZ]Ñ”hÀˆˆ ‚€ 0ÃäyçÔ½5s¹Ë3sáÎÜ{Š_ÑÕÕÕÕÕÿî:_¥¾STXã [Æcø/=#ÃÒÓ3ݱª·ôŒLËÍÝa›~YkÉIÉV¿Qc×€((pØÞòq,%%µZôÒóss]ã#)9ÐøC¥](F•A/Õ(hiP±ËÆaH=ä¡s¨ûíW_°K>†ϰââ"ãß›¯[¯õèÝÇúô==ë”@|ðÑûÞuè0¹3ú¾W‹Y`ïÍzÖ,œgµjÙ‘ÇþÎNqšµ<°ýüãj{ë¥çlðÉ£­eë¶VPóøÞsWyó˜‹w‰Ãùþš; ¤ =Vz¼´¼fI¨ltÉê7hh—ž3ÒÎ{ßRRSQaàÑkMKK·ÌZµ]œ7¨Ü²G›Š@ƒ‚‡Ð7ÿýwlÌð~v@ËV6åÎûmÂU7Ú7+?· 玲Í7Xa~ÍxòËݱùfXFF-wŸ7ï–×d¾ÌŸ c%OMMs×à@¦¿nÐHÊœbih¤¸ò¢üÞñ|æãó¤1G†¥(´·^|Ö6`$AND z`]_øá{˜ª+(Ó(èTýœŽ,üpn5ê]3¬L£&^}£}ûåNÿ¨QIœñ䃶cGNõШ—fJ£B^MõÐC` 3£˜‚ÖÞ1Ö·ÿ @OoÀ¡¶5+˵Šp‚}÷õJkа±­ûy zÕ?Xçî‡Z›v¹5 ýo›7Ú§K?q/ÿ!]º[ÛŽìÇV¡Â¶{Ÿ˜i'Ž<Ý 0´Ï¡õÛ¶·KÎáF:vêbÝzi[6o²Þm[·dYÏÃúX£&MQ–bg¼W,YdkZã*m'äÝ¢uËÉÞnß~õ…5iÖܾþâSÛ¶5˕ɵ óó]…¤!_ûÓ®ápHמ֪M;w©h ðV~ºÌ ¯wíÑ ŽÖŽ ·,£œˆ@5!ƒN:,D£Ø(§FmۺŖ-^hÇ¢Q?ÚOkV[jTûƒ¬£~É8? Q;¢Ž´ƒFýä4jÔ.5ê¿vÒ¨>¶å·ÍûH£Öئë­ó^iT‚Óªdh˜\€€ zø›€Ê‘‹ÖgÎöm¥Ftó¦\û †òˆ¾Ç"u‰ýßÓOÚêï¾±N]»¡7_l·]÷G»ïo/àøq0¬ŸÛ}·ßh 7ÁÐu’ÝpÙ6sögdy©£hùy¹n1ÄÑÐ>üÌ«–š–f›6¬GEÙdÓ½ì`ùEöÖ«Ø5¾Óå÷'¶hܹ«ýºþ{ôÞÿu•=ò)¼È:¢b6ÂuÙ«¾õÚÿ¶gßüÐ7kfÏMÌV¡rH·CqÞ:{â©vóÔ¿¢ñp¸-]ô‘KÛS ÞŸùÔ£vÃ÷¡qp€íÈÉ Ê¥}ýN€ { Qì!‡jÔ–ÍyöõÊÏìÐÃruö…gþf«¾ýÊéÚÝéØ-×\jNÓ†ý]ãÿÞÛ§8­ F]?ñöÜœ…¶º]iÔ_wÒ¨Í6ýÑû\#ÀiÔ+Íìš›ï‚F5µ<ùW[ðïºçv»÷É™Nç¦LºØ:B»!5ê–?M´gßšç´æ¹éÛwè”°sDzòþ»íÏyØMùQ£nƒžuëÕDZh¹L£šC£²Wpý§Eq¡ï[ºuêÖ³—gNsƵCïi©éhõ.pÉ~7h*G‰’çB¹ñ“®µ†šØáGõ³¯¸Øf¼ùo›óÆË®÷{Å ·¹áòN]zØ»o½ ãßÃŽÀüV †ÆyÄDŽЗ`޾¾.߃¾|Ñ<»ãá§mø)gºVð¸S‡Øç+–ºùû•Ÿ-µ›îzÐ:Ü „гýºau8è[ùùr5æ|;÷‰–ÆÈãÇØüÞµ“OƒýíhlôwåEßn»þ 4 æº2Ý|õ»ø×؈ÓÏÆÔ@‰M{ì~{õù§íìq¬Vº2è¡/ˆÂ"eü¨Ök”›¦C§€ÓpË?YhEXó3ðÄ“] 9$Ÿ†N‚Ó(4òƒF];ñ|û¿9‹lö/Y+ÌOžr»ë­S›Þ}ë×à?’Ýi;Ÿ~ûàßí¤SÏ´,ôÔÇv¢}¾} רã{·wwƱe6òÌó켋.³ììm6ùâ³í#hÔˆÓÎvšÅÑ%—_Ç?»µ ƒCP¶ÿ¹f¢]xÙÕ6ò÷Ð(h';<¯<÷´sá«í4ªz|åWÃ]^=ô°§P„¡íš·rF™=õGî½Ý~7ød›xõkÒ´¹åälwsÜgýá÷2qáZçî=]o|-†®?Â<ùå¨(üœ‚óM'z–ûŽ‹áØãåXÀ•m¹j5éù²ö:² vg·†ž€íÛ¶Z,Ìc#­WΡqØ}ó¦n6m;¢aq¬Ëƒ×èÙûHû Ç™'§ºtïå¶<Æa~ásžCôŸ/_bë×­uq?®^…ÅpÙðÑg:á()Qe {E´+Q#@ÕpÕ……´\¼ú(4ê8t6.»ú&7í–ƒ^+×áŒw)4ª¦÷òÝ{RRŠ­ƒnÌ{o¶M¾éŽ FåÛI§4j9†ëÙã-_£’žôÄ"ÙŽUu8: Û¶eA£êÛ×ï¬Qì¤pô±:Ò¦]G;âè~Bg¦ÇN•b]zôh:;­Ûu°b,Ä¥F}õù ûbÅ׫§nqúòùi¡Ü¢þÉÈ ‡¼ |‘·ãÅ<î„a6êŒóÜðÎQýÚIÇvwÃéÃFÿ¯aæ¡ ðòÖs/¾ŸÛæb´|÷íô´ ×ÛåÊð¼œ\1_ CëŸ-ýضemÁœx3ËCEä÷¤|ÙçÏy‹Üj£‚¶A%Kt‹èhˆÙcÎçcœóÊÞ¾Õ¼û7¿ÎÅzl¹Ò1ÛnE>ÊÆ<ÿ±1‘žx¼¼[ï¬TøÊÇò]+œ 4ou cÅoÓ¾£ qªÕª]Ç5^"ñí}bE@ªB ¨QýaÀwÒ¨cº¹ò°Ñg8]b¯[·¾Ó6¨\øš:žízõÔ—PâÔÝçË—£QïB£2]ÏžÃÞ^÷˜o^?µ¥Fm³‡¦Þê:Fõtwê~Ã!ÿû^£8ŸŸ–žµÂêl ¸Ó¨bhÊÉ<©QÄÿШOjî%0ÚY¨±s®V¹‡=K®òæ‹Ç•îlýr.û‘¼f×\zžk)ÒÓ<ÿW223lÓ¯Üu³æ-­Û¡‡¹¡¥”Ô ¥×u éî¿ó&×ãïû»ì—Ÿs5•ƒ€5ßçËmÆBÒOÔPi]ÿÿy£¿dá|{ùÙ¿Ûw>`c/¹£ÑgûÒoã3Ð`àð½;ÿ³Òù–vbðÓ·À1~––ä%4älÜöè}„~îYvÆØ±®ÍF{õ<ßç†I»" Q"@¢A-Õ¨Ù#3^‡Fµ¯>[ŽQ»Tì [4ÿ}§Q™Aâh5Š m¹ÖkÔ |wß7Ykôø0ØÞÀÊq6vÖ¨QNçmÁ½{=¡Öð+›%˜.|iÆS;iÔ蕳AÃÏOàèJ5 :ä; ^¯|žN£0Ð…eJÖŸä…jTÖ–ßJ5Jk9¬î?õÐËX¸¥åç啯²§Ëaï3Æ^lwÜx•M}xº5= …ÝsËuÖ¼ånAÇF²Ûøö[»ìœ:Ø-IKOsóKw<4Í7m†!±í,|²«NŸtŠ[i:iÜv.æ” i?c8ì‡Uß”ö¶ÙßæBöÒÛb…*¿?å‚’w0çÅU©~Yg-[µÁ‚˜O]%÷óò:ó-⬬ߜwÇPc˜_Z¶œÿ¿é®¿Ú™'㟯]xú‰ˆ{•=Õ~Dcƒ[ND ú(Ó¨€ù£Fñ72Î;Þn»a²Ýûø kÚ¼…Ý{ëõÎ òë—ó©Q÷? jUªQüz†Ÿ²Ž;mˆÝñÐßÝÈáD|J{Ö°cÝ—/Ô¨-øb‡u5jØH7d¿fÕ×¥ZÃlߺ½ô\×ù!¥ºÿÕiÔ«è°|ëôª%¾ÆqEëìLz‰Ó ~K—µe‹û¯T£{ü ¨QwC£†î¬Q7Üñ€Ó(j {úr2èaoÂÈÓÏq+ÊÑtt½S¶„Ùâ7ñJ›ýú‹n:ÜMw?ä>›;û {ô¹7ñã+ÇàÅ*Dë÷H{îíùXXöŒ{ÉŸziŽûaÑ.=³·~ióæ¾ƒÕ áeml£÷ÏnI‚1­aî˯¿Ý½Ä!t³CG`N¿¥Ô¹›ýýåwìU,¡±r²ÇϲpÄàNTÈzø^žç±tÿãÝ/Ñ1< ŸÉµE+žÃî %˜_ÇJXNÐüý9v`»ö6ëõ\ùŸxþŸÖ å¡ûÃ¥Wà“»ƒÝX&튀Dƒzºeó¢FQ.œ8ÙÞ¦Fá³×tJn¤Fa Èê±™Ð(|êFã_®FÁˆr›Åß̘â/YzbƒŸSq“Â5 ñØóïxH7›₵2´XªQC©Qí;–jÔ¡ÐQ»;‚ÖqÝO@£ ìqhÔaÐ(Õ½d’4*ä=ô#!Q{ ò¿ a:DÿÜK¯¼¡C.‰n>/XMv¬ ÚÙqU:‡‡œ‘ž2i¼[­Ùß{²7ï~àÅ ¹¡n?\Ä<8tM.¬t<ŸiÝ\âáŽãzl©rØÉ»ð2ð\.´ã Î0¿§ñæ°[µŒ =‡ûtŒ »HüÇ8–‰× //ã}y}þ¼š¸%ƒôôôâÍz#qây§üسϱƒ–/úðkÜ kÕ_M|¨»/óNuþ]~î„«¦ÄFQ“n˜t‘Ä: ~lj¢FñW5SҨݿ°^£Þ›õfâ„óFÿ:¾2¥zçP£Xv¿œLÃÇ9Ÿú ¹ál.*¡A¤‘¥ Õb´H†’qlÓ¶z£ÊV'Ü÷ǹ œÞpIÜ,¯ã>WÆÓù|Ã˺v'á?Æñ\o¼}¾,/ÝžÊãé?ýN`Wõ5¶L£°À¬>~øŠ Ì¢«Q¡piÔþ{EdÐ÷’µ7~4êã'ýÉ s³wÚ“ dÅÞrÀ`rß¿Ìþ2~?ð9X gííiËs}eöùìéœ=÷ùD:ß=]WÇE@"K€u™zÄÑDiTdÙÖ”ÜdÐ+ñ¤¸˜„ð?yE2 ‰Wä ¥½! ÚJ±—F½Ï”?Ùê{¶•8]§ˆ€ˆÀ>% Ú§x«mæe«°ªm«_ÁdÌ«ß3Q‰D@ÊH£ÊXÄSH=žž¶îUD@D f È Çì£Õ‰€ˆ€ÄôxzÚºW˜% ƒ³V7&" "OdÐãéië^E@D@b–€ zÌ>Zݘˆ€ˆ@<A§§­{ˆY2è1ûhuc" " ñD@=žž¶îUD@D f È Çì£Õ‰€ˆ€Ä*ÿ–;ÿHI¨'xº×šA€Ù.ðŽÖŒòª”&€¿J,Š0SeQ¥eåÿ í½¹`U zqRR²¥¥g§¦¦á¯á¯òʉ@õ"@1OMO-NIIáˆT1þ¦}ÕjMõº=•f÷ QIÒ¨Ý3ªÔQT+þd¼êR¥èí|5* •œШîý^U zÆßksg½‘œâ z± úÞ³WÊýDcHÆŠ²bÉ"^1sËú_’öÓ¥u™èH—F훇@KŽœúpÀ®QY6Tj:¼J#£V­+wdgÿ ÷“ _©D€…²½!PŒD™™µîÈÉ>áßàùþ«‡±ê¤Qûìɲ>±CX_%;²ÏJXó2v•žYkQnNö9(~…5ª² aRÝ&MÚ·k×û©5_5*qrrqQbbbI~¾«$Õ¨d±S¶zW¯þz=î¨Â%v(ÄÍH£öÁ£.).IHKO(Èúm[ãß6þú§z ßÕ vÝ y%%) ‰ jW‘y45ª²*Þrlž^§NýQ™µkOˆÍ»«vw¥w·Ú=’}R =ç}‚Õ z5"--=§výúöÑ%â=ÛJ½»U™CN¡h¸¥ ožhE99ÛFc…É¡Èë)øx>ÁÈE–ß[õ$"Ë´ºæ&Šì“¡^qˆ=qÇŽí@¯2r·oŽý÷àS‚ǰ‘«"JkTU :Ë\é Wñ†cétoÔ¹a¼7â¬8ä+'"PyҨʳ ?Ó­“Â×"}°*{hðàlÂo†w_‘㵉-d‹ôr.IîçQE‹€TÅÅÅ¡wž £ÎNGïäääÁ’ùÎIõ(h–B$ºnYD@*HÀõ¾ÓÒÒ†1Îï¦áJæÖ÷Öýè"ãä¢@@= ÐuI¨‰ŠŠŠ8wÞ,Xvg?°? ûð´òê¥áDc#ƒ 꺦ˆ€Ô®wŽâã=½söĹp—?©[ßÃî}¹'ƒà•ÿ«º(.*…ÖEE@D@ö¿87óçרgáÊGÁ_?þCôŸ ÔB^Bˆ–“Ay]WD@j?”¾Cîo±ÈXéΞy.‚ `Èÿ4æì{ãÏdrû™€†Ü÷3p]ND@j o¨ù½9‡Ú3±IÀ–sçtüû>‹ÐûŸ€ úþg®+Š€ˆ@M%ÀOÕèüŠvoÄý6pTÿG…€ zT°ë¢" " "Y2è‘å©ÜD@D@D *dУ‚]ÈA,Oå&" " Q! ƒ캨ˆ€ˆ€D–€ zdy*7ˆ ô¨`×EE@D@D ²dÐ#ËS¹‰€ˆ€ˆ@TÈ G».*" " ‘% ƒYžÊMD@D@¢B@=*ØuQˆ,ôÈòTn" " "2èQÁ®‹Š€ˆ€ˆ@d èï¡G–§r«>ÔX­>Ï¢:•„L¬:=•%bdÐ#†RU3þÏ;V³b©8Õ€@Ê £^ „ŠY2è‘å©Üª ŒŒŒÖ;w®m1\.Î lÛ¶-á³Ï>[ [àeÔãü}ˆÅÛ—Aŧ¿÷Äaöâ´´´wìØñÈ’%KR°¯žXü¾¡wΛÌZµj}’}6›àeÔC )\ã È ×øG¨'——wXÏž=Û\wÝuÖ¸qc+((°„uÒÃ9ÅË~II‰¥¦¦ÚâÅ‹íª«®:¦M›6þðÃ2èñòÄÑ}Ê ÇÑÃŽ£[- !:thQ:udÉãèÁïæV9rC½ËnРA ún’êÔL2è5ó¹©Ô»'€ysð{" zQQ‘%&Æ×¢wöJéü}s¿¤qhÞ”7ZáÒ ?g÷ˆkÎQ¾ IIIn¤†HjNÉUR¨ôŠñÚŸ©Ù³Ôüo%‰ÓhyÃÄmyF¬’ÙW›Óh„ÃïqþÞYPŸ&!içÁ ïoÆçï×Ô­¿/¿ ¹„P°\bV.šèAþ3/Ah… ‡§Óþð¼üö?SÔÐod¿ùæ{â‰'¬°°ÐÒÓÓ #¶uëVËÍÍ5,ø² /¼Ð0Gl9996gΛ1c†mÚ´ÉhcÆŒ±¶mÛ:ï¼óŽýë_ÿrÆž#t½{÷¶þýû[óæÍKî@lý—–¡ïGh8¶îtßÞã†F’:û–s…r—A¯®}ž¸WØ¼Š¾£®8î€e2˯ø©5ã |†g½zõr‹¼Ö­[g'N´ÇÜÔo`…E…ΨÓÀ?Þ°šÛ&Ožl} «ÿmú´é6uêTÃ15j”ñû3J‡ìl#FŒ°yóæó$CÝÒÌknÀ­«@ñëüüóÏ7ƒËz4x¨ªc{¦‰x'rñnŒÓš ,~ã·OSË ïS¼{Ÿ9*ÆKHÝÛžÁ³4¸÷øJSb(š=ˆ¥1à"/Αû¡r¿{ÇáuÉÓhÓ˜û4\vÉ%—¸^;Ó2:¼onËÿØ(`/žÃ÷1èü&ƒIgÜkÜ»ÈUüA{ž ~3ñIèÒ`>¾â9ꌈAÊJgä*Dyrø7¼žJgÇ'&À åàþo€ØÜO¶qÅ“½ö•+WZÓ¦MÝkಷݤIçy€ñ›7o¶µk×ZJJŠáWÔìÅ_´iÓ¦¹aw¦?nbÅã~hÀ·€ÃE_|ñÅB„kÁkj«âO˜õŠ,óàÙ€æ‹"ƒÑv2èÑ~e×g¥ˆÉ®QÙ-î·…&.ÝÞaΫO™2ÅÍ¿³Wß¡C;á„láÂ…Ö¥KÇnoóª) ƒ÷S‚{g£.;°ÑÿU c^x‘>U=ÒD+Ÿ_Üõ&+j—gRXèÙc¬òÚe²ØŽä õ¾}ûÚÆÝrh†Œ=òï¿ÿÞ–.]jC† qCñ×^{­Mš4ɰHÌÍ—×®]ÛÍ­Ç6!KÀh˜×=nÝ"¯¿ç}y{ê™ïKºÌÛ¿Øìóе-ﮘœFNb˜€ z ?Üx¾5pÌ;÷ÃʱÄ#ÜïÍþ®8„ŸKŒü½øûNMMñQÚŠ@LAÉÇ÷7•„?j«W¯NÀ¬$pÈ9 WÜ?õr°‡Î…€k×­eŠDü® ”ÃJÑ5›€ zÍ~~*ý. wžµlÙ2;å”Sü7Ö»H¦¨8"€]× ·ž·jÕªíqtëºÕ8"ü‚5ŽîX·Ëø>—Ô‡Û²eËH„9¬ŸöŒå'¾÷÷Æé—TüQšoÐCŸµ÷§)¥ˆ€ˆ€ˆ€ˆ€ìGê¡ïGغÔ~#À÷Zïö~Ã]ã.¤Q›÷ÈT`=HÚc %ˆd’Ïm¸ cš’ðÚÕ¤P Šðe”ÄV”]U–òâ«zçû*ߪ–Kç‹€T»Ò$–Ž ¹L@=ô}÷ðXi|o»Qrrr¿ÄÄÄÅÅÅ[Ÿ¼,+PKø»;V™kéˆ(Ò†üª”””¯°¿áïá/^­6ÂËà{§¥¥uDÅZø¶ÁcÉØú|hìC[ÏŒÝ÷ ³Däuò:(˜Ghš`”6" ñNZt´b ¶`»Û/ᇹx½ñú®7¡û Ó‡ºÐ}æá÷CÃL¾š‡Â"Pm¸Š€ ògøu0ÔÃQ²zðuQyÆ#® 55õT–6X©0Œøþؤ3\Žsù–sŒÑ ‘ÇZäÙ3˜†9 ×ð‡>ŒƒNüâêÃ7BÜØß”‘‘ÑŠ Ëq{Òžæ7Ãå¥MÃtÞ•ïk»ü=ªÄa¾”2o•p¶7¾éó)((x§†ºšã8ÌUŸô]±]Ÿ‹^v‡¢¢¢Kn ÿòxÛ 4ÖëŒp6†ðÏÁ–Ã÷#ßEÈw¬ ×#݈[Œ0+Uè>våD@â€3˜ÐC¡5 )xЊ+¡ М:Á¸&Гñ÷‚VýŒðyyyß`¿:#ƒGÛÁíWÈk ΟŽ}æ_‚ÌiØ#¯—ça êÝG¸æcØßŽüú!®)ÎíßçOFüxé TÖž\d 8¦x©A¶%xQg³gë˜ÇñRß„øGfåÁûœ‹JÒ/86ã¡2¼ˆø÷4ö{ <­¡2¶GüÓðçcwŽÓ€Ï„gåX‹-÷¯0öÛ±•OÀ5ì¡Ï"¢4å]ÜËà{c?š41??%™86 ÛÔhItçì·D>á¾ÇÖcÛþzè;#\3Téÿú—Œ{érà©Q§âZÔ=º#Pްåµ7b>?ƒ‘r"PÝøa­‹ñò®Aá8ÔNçZÇÁ­3úsý;ø#Ð#?•( qõ°½~ÂÞe"Íר$g#~üzT–nÁƒµpl5ârŸùq>>x,%¸ÕFD@HÀétâHhÆëÔxÎ¥ }ሟa{:ö×!èG9ø.ü=ˆã´ÞHs&ÓÒa.üŸžËFµè9Ä¿È0]Pã~B|øqð«ÝÈ,ÓÇà®6•! !÷ÊPÛ‹sÐúÜŠVi’Ö‚§¡¦sCRئÂse{¨óÇêâ\®>m‡Ê0 2á·cŸCøíþÛuhI³uLÇkäºP wŸŒÞ}Sì ¯¡ö mD@÷å zã ±w2<;½ )4ÐOÂÈrXS‚ÿ„Ùsæh_wøÍè¡g`„q#ÒAD-!áU¤É0zç#~“al[àXäÃQÊt¤§æ5D¿%Ò%ã8 ÿ&x¹AÈl\…Á »/p"Z¬Gaû޳çN[‚ü6¼èP©Æ…œÇ Ï-„§qŸ<.ÇËßióðò×BEZ‰üúaŸÇý³cØ;Ö°bæ¼¼œˆ€xÔ êK*Œöß ÿD§€; º2[ö²‚ΠƱ,ø¯w5<é">Úó ôˆžùøQFƒŽ½€s/ÀñÑH×Çü°z2ÒÿÇþ l‚Þ˜#è÷™G+¼j÷ùRéx%@#L=`c?Úôè¯s0ºG#ÐÚ±Û…Ø6‡q^}ü'_Œsކžq4Ðë Ï¥ ùéßGšG^Íúˆ°ÿ|W,¦ûqóæµÿÏyw–'4ìÊU•@¸a¨j~:?@€/«¡%:àI¼ìl¥r(‹/p'ø©¨$b[ /ùVl]ÏéÜ:Ž=‚ôÇÃ/B+B_¤áJÒÅh´F\6öýp:¯åÀ1~9ÒÏDº ¸þØçÈ@`l 9¸%@ƒÎ…ºW@[8ô=ÍA2Úaÿ5hÆ?á‹ÿtæuèÈ{8Ö átåë°ŸDýAœ×7òˆý—‘ÏEØÎÂÖÃunF>3à?Â9ËáOÀñwpœ‹wYÿ[ÊE‚€zp‘ ¸ë<\åá!¼Ðý±9,X >À‹¾$x %…ŠÂOÕX‰ú ¼aæÔá8§3*ç«hœYQš#][¤cyð‰Á<Ø`ø¾5zòCpÞôð?Ã~i9–ˆoìQ;ƒ Ý8ážðÔ~R6ÛR‡ãý°s´äh 6;\ÈÛ û_ ÌΈח Ä÷@ü—ˆcÇÄ_'#£ÑXh¸Op¹ØVµ·‡¦ÕEúÐÅ¿<$'Õ–_ö]9Æ—wŒéË› )/Þ_#<Ïð}ŸN[ø%Pž.0Þû]ÑÙ“þ„ŸS^úò®~¾ö+H@`+¬’Éùb{Ö"÷ÃUÌŽÇü~hØW,nyŽ÷>ÞŸƒC.Ðã>ÆÉ‰€ˆ@8¯#ÜÒQ+B5…q¡ºÅc^O¼¾0M¨c¼×!ÏüOz ýðkRêˆÿ‡Tv(ªÅgžIEND®B`‚ola-0.10.5.nojsmin/doxygen/json.dox0000644000175000017500000000173713023355232016630 0ustar wouterwouter/** * @defgroup json JSON * @brief JSON based APIs. * * The ola::web namespace provides: * - Classes for parsing and serializing JSON (RFC 7159) * - Implementation of JSON pointers (RFC 6901) * - Classes for applying JSON Patch documents (RFC 6902) * - A JSON Schema validator (http://www.json-schema.org). * * @par Serialization Example * * ~~~~~~~~~~~~~~~~~~~~~ \#include \#include JsonObject obj; obj.Add("name", "simon"); obj.Add("age", 10); obj.Add("male", true); JsonArray *friends = obj.AddArray("friends"); friends->Add("Peter"); friends->Add("Bob"); friends->Add("Jane"); const std::string output = JsonWriter::AsString(json); ~~~~~~~~~~~~~~~~~~~~~ * * @par Parsing Example * * ~~~~~~~~~~~~~~~~~~~~~ \#include \#include std::string error; JsonValue *value = JsonParser::Parse(json_string, &error); ~~~~~~~~~~~~~~~~~~~~~ */ ola-0.10.5.nojsmin/doxygen/dmx-cpp-client.dox0000644000175000017500000000551113023355232020475 0ustar wouterwouter/** * @page dmx_cpp_client_tutorial C++ DMX Client API Tutorial * @brief Send and Receive DMX512 data using the C++ API. * * [TOC] * * @section dmx_cpp_client_Overview Overview * This page introduces the OLA Client API, and provides sample programs to * send and receive DMX512 data from olad. For information on how to use more * advanced features of the API, see \ref cpp_client_tutorial. * * OLA comes with two C++ clients. The ola::client::StreamingClient is a * simplified client that is limited to sending DMX512 data. * ola::client::OlaClient is a full featured client that can both send and * receive data, as well as control all aspects of OLA, like patching ports, * configuring devices etc. * * @section dmx_cpp_client_Building Building * Once OLA is installed on your system, the examples can be built with: * * g++ example.cpp $(pkg-config --cflags --libs libola) * * @section dmx_cpp_client_StreamingClient Streaming Client DMX512 Transmit * * The quickest way to get started is by using ola::client::StreamingClient * The program below sends 100 frames of DMX data to the olad server on universe * number 1. The frames are sent 25ms apart which gives a frame rate of 40 fps. * * Each frame consists of 512 DMX data slots. The first slot is incremented by * one each frame, the other slots are always 0. This produces the following * sequence of DMX frames: * * ~~~~~~~~~~~~~~~~~~~~~ * Time (ms) DMX Data * 0 0,0,0,0,..... * 25 1,0,0,0,..... * 50 2,0,0,0,..... * 75 3,0,0,0,..... * .... * 2475 100,0,0,0,..... * ~~~~~~~~~~~~~~~~~~~~~ * * @snippet streaming_client.cpp Tutorial Example * * @section dmx_cpp_client_OLAClient_TX OLA Client DMX512 Transmit * * While ola::client::StreamingClient is easy to use, it has the drawback that * it can only send DMX512 data. It's not possible to receive DMX512, use RDM or * control the behavior of olad with the StreamingClient. To do that we need * to use ola::client::OlaClient. * * ola::client::OlaClient provides a much richer interface for interacting * with the server and uses a @ref event_driven "Event Driven" programming * model. This makes it more complicated to use. For more examples showing the * non-DMX512 aspects of OlaClient, see the @ref cpp_client_tutorial. * * The following code uses ola::client::OlaClient and behaves the same as the * \ref dmx_cpp_client_StreamingClient example above. * * @snippet callback_client_transmit.cpp Tutorial Example * * @section dmx_cpp_client_OLAClient_RX DMX512 Receive * * Receiving DMX involves setting up a callback handler and then instructing the * OlaClient to call the handler when new DMX512 data is received. The example * below will print a line for each DMX512 frame received on universe 1. * * @snippet receiver.cpp Tutorial Example * */ ola-0.10.5.nojsmin/CONTRIBUTING0000644000175000017500000000163213023355232015312 0ustar wouterwouterContributing to Open Lighting Architecture (OLA) =============================================================================== There are lots of ways you can help with OLA, such as running a Buildbot or writing documentation or user guides. If you’d like to contribute code (such as a new plugin, extending an existing feature or adding a brand new one), our preferred method is by forking us on GitHub, committing your code to there, then opening a pull request. We can then review and comment on your code if necessary and merge it in. It will also get checked automatically by Travis Continuous Integration (you will see a message within the pull request showing the status of the Travis tests); hence why we prefer pull requests to other methods such as patch submissions. When writing code, please read the README.developer file which covers coding style, the code review process and various other guidelines. ola-0.10.5.nojsmin/java/0000755000175000017500000000000013155164170014404 5ustar wouterwouterola-0.10.5.nojsmin/java/Makefile.in0000644000175000017500000004016113134123354016447 0ustar wouterwouter# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 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@ # OLA Java client VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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 = : build_triplet = @build@ host_triplet = @host@ subdir = java ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/ac_prog_java_cc.m4 \ $(top_srcdir)/config/ac_pthread_set_name.m4 \ $(top_srcdir)/config/ac_saleae.m4 \ $(top_srcdir)/config/acx_pthread.m4 \ $(top_srcdir)/config/ax_have_epoll.m4 \ $(top_srcdir)/config/ax_prog_doxygen.m4 \ $(top_srcdir)/config/ax_python_module.m4 \ $(top_srcdir)/config/libtool.m4 \ $(top_srcdir)/config/ltoptions.m4 \ $(top_srcdir)/config/ltsugar.m4 \ $(top_srcdir)/config/ltversion.m4 \ $(top_srcdir)/config/lt~obsolete.m4 \ $(top_srcdir)/config/maven.m4 $(top_srcdir)/config/ola.m4 \ $(top_srcdir)/config/pkg.m4 $(top_srcdir)/config/resolv.m4 \ $(top_srcdir)/config/stl_hash.m4 \ $(top_srcdir)/config/ola_version.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = 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 DATA = $(noinst_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPUNIT1_CFLAGS = @CPPUNIT1_CFLAGS@ CPPUNIT1_LIBS = @CPPUNIT1_LIBS@ CPPUNIT2_CFLAGS = @CPPUNIT2_CFLAGS@ CPPUNIT2_LIBS = @CPPUNIT2_LIBS@ CPPUNIT_CFLAGS = @CPPUNIT_CFLAGS@ CPPUNIT_LIBS = @CPPUNIT_LIBS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOXYGEN_PAPER_SIZE = @DOXYGEN_PAPER_SIZE@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ DX_CONFIG = @DX_CONFIG@ DX_DOCDIR = @DX_DOCDIR@ DX_DOT = @DX_DOT@ DX_DOXYGEN = @DX_DOXYGEN@ DX_DVIPS = @DX_DVIPS@ DX_EGREP = @DX_EGREP@ DX_ENV = @DX_ENV@ DX_FLAG_chi = @DX_FLAG_chi@ DX_FLAG_chm = @DX_FLAG_chm@ DX_FLAG_doc = @DX_FLAG_doc@ DX_FLAG_dot = @DX_FLAG_dot@ DX_FLAG_html = @DX_FLAG_html@ DX_FLAG_man = @DX_FLAG_man@ DX_FLAG_pdf = @DX_FLAG_pdf@ DX_FLAG_ps = @DX_FLAG_ps@ DX_FLAG_rtf = @DX_FLAG_rtf@ DX_FLAG_verbose = @DX_FLAG_verbose@ DX_FLAG_xml = @DX_FLAG_xml@ DX_HHC = @DX_HHC@ DX_LATEX = @DX_LATEX@ DX_MAKEINDEX = @DX_MAKEINDEX@ DX_PDFLATEX = @DX_PDFLATEX@ DX_PERL = @DX_PERL@ DX_PROJECT = @DX_PROJECT@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCJ_OPTS = @GCJ_OPTS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_CC = @JAVA_CC@ JAVA_CC_FLAGS = @JAVA_CC_FLAGS@ JAVA_CC_OPTS = @JAVA_CC_OPTS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAVEN = @MAVEN@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OLA_CLIENT_LIBS = @OLA_CLIENT_LIBS@ OLA_MAJOR_VERSION = @OLA_MAJOR_VERSION@ OLA_MINOR_VERSION = @OLA_MINOR_VERSION@ OLA_PROTOC = @OLA_PROTOC@ OLA_REVISION_VERSION = @OLA_REVISION_VERSION@ OLA_SERVER_LIBS = @OLA_SERVER_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ 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_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PLUGIN_LIBS = @PLUGIN_LIBS@ PROTOC = @PROTOC@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_CXX = @PTHREAD_CXX@ PTHREAD_CXXFLAGS = @PTHREAD_CXXFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RESOLV_LIBS = @RESOLV_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_aux_dir = @ac_aux_dir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ avahi_CFLAGS = @avahi_CFLAGS@ avahi_LIBS = @avahi_LIBS@ base_uuid_CFLAGS = @base_uuid_CFLAGS@ base_uuid_LIBS = @base_uuid_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libSaleaeDevice_LIBS = @libSaleaeDevice_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ libftdi_CFLAGS = @libftdi_CFLAGS@ libftdi_LIBS = @libftdi_LIBS@ liblo_CFLAGS = @liblo_CFLAGS@ liblo_LIBS = @liblo_LIBS@ libmicrohttpd_CFLAGS = @libmicrohttpd_CFLAGS@ libmicrohttpd_LIBS = @libmicrohttpd_LIBS@ libprotobuf2_CFLAGS = @libprotobuf2_CFLAGS@ libprotobuf2_LIBS = @libprotobuf2_LIBS@ libprotobuf_CFLAGS = @libprotobuf_CFLAGS@ libprotobuf_LIBS = @libprotobuf_LIBS@ libusb_CFLAGS = @libusb_CFLAGS@ libusb_LIBS = @libusb_LIBS@ libusb_error_name_CFLAGS = @libusb_error_name_CFLAGS@ libusb_error_name_LIBS = @libusb_error_name_LIBS@ libusb_hotplug_api_CFLAGS = @libusb_hotplug_api_CFLAGS@ libusb_hotplug_api_LIBS = @libusb_hotplug_api_LIBS@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ ola_major_version = @ola_major_version@ ola_minor_version = @ola_minor_version@ ola_revision_version = @ola_revision_version@ oldincludedir = @oldincludedir@ ossp_uuid_CFLAGS = @ossp_uuid_CFLAGS@ ossp_uuid_LIBS = @ossp_uuid_LIBS@ pdfdir = @pdfdir@ piddatadir = @piddatadir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ 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@ uuid_CFLAGS = @uuid_CFLAGS@ uuid_LIBS = @uuid_LIBS@ www_datadir = @www_datadir@ EXTRA_DIST = pom.xml \ src/main/java/ola/OlaClient.java \ src/main/java/ola/rpc/SimpleRpcController.java \ src/main/java/ola/rpc/StreamRpcChannel.java \ src/test/java/ola/OlaClientTest.java CLEANFILES = src/main/java/ola/proto/Ola.java \ src/main/java/ola/rpc/Rpc.java # .jars aren't really data, but it sure ain't a program. @BUILD_JAVA_LIBS_TRUE@noinst_DATA = ola.jar 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 java/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu java/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): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs tags TAGS: ctags CTAGS: cscope cscopelist: 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: 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-generic clean-libtool 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 mostlyclean-libtool 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 clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool 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 mostlyclean-libtool pdf pdf-am ps ps-am \ tags-am uninstall uninstall-am .PRECIOUS: Makefile src/main/java/ola/proto/Ola.java: ${top_srcdir}/common/protocol/Ola.proto $(PROTOC) --java_out=src/main/java --proto_path=${top_srcdir}/common/protocol ${top_srcdir}/common/protocol/Ola.proto src/main/java/ola/rpc/Rpc.java: ${top_srcdir}/common/rpc/Rpc.proto $(PROTOC) --java_out=src/main/java --proto_path=${top_srcdir}/common/rpc ${top_srcdir}/common/rpc/Rpc.proto ola.jar: src/main/java/ola/proto/Ola.java src/main/java/ola/rpc/Rpc.java mvn package # 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: ola-0.10.5.nojsmin/java/src/0000755000175000017500000000000013134123611015163 5ustar wouterwouterola-0.10.5.nojsmin/java/src/main/0000755000175000017500000000000013155164170016117 5ustar wouterwouterola-0.10.5.nojsmin/java/src/main/java/0000755000175000017500000000000013134123611017030 5ustar wouterwouterola-0.10.5.nojsmin/java/src/main/java/ola/0000755000175000017500000000000013134123611017603 5ustar wouterwouterola-0.10.5.nojsmin/java/src/main/java/ola/rpc/0000755000175000017500000000000013134123611020367 5ustar wouterwouterola-0.10.5.nojsmin/java/src/main/java/ola/rpc/SimpleRpcController.java0000644000175000017500000000446513023355232025210 0ustar wouterwouter/*********************************************************************** * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing * permissions and limitations under the License. * *************************************************************************/ package ola.rpc; import com.google.protobuf.RpcCallback; import com.google.protobuf.RpcController; /** * Simple Rpc Controller implementation. */ public class SimpleRpcController implements RpcController { private boolean failed = false; private boolean cancelled = false; private String error = null; private RpcCallback callback = null; /* (non-Javadoc) * @see com.google.protobuf.RpcController#errorText() */ public String errorText() { return error; } /* (non-Javadoc) * @see com.google.protobuf.RpcController#failed() */ public boolean failed() { return failed; } /* (non-Javadoc) * @see com.google.protobuf.RpcController#isCanceled() */ public boolean isCanceled() { return cancelled; } /* (non-Javadoc) * @see com.google.protobuf.RpcController#notifyOnCancel(com.google.protobuf.RpcCallback) */ public void notifyOnCancel(RpcCallback notifyCallback) { callback = notifyCallback; } /* (non-Javadoc) * @see com.google.protobuf.RpcController#reset() */ public void reset() { failed = false; cancelled = false; error = null; callback = null; } /* (non-Javadoc) * @see com.google.protobuf.RpcController#setFailed(java.lang.String) */ public void setFailed(String reason) { failed = true; error = reason; } /* (non-Javadoc) * @see com.google.protobuf.RpcController#startCancel() */ public void startCancel() { cancelled = true; callback.run(null); } } ola-0.10.5.nojsmin/java/src/main/java/ola/rpc/StreamRpcChannel.java0000644000175000017500000001510213023355232024425 0ustar wouterwouter/*********************************************************************** * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing * permissions and limitations under the License. * *************************************************************************/ package ola.rpc; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.net.Socket; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.logging.Level; import java.util.logging.Logger; import ola.proto.Ola.STREAMING_NO_RESPONSE; import ola.rpc.Rpc.RpcMessage; import com.google.protobuf.Descriptors.MethodDescriptor; import com.google.protobuf.DynamicMessage; import com.google.protobuf.Message; import com.google.protobuf.RpcCallback; import com.google.protobuf.RpcChannel; import com.google.protobuf.RpcController; /** * Basic RPC Channel implementation. All calls are done * synchronously. * * The RPC Channel is hard coded to localhost 9010 where the * olad daemon is running. */ public class StreamRpcChannel implements RpcChannel { private static Logger logger = Logger.getLogger(StreamRpcChannel.class.getName()); public static final int PORT = 9010; public static final String HOST = "localhost"; private static final int PROTOCOL_VERSION = 1; private static final int VERSION_MASK = 0xf0000000; private static final int SIZE_MASK = 0x0fffffff; private Socket socket = null; private BufferedOutputStream bos; private BufferedInputStream bis; private int sequence = 0; /** * Create new Rpc Channel Connection to olad. * @throws Exception */ public StreamRpcChannel() throws Exception { connect(); } /** * Open connection to olad daemon. * * @throws Exception */ public void connect() throws Exception { if (socket != null && socket.isConnected()) { logger.warning("Socket already connected."); return; } try { socket = new Socket(HOST, PORT); bos = new BufferedOutputStream(socket.getOutputStream()); bis = new BufferedInputStream(socket.getInputStream()); } catch (Exception e) { logger.severe("Error connecting. Make sure the olad daemon is running on port 9010"); throw e; } } /** * Close Rpc Channel. */ public void close() { if (socket != null && socket.isConnected()) { try { socket.close(); } catch (Exception e) { logger.warning("Error closing socket. " + e.getMessage()); } } } /* (non-Javadoc) * @see com.google.protobuf.RpcChannel#callMethod(com.google.protobuf.Descriptors.MethodDescriptor, com.google.protobuf.RpcController, com.google.protobuf.Message, com.google.protobuf.Message, com.google.protobuf.RpcCallback) */ public void callMethod(MethodDescriptor method, RpcController controller, Message requestMessage, Message responseMessage, RpcCallback done) { int messageId = sequence++; RpcMessage message = RpcMessage.newBuilder() .setType(Rpc.Type.REQUEST) .setId(messageId) .setName(method.getName()) .setBuffer(requestMessage.toByteString()) .build(); try { sendMessage(message); if (responseMessage.getDescriptorForType().getName().equals("STREAMING_NO_RESPONSE")) { // don't wait for response on streaming messages.. return; } RpcMessage response = readMessage(); if (response.getType().equals(Rpc.Type.RESPONSE)) { if (response.getId() != messageId) { controller.setFailed("Received message with id " + response.getId() + " , but was expecting " + messageId); } else { responseMessage = DynamicMessage.parseFrom(responseMessage.getDescriptorForType(), response.getBuffer()); if (done != null) { done.run(responseMessage); } } } else { controller.setFailed("No valid response received !"); } } catch (Exception e) { logger.severe("Error sending rpc message: " + e.getMessage()); controller.setFailed(e.getMessage()); done.run(null); } } /** * Send rpc message to olad. * * @param msg RpcMessage * @throws Exception */ private void sendMessage(RpcMessage msg) throws Exception { byte[] data = msg.toByteArray(); int headerContent = (PROTOCOL_VERSION << 28) & VERSION_MASK; headerContent |= data.length & SIZE_MASK; byte[] header = ByteBuffer.allocate(4).order(ByteOrder.nativeOrder()).putInt(headerContent).array(); if (logger.isLoggable(Level.FINEST)) { logger.info("Sending header " + header.length + " bytes"); for (byte b : header) { System.out.format("0x%x ", b); } logger.info("Sending data " + data.length + " bytes"); for (byte b : data) { System.out.format("0x%x ", b); } } bos.write(header); bos.write(data); bos.flush(); } /** * @return RpcMessage read back from olad. * * @throws Exception */ private RpcMessage readMessage() throws Exception { byte[] header = new byte[4]; bis.read(header); int headerValue = ByteBuffer.wrap(header).order(ByteOrder.nativeOrder()).getInt(); int size = headerValue & SIZE_MASK; byte[] data = new byte[size]; bis.read(data); if (logger.isLoggable(Level.FINEST)) { logger.info("Received header "); for (byte b : header) { System.out.format("0x%x ", b); } logger.info("Received data "); for (byte b : data) { System.out.format("0x%x ", b); } } return RpcMessage.parseFrom(data); } } ola-0.10.5.nojsmin/java/src/main/java/ola/OlaClient.java0000644000175000017500000003107213023355232022326 0ustar wouterwouter/*********************************************************************** * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing * permissions and limitations under the License. * *************************************************************************/ package ola; import java.util.logging.Logger; import ola.proto.Ola.DeviceConfigReply; import ola.proto.Ola.DeviceConfigRequest; import ola.proto.Ola.DeviceInfoReply; import ola.proto.Ola.DeviceInfoRequest; import ola.proto.Ola.DiscoveryRequest; import ola.proto.Ola.DmxData; import ola.proto.Ola.MergeMode; import ola.proto.Ola.MergeModeRequest; import ola.proto.Ola.OlaServerService; import ola.proto.Ola.OptionalUniverseRequest; import ola.proto.Ola.PatchAction; import ola.proto.Ola.PatchPortRequest; import ola.proto.Ola.PluginDescriptionReply; import ola.proto.Ola.PluginDescriptionRequest; import ola.proto.Ola.PluginListReply; import ola.proto.Ola.PluginListRequest; import ola.proto.Ola.PortPriorityRequest; import ola.proto.Ola.RDMRequest; import ola.proto.Ola.RDMResponse; import ola.proto.Ola.RegisterAction; import ola.proto.Ola.RegisterDmxRequest; import ola.proto.Ola.TimeCode; import ola.proto.Ola.TimeCodeType; import ola.proto.Ola.UID; import ola.proto.Ola.UIDListReply; import ola.proto.Ola.UniverseInfoReply; import ola.proto.Ola.UniverseNameRequest; import ola.proto.Ola.UniverseRequest; import ola.rpc.SimpleRpcController; import ola.rpc.StreamRpcChannel; import com.google.protobuf.ByteString; import com.google.protobuf.Message; import com.google.protobuf.RpcCallback; import com.google.protobuf.RpcChannel; import com.google.protobuf.RpcController; public class OlaClient { private static Logger logger = Logger.getLogger(OlaClient.class.getName()); private OlaServerService serverService; private RpcController controller; private RpcChannel channel; public OlaClient() throws Exception { channel = new StreamRpcChannel(); controller = new SimpleRpcController(); serverService = OlaServerService.Stub.newStub(channel); } /** * Generic method for making Rpc Calls. * * @param method Name of te Rpc Method to call * @param inputMessage Input RpcMessage * @return Message result message or null if the call failed. */ private Message callRpcMethod(String method, Message inputMessage) { final Message[] outputMessage = new Message[1]; controller.reset(); RpcCallback cb = new RpcCallback() { public void run(Message arg0) { outputMessage[0] = arg0; } }; serverService.callMethod(serverService.getDescriptorForType().findMethodByName(method), controller, inputMessage, cb); if (controller.failed()) { logger.warning("RPC Call failed: " + controller.errorText()); return null; } return outputMessage[0]; } /** * Get a list of plugins from olad. * * @return The list of plugings. */ public PluginListReply getPlugins() { return (PluginListReply) callRpcMethod("GetPlugins", PluginListRequest.newBuilder().build()); } /** * Get a plugin description from olad. * * @param pluginId number of the plugin for which to receive the description * @return The list of plugings. */ public PluginDescriptionReply getPluginDescription(int pluginId) { PluginDescriptionRequest request = PluginDescriptionRequest.newBuilder() .setPluginId(pluginId) .build(); return (PluginDescriptionReply) callRpcMethod("GetPluginDescription", request); } /** * Get device info from olad. * * @return The Device Info. */ public DeviceInfoReply getDeviceInfo() { return (DeviceInfoReply) callRpcMethod("GetDeviceInfo", DeviceInfoRequest.newBuilder().build()); } /** * Get candidate ports for universe. * * @param universe the id of the universe. * @return device info */ public DeviceInfoReply getCandidatePorts(int universe) { OptionalUniverseRequest request = OptionalUniverseRequest.newBuilder().setUniverse(universe).build(); return (DeviceInfoReply) callRpcMethod("GetCandidatePorts", request); } /** * Configure device. * * @param device the id of the device to configure. * @param data device configuration data. * @return */ public DeviceConfigReply configureDevice(int device, short[] data) { DeviceConfigRequest request = DeviceConfigRequest.newBuilder() .setDeviceAlias(device) .setData(convertToUnsigned(data)) .build(); return (DeviceConfigReply) callRpcMethod("ConfigureDevice", request); } /** * Get universe information. * * @param universe the id of the universe * @return UniverseInfo */ public UniverseInfoReply getUniverseInfo(int universe) { OptionalUniverseRequest request = OptionalUniverseRequest.newBuilder().setUniverse(universe).build(); return (UniverseInfoReply) callRpcMethod("GetUniverseInfo", request); } /** * Get UID's. * * @param universe the id of the universe * @return UIDListReply */ public UIDListReply getUIDs(int universe) { UniverseRequest request = UniverseRequest.newBuilder().setUniverse(universe).build(); return (UIDListReply) callRpcMethod("GetUIDs", request); } /** * Force discovery of a universe. * * @param universe the id of the universe * @param full * @return UID List */ public UIDListReply forceDiscovery(int universe, boolean full) { DiscoveryRequest request = DiscoveryRequest.newBuilder() .setUniverse(universe) .setFull(full) .build(); return (UIDListReply) callRpcMethod("ForceDiscovery", request); } /** * Retrieve dmx data from universe. * @param universe the id of the universe * @return */ public DmxData getDmx(int universe) { return (DmxData) callRpcMethod("GetDmx", UniverseRequest.newBuilder().setUniverse(universe).build()); } /** * Patch a port. * * @param device number * @param port number * @param action PachAction.PATCH or PatchAction.UNPATCH * @param universe number * @return true when succeeded. */ public boolean patchPort(int device, int port, PatchAction action, int universe) { PatchPortRequest patchRequest = PatchPortRequest.newBuilder() .setPortId(port) .setAction(action) .setDeviceAlias(device) .setUniverse(universe) .setIsOutput(true) .build(); return callRpcMethod("PatchPort", patchRequest) != null; } /** * Send dmx data to olad. * * @param universe number * @param values array of dmx data values * @return true when succeeded. */ public boolean sendDmx(int universe, short[] values) { DmxData dmxData = DmxData.newBuilder() .setUniverse(universe) .setData(convertToUnsigned(values)) .build(); return callRpcMethod("UpdateDmxData", dmxData) != null; } /** * Set port priority. * * @return true if request succeeded. */ public boolean setPortPriority(int device, int port, int priority, int mode, boolean output) { PortPriorityRequest request = PortPriorityRequest.newBuilder() .setDeviceAlias(device) .setPortId(port) .setPriority(priority) .setPriorityMode(mode) .setIsOutput(output) .build(); return callRpcMethod("SetPortPriority", request) != null; } /** * Set universe name. * * @param universe id of universe for which to set the name. * @param name The name to set. * @return true if the call succeeded. */ public boolean setUniverseName(int universe, String name) { UniverseNameRequest request = UniverseNameRequest.newBuilder() .setUniverse(universe) .setName(name) .build(); return callRpcMethod("SetUniverseName", request) != null; } /** * Define merge mode for a universe. * * @param universe The id of the universe * @param mode, merge mode to use * @return true if call succeeded. */ public boolean setMergeMode(int universe, MergeMode mode) { MergeModeRequest request = MergeModeRequest.newBuilder() .setUniverse(universe) .setMergeMode(mode) .build(); return callRpcMethod("SetMergeMode", request) != null; } /** * Register for dmx * @param universe * @param action RegisterAction * @return true if call succeeded. */ public boolean registerForDmx(int universe, RegisterAction action) { RegisterDmxRequest request = RegisterDmxRequest.newBuilder() .setUniverse(universe) .setAction(action) .build(); return callRpcMethod("RegisterForDmx", request) != null; } /** * Set source UID for device. * @param device The id of the device * @param estaId the UID to set. * @return true if call succeeded. */ public boolean setSourceUID(int device, int estaId) { UID request = UID.newBuilder() .setDeviceId(device) .setEstaId(estaId) .build(); return callRpcMethod("SetSourceUID", request) != null; } /** * Send TimeCode. * * @param type TimeCodeType * @param frames number of frames * @param hours * @param minutes * @param seconds * @return true if call succeeded. */ public boolean sendTimeCode(TimeCodeType type, int frames, int hours, int minutes, int seconds) { TimeCode request = TimeCode.newBuilder() .setFrames(frames) .setHours(hours) .setMinutes(minutes) .setSeconds(seconds) .setType(type) .build(); return callRpcMethod("SendTimeCode", request) != null; } /** * Send RDM Command. * * @param uid * @param subDevice * @param paramId * @param isSet * @param includeRawResponse * @param universe * @param data * @return RDMResponse */ public RDMResponse sendRDMCommand(UID uid, int subDevice, int paramId, boolean isSet, boolean includeRawResponse, int universe, short[] data) { RDMRequest request = RDMRequest.newBuilder() .setUid(uid) .setSubDevice(subDevice) .setParamId(paramId) .setIsSet(isSet) .setIncludeRawResponse(includeRawResponse) .setUniverse(universe) .setData(convertToUnsigned(data)) .build(); return (RDMResponse) callRpcMethod("RDMCommand", request); } /** * Send dmx data, but don't wait for response. * * @param universe the id of the universe * @param values dmx data */ public void streamDmx(int universe, short[] values) { DmxData dmxData = DmxData.newBuilder() .setUniverse(universe) .setData(convertToUnsigned(values)) .build(); callRpcMethod("StreamDmxData", dmxData); } /** * Convert short array to bytestring */ public ByteString convertToUnsigned(short[] values) { byte[] unsigned = new byte[values.length]; for (int i = 0; i < values.length; i++) { unsigned[i] = (byte) values[i]; } return ByteString.copyFrom(unsigned); } /** * Convert bytestring to short array. */ public short[] convertFromUnsigned(ByteString data) { byte[] values = data.toByteArray(); short[] signed = new short[values.length]; for (int i = 0; i < values.length; i++) { signed[i] = (short) ((short) values[i] & 0xFF); } return signed; } } ola-0.10.5.nojsmin/java/src/test/0000755000175000017500000000000013134123611016142 5ustar wouterwouterola-0.10.5.nojsmin/java/src/test/java/0000755000175000017500000000000013134123611017063 5ustar wouterwouterola-0.10.5.nojsmin/java/src/test/java/ola/0000755000175000017500000000000013134123611017636 5ustar wouterwouterola-0.10.5.nojsmin/java/src/test/java/ola/OlaClientTest.java0000644000175000017500000001204613023355232023221 0ustar wouterwouterpackage ola; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import ola.proto.Ola.DeviceConfigReply; import ola.proto.Ola.DeviceInfoReply; import ola.proto.Ola.DmxData; import ola.proto.Ola.MergeMode; import ola.proto.Ola.PatchAction; import ola.proto.Ola.PluginDescriptionReply; import ola.proto.Ola.PluginListReply; import ola.proto.Ola.RDMResponse; import ola.proto.Ola.RegisterAction; import ola.proto.Ola.TimeCodeType; import ola.proto.Ola.UID; import ola.proto.Ola.UIDListReply; import ola.proto.Ola.UniverseInfoReply; import org.junit.Before; import org.junit.Test; /** * Test interaction with ola daemon. * Assumes that an ola daemon is running. */ public class OlaClientTest { private OlaClient client; @Before public void setup() throws Exception { if (client == null) { client = new OlaClient(); } } @Test public void testGetPlugins() { PluginListReply reply = client.getPlugins(); assertNotNull(reply); System.out.println(reply); } @Test public void testGetPluginDescription() { PluginDescriptionReply reply = client.getPluginDescription(1); assertNotNull(reply); System.out.println(reply); } @Test public void testGetDeviceInfo() { DeviceInfoReply reply = client.getDeviceInfo(); assertNotNull(reply); System.out.println(reply); } @Test public void testGetCandidatePorts() { DeviceInfoReply reply = client.getCandidatePorts(0); assertNotNull(reply); System.out.println(reply); } @Test public void testConfigureDevice() { DeviceConfigReply reply = client.configureDevice(2, new short[] {200,200,200}); // TODO verify result.. System.out.println(reply); } @Test public void testGetUniverseInfo() { UniverseInfoReply reply = client.getUniverseInfo(0); assertNotNull(reply); System.out.println(reply); } @Test public void testGetUIDs() { UIDListReply reply = client.getUIDs(0); assertNotNull(reply); System.out.println(reply); } @Test public void testForceDiscovery() { UIDListReply reply = client.forceDiscovery(0, true); assertNotNull(reply); System.out.println(reply); } @Test public void testGetDmx() { client.sendDmx(0, new short[] {45,12,244}); DmxData reply = client.getDmx(0); short[] state = client.convertFromUnsigned(reply.getData()); assertEquals(45, state[0]); assertEquals(12, state[1]); assertEquals(244, state[2]); System.out.println(reply); } @Test public void testPatchPort() { assertTrue(client.patchPort(1, 0, PatchAction.PATCH, 0)); } @Test public void testSendDmx() { assertTrue(client.sendDmx(0, new short[] {10,23,244})); } @Test public void testSetPortPriority() { assertTrue(client.setPortPriority(1, 0, 0 ,0, true)); } @Test public void testSetUniverseName() { client.setUniverseName(0, "outerspace"); UniverseInfoReply reply = client.getUniverseInfo(0); assertEquals(reply.getUniverse(0).getName(), "outerspace"); } @Test public void testSetMergeMode() { assertTrue(client.setMergeMode(0, MergeMode.HTP)); } @Test public void testRegisterForDmx() { assertTrue(client.registerForDmx(0, RegisterAction.REGISTER)); } @Test public void testSetSourceUID() { assertTrue(client.setSourceUID(1, 5)); } @Test public void testSendTimeCode() { assertTrue(client.sendTimeCode(TimeCodeType.TIMECODE_DF, 10, 1, 1, 1)); } @Test public void testSendRDMCommand() { UID id = UID.newBuilder() .setDeviceId(1) .setEstaId(9) .build(); RDMResponse reply = client.sendRDMCommand(id, 0, 0, false, false, 0, new short[] {1,2,3}); assertNotNull(reply); System.out.println(reply); } @Test public void testStreamDmx() { client.sendDmx(0, new short[] {9, 9, 9, 9}); client.streamDmx(0, new short[] {14, 33, 55, 99}); assertTrue(client.sendDmx(0, new short[] {9, 9, 9, 9})); } @Test public void testSendDmxRepetitive() throws Exception { OlaClient client = new OlaClient(); for (int i = 0; i < 20; i++) { client.sendDmx(0, new short[] {135, 0, 0}); Thread.currentThread().sleep(50); client.sendDmx(0, new short[] {135, 0, 135}); Thread.currentThread().sleep(50); } for (short i = 0; i < 25; i+=3) { client.sendDmx(0, new short[] {i, 0, 0}); } for (short i = 0; i < 25; i+=3) { client.sendDmx(0, new short[] {255, i, 0}); } for (short i = 0; i < 25; i+=3) { client.sendDmx(0, new short[] {255, 255, i}); } client.sendDmx(0, new short[] {0, 0, 0}); } } ola-0.10.5.nojsmin/java/Makefile.am0000644000175000017500000000162513023355232016437 0ustar wouterwouter# OLA Java client EXTRA_DIST = pom.xml \ src/main/java/ola/OlaClient.java \ src/main/java/ola/rpc/SimpleRpcController.java \ src/main/java/ola/rpc/StreamRpcChannel.java \ src/test/java/ola/OlaClientTest.java src/main/java/ola/proto/Ola.java: ${top_srcdir}/common/protocol/Ola.proto $(PROTOC) --java_out=src/main/java --proto_path=${top_srcdir}/common/protocol ${top_srcdir}/common/protocol/Ola.proto src/main/java/ola/rpc/Rpc.java: ${top_srcdir}/common/rpc/Rpc.proto $(PROTOC) --java_out=src/main/java --proto_path=${top_srcdir}/common/rpc ${top_srcdir}/common/rpc/Rpc.proto ola.jar: src/main/java/ola/proto/Ola.java src/main/java/ola/rpc/Rpc.java mvn package CLEANFILES = src/main/java/ola/proto/Ola.java \ src/main/java/ola/rpc/Rpc.java if BUILD_JAVA_LIBS # .jars aren't really data, but it sure ain't a program. noinst_DATA = ola.jar endif ola-0.10.5.nojsmin/java/pom.xml0000644000175000017500000000256213023355232015721 0ustar wouterwouter 4.0.0 ola ola-java-client 0.0.1 Java implementation of OLA RPC org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.5 1.5 org.apache.maven.plugins maven-surefire-plugin 2.12 **/OlaClientTest.java com.google.protobuf protobuf-java 2.6.1 junit junit 4.8.2 test ola-0.10.5.nojsmin/javascript/0000755000175000017500000000000013155164170015631 5ustar wouterwouterola-0.10.5.nojsmin/javascript/Makefile.mk0000644000175000017500000000533113023355232017674 0ustar wouterwouterEXTRA_DIST += \ javascript/README \ javascript/new-src/.jscsrc \ javascript/new-src/.jshintrc \ javascript/new-src/Gruntfile.js \ javascript/new-src/README.md \ javascript/new-src/bower.json \ javascript/new-src/package.json \ javascript/new-src/css/style.css \ javascript/new-src/src/controllers/menu.js \ javascript/new-src/src/controllers/patch_universe.js \ javascript/new-src/src/controllers/rdm_universe.js \ javascript/new-src/src/controllers/universe.js \ javascript/new-src/src/controllers/fader_universe.js \ javascript/new-src/src/controllers/keypad_universe.js \ javascript/new-src/src/controllers/plugins.js \ javascript/new-src/src/controllers/add_universe.js \ javascript/new-src/src/controllers/plugin_info.js \ javascript/new-src/src/controllers/setting_universe.js \ javascript/new-src/src/controllers/header.js \ javascript/new-src/src/controllers/overview.js \ javascript/new-src/src/constants.js \ javascript/new-src/src/factories/ola.js \ javascript/new-src/src/app.js \ javascript/new-src/src/filters/start_form.js \ javascript/ola/base_frame.js \ javascript/ola/common/dmx_constants.js \ javascript/ola/common/dmx_monitor.js \ javascript/ola/common/keypad_controller.js \ javascript/ola/common/keypad_parser.js \ javascript/ola/common/plugin_list.js \ javascript/ola/common/rdm_section_list.js \ javascript/ola/common/section_render.js \ javascript/ola/common/server.js \ javascript/ola/common/server_stats.js \ javascript/ola/common/sorted_list.js \ javascript/ola/common/uid_list.js \ javascript/ola/dialog.js \ javascript/ola/full/available_port_table.js \ javascript/ola/full/base_universe_tab.js \ javascript/ola/full/custom_dragger.js \ javascript/ola/full/custom_dragscrollsupport.js \ javascript/ola/full/dmx_console.js \ javascript/ola/full/dmx_console_tab.js \ javascript/ola/full/dmx_monitor_tab.js \ javascript/ola/full/plugin_frame.js \ javascript/ola/full/rdm_attributes_panel.js \ javascript/ola/full/rdm_patcher.js \ javascript/ola/full/rdm_patcher_tab.js \ javascript/ola/full/rdm_tab.js \ javascript/ola/full/universe_frame.js \ javascript/ola/full/universe_settings_tab.js \ javascript/ola/home_frame.js \ javascript/ola/logger.js \ javascript/ola/mobile.js \ javascript/ola/mobile/controller_tab.js \ javascript/ola/mobile/monitor_tab.js \ javascript/ola/mobile/plugin_tab.js \ javascript/ola/mobile/universe_tab.js \ javascript/ola/new_universe_frame.js \ javascript/ola/ola.js \ javascript/ola/port_table.js \ javascript/ola/universe_control.js \ javascript/ola/universe_item.js ola-0.10.5.nojsmin/javascript/ola/0000755000175000017500000000000013155164170016404 5ustar wouterwouterola-0.10.5.nojsmin/javascript/ola/common/0000755000175000017500000000000013155164170017674 5ustar wouterwouterola-0.10.5.nojsmin/javascript/ola/common/server.js0000644000175000017500000005611413023355232021542 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * A class that handles interactions with the ola server. * Copyright (C) 2010 Simon Newton */ goog.require('goog.dom'); goog.require('goog.events'); goog.require('goog.net.HttpStatus'); goog.require('goog.net.XhrIoPool'); goog.provide('ola.common.Server'); goog.provide('ola.common.Server.EventType'); /** * A pending request. * @constructor * @param {string} url the URL to fetch. * @param {function()} callback the function to run when the request completes. * @param {string=} opt_method 'GET' or 'POST'. * @param {string=} opt_content The post form data. */ ola.common.Request = function(url, callback, opt_method, opt_content) { this.url = url; this.callback = callback; this.opt_method = opt_method; this.opt_content = opt_content; }; /** * Create a new Server object, this is used to communicate with the OLA server * and fires events when the state changes. * @constructor */ ola.common.Server = function() { goog.events.EventTarget.call(this); this.pool = new goog.net.XhrIoPool({}, 1); this.universes = {}; this.request_queue = new Array(); }; goog.inherits(ola.common.Server, goog.events.EventTarget); // This is a singleton, call ola.common.Server.getInstance() to access it. goog.addSingletonGetter(ola.common.Server); /** * Events for the Server object. * @type {Object} */ ola.common.Server.EventType = { PLUGIN_EVENT: 'plugin_change', PLUGIN_LIST_EVENT: 'plugin_list_change', SERVER_INFO_EVENT: 'server_info_change', UNIVERSE_EVENT: 'universe_change', UNIVERSE_LIST_EVENT: 'universe_list_change' }; /** * The url for the server stats * @type {string} */ ola.common.Server.SERVER_INFO_URL = 'json/server_stats'; /** * The url for the plugin info * @type {string} */ ola.common.Server.PLUGIN_INFO_URL = 'json/plugin_info'; /** * The url for the universe info. * @type {string} */ ola.common.Server.UNIVERSE_INFO_URL = 'json/universe_info'; /** * The url to fetch the list of universes. * @type {string} */ ola.common.Server.PLUGIN_UNIVERSE_LIST_URL = 'json/universe_plugin_list'; /** * The url to reload the server * @type {string} */ ola.common.Server.RELOAD_PLUGINS_URL = 'reload'; /** * The url to stop the server. * @type {string} */ ola.common.Server.STOP_SERVER_URL = 'quit'; /** * The url for the universe info. * @type {string} */ ola.common.Server.AVAILBLE_PORTS_URL = 'json/get_ports'; /** * The url to fetch the list of UIDs. * @type {string} */ ola.common.Server.UIDS_URL = 'json/rdm/uids'; /** * The url to trigger discovery. * @type {string} */ ola.common.Server.RDM_DISCOVERY_URL = 'rdm/run_discovery'; /** * The url to fetch the RDM sections. * @type {string} */ ola.common.Server.RDM_SECTIONS_URL = 'json/rdm/supported_sections'; /** * The url to fetch the contents of a section. * @type {string} */ ola.common.Server.RDM_GET_SECTION_INFO_URL = 'json/rdm/section_info'; /** * The url to set the RDM settings. * @type {string} */ ola.common.Server.RDM_SET_SECTION_INFO_URL = 'json/rdm/set_section_info'; /** * The url to toggle RDM identify mode. * @type {string} */ ola.common.Server.RDM_UID_IDENTIFY = 'json/rdm/uid_identify'; /** * The url to fetch information about a RDM UID (responder). * @type {string} */ ola.common.Server.RDM_UID_INFO = 'json/rdm/uid_info'; /** * The url to change the personality of a responder * @type {string} */ ola.common.Server.RDM_UID_PERSONALITY = 'json/rdm/uid_personalities'; /** * The url to create a new universe. * @type {string} */ ola.common.Server.NEW_UNIVERSE_URL = 'new_universe'; /** * The url to change the settings of a universe. * @type {string} */ ola.common.Server.MODIFY_UNIVERSE_URL = 'modify_universe'; /** * The url to set the DMX values. * @type {string} */ ola.common.Server.SET_DMX_URL = 'set_dmx'; /** * The url to return the current DMX values * @type {string} */ ola.common.Server.GET_DMX_URL = 'get_dmx'; /** * The request queue size. * This should be more than the max # of RDM sections we ever expect * @type {number} */ ola.common.Server.REQUEST_QUEUE_LIMIT = 30; /** * This event is fired when the server info changes * @constructor * @param {Object} server_info the server info. */ ola.common.ServerInfoChangeEvent = function(server_info) { goog.events.Event.call(this, ola.common.Server.EventType.SERVER_INFO_EVENT); this.server_info = server_info; }; goog.inherits(ola.common.ServerInfoChangeEvent, goog.events.Event); /** * This event is fired when the plugin list changes * @constructor * @param {Array.} new_list the list of Plugin objects. */ ola.PluginListChangeEvent = function(new_list) { goog.events.Event.call(this, ola.common.Server.EventType.PLUGIN_LIST_EVENT); this.plugins = new_list; }; goog.inherits(ola.PluginListChangeEvent, goog.events.Event); /** * This event is fired when the universe list changes * @constructor * @param {Array.} new_list the list of Universe objects. */ ola.UniverseListChangeEvent = function(new_list) { goog.events.Event.call(this, ola.common.Server.EventType.UNIVERSE_LIST_EVENT); this.universes = new_list; }; goog.inherits(ola.PluginListChangeEvent, goog.events.Event); /** * This event is fired when the plugin info is available * @constructor * @param {Object} plugin the new Plugin object. */ ola.PluginChangeEvent = function(plugin) { goog.events.Event.call(this, ola.common.Server.EventType.PLUGIN_EVENT); this.plugin = plugin; }; goog.inherits(ola.PluginChangeEvent, goog.events.Event); /** * This event is fired when the universe info is available * @constructor * @param {Object} universe the Universe object. */ ola.UniverseChangeEvent = function(universe) { goog.events.Event.call(this, ola.common.Server.EventType.UNIVERSE_EVENT); this.universe = universe; }; goog.inherits(ola.UniverseChangeEvent, goog.events.Event); /** * Check if this universe is active * @param {number} universe_id the ID of the universe to check. * @return {boolean} true if the universe exists, false otherwise. */ ola.common.Server.prototype.CheckIfUniverseExists = function(universe_id) { return this.universes[universe_id] != undefined; }; /** * Update the server info data */ ola.common.Server.prototype.UpdateServerInfo = function() { var on_complete = function(e) { var obj = e.target.getResponseJson(); this.dispatchEvent(new ola.common.ServerInfoChangeEvent(obj)); }; this.initiateRequest_(ola.common.Server.SERVER_INFO_URL, on_complete); }; /** * Reload the plugins * @param {function(Object)} callback the function to call when the request * completes. */ ola.common.Server.prototype.reloadPlugins = function(callback) { this.initiateRequest_(ola.common.Server.RELOAD_PLUGINS_URL, callback); }; /** * Stop the server * @param {function(Object)} callback the function to call when the request * completes. */ ola.common.Server.prototype.stopServer = function(callback) { this.initiateRequest_(ola.common.Server.STOP_SERVER_URL, callback); }; /** * Fetch the list of plugins & universes active on the server */ ola.common.Server.prototype.FetchUniversePluginList = function() { var on_complete = function(e) { if (e.target.getStatus() != goog.net.HttpStatus.OK) { ola.logger.info('Request failed: ' + e.target.getLastUri() + ' : ' + e.target.getLastError()); return; } var obj = e.target.getResponseJson(); // update the internal list of universes here this.universes = {}; for (var i = 0; i < obj['universes'].length; ++i) { this.universes[obj['universes'][i]['id']] = true; } this.dispatchEvent(new ola.PluginListChangeEvent(obj['plugins'])); this.dispatchEvent(new ola.UniverseListChangeEvent(obj['universes'])); }; this.initiateRequest_(ola.common.Server.PLUGIN_UNIVERSE_LIST_URL, on_complete); }; /** * Fetch the info for a plugin * @param {number} plugin_id the id of the plugin to fetch. */ ola.common.Server.prototype.FetchPluginInfo = function(plugin_id) { var on_complete = function(e) { var obj = e.target.getResponseJson(); this.dispatchEvent(new ola.PluginChangeEvent(obj)); }; var url = ola.common.Server.PLUGIN_INFO_URL + '?id=' + plugin_id; this.initiateRequest_(url, on_complete); }; /** * Fetch the info for a universe * @param {number} universe_id the id of the universe to fetch. */ ola.common.Server.prototype.FetchUniverseInfo = function(universe_id) { var on_complete = function(e) { var obj = e.target.getResponseJson(); this.dispatchEvent(new ola.UniverseChangeEvent(obj)); }; var url = ola.common.Server.UNIVERSE_INFO_URL + '?id=' + universe_id; this.initiateRequest_(url, on_complete); }; /** * Fetch the available ports. * @param {number=} opt_universe an optional universe id. * @param {function()} callback the callback to invoke when complete. */ ola.common.Server.prototype.fetchAvailablePorts = function(opt_universe, callback) { var url = ola.common.Server.AVAILBLE_PORTS_URL; if (opt_universe != undefined) { url += '?id=' + opt_universe; } this.initiateRequest_(url, callback); }; /** * Create a new universe * @param {number} universe_id the ID of the universe. * @param {string} name the new universe name. * @param {Array.} port_ids a list of ports to patch to this universe. * @param {function(Object)} callback the function to call when the request * completes. */ ola.common.Server.prototype.createUniverse = function(universe_id, name, port_ids, callback) { var post_data = 'id=' + universe_id + ( name ? '&name=' + encodeURI(name) : '') + '&add_ports=' + port_ids.join(','); this.initiateRequest_(ola.common.Server.NEW_UNIVERSE_URL, callback, 'POST', post_data); }; /** * Trigger RDM discovery for this universe. This returns when discovery * completes. * @param {number} universe_id the ID of the universe to run discovery for. * @param {boolean} full true if we should do full discovery, false for * incremental. * @param {function(Object)} callback the function to call when the discovery * request is ack'ed. */ ola.common.Server.prototype.runRDMDiscovery = function(universe_id, full, callback) { var url = ola.common.Server.RDM_DISCOVERY_URL + '?id=' + universe_id; if (!full) { url += '&incremental=true'; } this.initiateRequest_(url, callback); }; /** * Get the list of supported sections for a UID. * @param {number} universe_id the ID of the universe. * @param {string} uid the string representation of a UID. * @param {function(Object)} callback the function to call when the discovery * request is ack'ed. */ ola.common.Server.prototype.rdmGetSupportedSections = function(universe_id, uid, callback) { var url = (ola.common.Server.RDM_SECTIONS_URL + '?id=' + universe_id + '&uid=' + uid); this.initiateRequest_(url, callback); }; /** * Get the details for a particular rdm section * @param {number} universe_id the ID of the universe. * @param {string} uid the string representation of a UID. * @param {string} section_name the section to get. * @param {string} hint an arbitary string passed back to the server. * @param {function(Object)} callback the function to call when the discovery * request is ack'ed. */ ola.common.Server.prototype.rdmGetSectionInfo = function(universe_id, uid, section_name, hint, callback) { var url = (ola.common.Server.RDM_GET_SECTION_INFO_URL + '?id=' + universe_id + '&uid=' + uid + '§ion=' + section_name + '&hint=' + hint); this.initiateRequest_(url, callback); }; /** * Get the details for a particular rdm section * @param {number} universe_id the ID of the universe. * @param {string} uid the string representation of a UID. * @param {string} section_name the section to get. * @param {string} hint a cookie to pass back to the server. * @param {data} data passed back to the server. * @param {function(Object)} callback the function to call when the discovery * request is ack'ed. */ ola.common.Server.prototype.rdmSetSectionInfo = function(universe_id, uid, section_name, hint, data, callback) { var url = (ola.common.Server.RDM_SET_SECTION_INFO_URL + '?id=' + universe_id + '&uid=' + uid + '§ion=' + section_name + '&hint=' + hint + '&' + data); this.initiateRequest_(url, callback); }; /** * Fetch the uids for a universe * @param {number} universe_id the ID of the universe. * @param {function(Object)} callback the function to call when the request * completes. */ ola.common.Server.prototype.fetchUids = function(universe_id, callback) { var url = ola.common.Server.UIDS_URL + '?id=' + universe_id; this.initiateRequest_(url, callback); }; /** * Fetch the dmx start address, footprint & personality for a uid. * @param {number} universe_id the ID of the universe. * @param {string} uid the string representation of a UID. * @param {function(Object)} callback the function to call when the request * completes. */ ola.common.Server.prototype.rdmGetUIDInfo = function(universe_id, uid, callback) { var url = (ola.common.Server.RDM_UID_INFO + '?id=' + universe_id + '&uid=' + uid); this.initiateRequest_(url, callback); }; /** * Check if a device is in identify mode. * @param {number} universe_id the ID of the universe. * @param {string} uid the string representation of a UID. * @param {function(Object)} callback the function to call when the request * completes. */ ola.common.Server.prototype.rdmGetUIDIdentifyMode = function(universe_id, uid, callback) { var url = (ola.common.Server.RDM_UID_IDENTIFY + '?id=' + universe_id + '&uid=' + uid); this.initiateRequest_(url, callback); }; /** * Fetch the personalities for a device * @param {number} universe_id the ID of the universe. * @param {string} uid the string representation of a UID. * @param {function(Object)} callback the function to call when the request * completes. */ ola.common.Server.prototype.rdmGetUIDPersonalities = function(universe_id, uid, callback) { var url = (ola.common.Server.RDM_UID_PERSONALITY + '?id=' + universe_id + '&uid=' + uid); this.initiateRequest_(url, callback); }; /** * Update the settings for a universe. * @param {number} universe_id the id of the universe to modify. * @param {string} universe_name the new name. * @param {string} merge_mode HTP or LTP. * @param {Array.<{{id: string, mode: string, priority: number}}>} * port_priorities an array of new port priorities. * @param {Array.} ports_to_remove list of port ids to remove. * @param {Array.} ports_to_add list of port ids to add. * @param {function()} callback the callback to invoke when complete. */ ola.common.Server.prototype.modifyUniverse = function(universe_id, universe_name, merge_mode, port_priorities, ports_to_remove, ports_to_add, callback) { var post_data = ('id=' + universe_id + '&name=' + universe_name + '&merge_mode=' + merge_mode + '&add_ports=' + ports_to_add.join(',') + '&remove_ports=' + ports_to_remove.join(',')); modified_port_ids = new Array(); for (var i = 0; i < port_priorities.length; ++i) { var priority_setting = port_priorities[i]; post_data += ('&' + priority_setting.id + '_priority_value=' + priority_setting.priority); if (priority_setting.mode != undefined) { post_data += ('&' + priority_setting.id + '_priority_mode=' + priority_setting.mode); } modified_port_ids.push(priority_setting.id); } post_data += ('&modify_ports=' + modified_port_ids.join(',')); var url = ola.common.Server.MODIFY_UNIVERSE_URL; this.initiateRequest_(url, callback, 'POST', post_data); }; /** * Get the dmx values for a universe * @param {number} universe_id the id of the universe to get values for. * @param {function(e)} callback the callback to invoke when complete. */ ola.common.Server.prototype.getChannelValues = function(universe_id, callback) { var url = ola.common.Server.GET_DMX_URL + '?u=' + universe_id; this.initiateRequest_( url, function(e) { callback(e.target.getResponseJson()); }); }; /** * Update the dmx values for a universe * @param {number} universe_id the id of the universe to modify. * @param {Array.} data the channel values. * @param {function(e)} callback the callback to invoke when complete. */ ola.common.Server.prototype.setChannelValues = function(universe_id, data, callback) { var post_data = 'u=' + universe_id + '&d=' + data.join(','); var url = ola.common.Server.SET_DMX_URL; this.initiateRequest_( url, function(e) { callback(e.target); }, 'POST', post_data); }; /** * Check if a request completed properly and if not, show a dialog. * This checks just the HTTP code. * @param {Object} e the event object. * @return {boolean} true if ok, false otherwise. */ ola.common.Server.prototype.checkStatusDialog = function(e) { if (e.target.getStatus() != goog.net.HttpStatus.OK) { this.showErrorDialog_(e.target.getLastUri() + ' : ' + e.target.getLastError()); return false; } return true; }; /** * Check if a request completed properly and if not, show a dialog. * This checks both the HTTP code, and the existance of the 'error' property in * the response. * @param {Object} e the event object. * @return {object} The JSON output, or undefined if an error occured. */ ola.common.Server.prototype.checkForErrorDialog = function(e) { if (e.target.getStatus() == goog.net.HttpStatus.OK) { var response = e.target.getResponseJson(); if (response['error']) { this.showErrorDialog_(response['error']); return undefined; } return response; } else { this.showErrorDialog_(e.target.getLastUri() + ' : ' + e.target.getLastError()); return undefined; } }; /** * Check if a request completed properly and if not log the error * This checks both the HTTP code, and the existance of the 'error' property in * the response. * @param {Object} e the event object. * @return {object} The JSON output, or undefined if an error occured. */ ola.common.Server.prototype.checkForErrorLog = function(e) { if (e.target.getStatus() == goog.net.HttpStatus.OK) { var response = e.target.getResponseJson(); if (response['error']) { ola.logger.info(response['error']); return undefined; } return response; } else { ola.logger.info(e.target.getLastUri() + ' : ' + e.target.getLastError()); return undefined; } }; /** * Show the error dialog * @param {string} message the error message. * @private */ ola.common.Server.prototype.showErrorDialog_ = function(message) { var dialog = ola.Dialog.getInstance(); dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK); dialog.setTitle('Request Failed'); dialog.setContent(message); dialog.setVisible(true); }; /** * Initiate a JSON request * @param {string} url the url to fetch. * @param {function()} callback the callback to invoke when the request * completes. * @param {string=} opt_method 'GET' or 'POST'. * @param {string=} opt_content The post form data. * @private */ ola.common.Server.prototype.initiateRequest_ = function(url, callback, opt_method, opt_content) { if (this.request_queue.length >= ola.common.Server.REQUEST_QUEUE_LIMIT) { var dialog = ola.Dialog.getInstance(); dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK); dialog.setTitle('Failed to Communicate with Server'); dialog.setContent( 'The request pool was empty, the server is probably down.'); dialog.setVisible(true); return; } var request = new ola.common.Request(url, callback, opt_method, opt_content); this.request_queue.push(request); var t = this; this.pool.getObject( function(xhr) { if (!t.request_queue.length) return; var r = t.request_queue.shift(); if (r.callback) goog.events.listen(xhr, goog.net.EventType.COMPLETE, r.callback, false, t); goog.events.listen(xhr, goog.net.EventType.READY, t.cleanupRequest_, false, t); xhr.send(r.url, r.opt_method, r.opt_content); }, 1); }; /** * Clean up from a request, this removes the listener and returns the channel * to the pool. * @param {Object} e the event object. * @private */ ola.common.Server.prototype.cleanupRequest_ = function(e) { var xhr = e.target; goog.events.removeAll(xhr); this.pool.releaseObject(xhr); }; ola-0.10.5.nojsmin/javascript/ola/common/sorted_list.js0000644000175000017500000001236613023355232022570 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * A sorted list implementation that can be updated from a data model * Copyright (C) 2010 Simon Newton */ goog.require('goog.events'); goog.require('goog.ui.Control'); goog.provide('ola.common.DataItem'); goog.provide('ola.common.GenericControl'); goog.provide('ola.common.SortedList'); /** * The base data object that represents an item in a sorted list * @constructor */ ola.common.DataItem = function() {}; /** * Get the id of this node. * @return {number|string} the id of this element. */ ola.common.DataItem.prototype.id = goog.nullFunction; /** * Compare one item to another. * @param {ola.common.DataItem} other the other item to compare to. * @return {number} -1 if less than, 1 if greater than, 0 if equal. */ ola.common.DataItem.prototype.compare = function(other) { if (this.id() > other.id()) { return 1; } else if (this.id() < other.id()) { return -1; } return 0; }; /** * An Generic navigation control element. * @constructor * @param {Object} item the item to add. * @param {function()} callback the function to run when the item is clicked. * @param {goog.ui.ControlRenderer=} opt_renderer Renderer used to render or * decorate the component; defaults to {@link goog.ui.ControlRenderer}. * @param {goog.dom.DomHelper=} opt_domHelper An optional DOM helper. */ ola.common.GenericControl = function(item, callback, opt_renderer, opt_domHelper) { goog.ui.Control.call(this, '', opt_renderer, opt_domHelper); this._item = item; this.callback = callback; }; goog.inherits(ola.common.GenericControl, goog.ui.Control); /** * Return the underlying GenericItem * @return {ola.GenericItem} The item for this control. */ ola.common.GenericControl.prototype.item = function() { return this._item; }; /** * This component can't be used to decorate * @return {boolean} Always false. */ ola.common.GenericControl.prototype.canDecorate = function() { return false; }; /** * Setup the event handler for this object. */ ola.common.GenericControl.prototype.enterDocument = function() { ola.common.GenericControl.superClass_.enterDocument.call(this); goog.events.listen(this.getElement(), goog.events.EventType.CLICK, function() { this.callback(this._item); }, false, this); }; /** * Update this item with from new data * @param {ola.GenericItem} item the new item to update from. */ ola.common.GenericControl.prototype.update = function(item) { this.setContent(item.name()); }; /** * Represents a list on controls that are updated from a data model * @param {string} container_id the id of the container to use as the control * list. * @param {ola.common.SortedListComponentFactory} component_factory a * SortedListComponentFactory class to produce the SortedListComponents. * @constructor */ ola.common.SortedList = function(container_id, component_factory) { this.container = container_id; this.component_factory = component_factory; }; /** * Update this list from a new list of data items. * @param {Array.} item_list the new set of data items. */ ola.common.SortedList.prototype.updateFromData = function(item_list) { var component_index = 0; var item_index = 0; var item_count = item_list.length; item_list.sort(function(a, b) { return a.compare(b); }); while (component_index != this.container.getChildCount() && item_index != item_count) { var item = item_list[item_index]; var current_component = this.container.getChildAt(component_index); var component_item = current_component.item(); var comparison = item.compare(component_item); if (comparison == -1) { var component = this.component_factory.newComponent(item); this.container.addChildAt(component, component_index, true); item_index++; component_index++; } else if (comparison == 0) { current_component.update(item_list[item_index]); component_index++; item_index++; } else { var n = this.container.removeChild(current_component, true); delete f; } } // remove any remaining nodes while (component_index < this.container.getChildCount()) { var n = this.container.removeChildAt(component_index, true); delete n; } // add any remaining items for (; item_index < item_count; item_index++) { var component = this.component_factory.newComponent(item_list[item_index]); this.container.addChild(component, true); } }; ola-0.10.5.nojsmin/javascript/ola/common/section_render.js0000644000175000017500000000567213023355232023242 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Render an item * Copyright (C) 2010 Simon Newton */ goog.require('goog.dom'); goog.require('goog.ui.Checkbox'); goog.require('goog.ui.Control'); goog.require('goog.ui.Option'); goog.require('goog.ui.Select'); goog.provide('ola.common.SectionRenderer'); /** * Generate the html for an item * @param {Element} table the table object to add the row to. * @param {Object} item_info the data for the item. */ ola.common.SectionRenderer.RenderItem = function(table, item_info) { var type = item_info['type']; var value = item_info['value']; var id = item_info['id']; if (type == 'hidden') { // we don't need a new row here var input = goog.dom.createElement('input'); input.id = id; input.type = 'hidden'; input.value = value; goog.dom.appendChild(table, input); return; } // everything else needs a row var row = goog.dom.createElement('tr'); goog.dom.appendChild(table, row); var name_td = goog.dom.createElement('td'); name_td.innerHTML = item_info['description']; goog.dom.appendChild(row, name_td); var td = goog.dom.createElement('td'); goog.dom.appendChild(row, td); if (id) { // id implies this field is editable if (type == 'string' || type == 'uint' || type == 'hidden') { var input = goog.dom.createElement('input'); input.value = value; input.name = id; if (type == 'hidden') { input.type = 'hidden'; } goog.dom.appendChild(td, input); if (item_info['button']) { // this item get's it's own button var button = new goog.ui.CustomButton(item_info['button']); button.render(td); } } else if (type == 'bool') { var check = new goog.ui.Checkbox(); check.setChecked(value == 1); check.render(td); item_info['object'] = check; } else { // select box var select = new goog.ui.Select(); var count = value.length; for (var i = 0; i < count; ++i) { select.addItem(new goog.ui.Option(value[i]['label'])); } if (item_info['selected_offset'] != undefined) { select.setSelectedIndex(item_info['selected_offset']); } select.render(td); item_info['object'] = select; } } else { td.innerHTML = value; } }; ola-0.10.5.nojsmin/javascript/ola/common/dmx_constants.js0000644000175000017500000000255613023355232023121 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DMX constants. * Copyright (C) 2013 Peter Newman */ goog.provide('ola.common.DmxConstants'); /** The first channel number @type {number} */ ola.common.DmxConstants.MIN_CHANNEL_NUMBER = 1; /** The number of channels and max channel number @type {number} */ ola.common.DmxConstants.MAX_CHANNEL_NUMBER = 512; /** The minimum value of a channel @type {number} */ ola.common.DmxConstants.MIN_CHANNEL_VALUE = 0; /** The maximum value of a channel @type {number} */ ola.common.DmxConstants.MAX_CHANNEL_VALUE = 255; /** The channel level at which to change the background colour @type {number} */ ola.common.DmxConstants.BACKGROUND_CHANGE_CHANNEL_LEVEL = 90; ola-0.10.5.nojsmin/javascript/ola/common/dmx_monitor.js0000644000175000017500000001035413023355232022567 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The DMX monitor. * This calls a method when new DMX data arrives. * Copyright (C) 2012 Simon Newton */ goog.require('goog.Timer'); goog.require('goog.events'); goog.require('ola.common.DmxConstants'); goog.require('ola.common.Server'); goog.provide('ola.common.DmxMonitor'); /** * The DMX monitor tab. * @constructor */ ola.common.DmxMonitor = function(container) { this.container = container; this.value_cells = new Array(); this.setup = false; this.enabled = false; this.universe_id = undefined; }; /** The time between data fetches @type {number} */ ola.common.DmxMonitor.PAUSE_TIME_IN_MS = 1000; /** * Enable / Disable the monitor. * @param {boolean} enabled true to enable, false to disable. * @param {number} universe_id the universe to use. */ ola.common.DmxMonitor.prototype.setState = function(enabled, universe_id) { this.enabled = enabled; this.universe_id = universe_id; if (this.enabled) { if (!this.setup) { this.setupCells(); } this.fetchValues(); } }; /** * Setup the boxes if required. */ ola.common.DmxMonitor.prototype.setupCells = function() { for (var i = 0; i < ola.common.DmxConstants.MAX_CHANNEL_NUMBER; ++i) { var cell = goog.dom.createElement('div'); cell.title = 'Channel ' + (i + 1); var channel = goog.dom.createElement('div'); channel.innerHTML = i + 1; var span = goog.dom.createElement('span'); span.innerHTML = ' '; goog.dom.appendChild(cell, channel); goog.dom.appendChild(cell, span); goog.dom.appendChild(this.container, cell); this.value_cells.push(span); } this.setup = true; }; /** * Fetches the new DMX values. */ ola.common.DmxMonitor.prototype.fetchValues = function(e) { if (!this.enabled) return; var t = this; ola.common.Server.getInstance().getChannelValues( this.universe_id, function(data) { t.updateData(data['dmx']); }); }; /** * Called when new data arrives. */ ola.common.DmxMonitor.prototype.updateData = function(data) { var data_length = Math.min(ola.common.DmxConstants.MAX_CHANNEL_NUMBER, data.length); for (var i = 0; i < data_length; ++i) { this.setCellValue_(i, data[i]); } for (var i = data_length; i < ola.common.DmxConstants.MAX_CHANNEL_NUMBER; ++i) { this.clearCellValue_(i); } if (this.enabled) { var t = this; goog.Timer.callOnce( function(data) { t.fetchValues(); }, ola.common.DmxMonitor.PAUSE_TIME_IN_MS ); } }; /** * Set the value of a channel cell * @param {number} offset the channel offset. * @param {number} value the value to set the channel to. * @private */ ola.common.DmxMonitor.prototype.setCellValue_ = function(offset, value) { var element = this.value_cells[offset]; if (element == undefined) { return; } element.innerHTML = value; var remaining = ola.common.DmxConstants.MAX_CHANNEL_VALUE - value; element.style.background = 'rgb(' + remaining + ',' + remaining + ',' + remaining + ')'; if (value > ola.common.DmxConstants.BACKGROUND_CHANGE_CHANNEL_LEVEL) { element.style.color = '#ffffff'; } else { element.style.color = '#000000'; } }; /** * Erase a cell value to indicate we didn't get data. * @param {number} offset the channel offset. * @private */ ola.common.DmxMonitor.prototype.clearCellValue_ = function(offset) { var element = this.value_cells[offset]; if (element == undefined) { return; } element.innerHTML = ' '; element.style.background = '#ffffff'; }; ola-0.10.5.nojsmin/javascript/ola/common/uid_list.js0000644000175000017500000001206013023355232022040 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * An order preserving, list of UIDs * Copyright (C) 2010 Simon Newton */ goog.require('ola.common.DataItem'); goog.provide('ola.common.UidControl'); goog.provide('ola.common.UidControlFactory'); goog.provide('ola.common.UidItem'); /** * An object which represents a UID in a list. * @param {Object} data the data to use to construct this item. * @constructor */ ola.common.UidItem = function(data) { this._device_id = data['device_id']; this._manufacturer_id = data['manufacturer_id']; this._device = data['device']; this._manufacturer = data['manufacturer']; }; goog.inherits(ola.common.UidItem, ola.common.DataItem); /** * Get the device name * @return {string} the name of the device. */ ola.common.UidItem.prototype.deviceName = function() { return this._device; }; /** * Get the id of this universe. * @return {number} the uid id. */ ola.common.UidItem.prototype.id = function() { return this.asString(); }; /** * Convert a number to the hex representation * @param {number} n the number to convert. * @param {number} padding the length to pad to. * @return {string} the hex representation of the number. * @private */ ola.common.UidItem.prototype.toHex_ = function(n, padding) { if (n < 0) { n = 0xffffffff + n + 1; } var s = n.toString(16); while (s.length < padding) { s = '0' + s; } return s; }; /** * Return the string representation of the uid. * @return {string} the uid. */ ola.common.UidItem.prototype.asString = function() { return (this.toHex_(this._manufacturer_id, 4) + ':' + this.toHex_(this._device_id, 8)); }; /** * Return the uid as a string * @return {number} the uid as a string. */ ola.common.UidItem.prototype.toString = function() { var uid = ''; if (this._manufacturer) { uid += this._manufacturer; } if (this._manufacturer && this._device) { uid += ', '; } if (this._device) { uid += this._device; } if (this._manufacturer || this._device) { uid += ' ['; } uid += this.asString(); if (this._manufacturer || this._device) { uid += ']'; } return uid; }; /** * Compare one uid to another. * @param {ola.common.DataItem} other the other item to compare to. * @return {number} -1 if less than, 1 if greater than, 0 if equal. */ ola.common.UidItem.prototype.compare = function(other) { if (this._manufacturer_id > other._manufacturer_id) { return 1; } else if (this._manufacturer_id < other._manufacturer_id) { return -1; } return this._device_id - other._device_id; }; /** * An UID navigation control element. * @constructor * @param {Object} item the item to add. * @param {function()} callback the function to run when the item is clicked. * @param {goog.ui.ControlRenderer=} opt_renderer Renderer used to render or * decorate the component; defaults to {@link goog.ui.ControlRenderer}. * @param {goog.dom.DomHelper=} opt_domHelper An optional DOM helper. */ ola.common.UidControl = function(item, callback, opt_renderer, opt_domHelper) { ola.common.GenericControl.call(this, item, callback, opt_renderer, opt_domHelper); this.setContent(item.toString()); }; goog.inherits(ola.common.UidControl, ola.common.GenericControl); /** * Setup the event handler for this object. */ ola.common.UidControl.prototype.enterDocument = function() { ola.common.UidControl.superClass_.enterDocument.call(this); this.getElement().title = this.item().toString(); }; /** * Update this item with from new data. * @param {Object} item the item to update this control object with. */ ola.common.UidControl.prototype.update = function(item) { // We don't expect the uid to change here. this.setContent(item.toString()); }; /** * The base class for a factory which produces control items * @param {function()} callback the function to call when an item is clicked. * The * first arg is the item id. * @constructor */ ola.common.UidControlFactory = function(callback) { this.callback = callback; }; /** * Create a new UidControl object from some data * @param {Object} data the data to use for the control. * @return {ola.common.UidControl} The new UidControl object. */ ola.common.UidControlFactory.prototype.newComponent = function(data) { return new ola.common.UidControl(data, this.callback); }; ola-0.10.5.nojsmin/javascript/ola/common/keypad_parser.js0000644000175000017500000001342013023355232023056 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The keypad parser. * Copyright (C) 2011 Chris Stranex * * The parser takes commands (see below) and executes them. * * Syntax: * command ::= channel-part "@" value * * channel-part ::= channel | channel_range * * channel ::= *digit * Channels range between 1 and 512. * * channel_range ::= "ALL" | "*" | channel "THRU" channel | channel > channel * * value ::= *digit | "FULL" | "+" * Values range between 0 and 255. */ goog.require('ola.common.DmxConstants'); goog.provide('ola.common.KeypadCommand'); goog.provide('ola.common.KeypadParser'); /** * Create a new KeypadCommand * @param {number} start the starting slot. * @param {number} end the end slot, or undefined if this is a single slot * command. * @param {number} value the slot value. * @constructor */ ola.common.KeypadCommand = function(start, end, value) { this.start = start; this.end = end == undefined ? start : end; this.value = value; }; /** * Check if this command is valid * @return {bool} true if the command if valid, false otherwise. */ ola.common.KeypadCommand.prototype.isValid = function() { return ( (this.start >= ola.common.DmxConstants.MIN_CHANNEL_NUMBER && this.start <= ola.common.DmxConstants.MAX_CHANNEL_NUMBER) && (this.value >= ola.common.DmxConstants.MIN_CHANNEL_VALUE && this.value <= ola.common.DmxConstants.MAX_CHANNEL_VALUE) && (this.end == undefined || (this.end >= ola.common.DmxConstants.MIN_CHANNEL_NUMBER && this.end <= ola.common.DmxConstants.MAX_CHANNEL_NUMBER && this.end >= this.start)) ); }; /** * The KeypadParser class * @constructor */ ola.common.KeypadParser = function() { this.full_command_regex = new RegExp( /(?:([0-9]{1,3})(?:\s+THRU\s+([0-9]{0,3}))?)\s+@\s+([0-9]{0,3})$/); // similar to above, but allows for partially completed commands this.partial_command_regex = new RegExp( /(?:([0-9]{1,3})(?:\s+THRU\s+([0-9]{0,3}))?)(?:\s+@\s+([0-9]{0,3}))?$/); }; /** * Parse a full command * @param {string} str the input string. * @return {bool} true if the command is valid, false otherwise. */ ola.common.KeypadParser.prototype.parsePartialCommand = function(str) { if (str.length == 0) { return false; } var result = this.partial_command_regex.exec(this.aliases_(str)); if (result == null) { return false; } var start_token = result[1]; if (start_token != undefined) { var start = this.intOrUndefined_(result[1]); if (start == undefined || start == 0 || start > ola.common.DmxConstants.MAX_CHANNEL_NUMBER) { return false; } } var end_token = result[2]; if (end_token != undefined && end_token != '') { var end = this.intOrUndefined_(result[2]); if (end == undefined || end == 0 || end > ola.common.DmxConstants.MAX_CHANNEL_NUMBER) { return false; } } var value_token = result[3]; if (value_token != undefined && value_token != '') { var value = this.intOrUndefined_(result[3]); if (value == undefined || value > ola.common.DmxConstants.MAX_CHANNEL_VALUE) { return false; } } return true; }; /** * Parse a full command * @param {string} str the input string. * @return {KeypadCommand|undefined} Returns a KeypadCommand or undefined on * error. If returned, the KeypadCommand is guarenteed to be valid. */ ola.common.KeypadParser.prototype.parseFullCommand = function(str) { // It's empty so we can return true really if (str.length == 0) { return undefined; } var result = this.full_command_regex.exec(this.aliases_(str)); if (result == null) { return undefined; } var start = this.intOrUndefined_(result[1]); var end = this.intOrUndefined_(result[2]); var value = this.intOrUndefined_(result[3]); if (start == undefined || value == undefined) { return undefined; } if (result[2] != undefined) { // was a range if (end == undefined) return false; } var command = new ola.common.KeypadCommand(start, end, value); return command.isValid() ? command : undefined; }; /** * Convert a string to an int, or return undefined * @param {string} token the string to convert. * @return {number|undefined} The integer, or undefined. * @private */ ola.common.KeypadParser.prototype.intOrUndefined_ = function(token) { if (token == null || token == undefined) return undefined; var i = parseInt(token); return isNaN(i) ? undefined : i; }; /** * Converts aliases. * @param {string} str the input string. * @return {string} the output string. * @private */ ola.common.KeypadParser.prototype.aliases_ = function(str) { str = str.replace('>', 'THRU'); str = str.replace('*', ola.common.DmxConstants.MIN_CHANNEL_NUMBER + ' THRU ' + ola.common.DmxConstants.MAX_CHANNEL_NUMBER); str = str.replace('ALL', ola.common.DmxConstants.MIN_CHANNEL_NUMBER + ' THRU ' + ola.common.DmxConstants.MAX_CHANNEL_NUMBER); str = str.replace('@ +', '@ ' + ola.common.DmxConstants.MAX_CHANNEL_VALUE); str = str.replace('@ FULL', '@ ' + ola.common.DmxConstants.MAX_CHANNEL_VALUE); return str; }; ola-0.10.5.nojsmin/javascript/ola/common/keypad_controller.js0000644000175000017500000001604113023355232023747 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The keypad controller. * Copyright (C) 2011 Chris Stranex */ goog.require('goog.events'); goog.require('goog.events.KeyCodes'); goog.require('goog.events.KeyHandler'); goog.require('goog.ui.Button'); goog.require('goog.ui.Container'); goog.require('ola.common.KeypadParser'); goog.require('ola.common.Server'); goog.require('ola.common.Server.EventType'); goog.provide('ola.common.KeypadController'); /** * The Keypad Controller class. * @param {string} name Universe Name. * @param {number} universe_id Universe Id. * @constructor */ ola.common.KeypadController = function(name, universe_id) { this.universe_id = universe_id; this.parser = new ola.common.KeypadParser(); this.table = goog.dom.createElement('table'); this.caption_(name); this.display_(); this.keypad_(); }; /** * Button * @param {string} value the caption for the button. * @return {Element} the new Button element. * @private */ ola.common.KeypadController.prototype.button_ = function(value) { var button = new goog.ui.Button(goog.ui.FlatButtonRenderer); button.setContent(value); goog.events.listen(button, goog.ui.Component.EventType.ACTION, function() { this.buttonAction_(value); }, false, this); return button; }; /** * Input event. Triggered when text is entered into text box. * @param {string} key the key that was pressed. * @private */ ola.common.KeypadController.prototype.textEntry_ = function(key) { var text = this.command_input.value; var autocomplete = null; switch (key) { case goog.events.KeyCodes.SPACE: break; case goog.events.KeyCodes.ENTER: this.buttonAction_('ENTER'); return; default: return; } var key = text.substr(text.length - 1, 1); switch (key) { case 'F': autocomplete = 'ULL'; break; // If it's the T or > keys, autocomplete 'THRU' case 'T': autocomplete = 'HRU'; break; case 'A': autocomplete = 'LL @'; break; default: autocomplete = null; } if (autocomplete != null) { this.command_input.value = text + autocomplete; } }; /** * Button event. Triggered when a button is pushed. * @param {string} name the button that was pressed. * @private */ ola.common.KeypadController.prototype.buttonAction_ = function(name) { if (name == '<') { // Go Backward. Must scan for whitespace var end = this.command_input.value.length - 1; if (isNaN(parseInt(this.command_input.value.substr(end, 1)))) { var c = this.command_input.value.substr(end - 1, 1); var length = 0; switch (c) { case 'L': // FULL length = 3; break; case '@': length = 2; break; case 'U': // THRU length = 5; break; default: length = 0; } end -= length; } this.command_input.value = this.command_input.value.substr(0, end); this.buttonAction_(''); } else if (name == 'ENTER') { // Execute var command = this.parser.parseFullCommand(this.command_input.value); if (command != undefined) { this.execute(command); this.command_input.value = ''; } } else { var command = this.command_input.value + name; if (this.parser.parsePartialCommand(command) == true) { // Add it to the command textbox this.command_input.value = command; } } }; /** * Caption of the Table * @param {string} title the title for the table. * @private */ ola.common.KeypadController.prototype.caption_ = function(title) { var caption = goog.dom.createElement('caption'); caption.innerHTML = title; this.table.appendChild(caption); }; /** * First tr row * @private */ ola.common.KeypadController.prototype.display_ = function() { var tr = goog.dom.createElement('tr'); var td = goog.dom.createElement('td'); td.colSpan = '4'; this.command_input = goog.dom.createElement('input'); this.command_input.type = 'text'; td.appendChild(this.command_input); var key_handler = new goog.events.KeyHandler(this.command_input); goog.events.listen(key_handler, 'key', function(e) { this.textEntry_(e.keyCode); }, true, this); var button = this.button_('<'); button.addClassName('backspace-button'); button.render(td); tr.appendChild(td); this.table.appendChild(tr); }; /** * The main keypad button matrix * @private */ ola.common.KeypadController.prototype.keypad_ = function() { var values = ['7', '8', '9', ' THRU ', '4', '5', '6', ' @ ', '1', '2', '3', 'FULL', '0', 'ENTER']; for (i = 0; i < 3; ++i) { var tr = goog.dom.createElement('tr'); for (x = 0; x < 4; ++x) { var td = goog.dom.createElement('td'); var button = this.button_(values[(i * 4) + x]); button.render(td); tr.appendChild(td); } this.table.appendChild(tr); } var tr = goog.dom.createElement('tr'); var zerotd = goog.dom.createElement('td'); var button = this.button_(values[12]); button.render(zerotd); this.table.appendChild(zerotd); var entertd = goog.dom.createElement('td'); button = this.button_(values[13]); button.render(entertd); entertd.colSpan = '3'; this.table.appendChild(entertd); }; /** * Execute a KeypadCommand. * This asks ola for current dmx values before * running execute_() where the real work happens. * @param {KeypadCommand} command the command to execute. */ ola.common.KeypadController.prototype.execute = function(command) { var tab = this; ola.common.Server.getInstance().getChannelValues( this.universe_id, function(e) { tab.execute_(e, command); }); }; /** * Executes the KeypadCommand. This method * is called once DMX values are retrieved by the server. * @param {Object} e the event object. * @param {KeypadCommand} command the command to execute. * @private */ ola.common.KeypadController.prototype.execute_ = function(e, command) { var dmx_values = e['dmx']; if (command.start == command.end) { dmx_values[command.start - 1] = command.value; } else { for (i = command.start; i <= command.end; ++i) { dmx_values[i - 1] = command.value; } } // Send the values to OLA ola.common.Server.getInstance().setChannelValues( this.universe_id, dmx_values, function() {}); }; ola-0.10.5.nojsmin/javascript/ola/common/plugin_list.js0000644000175000017500000000657013023355232022566 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Object that represent a plugin item. * Copyright (C) 2010 Simon Newton */ goog.require('ola.common.DataItem'); goog.provide('ola.common.PluginControl'); goog.provide('ola.common.PluginControlFactory'); goog.provide('ola.common.PluginItem'); /** * An object which represents a plugin in the list * @param {Object} data the data to use to construct this item. * @constructor */ ola.common.PluginItem = function(data) { this._id = data['id']; this._name = data['name']; }; goog.inherits(ola.common.PluginItem, ola.common.DataItem); /** * Get the id of this universe. * @return {number} the universe id. */ ola.common.PluginItem.prototype.id = function() { return this._id; }; /** * Return the universe name * @return {string} the name. */ ola.common.PluginItem.prototype.name = function() { return this._name; }; /** * Compare one item to another. * @param {ola.common.DataItem} other the other item to compare to. * @return {number} -1 if less than, 1 if greater than, 0 if equal. */ ola.common.PluginItem.prototype.compare = function(other) { if (this.name() > other.name()) { return 1; } else if (this.name() < other.name()) { return -1; } return 0; }; /** * An Plugin navigation control element. * @constructor * @param {Object} item the item to add. * @param {function()} callback the function to run when the item is clicked. * @param {goog.ui.ControlRenderer=} opt_renderer Renderer used to render or * decorate the component; defaults to {@link goog.ui.ControlRenderer}. * @param {goog.dom.DomHelper=} opt_domHelper An optional DOM helper. */ ola.PluginControl = function(item, callback, opt_renderer, opt_domHelper) { ola.common.GenericControl.call(this, item, callback, opt_renderer, opt_domHelper); this.setContent(item.name()); }; goog.inherits(ola.PluginControl, ola.common.GenericControl); /** * Setup the event handler for this object. */ ola.PluginControl.prototype.enterDocument = function() { ola.PluginControl.superClass_.enterDocument.call(this); this.getElement().title = this._item.name() + ' Plugin'; }; /** * A factory which produces PluginControls * @param {function()} callback the funtion called when the control is clicked. * @constructor */ ola.common.PluginControlFactory = function(callback) { this.callback = callback; }; /** * @param {Object} data The new data for the row. * @return {ola.PluginControl} an instance of a PluginRow. */ ola.common.PluginControlFactory.prototype.newComponent = function(data) { return new ola.PluginControl(data, this.callback); }; ola-0.10.5.nojsmin/javascript/ola/common/rdm_section_list.js0000644000175000017500000001011413023355232023563 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * An item in the RDM section list * Copyright (C) 2010 Simon Newton */ goog.require('ola.common.DataItem'); goog.provide('ola.common.RdmSectionControl'); goog.provide('ola.common.RdmSectionControlFactory'); goog.provide('ola.common.RdmSectionItem'); /** * An object which represents a section in a list. * @param {Object} data the data to use to construct this item. * @constructor */ ola.common.RdmSectionItem = function(data) { this._id = data['id']; this._name = data['name']; this._hint = data['hint']; }; goog.inherits(ola.common.RdmSectionItem, ola.common.DataItem); /** * Get the id of this section. * @return {number} the uid id. */ ola.common.RdmSectionItem.prototype.id = function() { return this._id; }; /** * Get the hint for this section * @return {string} the section hint. */ ola.common.RdmSectionItem.prototype.hint = function() { return this._hint; }; /** * Return the uid as a string * @return {number} the uid as a string. */ ola.common.RdmSectionItem.prototype.toString = function() { return this._name; }; /** * Compare one uid to another. * @param {ola.common.DataItem} other the other item to compare to. * @return {number} -1 if less than, 1 if greater than, 0 if equal. */ ola.common.RdmSectionItem.prototype.compare = function(other) { if (this._name < other._name) { return -1; } else if (this._name > other._name) { return 1; } else { return 0; } }; /** * An section navigation control element. * @constructor * @param {Object} item the item to add. * @param {function()} callback the function to run when the item is clicked. * @param {goog.ui.ControlRenderer=} opt_renderer Renderer used to render or * decorate the component; defaults to {@link goog.ui.ControlRenderer}. * @param {goog.dom.DomHelper=} opt_domHelper An optional DOM helper. */ ola.common.RdmSectionControl = function(item, callback, opt_renderer, opt_domHelper) { ola.common.GenericControl.call(this, item, callback, opt_renderer, opt_domHelper); this.setContent(item.toString()); }; goog.inherits(ola.common.RdmSectionControl, ola.common.GenericControl); /** * Setup the event handler for this object. */ ola.common.RdmSectionControl.prototype.enterDocument = function() { ola.UniverseControl.superClass_.enterDocument.call(this); this.getElement().title = this.item().toString(); }; /** * Update this item with from new data. * @param {Object} item the item to add. */ ola.common.RdmSectionControl.prototype.update = function(item) { this.setContent(item.toString()); }; /** * The base class for a factory which produces control items * @param {function()} callback the function to call when an item is clicked. * The * first arg is the item id. * @constructor */ ola.common.RdmSectionControlFactory = function(callback) { this.callback = callback; }; /** * Create a new RdmSectionControl object from some data * @param {Object} data the data to use for the control. * @return {ola.common.RdmSectionControl} A new RdmSectionControl. */ ola.common.RdmSectionControlFactory.prototype.newComponent = function(data) { return new ola.common.RdmSectionControl(data, this.callback); }; ola-0.10.5.nojsmin/javascript/ola/common/server_stats.js0000644000175000017500000000513413023355232022754 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The class the manages the server stats table. * Copyright (C) 2010 Simon Newton */ goog.require('goog.dom'); goog.require('goog.events'); goog.require('ola.common.Server'); goog.require('ola.common.Server.EventType'); goog.provide('ola.common.ServerStats'); /** * A class that updates the server stats. * @param {string} element_id the id of the div to use for the home frame. * @constructor */ ola.common.ServerStats = function(element_id) { var ola_server = ola.common.Server.getInstance(); goog.events.listen(ola_server, ola.common.Server.EventType.SERVER_INFO_EVENT, this.updateServerInfo_, false, this); // update the server info now ola_server.UpdateServerInfo(); }; /** * The title of this tab */ ola.common.ServerStats.prototype.title = function() { return 'Home'; }; /** * Called when the tab loses focuse */ ola.common.ServerStats.prototype.blur = function() {}; /** * Update the tab */ ola.common.ServerStats.prototype.update = function() { ola.common.Server.getInstance().UpdateServerInfo(); }; /** * Update the home frame with new server data * @param {Object} e the event object. * @private */ ola.common.ServerStats.prototype.updateServerInfo_ = function(e) { goog.dom.$('server_hostname').innerHTML = e.server_info['hostname']; goog.dom.$('server_ip').innerHTML = e.server_info['ip']; goog.dom.$('server_broadcast').innerHTML = e.server_info['broadcast']; goog.dom.$('server_mac').innerHTML = e.server_info['hw_address']; goog.dom.$('server_instance_name').innerHTML = e.server_info['instance_name']; goog.dom.$('server_version').innerHTML = e.server_info['version']; goog.dom.$('server_uptime').innerHTML = e.server_info['up_since']; if (!e.server_info['quit_enabled']) { var stop_button = goog.dom.$('stop_button'); if (stop_button) { stop_button.style.display = 'none'; } } }; ola-0.10.5.nojsmin/javascript/ola/new_universe_frame.js0000644000175000017500000001167013023355232022625 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The new universe frame. * Copyright (C) 2010 Simon Newton */ goog.require('goog.dom'); goog.require('goog.events'); goog.require('goog.net.HttpStatus'); goog.require('ola.AvailablePort'); goog.require('ola.AvailablePortTable'); goog.require('ola.BaseFrame'); goog.require('ola.LoggerWindow'); goog.require('ola.common.Server'); goog.require('ola.common.Server.EventType'); goog.provide('ola.NewUniverseFrame'); /** * The class representing the Universe frame * @param {string} element_id the id of the element to use for this frame. * @constructor * @param {Object} ola_ui The OlaUI object. */ ola.NewUniverseFrame = function(element_id, ola_ui) { ola.BaseFrame.call(this, element_id); this.ola_ui = ola_ui; var cancel_button = goog.dom.$('cancel_new_universe_button'); goog.ui.decorate(cancel_button); goog.events.listen(cancel_button, goog.events.EventType.CLICK, ola_ui.ShowHome, false, ola_ui); var confirm_button = goog.dom.$('confirm_new_universe_button'); goog.ui.decorate(confirm_button); goog.events.listen(confirm_button, goog.events.EventType.CLICK, this.addUniverseButtonClicked, false, this); this.available_ports = new ola.AvailablePortTable(); this.available_ports.decorate(goog.dom.$('available_ports')); }; goog.inherits(ola.NewUniverseFrame, ola.BaseFrame); /** * Show this frame. We extend the base method so we can populate the ports. */ ola.NewUniverseFrame.prototype.Show = function() { // clear out the fields goog.dom.$('new_universe_id').value = ''; goog.dom.$('new_universe_name').value = ''; this.available_ports.update(); ola.UniverseFrame.superClass_.Show.call(this); }; /** * Called when the add universe button is clicked * @param {Object} e The event object. */ ola.NewUniverseFrame.prototype.addUniverseButtonClicked = function(e) { var dialog = ola.Dialog.getInstance(); var universe_id_input = goog.dom.$('new_universe_id'); var universe_id = parseInt(universe_id_input.value); if (isNaN(universe_id) || universe_id < 0 || universe_id > 4294967295) { dialog.setTitle('Invalid Universe Number'); dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK); dialog.setContent('The universe number must be between 0 and 4294967295'); dialog.setVisible(true); return; } var ola_server = ola.common.Server.getInstance(); // check if we already know about this universe if (ola_server.CheckIfUniverseExists(universe_id)) { dialog.setTitle('Universe already exists'); dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK); dialog.setContent('Universe ' + universe_id + ' already exists'); dialog.setVisible(true); return; } // universe names are optional var universe_name = goog.dom.$('new_universe_name').value; var selected_ports = this.available_ports.getSelectedRows(); if (selected_ports.length == 0) { dialog.setTitle('No ports selected'); dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK); dialog.setContent('At least one port must be bound to the universe'); dialog.setVisible(true); return; } var frame = this; ola_server.createUniverse( universe_id, universe_name, selected_ports, function(e) { frame.newUniverseComplete(e); }); dialog.setAsBusy(); dialog.setVisible(true); }; /** * Called when the new universe action completes. * @param {Object} e The event object. */ ola.NewUniverseFrame.prototype.newUniverseComplete = function(e) { var dialog = ola.Dialog.getInstance(); if (e.target.getStatus() != goog.net.HttpStatus.OK) { dialog.setTitle('New Universe Failed'); dialog.setContent(e.target.getLastUri() + ' : ' + e.target.getLastError()); dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK); dialog.setVisible(true); return; } var obj = e.target.getResponseJson(); if (obj['ok']) { dialog.setVisible(false); this.ola_ui.ShowUniverse(obj['universe'], true); // update the universe list now ola.common.Server.getInstance().FetchUniversePluginList(); } else { dialog.setTitle('New Universe Failed'); dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK); dialog.setContent(obj['message']); dialog.setVisible(true); } }; ola-0.10.5.nojsmin/javascript/ola/base_frame.js0000644000175000017500000000345313023355232021026 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The base class that all other frames inherit from. * Copyright (C) 2010 Simon Newton */ goog.require('goog.dom'); goog.provide('ola.BaseFrame'); /** * The base frame class * @param {string} element_id the id of the div to use for the home frame. * @constructor */ ola.BaseFrame = function(element_id) { this.element = goog.dom.$(element_id); }; /** * Check if this frame is visible. * @return {boolean} true if visible, false otherwise. */ ola.BaseFrame.prototype.IsVisible = function() { return this.element.style.display == 'block'; }; /** * Show this frame */ ola.BaseFrame.prototype.Show = function() { this.element.style.display = 'block'; }; /** * Hide this frame */ ola.BaseFrame.prototype.Hide = function() { this.element.style.display = 'none'; }; /** * Make this frame show the spinner */ ola.BaseFrame.prototype.setAsBusy = function() { this.element.innerHTML = ( '
'); }; /** * Make this frame show the spinner */ ola.BaseFrame.prototype.Clear = function() { this.element.innerHTML = ''; }; ola-0.10.5.nojsmin/javascript/ola/mobile.js0000644000175000017500000000442113023355232020205 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The mobile OLA UI. * Copyright (C) 2010 Simon Newton */ goog.require('goog.dom'); goog.require('goog.events'); goog.require('goog.ui.TabPane'); goog.require('ola.common.ServerStats'); goog.require('ola.mobile.ControllerTab'); goog.require('ola.mobile.MonitorTab'); goog.require('ola.mobile.PluginTab'); goog.require('ola.mobile.UniverseTab'); goog.provide('ola.mobile'); /** * Setup the OLA ola_ui widgets * @constructor */ ola.MobileUI = function() { this.tabs = new Array(); this.tabs.push(new ola.common.ServerStats()); this.tabs.push(new ola.mobile.UniverseTab()); this.tabs.push(new ola.mobile.MonitorTab()); this.tabs.push(new ola.mobile.ControllerTab()); this.tabs.push(new ola.mobile.PluginTab()); // setup the tab pane this.tabPane = new goog.ui.TabPane(goog.dom.$('tab_pane')); for (var i = 0; i < this.tabs.length; ++i) { this.tabPane.addPage(new goog.ui.TabPane.TabPage( goog.dom.$('tab_page_' + i), this.tabs[i].title())); } goog.events.listen(this.tabPane, goog.ui.TabPane.Events.CHANGE, this.updateSelectedTab, false, this); }; /** * Update the tab that was selected */ ola.MobileUI.prototype.updateSelectedTab = function() { var selected_tab = this.tabPane.getSelectedIndex(); for (var i = 0; i < this.tabs.length; ++i) { if (i != selected_tab) { this.tabs[i].blur(); } } this.tabs[selected_tab].update(); }; /** * The main setup function. */ ola.mobile.Setup = function() { var ola_ui = new ola.MobileUI(); }; goog.exportSymbol('ola.mobile.Setup', ola.mobile.Setup); ola-0.10.5.nojsmin/javascript/ola/mobile/0000755000175000017500000000000013155164170017653 5ustar wouterwouterola-0.10.5.nojsmin/javascript/ola/mobile/monitor_tab.js0000644000175000017500000000753313023355232022531 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The DMX monitor tab * Copyright (C) 2012 Simon Newton */ goog.require('goog.events'); goog.require('goog.ui.Button'); goog.require('goog.ui.Container'); goog.require('ola.BaseFrame'); goog.require('ola.UniverseControl'); goog.require('ola.UniverseItem'); goog.require('ola.common.DmxMonitor'); goog.require('ola.common.SectionRenderer'); goog.require('ola.common.Server'); goog.require('ola.common.Server.EventType'); goog.require('ola.common.SortedList'); goog.provide('ola.mobile.MonitorTab'); /** * The class representing the monitor frame * @constructor */ ola.mobile.MonitorTab = function() { this.monitor_frame = new ola.BaseFrame('monitor_frame'); this.universe_frame = new ola.BaseFrame('monitor_universe_frame'); this.hideAllFrames_(); this.resetState_(); this.ola_server = ola.common.Server.getInstance(); goog.events.listen(this.ola_server, ola.common.Server.EventType.UNIVERSE_LIST_EVENT, this.updateUniverseList_, false, this); this.monitor = new ola.common.DmxMonitor( goog.dom.$('monitor_frame')); }; /** * The title of this tab */ ola.mobile.MonitorTab.prototype.title = function() { return 'DMX Monitor'; }; /** * Called when the user navigates away from this tab */ ola.mobile.MonitorTab.prototype.blur = function() { this.monitor.setState(false, undefined); }; /** * Reset certain variables to their default state * @private */ ola.mobile.MonitorTab.prototype.resetState_ = function() { this.universe_list = undefined; }; /** * Hide all frames * @private */ ola.mobile.MonitorTab.prototype.hideAllFrames_ = function() { this.monitor_frame.Hide(); this.universe_frame.Hide(); }; /** * Called when the controller tab is clicked */ ola.mobile.MonitorTab.prototype.update = function() { this.hideAllFrames_(); this.resetState_(); this.universe_frame.setAsBusy(); this.universe_frame.Show(); this.ola_server.FetchUniversePluginList(); }; /** * Called when a list of universes is received * @param {Object} e the event object. * @private */ ola.mobile.MonitorTab.prototype.updateUniverseList_ = function(e) { if (this.universe_list == undefined) { this.universe_frame.Clear(); var universe_container = new goog.ui.Container(); universe_container.render(this.universe_frame.element); var tab = this; this.universe_list = new ola.common.SortedList( universe_container, new ola.UniverseControlFactory( function(item) { tab.universeSelected_(item.id(), item.name()); })); } var items = new Array(); for (var i = 0; i < e.universes.length; ++i) { var item = new ola.UniverseItem(e.universes[i]); items.push(item); } this.universe_list.updateFromData(items); }; /** * Called when a universe is selected * @param {number} universe_id the id of the universe selected. * @param {string} universe_name the name of the universe selected. * @private */ ola.mobile.MonitorTab.prototype.universeSelected_ = function( universe_id, universe_name) { this.hideAllFrames_(); this.monitor.setState(true, universe_id); this.monitor_frame.Show(); }; ola-0.10.5.nojsmin/javascript/ola/mobile/plugin_tab.js0000644000175000017500000000763613023355232022344 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The plugin tab for the mobile UI. * Copyright (C) 2010 Simon Newton */ goog.require('goog.events'); goog.require('goog.ui.Container'); goog.require('ola.BaseFrame'); goog.require('ola.common.PluginControlFactory'); goog.require('ola.common.PluginItem'); goog.require('ola.common.Server'); goog.require('ola.common.Server.EventType'); goog.require('ola.common.SortedList'); goog.provide('ola.mobile.PluginTab'); /** * The class representing the Plugin frame * @constructor */ ola.mobile.PluginTab = function() { this.plugin_frame = new ola.BaseFrame('plugin_frame'); this.plugin_info_frame = new ola.BaseFrame('plugin_info_frame'); this.hideAllFrames_(); this.plugin_list = undefined; this.ola_server = ola.common.Server.getInstance(); goog.events.listen(this.ola_server, ola.common.Server.EventType.PLUGIN_LIST_EVENT, this.updatePluginList_, false, this); goog.events.listen(this.ola_server, ola.common.Server.EventType.PLUGIN_EVENT, this.updatePluginInfo_, false, this); }; /** * The title of this tab */ ola.mobile.PluginTab.prototype.title = function() { return 'Plugins'; }; /** * Called when the tab loses focuse */ ola.mobile.PluginTab.prototype.blur = function() {}; /** * Hide all frames * @private */ ola.mobile.PluginTab.prototype.hideAllFrames_ = function() { this.plugin_frame.Hide(); this.plugin_info_frame.Hide(); }; /** * Called when the plugin tab is clicked */ ola.mobile.PluginTab.prototype.update = function() { this.hideAllFrames_(); this.plugin_frame.setAsBusy(); this.plugin_list = undefined; this.plugin_frame.Show(); this.ola_server.FetchUniversePluginList(); }; /** * Called when a new list of plugins is received. * @param {Object} e the event object. * @private */ ola.mobile.PluginTab.prototype.updatePluginList_ = function(e) { if (this.plugin_list == undefined) { this.plugin_frame.Clear(); var plugin_container = new goog.ui.Container(); plugin_container.render(this.plugin_frame.element); var tab = this; this.plugin_list = new ola.common.SortedList( plugin_container, new ola.common.PluginControlFactory( function(item) { tab.pluginSelected_(item.id()); })); } var items = new Array(); for (var i = 0; i < e.plugins.length; ++i) { var item = new ola.common.PluginItem(e.plugins[i]); items.push(item); } this.plugin_list.updateFromData(items); }; /** * Called when a plugin is selected. * @param {number} plugin_id the id of the plugin selected. * @private */ ola.mobile.PluginTab.prototype.pluginSelected_ = function(plugin_id) { this.hideAllFrames_(); this.plugin_info_frame.setAsBusy(); this.plugin_info_frame.Show(); this.ola_server.FetchPluginInfo(plugin_id); }; /** * Called when new plugin info is available * @param {Object} e the event object. * @private */ ola.mobile.PluginTab.prototype.updatePluginInfo_ = function(e) { this.plugin_info_frame.Clear(); var description = goog.string.htmlEscape(e.plugin['description']); description = description.replace(/\\n/g, '
'); this.plugin_info_frame.element.innerHTML = description; }; ola-0.10.5.nojsmin/javascript/ola/mobile/controller_tab.js0000644000175000017500000000775013023355232023226 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The controller tab. * Copyright (C) 2011 Chris Stranex */ goog.require('goog.events'); goog.require('goog.ui.Button'); goog.require('goog.ui.Container'); goog.require('ola.BaseFrame'); goog.require('ola.UniverseControl'); goog.require('ola.UniverseItem'); goog.require('ola.common.KeypadController'); goog.require('ola.common.SectionRenderer'); goog.require('ola.common.Server'); goog.require('ola.common.Server.EventType'); goog.require('ola.common.SortedList'); goog.provide('ola.mobile.ControllerTab'); /** * The class representing the Controller frame * @constructor */ ola.mobile.ControllerTab = function() { this.controller_frame = new ola.BaseFrame('controller_frame'); this.universe_frame = new ola.BaseFrame('controller_universe_frame'); this.hideAllFrames_(); this.resetState_(); this.ola_server = ola.common.Server.getInstance(); goog.events.listen(this.ola_server, ola.common.Server.EventType.UNIVERSE_LIST_EVENT, this.updateUniverseList_, false, this); }; /** * The title of this tab */ ola.mobile.ControllerTab.prototype.title = function() { return 'DMX Keypad'; }; /** * Called when the user navigates away from this tab */ ola.mobile.ControllerTab.prototype.blur = function() {}; /** * Reset certain variables to their default state * @private */ ola.mobile.ControllerTab.prototype.resetState_ = function() { this.universe_list = undefined; this.active_universe = undefined; }; /** * Hide all frames * @private */ ola.mobile.ControllerTab.prototype.hideAllFrames_ = function() { this.controller_frame.Hide(); this.universe_frame.Hide(); }; /** * Called when the controller tab is clicked */ ola.mobile.ControllerTab.prototype.update = function() { this.hideAllFrames_(); this.resetState_(); this.universe_frame.setAsBusy(); this.universe_frame.Show(); this.ola_server.FetchUniversePluginList(); }; /** * Called when a list of universes is received * @param {Object} e the event object. * @private */ ola.mobile.ControllerTab.prototype.updateUniverseList_ = function(e) { if (this.universe_list == undefined) { this.universe_frame.Clear(); var universe_container = new goog.ui.Container(); universe_container.render(this.universe_frame.element); var tab = this; this.universe_list = new ola.common.SortedList( universe_container, new ola.UniverseControlFactory( function(item) { tab.universeSelected_(item.id(), item.name()); })); } var items = new Array(); for (var i = 0; i < e.universes.length; ++i) { var item = new ola.UniverseItem(e.universes[i]); items.push(item); } this.universe_list.updateFromData(items); }; /** * Called when a universe is selected * @param {number} universe_id the id of the universe selected. * @param {string} universe_name the name of the universe selected. * @private */ ola.mobile.ControllerTab.prototype.universeSelected_ = function( universe_id, universe_name) { this.hideAllFrames_(); this.active_universe = universe_id; this.keypad = new ola.common.KeypadController( universe_name, universe_id); this.controller_frame.Clear(); this.controller_frame.element.appendChild(this.keypad.table); this.controller_frame.Show(); }; ola-0.10.5.nojsmin/javascript/ola/mobile/universe_tab.js0000644000175000017500000002733313023355232022702 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The universe tab. * Copyright (C) 2010 Simon Newton */ goog.require('goog.events'); goog.require('goog.net.HttpStatus'); goog.require('goog.ui.Button'); goog.require('goog.ui.Container'); goog.require('ola.BaseFrame'); goog.require('ola.UniverseControl'); goog.require('ola.UniverseItem'); goog.require('ola.common.RdmSectionControl'); goog.require('ola.common.RdmSectionControlFactory'); goog.require('ola.common.RdmSectionItem'); goog.require('ola.common.SectionRenderer'); goog.require('ola.common.Server'); goog.require('ola.common.Server.EventType'); goog.require('ola.common.SortedList'); goog.require('ola.common.UidControlFactory'); goog.require('ola.common.UidItem'); goog.provide('ola.mobile.UniverseTab'); /** * The class representing the Universe frame * @constructor */ ola.mobile.UniverseTab = function() { this.universe_frame = new ola.BaseFrame('universe_frame'); this.uid_frame = new ola.BaseFrame('uid_frame'); this.rdm_frame = new ola.BaseFrame('rdm_frame'); this.rdm_section_frame = new ola.BaseFrame('rdm_section_frame'); this.hideAllFrames_(); this.universe_list = undefined; this.active_universe = undefined; this.uid_list = undefined; this.active_uid = undefined; this.rdm_list = undefined; this.active_section = undefined; this.items = undefined; this.ola_server = ola.common.Server.getInstance(); goog.events.listen(this.ola_server, ola.common.Server.EventType.UNIVERSE_LIST_EVENT, this.updateUniverseList_, false, this); }; /** The title of this tab */ ola.mobile.UniverseTab.prototype.title = function() { return 'RDM'; }; /** * Called when the tab loses focuse */ ola.mobile.UniverseTab.prototype.blur = function() {}; /** * Hide all frames * @private */ ola.mobile.UniverseTab.prototype.hideAllFrames_ = function() { this.universe_frame.Hide(); this.uid_frame.Hide(); this.rdm_frame.Hide(); this.rdm_section_frame.Hide(); }; /** * Called when the universe tab is clicked */ ola.mobile.UniverseTab.prototype.update = function() { this.hideAllFrames_(); this.universe_frame.setAsBusy(); this.universe_list = undefined; this.active_universe = undefined; this.active_uid = undefined; this.active_section = undefined; this.universe_frame.Show(); this.ola_server.FetchUniversePluginList(); }; /** * Called when a new list of universes is received. * @param {Object} e the event object. * @private */ ola.mobile.UniverseTab.prototype.updateUniverseList_ = function(e) { if (this.universe_list == undefined) { this.universe_frame.Clear(); var universe_container = new goog.ui.Container(); universe_container.render(this.universe_frame.element); var tab = this; this.universe_list = new ola.common.SortedList( universe_container, new ola.UniverseControlFactory( function(item) { tab.universeSelected_(item.id()); })); } var items = new Array(); for (var i = 0; i < e.universes.length; ++i) { var item = new ola.UniverseItem(e.universes[i]); items.push(item); } this.universe_list.updateFromData(items); }; /** * Called when a universe is selected * @param {number} universe_id the id of the universe selected. * @private */ ola.mobile.UniverseTab.prototype.universeSelected_ = function(universe_id) { this.hideAllFrames_(); this.uid_frame.setAsBusy(); this.uid_list = undefined; this.rdm_list = undefined; this.active_universe = universe_id; this.uid_frame.Show(); var tab = this; this.ola_server.fetchUids( universe_id, function(e) { tab.updateUidList_(e); }); // setup a timer here }; /** * Called when a new list of uids is received. * @param {Object} e the event object. * @private */ ola.mobile.UniverseTab.prototype.updateUidList_ = function(e) { if (e.target.getStatus() != goog.net.HttpStatus.OK) { return; } if (this.uid_list == undefined) { this.uid_frame.Clear(); var uid_container = new goog.ui.Container(); uid_container.render(this.uid_frame.element); var tab = this; this.uid_list = new ola.common.SortedList( uid_container, new ola.common.UidControlFactory( function(item) { tab.uidSelected_(item.id()); })); var button = new goog.ui.Button('Back'); button.render(this.uid_frame.element); goog.events.listen(button, goog.ui.Component.EventType.ACTION, function() { this.update() }, false, this); } var obj = e.target.getResponseJson(); var uids = obj['uids']; var items = new Array(); for (var i = 0; i < uids.length; ++i) { items.push(new ola.common.UidItem(uids[i])); } this.uid_list.updateFromData(items); }; /** * Called when a uid is selected * @param {Object} uid the UID selected. * @private */ ola.mobile.UniverseTab.prototype.uidSelected_ = function(uid) { this.hideAllFrames_(); this.rdm_frame.setAsBusy(); this.rdm_list = undefined; this.active_uid = uid; this.rdm_frame.Show(); var tab = this; this.ola_server.rdmGetSupportedSections( this.active_universe, uid, function(e) { tab.updateSupportedSections_(e); }); }; /** * Called when a list of supported sections is received. * @param {Object} e the event object. * @private */ ola.mobile.UniverseTab.prototype.updateSupportedSections_ = function(e) { if (this.rdm_list == undefined) { this.rdm_frame.Clear(); var rdm_container = new goog.ui.Container(); rdm_container.render(this.rdm_frame.element); var tab = this; this.rdm_list = new ola.common.SortedList( rdm_container, new ola.common.RdmSectionControlFactory( function(item) { tab.sectionSelected_(item); })); var button = new goog.ui.Button('Back'); button.render(this.rdm_frame.element); goog.events.listen( button, goog.ui.Component.EventType.ACTION, function() { this.universeSelected_(this.active_universe) }, false, this); } var sections = e.target.getResponseJson(); var section_count = sections.length; var items = new Array(); for (var i = 0; i < section_count; ++i) { items.push(new ola.common.RdmSectionItem(sections[i])); } this.rdm_list.updateFromData(items); }; /** * Called when a section is selected * @param {Object} section the Section object. * @private */ ola.mobile.UniverseTab.prototype.sectionSelected_ = function(section) { this.hideAllFrames_(); this.rdm_section_frame.setAsBusy(); this.rdm_section_frame.Show(); this.active_section = section; this.loadSection_(); }; /** * Called when we need to load a section * @private */ ola.mobile.UniverseTab.prototype.loadSection_ = function() { var tab = this; this.ola_server.rdmGetSectionInfo( this.active_universe, this.active_uid, this.active_section.id(), this.active_section.hint(), function(e) { tab.updateSection_(e); }); }; /** * Called when a section is ready to be drawn * @param {Object} e the event object. * @private */ ola.mobile.UniverseTab.prototype.updateSection_ = function(e) { var section_response = e.target.getResponseJson(); this.rdm_section_frame.Clear(); var div = this.rdm_section_frame.element; div.innerHTML = ''; if (section_response['error']) { div.innerHTML = section_response['error']; return; } var items = section_response['items']; var count = items.length; var form = goog.dom.createElement('form'); form.id = this.active_section.id(); var tab = this; form.onsubmit = function() { tab.saveSection_(); return false}; var table = goog.dom.createElement('table'); table.className = 'ola-table'; var editable = false; for (var i = 0; i < count; ++i) { ola.common.SectionRenderer.RenderItem(table, items[i]); // if any field has an id and doesn't have it's own button we display the // save button. editable |= (items[i]['id'] && !items[i]['button']); } goog.dom.appendChild(form, table); goog.dom.appendChild(div, form); var button = new goog.ui.Button('Back'); button.render(div); goog.events.listen(button, goog.ui.Component.EventType.ACTION, function() { this.uidSelected_(this.active_uid) }, false, this); if (section_response['refresh']) { var button = new goog.ui.Button('Refresh'); button.render(div); goog.events.listen(button, goog.ui.Component.EventType.ACTION, function() { this.loadSection_() }, false, this); } if (editable) { var text = section_response['save_button'] || 'Save'; var button = new goog.ui.Button(text); button.render(div); goog.events.listen(button, goog.ui.Component.EventType.ACTION, function() { this.saveSection_() }, false, this); } this.items = section_response['items']; }; /** * Called when we need to save a section * @private */ ola.mobile.UniverseTab.prototype.saveSection_ = function() { var items = this.items; var count = items.length; var form = goog.dom.$(this.active_section.id()); var data = ''; for (var i = 0; i < count; ++i) { var id = items[i]['id']; if (id) { if (items[i]['type'] == 'uint') { // integer var value = form.elements[id].value; var int_val = parseInt(value); if (isNaN(int_val)) { this._showErrorDialog('Invalid Value', items[i]['description'] + ' must be an integer'); return; } var min = items[i]['min']; if (min != undefined && int_val < min) { this._showErrorDialog('Invalid Value', items[i]['description'] + ' must be > ' + (min - 1)); return; } var max = items[i]['max']; if (max != undefined && int_val > max) { this._showErrorDialog('Invalid Value', items[i]['description'] + ' must be < ' + (max + 1)); return; } data += id + '=' + value + '&'; } else if (items[i]['type'] == 'string') { var value = form.elements[id].value; data += id + '=' + value + '&'; } else if (items[i]['type'] == 'bool') { var checked = items[i]['object'].isChecked(); data += id + '=' + (checked ? '1' : '0') + '&'; } else if (items[i]['type'] == 'select') { var offset = items[i]['object'].getSelectedIndex(); var value = items[i]['value'][offset]['value']; data += id + '=' + value + '&'; } } } var tab = this; this.ola_server.rdmSetSectionInfo( this.active_universe, this.active_uid, this.active_section.id(), this.active_section.hint(), data, function(e) { tab.saveSectionComplete_(e); }); }; /** * Called when the save section completes. * @param {Object} e the event object. * @private */ ola.mobile.UniverseTab.prototype.saveSectionComplete_ = function(e) { var response = e.target.getResponseJson(); if (response['error']) { alert(response['error']); } else { // reload data this.loadSection_(); } }; ola-0.10.5.nojsmin/javascript/ola/full/0000755000175000017500000000000013155164170017346 5ustar wouterwouterola-0.10.5.nojsmin/javascript/ola/full/universe_frame.js0000644000175000017500000001276413023355232022723 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The universe frame. * Copyright (C) 2010 Simon Newton */ goog.require('goog.dom'); goog.require('goog.events'); goog.require('goog.ui.TabPane'); goog.require('ola.BaseFrame'); goog.require('ola.Dialog'); goog.require('ola.DmxConsoleTab'); goog.require('ola.DmxMonitorTab'); goog.require('ola.RDMPatcherTab'); goog.require('ola.RDMTab'); goog.require('ola.UniverseSettingsTab'); goog.require('ola.common.Server'); goog.provide('ola.UniverseFrame'); /** * The class representing the Universe frame * @param {string} element_id the id of the element to use for this frame. * @param {Object} ola_ui the OlaUI object. * @constructor */ ola.UniverseFrame = function(element_id, ola_ui) { ola.BaseFrame.call(this, element_id); this.ola_ui = ola_ui; this.current_universe = undefined; // setup the tab pane this.tabPane = new goog.ui.TabPane(goog.dom.$(element_id + '_tab_pane')); this.tabPane.addPage(new goog.ui.TabPane.TabPage( goog.dom.$('tab_page_1'), 'Settings')); this.tabPane.addPage(new goog.ui.TabPane.TabPage( goog.dom.$('tab_page_2'), 'RDM')); this.tabPane.addPage(new goog.ui.TabPane.TabPage( goog.dom.$('tab_page_3'), 'RDM Patcher')); this.tabPane.addPage(new goog.ui.TabPane.TabPage( goog.dom.$('tab_page_4'), 'DMX Monitor')); this.tabPane.addPage(new goog.ui.TabPane.TabPage( goog.dom.$('tab_page_5'), 'DMX Console')); this.tabs = new Array(); this.tabs.push( new ola.UniverseSettingsTab( 'tab_page_1', function() { ola_ui.ShowHome(); }) ); // We need to make the RDM pane visible here otherwise the splitter // doesn't render correctly. this.tabPane.setSelectedIndex(1); this.tabs.push(new ola.RDMTab('tab_page_2')); this.tabPane.setSelectedIndex(0); this.tabs.push(new ola.RDMPatcherTab('tab_page_3')); this.tabs.push(new ola.DmxMonitorTab('tab_page_4')); this.tabs.push(new ola.DmxConsoleTab('tab_page_5')); goog.events.listen(this.tabPane, goog.ui.TabPane.Events.CHANGE, this.updateSelectedTab_, false, this); var server = ola.common.Server.getInstance(); goog.events.listen(server, ola.common.Server.EventType.UNIVERSE_LIST_EVENT, this.newUniverseList_, false, this); }; goog.inherits(ola.UniverseFrame, ola.BaseFrame); /** * Set the size of the split pane to match the parent element * @param {Object} e the event object. */ ola.UniverseFrame.prototype.setSplitPaneSize = function(e) { var big_frame = goog.dom.$('ola-splitpane-content'); var big_size = goog.style.getBorderBoxSize(big_frame); var selected_tab = this.tabPane.getSelectedIndex(); this.tabs[selected_tab].sizeChanged(big_size); }; /** * Show this frame. We extend the base method so we can populate the correct * tab. * @param {number} universe_id the universe id to show. * @param {boolean} opt_select_main_tab set to true to display the main tab. */ ola.UniverseFrame.prototype.Show = function(universe_id, opt_select_main_tab) { if (this.current_universe != universe_id) { for (var i = 0; i < this.tabs.length; ++i) { this.tabs[i].setUniverse(universe_id); } this.current_universe = universe_id; } ola.UniverseFrame.superClass_.Show.call(this); if (opt_select_main_tab) { this.tabPane.setSelectedIndex(0); } this.updateSelectedTab_(); }; /** * Hide this frame. We extend the base method so we can notify the active tab. */ ola.UniverseFrame.prototype.Hide = function() { for (var i = 0; i < this.tabs.length; ++i) { if (this.tabs[i].isActive()) { this.tabs[i].setActive(false); } } ola.UniverseFrame.superClass_.Hide.call(this); }; /** * Update the tab that was selected * @param {Object} e the event object. * @private */ ola.UniverseFrame.prototype.updateSelectedTab_ = function(e) { if (!this.IsVisible()) { return; } for (var i = 0; i < this.tabs.length; ++i) { if (this.tabs[i].isActive()) { this.tabs[i].setActive(false); } } this.setSplitPaneSize(); var selected_tab = this.tabPane.getSelectedIndex(); this.tabs[selected_tab].setActive(true); }; /** * Called when new universes are available. We use this to detect if this * universe has been deleted. * @param {Object} e the event object. * @private */ ola.UniverseFrame.prototype.newUniverseList_ = function(e) { var found = false; for (var i = 0; i < e.universes.length; ++i) { if (e.universes[i]['id'] == this.current_universe) { found = true; break; } } if (this.IsVisible() && !found) { var dialog = ola.Dialog.getInstance(); dialog.setTitle('Universe ' + this.current_universe + ' Removed'); dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK); dialog.setContent('This universe has been removed by another user.'); dialog.setVisible(true); this.ola_ui.ShowHome(); } }; ola-0.10.5.nojsmin/javascript/ola/full/universe_settings_tab.js0000644000175000017500000002052113023355232024305 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The RDM patcher tab. * Copyright (C) 2010 Simon Newton */ goog.require('goog.events'); goog.require('goog.net.HttpStatus'); goog.require('goog.ui.AnimatedZippy'); goog.require('ola.AvailablePort'); goog.require('ola.AvailablePortTable'); goog.require('ola.Dialog'); goog.require('ola.Port'); goog.require('ola.PortTable'); goog.require('ola.common.BaseUniverseTab'); goog.require('ola.common.Server'); goog.provide('ola.UniverseSettingsTab'); /** * The class that manages the RDMPatcher. * @constructor */ ola.UniverseSettingsTab = function(element, on_remove) { ola.common.BaseUniverseTab.call(this, element); this.on_remove = on_remove; this.server = ola.common.Server.getInstance(); var save_button = goog.dom.$('universe_save_button'); goog.ui.decorate(save_button); goog.events.listen(save_button, goog.events.EventType.CLICK, function() { this.saveButtonClicked_(false); }, false, this); this.merge_mode = goog.ui.decorate(goog.dom.$('universe_merge_mode')); this.input_table = new ola.PortTable(); this.input_table.decorate(goog.dom.$('input_ports')); this.output_table = new ola.PortTable(); this.output_table.decorate(goog.dom.$('output_ports')); var z1 = new goog.ui.AnimatedZippy('additional_ports_expander', 'additional_ports'); this.available_ports = new ola.AvailablePortTable(); this.available_ports.decorate(goog.dom.$('universe_available_ports')); // setup notifications when the universe list changes goog.events.listen(this.server, ola.common.Server.EventType.UNIVERSE_EVENT, this.updateFromData_, false, this); }; goog.inherits(ola.UniverseSettingsTab, ola.common.BaseUniverseTab); /** * Set the universe for the patcher */ ola.UniverseSettingsTab.prototype.setUniverse = function(universe_id) { ola.UniverseSettingsTab.superClass_.setUniverse.call(this, universe_id); }; /** * Called when the view port size changes */ ola.UniverseSettingsTab.prototype.sizeChanged = function(frame_size) { ola.UniverseSettingsTab.superClass_.sizeChanged.call(this, frame_size); }; /** * Controls if we should do all the work involved in rendering the patcher. * This isn't needed if the patcher isn't visible. */ ola.UniverseSettingsTab.prototype.setActive = function(state) { ola.UniverseSettingsTab.superClass_.setActive.call(this, state); if (this.isActive()) this.updateView_(); }; /** * Fetch the latest data from the server to update the view * @private */ ola.UniverseSettingsTab.prototype.updateView_ = function() { this.server.FetchUniverseInfo(this.getUniverse()); this.available_ports.update(this.getUniverse()); }; /** * Update the tab from a Universe object * @param {Object} e the event object. * @private */ ola.UniverseSettingsTab.prototype.updateFromData_ = function(e) { if (this.getUniverse() != e.universe['id']) { ola.logger.info('Mismatched universe, expected ' + this.getUniverse() + ', got ' + e.universe['id']); return; } goog.dom.$('universe_id').innerHTML = e.universe['id']; goog.dom.$('universe_name').value = e.universe['name']; if (e.universe['merge_mode'] == 'HTP') { this.merge_mode.setSelectedIndex(0); } else { this.merge_mode.setSelectedIndex(1); } this.input_table.update(e.universe['input_ports']); this.output_table.update(e.universe['output_ports']); }; /** * Create a priority setting object from a port component * @param {Object} port_component the port component to generate the setting * from. * @param {Array.} setting_list the list to add the setting to. * @private */ ola.UniverseSettingsTab.prototype.generatePrioritySettingFromComponent_ = function(port_component, setting_list) { var priority = port_component.priority(); if (priority != undefined) { var priority_setting = new Object(); priority_setting.id = port_component.portId(); priority_setting.priority = priority; var priority_mode = port_component.priorityMode(); if (priority_mode != undefined) { priority_setting.mode = priority_mode; } setting_list.push(priority_setting); } }; /** * Called when the save button is clicked * @param {boolean} remove_confirmed true if the user confirmed the removal of * this universe. * @private */ ola.UniverseSettingsTab.prototype.saveButtonClicked_ = function( remove_confirmed) { var dialog = ola.Dialog.getInstance(); var port_priorities = new Array(); var remove_ports = new Array(); var one_port_selected = false; var count = this.input_table.getChildCount(); for (var i = 0; i < count; ++i) { var port = this.input_table.getChildAt(i); if (port.isSelected()) { one_port_selected = true; this.generatePrioritySettingFromComponent_(port, port_priorities); } else { remove_ports.push(port.portId()); } } var count = this.output_table.getChildCount(); for (var i = 0; i < count; ++i) { var port = this.output_table.getChildAt(i); if (port.isSelected()) { one_port_selected = true; this.generatePrioritySettingFromComponent_(port, port_priorities); } else { remove_ports.push(port.portId()); } } // figure out the new ports to add var new_ports = this.available_ports.getSelectedRows(); // if we're deleting the universe ask for confirmation if ((!one_port_selected) && new_ports.length == 0) { if (remove_confirmed) { this.was_removed = true; } else { goog.events.listen( dialog, goog.ui.Dialog.EventType.SELECT, this.removeConfirmed_, false, this); dialog.setTitle('Confirm Universe Removal'); dialog.setButtonSet(goog.ui.Dialog.ButtonSet.YES_NO); dialog.setContent( 'Removing all ports will cause this universe to be deleted. Is ' + 'this ok?'); dialog.setVisible(true); return; } } else { this.was_removed = false; } var name = goog.dom.$('universe_name').value; if (name == '') { dialog.setTitle('Empty Universe Name'); dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK); dialog.setContent('The universe name cannot be empty'); dialog.setVisible(true); return; } var tab = this; this.server.modifyUniverse( this.getUniverse(), name, this.merge_mode.getValue(), port_priorities, remove_ports, new_ports, function(e) { tab.saveCompleted_(e); }); var dialog = ola.Dialog.getInstance(); dialog.setAsBusy(); dialog.setVisible(true); }; /** * Called when the universe removal is confirmed * @param {Object} e the event object. * @private */ ola.UniverseSettingsTab.prototype.removeConfirmed_ = function(e) { var dialog = ola.Dialog.getInstance(); goog.events.unlisten( dialog, goog.ui.Dialog.EventType.SELECT, this.removeConfirmed_, false, this); if (e.key == goog.ui.Dialog.DefaultButtonKeys.YES) { dialog.setVisible(false); this.saveButtonClicked_(true); } }; /** * Called when the changes are saved * @param {Object} e the event object. * @private */ ola.UniverseSettingsTab.prototype.saveCompleted_ = function(e) { var dialog = ola.Dialog.getInstance(); if (e.target.getStatus() == goog.net.HttpStatus.OK) { dialog.setVisible(false); if (this.was_removed && this.on_remove) { this.on_remove(); } this.updateView_(); } else { dialog.setTitle('Failed to Save Settings'); dialog.setContent(e.target.getLastUri() + ' : ' + e.target.getLastError()); dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK); dialog.setVisible(true); } }; ola-0.10.5.nojsmin/javascript/ola/full/custom_dragscrollsupport.js0000644000175000017500000000375013023355232025067 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The custom OLA DragScrollSupport. * This adds an enable(bool) method so we can turn the scrolling behaviour on * and off. * Copyright (C) 2010 Simon Newton */ goog.require('goog.fx.DragScrollSupport'); goog.provide('ola.CustomDragScrollSupport'); ola.CustomDragScrollSupport = function(containerNode, opt_verticalMargin) { goog.fx.DragScrollSupport.call(this, containerNode, opt_verticalMargin, true); }; goog.inherits(ola.CustomDragScrollSupport, goog.fx.DragScrollSupport); ola.CustomDragScrollSupport.prototype.setEnabled = function(state) { if (state) { this.eventHandler_.listen(goog.dom.getOwnerDocument(this.containerNode_), goog.events.EventType.MOUSEMOVE, this.onMouseMove); } else { this.eventHandler_.unlisten(goog.dom.getOwnerDocument(this.containerNode_), goog.events.EventType.MOUSEMOVE, this.onMouseMove); } }; ola.CustomDragScrollSupport.prototype.updateBoundaries = function() { this.containerBounds_ = goog.style.getBounds(this.containerNode_); this.scrollBounds_ = this.verticalMargin_ ? this.constrainBounds_(this.containerBounds_.clone()) : this.containerBounds_; }; ola-0.10.5.nojsmin/javascript/ola/full/rdm_patcher.js0000644000175000017500000007377613023355232022213 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The RDM patcher. * Copyright (C) 2010 Simon Newton */ goog.require('goog.array'); goog.require('goog.dom'); goog.require('goog.dom.classes'); goog.require('goog.events'); goog.require('goog.math.Rect'); goog.require('goog.ui.Checkbox'); goog.require('goog.ui.MenuItem'); goog.require('goog.ui.Select'); goog.require('ola.CustomDragScrollSupport'); goog.require('ola.CustomDragger'); goog.require('ola.Dialog'); goog.require('ola.common.DmxConstants'); goog.require('ola.common.Server'); goog.require('ola.common.Server.EventType'); goog.require('ola.common.UidItem'); goog.provide('ola.RDMPatcher'); goog.provide('ola.RDMPatcherDevice'); /** * This represents a desired address change for a device * @constructor */ ola.RDMPatcherAddressChange = function(device, new_start_address) { this.device = device; this.new_start_address = new_start_address; }; /** * The model of an RDM device. * @param {string} uid the uid of the device. * @param {number} start_address the start address, from 1 - 512. * @param {number} footprint the number of dmx channels consumed. * @constructor */ ola.RDMPatcherDevice = function(uid, label, start_address, footprint, current_personality, personality_count) { this.uid = uid; this.label = label; // convert to 0 offset this.start = start_address - 1; this.footprint = footprint; this.current_personality = current_personality; this.personality_count = personality_count; this.setStart(start_address); this._divs = new Array(); }; /** * Set the start address of this device * @param {number} start_address the start address, from 1 - 512. */ ola.RDMPatcherDevice.prototype.setStart = function(start_address) { this.start = start_address - 1; this.updateEnd_(); }; /** * Set the footprint of this device * @param {number} footprint the footprint, from 1 - 512. */ ola.RDMPatcherDevice.prototype.setFootprint = function(footprint) { this.footprint = footprint; this.updateEnd_(); }; /** * Update the end address. * @private */ ola.RDMPatcherDevice.prototype.updateEnd_ = function() { this.end = Math.min(this.start + this.footprint - 1, ola.common.DmxConstants.MAX_CHANNEL_NUMBER); }; /** * Associated a div with this Device */ ola.RDMPatcherDevice.prototype.resetDivs = function() { for (var i = 0; i < this._divs.length; ++i) { goog.events.removeAll(this._divs[i]); } this._divs = new Array(); }; /** * Associated a div with this Device */ ola.RDMPatcherDevice.prototype.addDiv = function(div) { this._divs.push(div); }; /** * Get the list of divs associated with this device */ ola.RDMPatcherDevice.prototype.getDivs = function() { return this._divs; }; /** * Check if a device overflows the 512 channel count. */ ola.RDMPatcherDevice.prototype.overflows = function(div) { return ((this.start + this.footprint) > ola.common.DmxConstants.MAX_CHANNEL_NUMBER); }; /** * A comparison function used to sort an array of devices based on start * address. */ ola.RDMPatcherDevice.sortByAddress = function(a, b) { return a.start - b.start; }; /** * A comparison function used to sort an array of devices based on footprint. */ ola.RDMPatcherDevice.sortByFootprint = function(a, b) { return a.footprint - b.footprint; }; /** * The class representing the patcher. * @param {string} element_id the id of the element to use for this patcher. * @constructor */ ola.RDMPatcher = function(element_id, status_id) { this.element = goog.dom.$(element_id); this.status_line = goog.dom.$(status_id); this.universe_id = undefined; // this of RDMPatcherDevice objects this.devices = new Array(); // the top level divs that form each row this.rows = new Array(); // the background tds used to set the row height correctly this.background_tds = new Array(); // the tables that the device divs live in this.device_tables = new Array(); // store a reference to the draggers so we can clean the up properly this.draggers = new Array(); this.dialog = undefined; this.active_device = undefined; this.start_address_input = undefined; this.scroller = new ola.CustomDragScrollSupport(this.element); // the per-personality footprints for the active device this.personalities = undefined; // the queue of pending address changes for the auto patcher this.address_changes = new Array(); this.patching_failures = false; }; /* Constants */ /** The number of channels per row @type {number} */ ola.RDMPatcher.CHANNELS_PER_ROW = 8; /** The height of each row @type {number} */ ola.RDMPatcher.HEIGHT_PER_DEVICE = 14; /** The number of rows @type {number} */ ola.RDMPatcher.NUMBER_OF_ROWS = (ola.common.DmxConstants.MAX_CHANNEL_NUMBER / ola.RDMPatcher.CHANNELS_PER_ROW); /** * Called when the size of the patcher changes */ ola.RDMPatcher.prototype.sizeChanged = function(new_height) { this.element.style.height = new_height + 'px'; this.scroller.updateBoundaries(); }; /** * Set the list of devices. * @param {Array.} devices the list of RDMPatcherDevice * devices to set. */ ola.RDMPatcher.prototype.setDevices = function(devices) { this.devices = devices; }; /** * Set the universe this patcher is operating on * @param {number} universe_id the universe to use. */ ola.RDMPatcher.prototype.setUniverse = function(universe_id) { this.universe_id = universe_id; }; /** * Hide the patcher */ ola.RDMPatcher.prototype.hide = function() { // hide all the rows for (var i = 0; i < this.rows.length; ++i) { this.rows[i].style.display = 'none'; } }; /** * Render the patcher view. */ ola.RDMPatcher.prototype.update = function() { if (this.rows.length == 0) { this.setup_(); } for (var i = 0; i < this.rows.length; ++i) { this.rows[i].style.display = 'block'; } this.render_(); }; /** * A simple version of Auto patch. */ ola.RDMPatcher.prototype.autoPatch = function() { this.address_changes = new Array(); var channels_required = 0; // first work out how many channels we need; for (var i = 0; i < this.devices.length; ++i) { channels_required += this.devices[i].footprint; } // sort by ascending footprint this.devices.sort(ola.RDMPatcherDevice.sortByFootprint); if (channels_required > ola.common.DmxConstants.MAX_CHANNEL_NUMBER) { // we're going to have to overlap. to minimize overlapping we assign // largest footprint first var devices = this.devices.slice(0); while (devices.length) { var devices_next_round = new Array(); var channel = 0; var device; ola.logger.info('new round'); while (devices.length && channel < ola.common.DmxConstants.MAX_CHANNEL_NUMBER) { var device = devices.pop(); var remaining = ola.common.DmxConstants.MAX_CHANNEL_NUMBER - channel; ola.logger.info(device.label + ' : ' + device.footprint); if (device.footprint > remaining) { // deal with this device next round devices_next_round.unshift(device); ola.logger.info('deferring ' + device.label); } else { this.address_changes.push(new ola.RDMPatcherAddressChange( device, channel + 1)); ola.logger.info('set ' + device.label + ' to ' + channel); channel += device.footprint; } } devices = devices.concat(devices_next_round); } } else { // this is the easy case. Just assign starting with the smallest footprint. var channel = 0; for (var i = 0; i < this.devices.length; ++i) { this.address_changes.push(new ola.RDMPatcherAddressChange( this.devices[i], channel + 1)); channel += this.devices[i].footprint; } } if (this.address_changes.length) { var dialog = ola.Dialog.getInstance(); dialog.setAsBusy(); dialog.setVisible(true); // start the update sequence this.patching_failures = false; this.updateNextDevice_(); } }; /** * Setup the patcher * @private */ ola.RDMPatcher.prototype.setup_ = function() { for (var i = 0; i < ola.RDMPatcher.NUMBER_OF_ROWS; ++i) { var row_div = goog.dom.createElement('div'); row_div.className = 'patch_row'; this.rows.push(row_div); var spacer_table = goog.dom.createElement('table'); spacer_table.className = 'patcher_table'; var spacer_tr = goog.dom.createElement('tr'); spacer_tr.id = 'str_' + i; for (var j = 0; j < ola.RDMPatcher.CHANNELS_PER_ROW; ++j) { var td = goog.dom.createElement('td'); goog.dom.appendChild(spacer_tr, td); this.background_tds.push(td); } goog.dom.appendChild(spacer_table, spacer_tr); goog.dom.appendChild(row_div, spacer_table); var content_table = goog.dom.createElement('table'); content_table.className = 'content_table'; var title_tr = goog.dom.createElement('tr'); for (var j = 0; j < ola.RDMPatcher.CHANNELS_PER_ROW; ++j) { var td = goog.dom.createElement('td'); td.className = 'patcher_title'; td.innerHTML = 1 + i * ola.RDMPatcher.CHANNELS_PER_ROW + j; goog.dom.appendChild(title_tr, td); } goog.dom.appendChild(content_table, title_tr); this.device_tables.push(content_table); goog.dom.appendChild(row_div, content_table); goog.dom.appendChild(this.element, row_div); } }; /** * Render the patcher. * @private */ ola.RDMPatcher.prototype.render_ = function() { this.devices.sort(ola.RDMPatcherDevice.sortByAddress); // Each channel is assigned N slots, where N is the max number of devices // that occupy any one channel. We start out with a single slot, and add more // if we detect overlapping devices. var slots = new Array(); slots.push(goog.array.repeat( false, ola.common.DmxConstants.MAX_CHANNEL_NUMBER)); for (var i = 0; i < this.draggers.length; ++i) { goog.events.removeAll(this.draggers[i]); } this.draggers = new Array(); // for each device, figure out which slot it's going to live in for (var i = 0; i < this.devices.length; ++i) { var device = this.devices[i]; var found_free_slot = false; var slot; for (slot = 0; slot < slots.length; ++slot) { var channel; for (channel = device.start; channel <= device.end; ++channel) { if (slots[slot][channel]) break; } if (channel > device.end) { found_free_slot = true; break; } } if (!found_free_slot) { slots.push(goog.array.repeat( false, ola.common.DmxConstants.MAX_CHANNEL_NUMBER)); } // mark all appropriate channels in this slot as occupied. for (channel = device.start; channel <= device.end; ++channel) { slots[slot][channel] = device; } device.resetDivs(); } // calculate the first/last free slot & max unused channels var first_free_channel = ola.common.DmxConstants.MAX_CHANNEL_NUMBER; var last_free_channel = -1; var max_unused_channels = 0; var last_channel_used = true; var running_channel_count = 0; for (var channel = 0; channel < ola.common.DmxConstants.MAX_CHANNEL_NUMBER; ++channel) { var used = false; for (var slot = 0; slot < slots.length; ++slot) { if (slots[slot][channel]) { used = true; break; } } if (!used) { running_channel_count++; if (channel < first_free_channel) { first_free_channel = channel; } if (channel > last_free_channel) { last_free_channel = channel; } } if (used && !last_channel_used && running_channel_count > max_unused_channels) { max_unused_channels = running_channel_count; running_channel_count = 0; } last_channel_used = used; } if (running_channel_count > max_unused_channels) { max_unused_channels = running_channel_count; } // update the status line var status_line; if (first_free_channel == ola.common.DmxConstants.MAX_CHANNEL_NUMBER) { status_line = 'No slots free'; } else { first_free_channel++; last_free_channel++; status_line = ('Free slots: first: ' + first_free_channel + ', last: ' + last_free_channel + ', max contiguous: ' + max_unused_channels); } this.status_line.innerHTML = status_line; // now update the cell heights according to how many slots we need this.updateCellHeights_(slots.length); // now loop over all the rows in the patcher table, and render them for (var row = 0; row < this.device_tables.length; ++row) { var table = this.device_tables[row]; var offset = row * ola.RDMPatcher.CHANNELS_PER_ROW; var tr = goog.dom.getFirstElementChild(table); tr = goog.dom.getNextElementSibling(tr); var slot = 0; // updating in place leads to less chances of memory leaks in crappy // browers while (slot < slots.length) { if (tr == undefined) { tr = goog.dom.createElement('tr'); goog.dom.appendChild(table, tr); } else { var td = goog.dom.getFirstElementChild(tr); while (td != undefined) { goog.dom.removeChildren(td); td = goog.dom.getNextElementSibling(td); } } this.renderSlot_(tr, slots[slot], offset); tr = goog.dom.getNextElementSibling(tr); slot++; } while (tr != undefined) { var td = goog.dom.getFirstElementChild(tr); while (td != undefined) { goog.dom.removeChildren(td); td.colSpan = 1; td = goog.dom.getNextElementSibling(td); } tr = goog.dom.getNextElementSibling(tr); } } }; /** * Render a slot in the patcher table. * @param {element} tr the row to use. May contain tds already. * @private */ ola.RDMPatcher.prototype.renderSlot_ = function(tr, slot_data, start_channel) { var channel = start_channel; var end_channel = start_channel + ola.RDMPatcher.CHANNELS_PER_ROW; var td = goog.dom.getFirstElementChild(tr); while (channel < end_channel) { if (td == undefined) { td = goog.dom.createElement('td'); goog.dom.appendChild(tr, td); } td.colSpan = 1; td.className = ''; if (slot_data[channel]) { var device = slot_data[channel]; td.className = 'patcher_occupied_cell'; // work out the number of channels this spans var remaining_length = device.end - channel + 1; var colspan = Math.min(remaining_length, end_channel - channel); td.colSpan = colspan; channel += colspan; // create a new div var div = goog.dom.createElement('div'); div.innerHTML = device.label; if (device.overflows()) { div.className = 'patcher_overflow_device'; div.title = 'Device overflows the ' + ola.common.DmxConstants.MAX_CHANNEL_NUMBER + ' slot limit'; } else { div.className = 'patcher_device'; } device.addDiv(div); goog.dom.appendChild(td, div); goog.events.listen( div, goog.events.EventType.CLICK, function(d) { return function(e) { this.configureDevice_(d, e); }; }(device), false, this); // setup the dragger var dragger = new ola.CustomDragger(div); dragger.setScrollTarget(this.element); dragger.setHysteresis(8); goog.events.listen( dragger, goog.fx.Dragger.EventType.START, function(d1, d2, d3) { return function(e) { this.startDrag_(d1, d2, e); }; }(div, device), false, this); goog.events.listen( dragger, goog.fx.Dragger.EventType.END, function(d1, d2) { return function(e) { this.endDrag_(d1, d2, e); }; }(div, device), false, this); dragger.setScrollTarget(this.element); this.draggers.push(dragger); } else { channel++; } td = goog.dom.getNextElementSibling(td); } while (td != undefined) { var next = goog.dom.getNextElementSibling(td); goog.dom.removeNode(td); td = next; } }; /** * Called when we start dragging a device * @private */ ola.RDMPatcher.prototype.startDrag_ = function(div, device, e) { // remove any other divs associated with this device var device_divs = device.getDivs(); for (var i = 0; i < device_divs.length; ++i) { if (div != device_divs[i]) { goog.dom.removeNode(device_divs[i]); } } var row_table = goog.dom.getFirstElementChild(this.element); while (!goog.dom.classes.has(row_table, 'patch_row')) { row_table = goog.dom.getNextElementSibling(row_table); } var row_table_size = goog.style.getBorderBoxSize(row_table); // figure out the cell size, remember to account for the borders this.cell_width = row_table_size.width / ola.RDMPatcher.CHANNELS_PER_ROW - 1; // reparent the div and set the styles correctly goog.dom.appendChild(this.element, div); div.className = 'draggable_device'; goog.style.setOpacity(div, 0.50); div.style.width = this.cell_width + 'px'; // set the position of the div to center under the mouse cursor var div_size = goog.style.getBorderBoxSize(div); var patcher_offset = goog.style.getClientPosition(this.element); div.style.top = (this.element.scrollTop + e.clientY - patcher_offset.y - div_size.height / 2) + 'px'; div.style.left = (e.clientX - patcher_offset.x - div_size.width / 2) + 'px'; // set the limits of the drag actions var patcher_height = ola.RDMPatcher.NUMBER_OF_ROWS * this.cell_height; e.dragger.setLimits(new goog.math.Rect( 0, 0, row_table_size.width - div_size.width - 1, patcher_height - div_size.height - 1)); this.scroller.setEnabled(true); return true; }; /** * Called when the dragging finishes * @private */ ola.RDMPatcher.prototype.endDrag_ = function(div, device, e) { goog.style.setOpacity(div, 1); this.scroller.setEnabled(false); var box = goog.style.getBorderBoxSize(div); var deltaX = Math.max(0, e.dragger.deltaX); var deltaY = Math.max(0, e.dragger.deltaY); var center_x = Math.min( deltaX + (box.width / 2), this.cell_width * ola.RDMPatcher.CHANNELS_PER_ROW - 1); var center_y = Math.min( deltaY + (box.height / 2), this.cell_height * ola.RDMPatcher.NUMBER_OF_ROWS - 1); var new_start_address = (Math.floor(center_x / this.cell_width) + ola.RDMPatcher.CHANNELS_PER_ROW * Math.floor(center_y / this.cell_height)); goog.dom.removeNode(div); this.setStartAddress_(device, new_start_address + 1); }; /** * Update the heights of the cells, given the current layout of devices * @private */ ola.RDMPatcher.prototype.updateCellHeights_ = function(overlapping_devices) { // +1 for the title row, and always render at least one row so it looks nice var rows = 1 + Math.max(1, overlapping_devices); var height = rows * ola.RDMPatcher.HEIGHT_PER_DEVICE; for (var i = 0; i < this.rows.length; ++i) { this.rows[i].style.height = height + 'px'; } for (var i = 0; i < this.background_tds.length; ++i) { this.background_tds[i].style.height = (height - 1) + 'px'; } this.cell_height = height; }; /** * Called when the user clicks on a device to configure it. * @param {Object} e the event object. * @private */ ola.RDMPatcher.prototype.configureDevice_ = function(device, e) { if (!e.target.parentNode) { // this was a drag action and the div has been removed, don't show the // dialog. return; } if (this.dialog == undefined) { this.dialog = new goog.ui.Dialog(null, true); this.dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK_CANCEL); goog.events.listen(this.dialog, goog.ui.Dialog.EventType.SELECT, this.saveDevice_, false, this); var table = goog.dom.createElement('table'); // start address var tr = goog.dom.createElement('tr'); var td = goog.dom.createElement('td'); td.innerHTML = 'Start Address'; goog.dom.appendChild(tr, td); td = goog.dom.createElement('td'); this.start_address_input = goog.dom.createElement('input'); goog.dom.appendChild(td, this.start_address_input); goog.dom.appendChild(tr, td); goog.dom.appendChild(table, tr); // personality var tr = goog.dom.createElement('tr'); var td = goog.dom.createElement('td'); td.innerHTML = 'Personality'; goog.dom.appendChild(tr, td); td = goog.dom.createElement('td'); td.noWrap = true; goog.dom.appendChild(tr, td); this.personality_select = new goog.ui.Select(); this.personality_select.render(td); this.personality_spinner = goog.dom.createElement('img'); this.personality_spinner.src = '/loader-mini.gif'; this.personality_spinner.style.display = 'none'; this.personality_spinner.style.verticalAlign = 'middle'; goog.dom.appendChild(td, this.personality_spinner); this.personality_row = tr; goog.dom.appendChild(table, tr); goog.events.listen( this.personality_select, goog.ui.Component.EventType.ACTION, this.setPersonality_, false, this); // now do the identify checkbox tr = goog.dom.createElement('tr'); td = goog.dom.createElement('td'); td.innerHTML = 'Identify'; goog.dom.appendChild(tr, td); td = goog.dom.createElement('td'); td.noWrap = true; var check = new goog.ui.Checkbox(); check.render(td); goog.events.listen( check, goog.ui.Component.EventType.CHANGE, this.toggleIdentify_, false, this); this.identify_box = check; this.identify_spinner = goog.dom.createElement('img'); this.identify_spinner.src = '/loader-mini.gif'; this.identify_spinner.style.display = 'none'; this.identify_spinner.style.verticalAlign = 'middle'; goog.dom.appendChild(td, this.identify_spinner); goog.dom.appendChild(tr, td); goog.dom.appendChild(table, tr); var content = this.dialog.getContentElement(); goog.dom.appendChild(content, table); } this.active_device = device; // fetch the identify mode var server = ola.common.Server.getInstance(); var patcher = this; server.rdmGetUIDIdentifyMode( this.universe_id, device.uid, function(e) { patcher.getIdentifyComplete_(e); }); this.personality_row.style.display = 'none'; var dialog = ola.Dialog.getInstance(); dialog.setAsBusy(); dialog.setVisible(true); }; /** * Called when the get identify mode completes. * @param {Object} e the event object. * @private */ ola.RDMPatcher.prototype.getIdentifyComplete_ = function(e) { var response = ola.common.Server.getInstance().checkForErrorLog(e); if (response != undefined) { var mode = (response['identify_mode'] ? goog.ui.Checkbox.State.CHECKED : goog.ui.Checkbox.State.UNCHECKED); this.identify_box.setChecked(mode); } if (this.active_device.personality_count == undefined || this.active_device.personality_count < 2) { this.displayConfigureDevice_(); } else { var server = ola.common.Server.getInstance(); var patcher = this; server.rdmGetUIDPersonalities( this.universe_id, this.active_device.uid, function(e) { patcher.getPersonalitiesComplete_(e); }); } }; /** * Called when the fetch personalities completes. * @param {Object} e the event object. * @private */ ola.RDMPatcher.prototype.getPersonalitiesComplete_ = function(e) { var response = ola.common.Server.getInstance().checkForErrorLog(e); if (response != undefined) { // remove all items from select for (var i = (this.personality_select.getItemCount() - 1); i >= 0; --i) { this.personality_select.removeItemAt(i); } this.personalities = new Array(); personalities = response['personalities']; for (var i = 0; i < personalities.length; ++i) { if (personalities[i]['footprint'] > 0) { var label = (personalities[i]['name'] + ' (' + personalities[i]['footprint'] + ')'); var item = new goog.ui.MenuItem(label); this.personality_select.addItem(item); if (response['selected'] == i + 1) { this.personality_select.setSelectedItem(item); } this.personalities.push(personalities[i]); } } this.personality_row.style.display = 'table-row'; } this.displayConfigureDevice_(); }; /** * Display the configure device dialog * @private */ ola.RDMPatcher.prototype.displayConfigureDevice_ = function(e) { ola.Dialog.getInstance().setVisible(false); this.start_address_input.value = this.active_device.start + 1; this.dialog.setTitle(this.active_device.label); this.dialog.setVisible(true); this.start_address_input.focus(); }; /** * Save the start address for a device * @param {Object} e the event object. * @private */ ola.RDMPatcher.prototype.saveDevice_ = function(e) { if (e.key == goog.ui.Dialog.DefaultButtonKeys.CANCEL || this.start_address_input == undefined || this.active_device == undefined) { return; } var value = parseInt(this.start_address_input.value); if (isNaN(value) || value < ola.common.DmxConstants.MIN_CHANNEL_NUMBER || value > ola.common.DmxConstants.MAX_CHANNEL_NUMBER) { alert('Must be between ' + ola.common.DmxConstants.MIN_CHANNEL_NUMBER + ' and ' + ola.common.DmxConstants.MAX_CHANNEL_NUMBER); return; } this.setStartAddress_(this.active_device, value); }; /** * Called to set the start address of a device * @private */ ola.RDMPatcher.prototype.setStartAddress_ = function(device, start_address) { var server = ola.common.Server.getInstance(); var patcher = this; server.rdmSetSectionInfo( this.universe_id, device.uid, 'dmx_address', '', 'address=' + start_address, function(e) { patcher.setStartAddressComplete_(device, start_address, e); }); var dialog = ola.Dialog.getInstance(); dialog.setAsBusy(); dialog.setVisible(true); }; /** * Called when the start address set command completes * @private */ ola.RDMPatcher.prototype.setStartAddressComplete_ = function(device, start_address, e) { var response = ola.common.Server.getInstance().checkForErrorDialog(e); if (response != undefined) { var dialog = ola.Dialog.getInstance(); dialog.setVisible(false); device.setStart(start_address); } this.render_(); }; /** * Set the personality. * @param {Object} e the event object. * @private */ ola.RDMPatcher.prototype.setPersonality_ = function(e) { var server = ola.common.Server.getInstance(); this.personality_spinner.style.display = 'inline'; var selected = this.personalities[e.target.getSelectedIndex()]; var patcher = this; var new_footprint = selected['footprint']; server.rdmSetSectionInfo( this.universe_id, this.active_device.uid, 'personality', '', 'int=' + selected['index'], function(e) { patcher.personalityComplete_(e, new_footprint); }); }; /** * Called when the set personality request completes. * @param {Object} e the event object. * @private */ ola.RDMPatcher.prototype.personalityComplete_ = function(e, new_footprint) { this.personality_spinner.style.display = 'none'; var response = ola.common.Server.getInstance().checkForErrorDialog(e); if (response == undefined) { this.dialog.setVisible(false); } else { this.active_device.setFootprint(new_footprint); this.render_(); } }; /** * Toggle the identify mode * @param {Object} e the event object. * @private */ ola.RDMPatcher.prototype.toggleIdentify_ = function(e) { var server = ola.common.Server.getInstance(); this.identify_spinner.style.display = 'inline'; var patcher = this; server.rdmSetSectionInfo( this.universe_id, this.active_device.uid, 'identify_device', '', 'bool=' + (e.target.isChecked() ? '1' : '0'), function(e) { patcher.identifyComplete_(e); }); }; /** * Called when the identify request completes. * @param {Object} e the event object. * @private */ ola.RDMPatcher.prototype.identifyComplete_ = function(e) { this.identify_spinner.style.display = 'none'; var response = ola.common.Server.getInstance().checkForErrorDialog(e); if (response == undefined) { this.dialog.setVisible(false); } }; /** * Update the start address for the next device in the queue. * @param {Object} e the event object. * @private */ ola.RDMPatcher.prototype.updateNextDevice_ = function(e) { var server = ola.common.Server.getInstance(); var address_change = this.address_changes[0]; var patcher = this; server.rdmSetSectionInfo( this.universe_id, address_change.device.uid, 'dmx_address', '', 'address=' + address_change.new_start_address, function(e) { patcher.updateStartAddressComplete_(e); }); }; /** * Called when a device's start address is updated. * @param {Object} e the event object. * @private */ ola.RDMPatcher.prototype.updateStartAddressComplete_ = function(e) { var response = ola.common.Server.getInstance().checkForErrorLog(e); var address_change = this.address_changes.shift(); if (response == undefined) { // mark as error this.patching_failures = true; } else { address_change.device.setStart(address_change.new_start_address); } if (this.address_changes.length) { this.updateNextDevice_(); } else { var dialog = ola.Dialog.getInstance(); if (this.patching_failures) { dialog.setTitle('Failed to Set Start Address'); dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK); dialog.setContent( 'Some devices failed to change their DMX start address, ' + ' click refresh to fetch the current state.'); dialog.setVisible(true); } else { dialog.setVisible(false); } this.render_(); } }; ola-0.10.5.nojsmin/javascript/ola/full/base_universe_tab.js0000644000175000017500000000376013023355232023365 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The base class for the tabs used in the universe pane. * Copyright (C) 2010 Simon Newton */ goog.require('goog.math'); goog.require('goog.style'); goog.provide('ola.common.BaseUniverseTab'); /** * The base tab for the universe view. * @param {element} element the element to use for the tab. * @constructor */ ola.common.BaseUniverseTab = function(element) { this.element = goog.dom.$(element); this.active = false; this.universe_id = undefined; }; /** * Called when the universe changes. */ ola.common.BaseUniverseTab.prototype.setUniverse = function(universe_id) { this.universe_id = universe_id; }; /** * Get the current universe; */ ola.common.BaseUniverseTab.prototype.getUniverse = function() { return this.universe_id; }; /** * Called when the view port size changes */ ola.common.BaseUniverseTab.prototype.sizeChanged = function(frame_size) { goog.style.setBorderBoxSize( this.element, new goog.math.Size(frame_size.width - 7, frame_size.height - 34)); }; /** * Called when the tab becomes visible. */ ola.common.BaseUniverseTab.prototype.setActive = function(state) { this.active = state; }; /** * Returns true if this tab is active (visible); */ ola.common.BaseUniverseTab.prototype.isActive = function() { return this.active; }; ola-0.10.5.nojsmin/javascript/ola/full/available_port_table.js0000644000175000017500000001304313023355232024033 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The table that holds a list of available ports. * Copyright (C) 2010 Simon Newton */ goog.require('goog.dom'); goog.require('goog.events'); goog.require('goog.ui.Checkbox'); goog.require('goog.ui.Component'); goog.require('ola.LoggerWindow'); goog.require('ola.common.Server'); goog.provide('ola.AvailablePort'); goog.provide('ola.AvailablePortTable'); /** * A row in the available ports list. * @param {Object} data the data to build this row from. * @constructor */ ola.AvailablePort = function(data, opt_domHelper) { goog.ui.Component.call(this, opt_domHelper); this.data = data; }; goog.inherits(ola.AvailablePort, goog.ui.Component); /** * This component can't be used to decorate * @return {bool} false. */ ola.AvailablePort.prototype.canDecorate = function() { return false; }; /** * Create the dom for this component */ ola.AvailablePort.prototype.createDom = function() { var tr = this.dom_.createDom('tr', {}); tr.style.cursor = 'pointer'; var td = goog.dom.createDom('td', {}, ''); this.dom_.appendChild(tr, td); this.checkbox = new goog.ui.Checkbox(); this.checkbox.render(td); this.dom_.appendChild(tr, goog.dom.createDom('td', {}, this.data['device'])); this.dom_.appendChild(tr, goog.dom.createDom('td', {}, this.data['is_output'] ? 'Output' : 'Input')); this.dom_.appendChild(tr, goog.dom.createDom('td', {}, this.data['description'])); this.setElementInternal(tr); }; /** * Attach the listener. */ ola.AvailablePort.prototype.enterDocument = function() { ola.AvailablePort.superClass_.enterDocument.call(this); goog.events.listen(this.getElement(), goog.events.EventType.CLICK, function() { this.checkbox.toggle(); }, false, this); }; /** * Clean up this object. */ ola.AvailablePort.prototype.exitDocument = function() { ola.AvailablePort.superClass_.exitDocument.call(this); this.checkbox.exitDocument(); goog.events.removeAll(this.getElement()); }; /** * Dispose of this object. */ ola.AvailablePort.prototype.dispose = function() { if (!this.getDisposed()) { ola.AvailablePort.superClass_.dispose.call(this); this.checkbox.dispose(); } }; /** * Get the port id for this item * @return {string} the id of this port. */ ola.AvailablePort.prototype.portId = function() { return this.data['id']; }; /** * Check is this row was selected * @return {boolean} true if selected, false otherwise. */ ola.AvailablePort.prototype.isSelected = function() { return this.checkbox.isChecked(); }; /** * An available port table component. * @constructor */ ola.AvailablePortTable = function(opt_domHelper) { goog.ui.Component.call(this, opt_domHelper); }; goog.inherits(ola.AvailablePortTable, goog.ui.Component); /** * Create the dom for the AvailablePortTable * @param {Element} container the dom element to decorate. */ ola.AvailablePortTable.prototype.createDom = function(container) { this.decorateInternal(this.dom_.createElement('tbody')); }; /** * Decorate an existing element */ ola.AvailablePortTable.prototype.decorateInternal = function(element) { ola.AvailablePortTable.superClass_.decorateInternal.call(this, element); }; /** * Check if we can decorate an element. * @param {Element} element the dom element to check. * @return {boolean} true if this element can be decorated, false otherwise. */ ola.AvailablePortTable.prototype.canDecorate = function(element) { return element.tagName == 'TBODY'; }; /** * Returns the list of selected ports * @return {Array.} */ ola.AvailablePortTable.prototype.getSelectedRows = function() { var selected_ports = new Array(); var count = this.getChildCount(); for (var i = 0; i < count; ++i) { var port = this.getChildAt(i); if (port.isSelected()) { selected_ports.push(port.portId()); } } return selected_ports; }; /** * Clear all rows from this table */ ola.AvailablePortTable.prototype.removeAllRows = function() { while (this.getChildCount()) { var row = this.removeChildAt(0, true); row.dispose(); } }; /** * Update the list of available ports * @param {number} universe_id the id of the universe to fetch the available * ports for. */ ola.AvailablePortTable.prototype.update = function(universe_id) { var table = this; ola.common.Server.getInstance().fetchAvailablePorts( universe_id, function(e) { table.updateCompleted_(e); }); }; /** * Called when the list of available ports is returned * @private */ ola.AvailablePortTable.prototype.updateCompleted_ = function(e) { if (!ola.common.Server.getInstance().checkStatusDialog(e)) { return; } this.removeAllRows(); var ports = e.target.getResponseJson(); var port_length = ports.length; for (var i = 0; i < port_length; ++i) { var component = new ola.AvailablePort(ports[i]); this.addChild(component, true); } }; ola-0.10.5.nojsmin/javascript/ola/full/rdm_attributes_panel.js0000644000175000017500000003123413023355232024111 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The RDM attributes panel. * Copyright (C) 2010 Simon Newton */ goog.require('goog.Timer'); goog.require('goog.dom'); goog.require('goog.events'); goog.require('goog.ui.AnimatedZippy'); goog.require('goog.ui.Checkbox'); goog.require('goog.ui.Component'); goog.require('goog.ui.Component.EventType'); goog.require('goog.ui.Control'); goog.require('goog.ui.Option'); goog.require('goog.ui.Select'); goog.require('ola.Dialog'); goog.require('ola.common.SectionRenderer'); goog.require('ola.common.Server'); goog.require('ola.common.Server.EventType'); goog.provide('ola.RDMAttributesPanel'); /** * The class representing the panel. * @param {string} element_id the id of the element to use for this frame. * @constructor */ ola.RDMAttributesPanel = function(element_id, toolbar) { this.element = goog.dom.$(element_id); this.current_universe = undefined; this.current_uid = undefined; this.divs = new Array(); this.zippies = new Array(); // This holds the list of sections, and is updated as a section is loaded this.section_data = undefined; this.expander_button = toolbar.getChild('showAllSectionsButton'); this.expander_button.setTooltip('Show All Attributes'); this.expander_button.setEnabled(false); goog.events.listen(this.expander_button, goog.ui.Component.EventType.ACTION, function() { this.expandAllSections_(); }, false, this); this.collapse_button = toolbar.getChild('hideAllSectionsButton'); this.collapse_button.setTooltip('Hide All Attributes'); this.collapse_button.setEnabled(false); goog.events.listen(this.collapse_button, goog.ui.Component.EventType.ACTION, function() { this.hideAllSections_(); }, false, this); var refresh_menu = toolbar.getChild('refreshButton'); refresh_menu.setTooltip('Configure how often attributes are refreshed'); goog.events.listen(refresh_menu, goog.ui.Component.EventType.ACTION, this.refreshChanged_, false, this); this.refresh_timer = new goog.Timer(30000); goog.events.listen( this.refresh_timer, goog.Timer.TICK, this.refreshEvent_, false, this); }; /** * The mapping of strings to timeout intervals. */ ola.RDMAttributesPanel.RefreshInterval = { '30s': 30000, '1m': 60000, '5m': 300000 }; /** * Change the current universe. * @param {number} universe_id the current universe. */ ola.RDMAttributesPanel.prototype.updateUniverse = function(universe_id) { this.current_universe = universe_id; this.current_uid = undefined; }; /** * Show the attributes for a particular UID. * @param {ola.UidItem} item the uid to show. */ ola.RDMAttributesPanel.prototype.showUID = function(item) { this.setLoading_(this.element); var server = ola.common.Server.getInstance(); var panel = this; server.rdmGetSupportedSections( this.current_universe, item.asString(), function(e) { panel.supportedSections_(e); }); this.current_uid = item.asString(); this.expander_button.setEnabled(true); this.collapse_button.setEnabled(true); }; /** * Clear the panel. */ ola.RDMAttributesPanel.prototype.clear = function() { this.current_uid = undefined; this.expander_button.setEnabled(false); this.collapse_button.setEnabled(false); this.setEmpty_(); }; /** * Expand all the sections. * @private */ ola.RDMAttributesPanel.prototype.expandAllSections_ = function() { for (var i = 0; i < this.zippies.length; ++i) { if (!this.zippies[i].isExpanded()) { this.zippies[i].setExpanded(true); this.expandSection_(i); } } }; /** * Hide all the sections. * @private */ ola.RDMAttributesPanel.prototype.hideAllSections_ = function() { for (var i = 0; i < this.zippies.length; ++i) { if (this.zippies[i].isExpanded()) { this.zippies[i].setExpanded(false); } } }; /** * Set the refresh rate * @param {Object} e the event object. * @private */ ola.RDMAttributesPanel.prototype.refreshChanged_ = function(e) { var value = e.target.getCaption(); if (value == 'Never') { this.refresh_timer.stop(); } else { var timeout = ola.RDMAttributesPanel.RefreshInterval[value]; if (timeout != undefined) { this.refresh_timer.setInterval(timeout); } else { ola.logger.info('Invalid timeout ' + value); } this.refresh_timer.start(); } }; /** * Called when the refresh timer fires * @private */ ola.RDMAttributesPanel.prototype.refreshEvent_ = function(e) { for (var i = 0; i < this.zippies.length; ++i) { if (this.zippies[i].isExpanded()) { this.loadSection_(i); } } }; /** * Display the 'empty' page. * @private */ ola.RDMAttributesPanel.prototype.setEmpty_ = function() { this.element.innerHTML = ''; }; /** * Display the loading image * @private */ ola.RDMAttributesPanel.prototype.setLoading_ = function(element) { element.innerHTML = ( '
' + '
Loading...
'); }; /** * Called when the supported sections request completes. * @param {Object} e the event object. * @private */ ola.RDMAttributesPanel.prototype.supportedSections_ = function(e) { this.element.innerHTML = ''; this.divs = new Array(); this.zippies = new Array(); var sections = e.target.getResponseJson(); var section_count = sections.length; for (var i = 0; i < section_count; ++i) { var section = obj[i]; var fieldset = goog.dom.createElement('fieldset'); var legend = goog.dom.createElement('legend'); var image = goog.dom.createElement('img'); image.src = '/blank.gif'; image.width = '12'; image.height = '12'; goog.dom.appendChild(legend, image); var title = goog.dom.createTextNode(' ' + sections[i]['name']); goog.dom.appendChild(legend, title); var div = goog.dom.createElement('div'); div.align = 'center'; this.setLoading_(div); goog.dom.appendChild(fieldset, legend); goog.dom.appendChild(fieldset, div); goog.dom.appendChild(this.element, fieldset); var z = new goog.ui.AnimatedZippy(legend, div); this.divs.push(div); this.zippies.push(z); goog.events.listen(legend, goog.events.EventType.CLICK, (function(x) { return function(e) { if (e.expanded) return; this.expandSection_(x); } })(i), false, this); sections['data'] = undefined; sections['loaded'] = false; } this.section_data = sections; }; /** * Called when one of the zippies is expanded * @private */ ola.RDMAttributesPanel.prototype.expandSection_ = function(index) { if (this.section_data[index]['loaded']) return; this.loadSection_(index); }; /** * Load the contents for a zippy section * @private */ ola.RDMAttributesPanel.prototype.loadSection_ = function(index) { var server = ola.common.Server.getInstance(); var panel = this; server.rdmGetSectionInfo( this.current_universe, this.current_uid, this.section_data[index]['id'], this.section_data[index]['hint'], function(e) { panel.populateSection_(e, index); }); this.section_data[index]['loaded'] = true; }; /** * Populate a zippy * @param {Object} e the event object. * @param {int} index the index of the zippy to populate. * @private */ ola.RDMAttributesPanel.prototype.populateSection_ = function(e, index) { var section_response = e.target.getResponseJson(); var div = this.divs[index]; div.innerHTML = ''; if (section_response['error']) { var error_title = 'Error: ' + this.section_data[index]['name']; this.showErrorDialog_(error_title, section_response['error']); this.section_data[index]['loaded'] = false; var zippy = this.zippies[index]; if (zippy.isExpanded()) { zippy.setExpanded(false); } return; } var panel = this; // used in the onsubmit handler below var items = section_response['items']; var count = items.length; var form = goog.dom.createElement('form'); form.id = this.section_data[index]['id']; form.onsubmit = function() { panel.saveSection_(index); return false}; var table = goog.dom.createElement('table'); table.className = 'ola-table'; var editable = false; for (var i = 0; i < count; ++i) { ola.common.SectionRenderer.RenderItem(table, items[i]); // if any field has an id and doesn't have it's own button we display the // save button. editable |= (items[i]['id'] && !items[i]['button']); } goog.dom.appendChild(form, table); goog.dom.appendChild(div, form); if (section_response['refresh']) { var button = new goog.ui.CustomButton('Refresh'); button.render(div); goog.events.listen(button, goog.ui.Component.EventType.ACTION, function() { this.loadSection_(index) }, false, this); } if (editable) { var text = section_response['save_button'] || 'Save'; var button = new goog.ui.CustomButton(text); button.render(div); goog.events.listen(button, goog.ui.Component.EventType.ACTION, function() { this.saveSection_(index) }, false, this); } this.section_data[index]['data'] = section_response; }; /** * Save the contents of a section. * @private */ ola.RDMAttributesPanel.prototype.saveSection_ = function(index) { var items = this.section_data[index]['data']['items']; var count = items.length; var form = goog.dom.$(this.section_data[index]['id']); var data = ''; for (var i = 0; i < count; ++i) { var id = items[i]['id']; if (id) { if (items[i]['type'] == 'uint') { // integer var value = form.elements[id].value; var int_val = parseInt(value); if (isNaN(int_val)) { this.showErrorDialog_('Invalid Value', items[i]['description'] + ' must be an integer'); return; } var min = items[i]['min']; if (min != undefined && int_val < min) { this.showErrorDialog_('Invalid Value', items[i]['description'] + ' must be > ' + (min - 1)); return; } var max = items[i]['max']; if (max != undefined && int_val > max) { this.showErrorDialog_('Invalid Value', items[i]['description'] + ' must be < ' + (max + 1)); return; } data += id + '=' + value + '&'; } else if (items[i]['type'] == 'string') { var value = form.elements[id].value; data += id + '=' + value + '&'; } else if (items[i]['type'] == 'bool') { var checked = items[i]['object'].isChecked(); data += id + '=' + (checked ? '1' : '0') + '&'; } else if (items[i]['type'] == 'select') { var offset = items[i]['object'].getSelectedIndex(); var value = items[i]['value'][offset]['value']; data += id + '=' + value + '&'; } } } var server = ola.common.Server.getInstance(); var panel = this; server.rdmSetSectionInfo( this.current_universe, this.current_uid, this.section_data[index]['id'], this.section_data[index]['hint'], data, function(e) { panel.saveSectionComplete_(e, index); }); }; /** * Called when the save is complete * @param {Object} e the event object. * @private */ ola.RDMAttributesPanel.prototype.saveSectionComplete_ = function(e, index) { var response = e.target.getResponseJson(); if (response['error']) { var error_title = 'Set ' + this.section_data[index]['name'] + ' Failed'; this.showErrorDialog_(error_title, response['error']); } else { // reload data this.loadSection_(index); } }; /** * Show the dialog with an error message * @private */ ola.RDMAttributesPanel.prototype.showErrorDialog_ = function(title, error) { var dialog = ola.Dialog.getInstance(); dialog.setTitle(title); dialog.setContent(error); dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK); dialog.setVisible(true); }; ola-0.10.5.nojsmin/javascript/ola/full/custom_dragger.js0000644000175000017500000000452313023355232022710 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The custom OLA dragger. * This overrides the initializeDrag_to update deltaX & deltaY after START has * been fired. This is needed because we re-parent the target when we start * dragging. * Copyright (C) 2010 Simon Newton */ goog.require('goog.fx.Dragger'); goog.provide('ola.CustomDragger'); ola.CustomDragger = function(target, opt_handle, opt_limits) { goog.fx.Dragger.call(this, target, opt_handle, opt_limits); }; goog.inherits(ola.CustomDragger, goog.fx.Dragger); /** * Event handler that is used to start the drag * @param {goog.events.BrowserEvent|goog.events.Event} e Event object. * @private */ ola.CustomDragger.prototype.initializeDrag_ = function(e) { var rv = this.dispatchEvent(new goog.fx.DragEvent( goog.fx.Dragger.EventType.START, this, e.clientX, e.clientY, /** @type {goog.events.BrowserEvent} */(e))); if (rv !== false) { this.deltaX = this.target.offsetLeft; this.deltaY = this.target.offsetTop; this.dragging_ = true; } ola.logger.info('delta from parent: ' + this.deltaX + ', ' + this.deltaY); }; ola.CustomDragger.prototype.calculatePosition_ = function(dx, dy) { // Update the position for any change in body scrolling var pageScroll = new goog.math.Coordinate(this.scrollTarget_.scrollLeft, this.scrollTarget_.scrollTop); dx += pageScroll.x - this.pageScroll.x; dy += pageScroll.y - this.pageScroll.y; this.pageScroll = pageScroll; this.deltaX += dx; this.deltaY += dy; var x = this.limitX(this.deltaX); var y = this.limitY(this.deltaY); return new goog.math.Coordinate(x, y); }; ola-0.10.5.nojsmin/javascript/ola/full/dmx_console.js0000644000175000017500000002464013023355232022217 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The dmx console. * Copyright (C) 2010 Simon Newton */ goog.require('goog.dom'); goog.require('goog.events'); goog.require('goog.ui.Component'); goog.require('goog.ui.Container'); goog.require('goog.ui.Control'); goog.require('goog.ui.Slider'); goog.require('goog.ui.Toolbar'); goog.require('goog.ui.ToolbarButton'); goog.require('goog.ui.ToolbarSeparator'); goog.require('ola.common.DmxConstants'); goog.provide('ola.DmxConsole'); /** * The class representing the console. * @constructor */ ola.DmxConsole = function() { this.setup = false; this.sliders = new Array(); this.slider_values = new Array(); this.data = new Array(ola.common.DmxConstants.MAX_CHANNEL_NUMBER); this.value_cells = new Array(); this.slider_offset = 0; }; goog.inherits(ola.DmxConsole, goog.events.EventTarget); /** The number of sliders to render @type {number} */ ola.DmxConsole.NUMBER_OF_SLIDERS = 16; /** The name of the change event @type {string} */ ola.DmxConsole.CHANGE_EVENT = 'console-change-event'; /** * We use events here so we can throttle the rate. * @constructor */ ola.DmxConsoleChangeEvent = function() { goog.events.Event.call(this, ola.DmxConsole.CHANGE_EVENT); }; goog.inherits(ola.DmxConsoleChangeEvent, goog.events.Event); /** * Return the console data as an array * @return {Array.} a list of channel data from the console. */ ola.DmxConsole.prototype.getData = function() { return this.data; }; /** * Set the data for this console */ ola.DmxConsole.prototype.setData = function(data) { var data_length = Math.min(ola.common.DmxConstants.MAX_CHANNEL_NUMBER, data.length); for (var i = 0; i < data_length; ++i) { this.data[i] = data[i]; } for (var i = data_length; i < ola.common.DmxConstants.MAX_CHANNEL_NUMBER; ++i) { this.data[i] = 0; } this.updateSliderOffsets_(); var data_length = this.data.length; for (var i = 0; i < data_length; ++i) { this.setCellValue_(i, this.data[i]); } }; /** * Reset the console. This resets the underlying data but doesn't update the * screen. */ ola.DmxConsole.prototype.resetConsole = function() { var data_length = this.data.length; for (var i = 0; i < data_length; ++i) { this.data[i] = 0; } this.slider_offset = 0; }; /** * Setup the console if it hasn't already been setup */ ola.DmxConsole.prototype.setupIfRequired = function() { if (this.setup) { return; } // setup the toolbar var toolbar = new goog.ui.Toolbar(); this.previous_page_button = new goog.ui.ToolbarButton( goog.dom.createDom('div', 'ola-icon ola-icon-prev')); this.previous_page_button.setTooltip('Previous Page'); this.next_page_button = new goog.ui.ToolbarButton( goog.dom.createDom('div', 'ola-icon ola-icon-next')); this.next_page_button.setTooltip('Next Page'); this.previous_page_button.setEnabled(false); var blackout_button = new goog.ui.ToolbarButton( goog.dom.createDom('div', 'ola-icon ola-icon-dbo')); blackout_button.setTooltip('Set all channels to 0'); var full_button = new goog.ui.ToolbarButton( goog.dom.createDom('div', 'ola-icon ola-icon-full')); full_button.setTooltip('Set all channels to full'); toolbar.addChild(this.previous_page_button, true); toolbar.addChild(this.next_page_button, true); toolbar.addChild(new goog.ui.ToolbarSeparator(), true); toolbar.addChild(blackout_button, true); toolbar.addChild(full_button, true); toolbar.render(goog.dom.getElement('console_toolbar')); goog.events.listen(this.previous_page_button, goog.ui.Component.EventType.ACTION, this.previousPageClicked_, false, this); goog.events.listen(this.next_page_button, goog.ui.Component.EventType.ACTION, this.nextPageClicked_, false, this); goog.events.listen(blackout_button, goog.ui.Component.EventType.ACTION, this.blackoutButtonClicked_, false, this); goog.events.listen(full_button, goog.ui.Component.EventType.ACTION, this.fullButtonClicked_, false, this); // setup the value display var value_table = goog.dom.$('channel_values'); for (var i = 0; i < ola.common.DmxConstants.MAX_CHANNEL_NUMBER; ++i) { var div = goog.dom.createElement('div'); div.innerHTML = 0; div.title = 'Channel ' + (i + 1); goog.dom.appendChild(value_table, div); this.value_cells.push(div); } // setup the sliders var channel_row = goog.dom.$('console_channel_row'); var value_row = goog.dom.$('console_value_row'); var slider_row = goog.dom.$('console_slider_row'); for (var i = 0; i < ola.DmxConsole.NUMBER_OF_SLIDERS; ++i) { var channel_td = goog.dom.createElement('td'); channel_td.innerHTML = i + 1; goog.dom.appendChild(channel_row, channel_td); var value_td = goog.dom.createElement('td'); value_td.innerHTML = '0'; goog.dom.appendChild(value_row, value_td); this.slider_values.push(value_td); var slider_td = goog.dom.createElement('td'); goog.dom.appendChild(slider_row, slider_td); var slider = new goog.ui.Slider; slider.setOrientation(goog.ui.Slider.Orientation.VERTICAL); slider.setMinimum(0); slider.setMaximum(ola.common.DmxConstants.MAX_CHANNEL_VALUE); slider.render(slider_td); goog.events.listen( slider, goog.ui.Component.EventType.CHANGE, (function(offset) { return function() { this.sliderChanged_(offset) }; } )(i), false, this); this.sliders.push(slider); } this.setup = true; // zero data this.setAllChannels_(ola.common.DmxConstants.MIN_CHANNEL_VALUE); }; /** * Update the console to reflect the data. This is called when it becomes * visible. */ ola.DmxConsole.prototype.update = function() { // set the state of the prev / next buttons if (this.slider_offset == 0) { this.previous_page_button.setEnabled(false); } else { this.previous_page_button.setEnabled(true); } if (this.slider_offset == ola.common.DmxConstants.MAX_CHANNEL_NUMBER - ola.DmxConsole.NUMBER_OF_SLIDERS) { this.next_page_button.setEnabled(false); } else { this.next_page_button.setEnabled(true); } }; /** * Called when the next page button is clicked * @private */ ola.DmxConsole.prototype.nextPageClicked_ = function() { this.slider_offset += ola.DmxConsole.NUMBER_OF_SLIDERS; this.previous_page_button.setEnabled(true); var page_limit = (ola.common.DmxConstants.MAX_CHANNEL_NUMBER - ola.DmxConsole.NUMBER_OF_SLIDERS); if (this.slider_offset >= page_limit) { this.slider_offset = page_limit; this.next_page_button.setEnabled(false); } this.updateSliderOffsets_(); }; /** * Called when the previous page button is clicked * @private */ ola.DmxConsole.prototype.previousPageClicked_ = function() { this.slider_offset -= ola.DmxConsole.NUMBER_OF_SLIDERS; this.next_page_button.setEnabled(true); if (this.slider_offset <= 0) { this.slider_offset = 0; this.previous_page_button.setEnabled(false); } this.updateSliderOffsets_(); }; /** * Update the slider offsets. * @private */ ola.DmxConsole.prototype.updateSliderOffsets_ = function() { var channel_row = goog.dom.$('console_channel_row'); var td = goog.dom.getFirstElementChild(channel_row); var i = this.slider_offset; while (i < this.data.length && td != undefined) { td.innerHTML = i + 1; i++; td = goog.dom.getNextElementSibling(td); } // set the values of the sliders for (var i = 0; i < this.sliders.length; ++i) { this.sliders[i].setValue(this.data[this.slider_offset + i]); } }; /** * Called when the blackout button is clicked. * @private */ ola.DmxConsole.prototype.blackoutButtonClicked_ = function() { this.setAllChannels_(ola.common.DmxConstants.MIN_CHANNEL_VALUE); }; /** * Called when the full on button is clicked. * @private */ ola.DmxConsole.prototype.fullButtonClicked_ = function() { this.setAllChannels_(ola.common.DmxConstants.MAX_CHANNEL_VALUE); }; /** * Set all channels to a value. * @param {number} value the value to set all channels to. * @private */ ola.DmxConsole.prototype.setAllChannels_ = function(value) { var data_length = this.data.length; for (var i = 0; i < data_length; ++i) { this.data[i] = value; this.setCellValue_(i, value); } for (var i = 0; i < this.sliders.length; ++i) { this.sliders[i].setValue(value); } this.dispatchEvent(new ola.DmxConsoleChangeEvent()); }; /** * Called when the value of a slider changes. * @param {number} offset the offset of the slider that changed. * @private */ ola.DmxConsole.prototype.sliderChanged_ = function(offset) { var value = this.sliders[offset].getValue(); this.slider_values[offset].innerHTML = value; var channel = this.slider_offset + offset; this.setCellValue_(channel, value); if (this.data[channel] != value) { this.data[channel] = value; this.dispatchEvent(new ola.DmxConsoleChangeEvent()); } }; /** * Set the value of a channel cell * @param {number} offset the channel offset. * @param {number} value the value to set the channel to. * @private */ ola.DmxConsole.prototype.setCellValue_ = function(offset, value) { var element = this.value_cells[offset]; if (element == undefined) { return; } element.innerHTML = value; var remaining = ola.common.DmxConstants.MAX_CHANNEL_VALUE - value; element.style.background = 'rgb(' + remaining + ',' + remaining + ',' + remaining + ')'; if (value > ola.common.DmxConstants.BACKGROUND_CHANGE_CHANNEL_LEVEL) { element.style.color = '#ffffff'; } else { element.style.color = '#000000'; } }; ola-0.10.5.nojsmin/javascript/ola/full/rdm_patcher_tab.js0000644000175000017500000001651113023355232023021 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The RDM patcher tab. * Copyright (C) 2010 Simon Newton */ goog.require('goog.dom'); goog.require('goog.ui.Toolbar'); goog.require('goog.ui.ToolbarButton'); goog.require('goog.ui.ToolbarMenuButton'); goog.require('goog.ui.ToolbarSeparator'); goog.require('ola.Dialog'); goog.require('ola.RDMPatcher'); goog.require('ola.RDMPatcherDevice'); goog.require('ola.common.BaseUniverseTab'); goog.require('ola.common.Server'); goog.require('ola.common.UidItem'); goog.provide('ola.RDMPatcherTab'); /** * The tab for the RDM patcher. * @constructor * @param {Element} element the DOM element to use. */ ola.RDMPatcherTab = function(element) { ola.common.BaseUniverseTab.call(this, element); var toolbar = new goog.ui.Toolbar(); toolbar.decorate(goog.dom.$('patcher_toolbar')); var autopatch_button = toolbar.getChild('autoPatchButton'); autopatch_button.setTooltip('Automatically Patch Devices'); goog.events.listen(autopatch_button, goog.ui.Component.EventType.ACTION, function() { this.autoPatchButtonClicked_(); }, false, this); var refresh_button = toolbar.getChild('patcherRefreshButton'); refresh_button.setTooltip('Refresh Devices'); goog.events.listen(refresh_button, goog.ui.Component.EventType.ACTION, function() { this.update_(); }, false, this); this.patcher = new ola.RDMPatcher('patcher_div', 'patcher_status'); // These are devices that we know exist, but we don't have the start address // or footprint for. this.pending_devices = new Array(); // These are devices that we have all the info for. this.devices = new Array(); this.loading_div = goog.dom.createElement('div'); this.loading_div.style.width = '100%'; this.loading_div.style.textAlign = 'center'; this.loading_div.innerHTML = '
Loading...'; this.loading_div.style.marginTop = '10px'; goog.dom.appendChild(goog.dom.$('patcher_div'), this.loading_div); }; goog.inherits(ola.RDMPatcherTab, ola.common.BaseUniverseTab); /** * Set the universe for the patcher */ ola.RDMPatcherTab.prototype.setUniverse = function(universe_id) { ola.RDMPatcherTab.superClass_.setUniverse.call(this, universe_id); this.patcher.setUniverse(universe_id); this.pending_devices = new Array(); this.patcher.setDevices(new Array()); }; /** * Called when the view port size changes */ ola.RDMPatcherTab.prototype.sizeChanged = function(frame_size) { ola.RDMPatcherTab.superClass_.sizeChanged.call(this, frame_size); // tab bar: 34, toolbar: 27, status line 16, extra: 5 this.patcher.sizeChanged(frame_size.height - 34 - 27 - 16 - 5); }; /** * Controls if we should do all the work involved in rendering the patcher. * This isn't needed if the patcher isn't visible. */ ola.RDMPatcherTab.prototype.setActive = function(state) { ola.RDMPatcherTab.superClass_.setActive.call(this, state); if (!this.isActive()) return; this.update_(); }; /** * Called when the UID list changes. * @param {Object} e the event object. * @private */ ola.RDMPatcherTab.prototype.updateUidList_ = function(e) { var response = ola.common.Server.getInstance().checkForErrorLog(e); if (response == undefined) { return; } // It would be really nice to re-used the old values so we didn't have to // re-fetch everything but until we have some notification mechanism we can't // risk caching stale data. this.pending_devices = new Array(); this.devices = new Array(); var uids = e.target.getResponseJson()['uids']; for (var i = 0; i < uids.length; ++i) { this.pending_devices.push(new ola.common.UidItem(uids[i])); } if (this.isActive()) { this.fetchNextDeviceOrRender_(); } }; /** * Fetch the information for the next device in the list, or render the patcher * if we've run out of devices. * @private */ ola.RDMPatcherTab.prototype.fetchNextDeviceOrRender_ = function() { // fetch the new device in the list if (!this.pending_devices.length) { this.patcher.setDevices(this.devices); this.loading_div.style.display = 'none'; this.patcher.update(); return; } var server = ola.common.Server.getInstance(); var device = this.pending_devices.shift(); ola.logger.info('Fetching device ' + device.asString()); var tab = this; server.rdmGetUIDInfo( this.getUniverse(), device.asString(), function(e) { tab.deviceInfoComplete_(device, e); }); }; /** * Called when we get new information for a device * @param {Object} e the event object. * @private */ ola.RDMPatcherTab.prototype.deviceInfoComplete_ = function(device, e) { if (!this.isActive()) { return; } var response = ola.common.Server.getInstance().checkForErrorLog(e); if (response == undefined) { this.fetchNextDeviceOrRender_(); return; } var label = device.deviceName(); if (label) { label += ' [' + device.asString() + ']'; } else { label = device.asString(); } if (response['footprint'] > 0) { this.devices.push( new ola.RDMPatcherDevice( device.asString(), label, response['address'], response['footprint'], response['personality'], response['personality_count']) ); } this.fetchNextDeviceOrRender_(); }; /** * Fetch the devices and render * @private */ ola.RDMPatcherTab.prototype.update_ = function() { // we've just become visible this.patcher.hide(); this.loading_div.style.display = 'block'; var server = ola.common.Server.getInstance(); var tab = this; server.fetchUids( this.universe_id, function(e) { tab.updateUidList_(e); }); }; /** * Called when the user clicks on the auto patch button * @private */ ola.RDMPatcherTab.prototype.autoPatchButtonClicked_ = function() { var dialog = ola.Dialog.getInstance(); dialog.setTitle('Confirm Auto Patch'); dialog.setButtonSet(goog.ui.Dialog.ButtonSet.YES_NO); dialog.setContent('This will change the start addresses of all devices.' + ' Are you sure you want to continue?'); goog.events.listen( dialog, goog.ui.Dialog.EventType.SELECT, this.autoPatchConfirmed_, false, this); dialog.setVisible(true); }; /** * Called when the auto patch is confirmed * @param {Object} e the event object. * @private */ ola.RDMPatcherTab.prototype.autoPatchConfirmed_ = function(e) { var dialog = ola.Dialog.getInstance(); goog.events.unlisten(dialog, goog.ui.Dialog.EventType.SELECT, this.autoPatchButtonClicked_, false, this); if (e.key == goog.ui.Dialog.DefaultButtonKeys.YES) { this.patcher.autoPatch(); return false; } }; ola-0.10.5.nojsmin/javascript/ola/full/dmx_console_tab.js0000644000175000017500000000575413023355232023052 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The DMX console tab. * Copyright (C) 2010 Simon Newton */ goog.require('goog.Timer'); goog.require('goog.events'); goog.require('ola.DmxConsole'); goog.require('ola.common.BaseUniverseTab'); goog.require('ola.common.Server'); goog.provide('ola.DmxConsoleTab'); /** * The DMX console tab. * @constructor */ ola.DmxConsoleTab = function(element) { ola.common.BaseUniverseTab.call(this, element); // setup the console this.dmx_console = new ola.DmxConsole(); this.tick_timer = new goog.Timer(1000); this.mute_events = true; goog.events.listen( this.tick_timer, goog.Timer.TICK, this.consoleChanged_, false, this); goog.events.listen( this.dmx_console, ola.DmxConsole.CHANGE_EVENT, this.consoleChanged_, false, this); }; goog.inherits(ola.DmxConsoleTab, ola.common.BaseUniverseTab); /** * Set the universe. */ ola.DmxConsoleTab.prototype.setUniverse = function(universe_id) { ola.DmxConsoleTab.superClass_.setUniverse.call(this, universe_id); this.dmx_console.resetConsole(); }; /** * Called when the tab changes visibiliy. */ ola.DmxConsoleTab.prototype.setActive = function(state) { ola.DmxConsoleTab.superClass_.setActive.call(this, state); if (this.isActive()) { this.mute_events = true; this.dmx_console.setupIfRequired(); this.dmx_console.update(); this.loadValues(); } else { this.tick_timer.stop(); } }; /** * Fetches the new DMX values. */ ola.DmxConsoleTab.prototype.loadValues = function(e) { var t = this; ola.common.Server.getInstance().getChannelValues( this.getUniverse(), function(data) { t.newValues(data['dmx']); }); }; /** * Update the console with the new values */ ola.DmxConsoleTab.prototype.newValues = function(data) { this.dmx_console.setData(data); this.mute_events = false; if (this.isActive()) this.tick_timer.start(); }; /** * Called when the console values change * @private */ ola.DmxConsoleTab.prototype.consoleChanged_ = function(e) { if (this.mute_events) { return; } this.mute_events = true; var data = this.dmx_console.getData(); var t = this; ola.common.Server.getInstance().setChannelValues( this.getUniverse(), data, function(e) { t.mute_events = false; }); }; ola-0.10.5.nojsmin/javascript/ola/full/dmx_monitor_tab.js0000644000175000017500000000451513023355232023071 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The DMX monitor tab. * Copyright (C) 2012 Simon Newton */ goog.require('goog.events'); goog.require('goog.ui.Toolbar'); goog.require('ola.common.BaseUniverseTab'); goog.require('ola.common.DmxMonitor'); goog.provide('ola.DmxMonitorTab'); /** * The DMX monitor tab. * @constructor */ ola.DmxMonitorTab = function(element) { ola.common.BaseUniverseTab.call(this, element); this.dmx_monitor = new ola.common.DmxMonitor( goog.dom.$('monitor_values')); this.setup = false; }; goog.inherits(ola.DmxMonitorTab, ola.common.BaseUniverseTab); /** * Called when the tab changes visibiliy. */ ola.DmxMonitorTab.prototype.setActive = function(state) { ola.DmxMonitorTab.superClass_.setActive.call(this, state); if (this.isActive() && !this.setup) { // setup the toolbar var toolbar = new goog.ui.Toolbar(); toolbar.decorate(goog.dom.$('monitor_toolbar')); var view_button = toolbar.getChild('monitor_view_button'); view_button.setTooltip('Change the DMX Monitor layout'); goog.events.listen(view_button, goog.ui.Component.EventType.ACTION, this.viewChanged_, false, this); this.setup = true; } this.dmx_monitor.setState(state, this.getUniverse()); }; /** * Called when the view changes * @param {Object} e the event object. * @private */ ola.DmxMonitorTab.prototype.viewChanged_ = function(e) { var value = e.target.getCaption(); if (value == 'Full') { goog.dom.$('monitor_values').className = 'monitor_full'; } else { goog.dom.$('monitor_values').className = 'monitor_compact'; } }; ola-0.10.5.nojsmin/javascript/ola/full/rdm_tab.js0000644000175000017500000001462713023355232021321 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The RDM Tab. * Copyright (C) 2010 Simon Newton */ goog.require('goog.Timer'); goog.require('goog.dom'); goog.require('goog.events'); goog.require('goog.math'); goog.require('goog.net.HttpStatus'); goog.require('goog.ui.Component'); goog.require('goog.ui.Container'); goog.require('goog.ui.SplitPane'); goog.require('goog.ui.SplitPane.Orientation'); goog.require('goog.ui.Toolbar'); goog.require('goog.ui.ToolbarButton'); goog.require('goog.ui.ToolbarMenuButton'); goog.require('goog.ui.ToolbarSeparator'); goog.require('ola.Dialog'); goog.require('ola.RDMAttributesPanel'); goog.require('ola.common.BaseUniverseTab'); goog.require('ola.common.Server'); goog.require('ola.common.Server'); goog.require('ola.common.Server.EventType'); goog.require('ola.common.SortedList'); goog.require('ola.common.UidControl'); goog.require('ola.common.UidControlFactory'); goog.provide('ola.RDMTab'); /** * The RDM Tab. * @constructor */ ola.RDMTab = function(element) { ola.common.BaseUniverseTab.call(this, element); var toolbar = new goog.ui.Toolbar(); toolbar.decorate(goog.dom.$('rdm_toolbar')); var discovery_button = toolbar.getChild('discoveryButton'); discovery_button.setTooltip('Run full RDM discovery for this universe'); goog.events.listen(discovery_button, goog.ui.Component.EventType.ACTION, function() { this.discoveryButtonClicked_(true); }, false, this); var incremental_discovery_button = toolbar.getChild( 'incrementalDiscoveryButton'); incremental_discovery_button.setTooltip( 'Run incremental RDM discovery for this universe'); goog.events.listen(incremental_discovery_button, goog.ui.Component.EventType.ACTION, function() { this.discoveryButtonClicked_(false); }, false, this); this.splitpane = new goog.ui.SplitPane( new goog.ui.Component(), new goog.ui.Component(), goog.ui.SplitPane.Orientation.HORIZONTAL); this.splitpane.setInitialSize(250); this.splitpane.setHandleSize(2); this.splitpane.decorate(goog.dom.$('rdm_split_pane')); var rdm_panel = new ola.RDMAttributesPanel('rdm_attributes', toolbar); this.rdm_panel = rdm_panel; var frame = this; var uid_container = new goog.ui.Container(); uid_container.decorate(goog.dom.$('uid_container')); this.uid_list = new ola.common.SortedList( uid_container, new ola.common.UidControlFactory( function(item) { rdm_panel.showUID(item); })); // setup the uid timer this.uid_timer = new goog.Timer(ola.RDMTab.UID_REFRESH_INTERVAL); goog.events.listen( this.uid_timer, goog.Timer.TICK, this.updateUidList_, false, this); }; goog.inherits(ola.RDMTab, ola.common.BaseUniverseTab); /** * How often to refresh the list of UIDs. * @type {number} */ ola.RDMTab.UID_REFRESH_INTERVAL = 5000; /** * Set the universe for the patcher */ ola.RDMTab.prototype.setUniverse = function(universe_id) { ola.RDMTab.superClass_.setUniverse.call(this, universe_id); this.rdm_panel.updateUniverse(universe_id); this.rdm_panel.clear(); }; /** * Called when the view port size changes */ ola.RDMTab.prototype.sizeChanged = function(frame_size) { // don't call the base method. this.splitpane.setSize( new goog.math.Size(frame_size.width - 7, frame_size.height - 67)); }; /** * Controls if we should do all the work involved in rendering the patcher. * This isn't needed if the patcher isn't visible. */ ola.RDMTab.prototype.setActive = function(state) { ola.RDMTab.superClass_.setActive.call(this, state); this.updateUidList_(); if (this.isActive()) { this.updateUidList_(); } else { this.uid_timer.stop(); } }; /** * Fetch the uid list * @private */ ola.RDMTab.prototype.updateUidList_ = function() { var tab = this; var server = ola.common.Server.getInstance(); server.fetchUids( this.getUniverse(), function(e) { tab.newUIDs_(e); }); this.uid_timer.start(); }; /** * Update the UID list * @param {Object} e the event object. * @private */ ola.RDMTab.prototype.newUIDs_ = function(e) { if (e.target.getStatus() != goog.net.HttpStatus.OK) { ola.logger.info('Request failed: ' + e.target.getLastUri() + ' : ' + e.target.getLastError()); return; } this.updateUIDList_(e); }; /** * Called when the discovery button is clicked. * @private */ ola.RDMTab.prototype.discoveryButtonClicked_ = function(full) { var server = ola.common.Server.getInstance(); var tab = this; server.runRDMDiscovery( this.getUniverse(), full, function(e) { tab.discoveryComplete_(e); }); var dialog = ola.Dialog.getInstance(); dialog.setAsBusy(); dialog.setTitle('RDM Discovery Running...'); dialog.setVisible(true); }; /** * Called when the discovery request returns. * @param {Object} e the event object. * @private */ ola.RDMTab.prototype.discoveryComplete_ = function(e) { var dialog = ola.Dialog.getInstance(); dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK); if (e.target.getStatus() == goog.net.HttpStatus.OK) { dialog.setVisible(false); this.updateUIDList_(e); } else { dialog.setTitle('Failed to Start Discovery Process'); dialog.setContent(e.target.getLastUri() + ' : ' + e.target.getLastError()); dialog.setVisible(true); } }; /** * Update the UID list from a http response * @param {Object} e the event object. * @private */ ola.RDMTab.prototype.updateUIDList_ = function(e) { var obj = e.target.getResponseJson(); var uids = obj['uids']; var items = new Array(); for (var i = 0; i < uids.length; ++i) { items.push(new ola.common.UidItem(uids[i])); } this.uid_list.updateFromData(items); }; ola-0.10.5.nojsmin/javascript/ola/full/plugin_frame.js0000644000175000017500000001026013023355232022346 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The plugin frame. * Copyright (C) 2010 Simon Newton */ goog.require('goog.dom'); goog.require('goog.events'); goog.require('goog.string'); goog.require('ola.BaseFrame'); goog.require('ola.common.PluginItem'); goog.require('ola.common.Server'); goog.require('ola.common.Server.EventType'); goog.provide('ola.PluginFrame'); /** * The class representing the Plugin frame * @param {string} element_id the ID of the element to use. * @constructor */ ola.PluginFrame = function(element_id, show_plugin_fn) { ola.BaseFrame.call(this, element_id); this._show_plugin_fn = show_plugin_fn; goog.events.listen( ola.common.Server.getInstance(), ola.common.Server.EventType.PLUGIN_EVENT, this.UpdateFromData_, false, this); this.controls = new Array(); }; goog.inherits(ola.PluginFrame, ola.BaseFrame); /** * Update this plugin frame from a Plugin object * @param {ola.PluginChangeEvent} e the plugin event. * @private */ ola.PluginFrame.prototype.UpdateFromData_ = function(e) { goog.dom.$('plugin_name').innerHTML = e.plugin['name']; goog.dom.$('plugin_preference_source').innerHTML = e.plugin['preferences_source']; var enabled_span = goog.dom.$('plugin_enabled'); if (e.plugin['enabled']) { enabled_span.innerHTML = 'Yes'; enabled_span.className = 'plugin_enabled'; } else { enabled_span.innerHTML = 'No'; enabled_span.className = 'plugin_disabled'; } var active_span = goog.dom.$('plugin_active'); if (e.plugin['active']) { active_span.innerHTML = 'Yes'; active_span.className = 'plugin_enabled'; } else { active_span.innerHTML = 'No'; active_span.className = 'plugin_disabled'; } var possible_conflicts = e.plugin['enabled'] && !e.plugin['active']; var conflict_row = goog.dom.$('plugin_conflict_row'); var conflict_list = e.plugin['conflicts_with']; if (conflict_list.length) { conflict_row.style.display = 'table-row'; // remove old controls for (var i = 0; i < this.controls.length; ++i) { this.controls[i].dispose(); } this.controls = new Array(); var conflicts = goog.dom.$('plugin_conflict_list'); conflicts.innerHTML = ''; // add new controls for (var i = 0; i < conflict_list.length; ++i) { var plugin = conflict_list[i]; var control = new goog.ui.Control( goog.dom.createDom('span', null, plugin['name'])); control.render(conflicts); this.AttachListener_(control, plugin['id']); this.controls.push(control); if (possible_conflicts && plugin['active']) { var icon = goog.dom.createDom('img', {'src': '/warning.png'}); goog.dom.appendChild(conflicts, icon); } goog.dom.appendChild(conflicts, goog.dom.createDom('br')); } } else { conflict_row.style.display = 'none'; } var description = goog.string.htmlEscape(e.plugin['description']); description = description.replace(/\\n/g, '
'); goog.dom.$('plugin_description').innerHTML = description; }; /** * Called when a plugin name is clicked. * @param {ola.int} id the plugin id. * @private */ ola.PluginFrame.prototype.PluginControlClicked_ = function(id) { this._show_plugin_fn(id); }; /** * Attach a listener to a control. * @private */ ola.PluginFrame.prototype.AttachListener_ = function(control, plugin_id) { goog.events.listen(control, goog.ui.Component.EventType.ACTION, function(e) { this.PluginControlClicked_(plugin_id); }, false, this); }; ola-0.10.5.nojsmin/javascript/ola/universe_item.js0000644000175000017500000000412313023355232021613 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Object that represent a universe. * Copyright (C) 2010 Simon Newton */ goog.require('ola.common.DataItem'); goog.provide('ola.UniverseItem'); /** * An object which represents a universe in the list * @param {Object} data the data to use to construct this item. * @constructor */ ola.UniverseItem = function(data) { this._id = data['id']; this._name = data['name']; this._input_ports = data['input_ports']; this._output_ports = data['output_ports']; this._rdm_devices = data['rdm_devices']; }; goog.inherits(ola.UniverseItem, ola.common.DataItem); /** * Get the id of this universe. * @return {number} the universe id. */ ola.UniverseItem.prototype.id = function() { return this._id; }; /** * Return the universe name * @return {string} the name. */ ola.UniverseItem.prototype.name = function() { return this._name; }; /** * Return the number of input ports * @return {number} the number of input ports. */ ola.UniverseItem.prototype.inputPortCount = function() { return this._input_ports; }; /** * Return the number of output ports * @return {number} the number of output ports. */ ola.UniverseItem.prototype.outputPortCount = function() { return this._output_ports; }; /** * Return the number of RDm devices. * @return {number} the number of RDM devices. */ ola.UniverseItem.prototype.rdmDeviceCount = function() { return this._rdm_devices; }; ola-0.10.5.nojsmin/javascript/ola/ola.js0000644000175000017500000001771613023355232017524 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The main OLA UI. * Copyright (C) 2010 Simon Newton */ goog.require('goog.Timer'); goog.require('goog.dom'); goog.require('goog.dom.ViewportSizeMonitor'); goog.require('goog.events'); goog.require('goog.math'); goog.require('goog.ui.AnimatedZippy'); goog.require('goog.ui.Component'); goog.require('goog.ui.Container'); goog.require('goog.ui.Control'); goog.require('goog.ui.SplitPane'); goog.require('goog.ui.SplitPane.Orientation'); goog.require('ola.HomeFrame'); goog.require('ola.LoggerWindow'); goog.require('ola.NewUniverseFrame'); goog.require('ola.PluginFrame'); goog.require('ola.UniverseControl'); goog.require('ola.UniverseFrame'); goog.require('ola.UniverseItem'); goog.require('ola.common.GenericControl'); goog.require('ola.common.PluginControlFactory'); goog.require('ola.common.PluginItem'); goog.require('ola.common.Server'); goog.require('ola.common.Server.EventType'); goog.require('ola.common.SortedList'); goog.provide('ola.OlaUi'); goog.provide('ola.Setup'); /** * How often to update the universe / plugin list * @type {number} */ ola.LIST_UPDATE_INTERVAL_MS = 5000; /** * The id of the home frame * @type {string} */ ola.HOME_FRAME_ID = 'home_frame'; /** * The id of the universe frame * @type {string} */ ola.UNIVERSE_FRAME_ID = 'universe_frame'; /** * The id of the plugin frame * @type {string} */ ola.PLUGIN_FRAME_ID = 'plugin_frame'; /** * The id of the split pane * @type {string} */ ola.SPLIT_PANE_ID = 'split_pane'; /** * The id of the new universe frame * @type {string} */ ola.NEW_UNIVERSE_FRAME_ID = 'new_universe_frame'; /** * Setup the OLA ola_ui widgets * @constructor */ ola.OlaUI = function() { this.logger_window = new ola.LoggerWindow(); this.ola_server = ola.common.Server.getInstance(); this.home_frame = new ola.HomeFrame(ola.HOME_FRAME_ID); this.universe_frame = new ola.UniverseFrame(ola.UNIVERSE_FRAME_ID, this); var t = this; this.plugin_frame = new ola.PluginFrame( ola.PLUGIN_FRAME_ID, function(item) { t.ShowPlugin_(item); }); this.new_universe_frame = new ola.NewUniverseFrame(ola.NEW_UNIVERSE_FRAME_ID, this); goog.events.listen(goog.dom.$('new_universe_button'), goog.events.EventType.CLICK, this.ShowNewUniverse_, false, this); // setup the main split pane var lhs = new goog.ui.Component(); var rhs = new goog.ui.Component(); this.splitpane1 = new goog.ui.SplitPane(lhs, rhs, goog.ui.SplitPane.Orientation.HORIZONTAL); this.splitpane1.setInitialSize(130); this.splitpane1.setHandleSize(2); this.splitpane1.decorate(goog.dom.$(ola.SPLIT_PANE_ID)); // redraw on resize events this.vsm = new goog.dom.ViewportSizeMonitor(); this.UpdateUI_(); goog.events.listen(this.vsm, goog.events.EventType.RESIZE, this.UpdateUI_, false, this); this.SetupNavigation_(); this.ShowHome(); // show the main frame now goog.dom.$(ola.SPLIT_PANE_ID).style.visibility = 'visible'; }; /** * Setup the navigation section of the UI * @private */ ola.OlaUI.prototype.SetupNavigation_ = function() { var home_control = goog.dom.$('home_control'); goog.ui.decorate(home_control); goog.events.listen(home_control, goog.events.EventType.CLICK, this.ShowHome, false, this); var z1 = new goog.ui.AnimatedZippy('plugin_list_control', 'plugin_container'); var z2 = new goog.ui.AnimatedZippy('universe_list_control', 'universe_container'); // setup the plugin & universe lists var plugin_container = new goog.ui.Container(); plugin_container.decorate(goog.dom.$('plugin_container')); var ui = this; this.plugin_list = new ola.common.SortedList( plugin_container, new ola.common.PluginControlFactory( function(item) { ui.ShowPlugin_(item.id()); })); goog.events.listen(this.ola_server, ola.common.Server.EventType.PLUGIN_LIST_EVENT, this.updatePluginList_, false, this); var universe_container = new goog.ui.Container(); universe_container.decorate(goog.dom.$('universe_container')); this.universe_list = new ola.common.SortedList( universe_container, new ola.UniverseControlFactory( function(item) { ui.ShowUniverse(item.id(), true); })); goog.events.listen(this.ola_server, ola.common.Server.EventType.UNIVERSE_LIST_EVENT, this.updateUniverseList_, false, this); this.timer = new goog.Timer(ola.LIST_UPDATE_INTERVAL_MS); goog.events.listen(this.timer, goog.Timer.TICK, function() { this.FetchUniversePluginList(); }, false, this.ola_server); this.ola_server.FetchUniversePluginList(); this.timer.start(); }; /** * Update universe list. * @param {Object} e the event object. * @private */ ola.OlaUI.prototype.updateUniverseList_ = function(e) { var items = new Array(); ola.logger.info('Got ' + e.universes.length + ' universes'); for (var i = 0; i < e.universes.length; ++i) { items.push(new ola.UniverseItem(e.universes[i])); } this.universe_list.updateFromData(items); }; /** * Update the plugin list * @param {Object} e the event object. * @private */ ola.OlaUI.prototype.updatePluginList_ = function(e) { var items = new Array(); for (var i = 0; i < e.plugins.length; ++i) { var item = new ola.common.PluginItem(e.plugins[i]); items.push(item); } this.plugin_list.updateFromData(items); }; /** * Display the home frame */ ola.OlaUI.prototype.ShowHome = function() { this.HideAllFrames_(); this.home_frame.Show(); }; /** * Display the universe frame * @param {number} universe_id the ID of the universe to load in the frame. * @param {boolean} opt_select_main_tab set to true to display the main tab. */ ola.OlaUI.prototype.ShowUniverse = function(universe_id, opt_select_main_tab) { this.HideAllFrames_(); this.universe_frame.Show(universe_id, opt_select_main_tab); }; /** * Display the new universe frame * @private */ ola.OlaUI.prototype.ShowNewUniverse_ = function() { this.HideAllFrames_(); this.new_universe_frame.Show(); }; /** * Display the plugin frame * @param {number} plugin_id the ID of the plugin to show in the frame. * @private */ ola.OlaUI.prototype.ShowPlugin_ = function(plugin_id) { this.ola_server.FetchPluginInfo(plugin_id); this.HideAllFrames_(); this.plugin_frame.Show(); }; /** * Hide all the frames. * @private */ ola.OlaUI.prototype.HideAllFrames_ = function() { this.home_frame.Hide(); this.universe_frame.Hide(); this.plugin_frame.Hide(); this.new_universe_frame.Hide(); }; /** * Update the UI size. This is called when the window size changes * @param {Object} e the event object. * @private */ ola.OlaUI.prototype.UpdateUI_ = function(e) { var size = this.vsm.getSize(); this.splitpane1.setSize(new goog.math.Size(size.width, size.height - 85)); this.logger_window.SetSize(size); this.universe_frame.setSplitPaneSize(); }; /** * The main setup function. */ ola.Setup = function() { var ola_ui = new ola.OlaUI(); }; goog.exportSymbol('ola.Setup', ola.Setup); ola-0.10.5.nojsmin/javascript/ola/universe_control.js0000644000175000017500000000457713023355232022352 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The universe controls * Copyright (C) 2010 Simon Newton */ goog.require('ola.common.GenericControl'); goog.provide('ola.UniverseControl'); /** * An Universe navigation control element. * @constructor * @param {Object} item the item to add. * @param {function()} callback the function to run when the item is clicked. * @param {goog.ui.ControlRenderer=} opt_renderer Renderer used to render or * decorate the component; defaults to {@link goog.ui.ControlRenderer}. * @param {goog.dom.DomHelper=} opt_domHelper An optional DOM helper. */ ola.UniverseControl = function(item, callback, opt_renderer, opt_domHelper) { ola.common.GenericControl.call(this, item, callback, opt_renderer, opt_domHelper); this.setContent(item.name()); }; goog.inherits(ola.UniverseControl, ola.common.GenericControl); /** * Setup the event handler for this object. */ ola.UniverseControl.prototype.enterDocument = function() { ola.UniverseControl.superClass_.enterDocument.call(this); this.getElement().title = 'Universe ' + this._item.id(); }; /** * A factory which produces UniverseControls * @param {function()} callback the funtion called when the control is clicked. * @constructor */ ola.UniverseControlFactory = function(callback) { this.callback = callback; }; /** * Create a new UniverseControl * @param {Object} item The item for the control. * @return {ola.UniverseControl} an instance of a UniverseRow. */ ola.UniverseControlFactory.prototype.newComponent = function(item) { return new ola.UniverseControl(item, this.callback); }; ola-0.10.5.nojsmin/javascript/ola/port_table.js0000644000175000017500000002057513023355232021101 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The table that holds a list of available ports. * Copyright (C) 2010 Simon Newton */ goog.require('goog.dom'); goog.require('goog.events'); goog.require('goog.ui.Checkbox'); goog.require('goog.ui.Component'); goog.require('goog.ui.MenuItem'); goog.require('goog.ui.Select'); goog.require('ola.LoggerWindow'); goog.require('ola.common.Server'); goog.provide('ola.Port'); goog.provide('ola.PortTable'); /** * A row in the available ports list. * @param {Object} data the data to build this row from. * @constructor * @param {goog.dom.DomHelper=} opt_domHelper An optional DOM helper. */ ola.Port = function(data, opt_domHelper) { goog.ui.Component.call(this, opt_domHelper); this.data = data; }; goog.inherits(ola.Port, goog.ui.Component); /** * This component can't be used to decorate * @return {bool} false. */ ola.Port.prototype.canDecorate = function() { return false; }; /** * Create the dom for this component */ ola.Port.prototype.createDom = function() { var tr = this.dom_.createDom('tr', {}); tr.style.cursor = 'pointer'; var td = goog.dom.createDom('td', {}, ''); this.checkbox = new goog.ui.Checkbox(); this.checkbox.setChecked(true); this.checkbox.render(td); this.dom_.appendChild(tr, td); this.dom_.appendChild( tr, goog.dom.createDom('td', {}, this.data['device'])); this.dom_.appendChild(tr, goog.dom.createDom('td', {}, this.data['description'])); var priority = this.data['priority']; if (priority['priority_capability'] == undefined) { // this port doesn't support priorities at all this.dom_.appendChild( tr, goog.dom.createDom('td', {}, 'Not supported')); } else { // Now we know it supports priorities, lets create the common UI elements // for them this.priority_input = goog.dom.createElement('input'); this.priority_input.value = priority['value']; this.priority_input.maxLength = 3; this.priority_input.size = 3; if (priority['priority_capability'] == 'full') { // this port supports both modes this.priority_select = new goog.ui.Select(); this.priority_select.addItem(new goog.ui.MenuItem('Inherit')); this.priority_select.addItem(new goog.ui.MenuItem('Static')); this.priority_select.setSelectedIndex( priority['current_mode'] == 'inherit' ? 0 : 1); this.prioritySelectChanged_(); var td = goog.dom.createElement('td'); this.priority_select.render(td); this.dom_.appendChild(td, this.priority_input); this.dom_.appendChild(tr, td); } else if (priority['priority_capability'] == 'static') { // this port only supports Static priorities this.dom_.appendChild(tr, this.priority_input); } } this.setElementInternal(tr); }; /** * Setup the event handlers */ ola.Port.prototype.enterDocument = function() { ola.Port.superClass_.enterDocument.call(this); if (this.priority_select != undefined) { goog.events.listen( this.priority_select, goog.ui.Component.EventType.ACTION, this.prioritySelectChanged_, false, this); // don't toggle the check box if we're changing priorities goog.events.listen( this.priority_select.getElement(), goog.events.EventType.CLICK, function(e) { e.stopPropagation(); }); } if (this.priority_input != undefined) { // don't toggle the check box if we're changing priorities goog.events.listen( this.priority_input, goog.events.EventType.CLICK, function(e) { e.stopPropagation(); }); } goog.events.listen(this.getElement(), goog.events.EventType.CLICK, function() { this.checkbox.toggle(); }, false, this); }; /** * Clean up this object. */ ola.Port.prototype.exitDocument = function() { ola.AvailablePort.superClass_.exitDocument.call(this); this.checkbox.exitDocument(); if (this.priority_input) { goog.events.removeAll(this.priority_input); } if (this.priority_select) { goog.events.removeAll(this.priority_select.getElement()); goog.events.removeAll(this.priority_select); this.priority_select.exitDocument(); } goog.events.removeAll(this.getElement()); }; /** * Dispose of this object. */ ola.Port.prototype.dispose = function() { if (!this.getDisposed()) { ola.Port.superClass_.dispose.call(this); this.checkbox.dispose(); this.checkbox = undefined; if (this.priority_select) { this.priority_select.dispose(); this.priority_select = undefined; } this.priority_input = undefined; } }; /** * Get the port id for this item * @return {string} the id of this port. */ ola.Port.prototype.portId = function() { return this.data['id']; }; /** * Check is this row was selected * @return {boolean} true if selected, false otherwise. */ ola.Port.prototype.isSelected = function() { return this.checkbox.isChecked(); }; /** * Get the priority value for this port * @return {number|undefined} the priority value or undefined if this port * doesn't support priorities. */ ola.Port.prototype.priority = function() { var priority_capability = this.data['priority']['priority_capability']; if (priority_capability != undefined) { return this.priority_input.value; } else { return undefined; } }; /** * Get the priority mode for this port * @return {string|undefined} the priority mode (inherit|static) or undefined * if this port doesn't support priority modes. */ ola.Port.prototype.priorityMode = function() { var priority_capability = this.data['priority']['priority_capability']; if (priority_capability == 'full') { if (this.priority_select.getValue() == 'Inherit') { return 'inherit'; } else { return 'static'; } } else if (priority_capability == 'static') { return 'static'; } else { return undefined; } }; /** * Called when the port priority changes * @param {Object} e the event object. * @private */ ola.Port.prototype.prioritySelectChanged_ = function(e) { var item = this.priority_select.getSelectedItem(); if (item.getCaption() == 'Static') { // static mode this.priority_input.style.visibility = 'visible'; } else { // inherit mode this.priority_input.style.visibility = 'hidden'; } }; /** * An available port table component. * @constructor * @param {goog.dom.DomHelper=} opt_domHelper An optional DOM helper. */ ola.PortTable = function(opt_domHelper) { goog.ui.Component.call(this, opt_domHelper); }; goog.inherits(ola.PortTable, goog.ui.Component); /** * Create the dom for the PortTable. */ ola.PortTable.prototype.createDom = function() { this.decorateInternal(this.dom_.createElement('tbody')); }; /** * Decorate an existing element * @param {Element} element the dom element to decorate. */ ola.PortTable.prototype.decorateInternal = function(element) { ola.PortTable.superClass_.decorateInternal.call(this, element); }; /** * Check if we can decorate an element. * @param {Element} element the dom element to check. * @return {boolean} true if this element can be decorated, false otherwise. */ ola.PortTable.prototype.canDecorate = function(element) { return element.tagName == 'TBODY'; }; /** * Clear all rows from this table */ ola.PortTable.prototype.removeAllRows = function() { while (this.getChildCount()) { var row = this.removeChildAt(0, true); row.dispose(); } }; /** * Update the list of available ports * @param {Array.} ports the new list of ports. */ ola.PortTable.prototype.update = function(ports) { this.removeAllRows(); var port_length = ports.length; for (var i = 0; i < port_length; ++i) { var component = new ola.Port(ports[i]); this.addChild(component, true); } }; ola-0.10.5.nojsmin/javascript/ola/logger.js0000644000175000017500000000547413023355232020226 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The class that handles the logging. * Copyright (C) 2010 Simon Newton */ goog.require('goog.debug.DivConsole'); goog.require('goog.debug.LogManager'); goog.require('goog.debug.Logger'); goog.require('goog.dom'); goog.require('goog.events'); goog.require('goog.math'); goog.require('goog.positioning.Corner'); goog.require('goog.ui.Control'); goog.require('goog.ui.Popup'); goog.provide('ola.LoggerWindow'); /** The logger instance */ ola.logger = goog.debug.Logger.getLogger('ola'); /** * Setup the logger window * @constructor */ ola.LoggerWindow = function() { goog.debug.LogManager.getRoot().setLevel(goog.debug.Logger.Level.ALL); // setup the log console var log_console = new goog.debug.DivConsole(goog.dom.$('log')); log_console.setCapturing(true); // setup the control which shows the console this.log_control = goog.dom.$('log_control'); var control = new goog.ui.Control(); control.decorate(this.log_control); goog.events.listen(this.log_control, goog.events.EventType.CLICK, this.Show, false, this); // setup the popup that the console is contained in var popupElt = document.getElementById('log_popup'); this.popup = new goog.ui.Popup(popupElt); this.popup.setHideOnEscape(true); this.popup.setAutoHide(true); }; /** * Display the logger window */ ola.LoggerWindow.prototype.Show = function() { this.popup.setVisible(false); this.popup.setPinnedCorner(goog.positioning.Corner.TOP_RIGHT); var margin = new goog.math.Box(2, 2, 2, 2); this.popup.setMargin(margin); this.popup.setPosition(new goog.positioning.AnchoredViewportPosition( this.log_control, goog.positioning.Corner.BOTTOM_RIGHT)); this.popup.setVisible(true); }; /** * Set the size of the logger window * @param {number} size the size of the main window. */ ola.LoggerWindow.prototype.SetSize = function(size) { goog.style.setBorderBoxSize( goog.dom.$('log_popup'), new goog.math.Size(0.75 * size.width, 0.5 * size.height)); this.popup.setPosition(new goog.positioning.AnchoredViewportPosition( this.log_control, goog.positioning.Corner.BOTTOM_RIGHT)); }; ola-0.10.5.nojsmin/javascript/ola/dialog.js0000644000175000017500000000256213023355232020201 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The OLA dialog box * Copyright (C) 2010 Simon Newton */ goog.require('goog.ui.Dialog'); goog.provide('ola.Dialog'); /** * The OLA Dialog class * @constructor */ ola.Dialog = function() { goog.ui.Dialog.call(this, null, true); }; goog.inherits(ola.Dialog, goog.ui.Dialog); // This is a singleton, call ola.Dialog.getInstance() to access it. goog.addSingletonGetter(ola.Dialog); /** * Make this dialog show the spinner */ ola.Dialog.prototype.setAsBusy = function() { this.setTitle('Waiting for server response....'); this.setButtonSet(null); this.setContent('
' + '
'); }; ola-0.10.5.nojsmin/javascript/ola/home_frame.js0000644000175000017500000002076313023355232021047 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The home frame. * Copyright (C) 2010 Simon Newton */ goog.require('goog.dom'); goog.require('goog.events'); goog.require('goog.net.HttpStatus'); goog.require('goog.ui.Component'); goog.require('goog.ui.CustomButton'); goog.require('ola.BaseFrame'); goog.require('ola.Dialog'); goog.require('ola.LoggerWindow'); goog.require('ola.UniverseItem'); goog.require('ola.common.Server'); goog.require('ola.common.Server.EventType'); goog.require('ola.common.ServerStats'); goog.require('ola.common.SortedList'); goog.provide('ola.HomeFrame'); /** * A container that uses the tbody element * @constructor * @param {goog.dom.DomHelper=} opt_domHelper An optional DOM helper. */ ola.TableContainer = function(opt_domHelper) { goog.ui.Component.call(this, opt_domHelper); }; goog.inherits(ola.TableContainer, goog.ui.Component); /** * Create the dom for the TableContainer * @param {Element} container Not used. */ ola.TableContainer.prototype.createDom = function(container) { this.decorateInternal(this.dom_.createElement('tbody')); }; /** * Decorate an existing element * @param {Element} element the element to decorate. */ ola.TableContainer.prototype.decorateInternal = function(element) { ola.TableContainer.superClass_.decorateInternal.call(this, element); }; /** * Check if we can decorate an element. * @param {Element} element the dom element to check. * @return {boolean} True if the element is a TBODY. */ ola.TableContainer.prototype.canDecorate = function(element) { return element.tagName == 'TBODY'; }; /** * A line in the active universe list. * @param {ola.UniverseItem} universe_item the item to use for this row. * @constructor * @param {goog.dom.DomHelper=} opt_domHelper An optional DOM helper. */ ola.UniverseRow = function(universe_item, opt_domHelper) { goog.ui.Component.call(this, opt_domHelper); this._item = universe_item; }; goog.inherits(ola.UniverseRow, goog.ui.Component); /** * Return the underlying UniverseItem * @return {ola.UniverseItem} The underlying item object. */ ola.UniverseRow.prototype.item = function() { return this._item; }; /** * This component can't be used to decorate * @return {boolean} always false. */ ola.UniverseRow.prototype.canDecorate = function() { return false; }; /** * Create the dom for this component */ ola.UniverseRow.prototype.createDom = function() { var tr = this.dom_.createDom( 'tr', {}, goog.dom.createDom('td', {}, this._item.id().toString()), goog.dom.createDom('td', {}, this._item.name()), goog.dom.createDom('td', {}, this._item.inputPortCount().toString()), goog.dom.createDom('td', {}, this._item.outputPortCount().toString()), goog.dom.createDom('td', {}, this._item.rdmDeviceCount().toString())); this.setElementInternal(tr); }; /** * Update this item with from new data * @param {ola.UniverseItem} universe_item the new item to update from. */ ola.UniverseRow.prototype.update = function(universe_item) { var element = this.getElement(); var td = goog.dom.getFirstElementChild(element); td = goog.dom.getNextElementSibling(td); td.innerHTML = universe_item.name(); td = goog.dom.getNextElementSibling(td); td.innerHTML = universe_item.inputPortCount().toString(); td = goog.dom.getNextElementSibling(td); td.innerHTML = universe_item.outputPortCount().toString(); td = goog.dom.getNextElementSibling(td); td.innerHTML = universe_item.rdmDeviceCount().toString(); }; /** * The base class for a factory which produces UniverseRows * @constructor */ ola.UniverseRowFactory = function() {}; /** * @param {Object} data the data for the new row. * @return {ola.UniverseRow} an instance of a UniverseRow. */ ola.UniverseRowFactory.prototype.newComponent = function(data) { return new ola.UniverseRow(data); }; /** * A class representing the home frame * @param {string} element_id the id of the div to use for the home frame. * @constructor */ ola.HomeFrame = function(element_id) { var ola_server = ola.common.Server.getInstance(); ola.BaseFrame.call(this, element_id); var reload_button = goog.dom.$('reload_button'); goog.ui.decorate(reload_button); goog.events.listen(reload_button, goog.events.EventType.CLICK, this.reloadButtonClicked, false, this); var stop_button = goog.dom.$('stop_button'); goog.ui.decorate(stop_button); goog.events.listen(stop_button, goog.events.EventType.CLICK, this.stopButtonClicked, false, this); var new_universe_button = goog.dom.$('new_universe_button'); goog.ui.decorate(new_universe_button); goog.events.listen(ola_server, ola.common.Server.EventType.UNIVERSE_LIST_EVENT, this.universeListChanged_, false, this); this.server_stats = new ola.common.ServerStats(); var table_container = new ola.TableContainer(); table_container.decorate(goog.dom.$('active_universe_list')); this.universe_list = new ola.common.SortedList(table_container, new ola.UniverseRowFactory()); }; goog.inherits(ola.HomeFrame, ola.BaseFrame); /** * Update the universe set * @param {Object} e the event object. * @private */ ola.HomeFrame.prototype.universeListChanged_ = function(e) { var items = new Array(); for (var i = 0; i < e.universes.length; ++i) { items.push(new ola.UniverseItem(e.universes[i])); } this.universe_list.updateFromData(items); }; /** * Called when the stop button is clicked * @param {Object} e the event object. */ ola.HomeFrame.prototype.stopButtonClicked = function(e) { var dialog = ola.Dialog.getInstance(); goog.events.listen(dialog, goog.ui.Dialog.EventType.SELECT, this.stopServerConfirmed, false, this); dialog.setTitle('Please confirm'); dialog.setButtonSet(goog.ui.Dialog.ButtonSet.YES_NO); dialog.setContent( 'Are you sure? OLA may not be configured to restart automatically'); dialog.setVisible(true); }; /** * Called when the stop dialog exits. * @param {Object} e the event object. */ ola.HomeFrame.prototype.stopServerConfirmed = function(e) { var dialog = ola.Dialog.getInstance(); goog.events.unlisten(dialog, goog.ui.Dialog.EventType.SELECT, this.stopServerConfirmed, false, this); if (e.key == goog.ui.Dialog.DefaultButtonKeys.YES) { dialog.setAsBusy(); dialog.setVisible(true); var frame = this; ola.common.Server.getInstance().stopServer( function(e) { frame.stopServerComplete(e); }); } }; /** * Update the home frame with new server data * @param {Object} e the event object. */ ola.HomeFrame.prototype.stopServerComplete = function(e) { var dialog = ola.Dialog.getInstance(); if (e.target.getStatus() == goog.net.HttpStatus.OK) { dialog.setVisible(false); } else { dialog.setTitle('Failed to stop the server'); dialog.setContent(e.target.getLastUri() + ' : ' + e.target.getLastError()); dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK); } }; /** * Called when the reload button is clicked * @param {Object} e the event object. */ ola.HomeFrame.prototype.reloadButtonClicked = function(e) { var dialog = ola.Dialog.getInstance(); dialog.setAsBusy(); dialog.setVisible(true); var frame = this; ola.common.Server.getInstance().reloadPlugins( function(e) { frame.pluginReloadComplete(e); }); }; /** * Update the home frame with new server data * @param {Object} e the event object. */ ola.HomeFrame.prototype.pluginReloadComplete = function(e) { var dialog = ola.Dialog.getInstance(); if (e.target.getStatus() == goog.net.HttpStatus.OK) { dialog.setVisible(false); } else { dialog.setTitle('Failed to Reload plugins'); dialog.setContent(e.target.getLastUri() + ' : ' + e.target.getLastError()); dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK); } }; ola-0.10.5.nojsmin/javascript/new-src/0000755000175000017500000000000013155164170017207 5ustar wouterwouterola-0.10.5.nojsmin/javascript/new-src/README.md0000644000175000017500000001070413023355232020463 0ustar wouterwouter# web-interface the web interface for ola is build using - [angularjs](http://angularjs.com) - [bootstrap](http://getbootstrap.com) - [jquery](http://jquery.com) which are all under the MIT license and thus can be included. ## Compile web-interface [grunt](http://gruntjs.com/) is used for the compilation process but first [node](http://nodejs.org/) must be installed for grunt and its plug-ins to be able to work and be downloaded so when node is installed first open a terminal and navigate to this directory then run ```bash npm install ``` and optionally ```bash sudo npm install --global grunt-cli ``` to give you a nicer way to run the grunt task runner from the command-line ```bash grunt build ``` to generate the minified versions of app.js and style.css ## Karma and Coveralls.io in the future there is the ability to do coverage tests with grunt plug-ins such as [grunt-karma-coveralls](https://github.com/mattjmorrison/grunt-karma-coveralls) which is a plugin for [karma](http://karma-runner.github.io/) ## Angular JS License The MIT License Copyright (c) 2010-2012 Google, Inc. http://angularjs.org Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## Bootstrap License The MIT License (MIT) Copyright (c) 2011-2015 Twitter, Inc Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## jQuery license Copyright jQuery Foundation and other contributors, https://jquery.org/ This software consists of voluntary contributions made by many individuals. For exact contribution history, see the revision history available at https://github.com/jquery/jquery Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ola-0.10.5.nojsmin/javascript/new-src/css/0000755000175000017500000000000013155164170017777 5ustar wouterwouterola-0.10.5.nojsmin/javascript/new-src/css/style.css0000644000175000017500000001321513023355232021646 0ustar wouterwouter.keypad { width: 300px; text-align: center; right: 0; left: 0; margin-left: auto; margin-right: auto; margin-top: 5px; } .backspace.btn { width: 50px; margin: 2px; } .keypad-keys { margin-right: 7%; margin-left: 7%; margin-bottom: 7%; width: 86%; } .keypad-field.static-fake { display: inline-block; vertical-align: middle; padding-top: 5%; width: 190px; height: 50px; margin: 2px; } .keypad-keys .btn { width: 100%; } .btn-keypad { color: #333; background-color: #fff; border-color: #ccc; height: 50px; } .fader-fader { writing-mode: vertical-rl; -webkit-appearance: slider-vertical; } .fader-group { display: inline-block; text-align: center; border: solid #67a7e3 1px; border-radius: 4px; margin: 1px; } .faders { text-align: center; padding: 1px; } button.col-xs-3, button.col-xs-3:active, button.col-xs-3:focus { color: #ffffff; background-color: #67a7e3; border-color: transparent; } .col-xs-2.ng-binding { text-align: center; color: #ffffff; background-color: #67a7e3; height: 26px; line-height: 2; font-weight: bold; } .on, .off { color: #ffffff; background-color: #67a7e3; border-color: transparent; } .right-col { border-bottom-right-radius: 4px; border-top-right-radius: 4px; } .left-col { border-bottom-left-radius: 4px; border-top-left-radius: 4px; } .navigate { padding-left: 0; padding-right: 0; padding-bottom: 15px; height: 41px; } .navigate > .col-xs-3, .navigate > .col-xs-2 { height: 100%; outline: none!important; } .value-div { display: inline-block; } .value-span { display: inline-block; font-size: 11px; border-bottom: 1px solid #67a7e3; border-right: 1px solid #67a7e3; width: 20px; text-align: center; margin: 1px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; border-top-right-radius: 4px } .row { padding: 5px; text-align: center; } .index, .value { text-align: center; width: 100%; height: 50%; } .channel { width: 30px; font-size: 10px; text-align: center; display: inline-block; border: 1px solid #337ab7; border-radius: 4px; } .status { padding: 5px; text-align: center; border: solid black 1px; } .status-light { width: 20px; } .status-light, .status { display: inline-block; border-radius: 20px; } th.top-table, tr.special-mouse > td { text-align: center; padding: 8px; } .plugin-table { text-align: center; width: 100%; margin-bottom: 10px; } .round-corners { border: solid black 1px; border-radius: 10px; } .top-table { border-bottom: solid black 1px; } tr.striped-table:nth-of-type(even) { background-color: #F8F8F8; border-top: solid lightgrey 1px; border-bottom: solid lightgrey 1px; } .special-mouse { cursor: pointer; } .navbar-info { margin-top: 8px; margin-bottom: 8px; font-size: 12px; text-align: center; } .navbar-desktop { float: right!important; } @media (min-width: 768px) { .navbar-mobile { display: none; } .number { width: 50px !important; } } @media (max-width: 768px) { .navbar-desktop { display: none; } .save-settings { width: 100%; } } div.checkbox-tr { text-align: center; vertical-align: middle; } table.info > tbody > tr > td { border-bottom: solid grey 1px; padding-left: 5px; padding-right: 5px; } table.table > tbody > tr > td.left-table { text-align: left; } .settings-table { text-align: left; } .settings-table > table { width: 100%; } input.priority { width: 70px; } select.priority { width: 90px; display: inline; } .caption-overview { width: 49%; display: inline-block; } .button-caption { text-align: right; } .btn-grey { background-color: #d3d3d3; color: #333; border-color: #BABABA; } td.align { text-align: left; } .plugin-icon { color: #898989; } div#header-universe { padding-bottom: 10px; } div#header-universe > h4 { display: inline; padding-right: 10px; } div#header-universe > div { color: lightgray; display: inline; } .static-fake { height: 34px; padding: 6px 12px; background-color: #eee; border: 1px solid #ccc; border-radius: 4px; box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; } .table-condensed>tbody>tr>td, .table-condensed>tbody>tr>th, .table-condensed>tfoot>tr>td, .table-condensed>tfoot>tr>th, .table-condensed>thead>tr>td, .table-condensed>thead>tr>th { padding: 3px; } .number { cursor: text!important; } .settings, .input-group, .save-settings { margin-top: 5px; } /* Begin custom checkboxes for plugins page */ /* Hide checkbox */ input.form-control[type="checkbox"] { display: none; } /* Mock checkbox in label */ input.form-control[type="checkbox"] + label span.glyphicon:before { width: 20px; height: 20px; border-radius: 4px; border: solid #ccc 1px; content: "\e014"; /* Use cross as standard glyph */ color: #d9534f; background-color: #fff; cursor: pointer; } /* Use check glyph if checked */ input.form-control[type="checkbox"]:checked + label span.glyphicon:before { content: "\e013"; color: #5cb85c; } /* grey out checkbox if disabled */ input.form-control[type="checkbox"][disabled] + label span.glyphicon:before { color: darkgrey; } /* End custom checkboxes */ label.fake-check { margin-top: 5px; margin-bottom: 0; } .nav-tabs { overflow-x: auto; overflow-y: hidden; display: -webkit-box; display: -moz-box; } .nav-tabs>li { float:none; } .nav-tabs::-webkit-scrollbar { -webkit-appearance: none; } .nav-tabs::-webkit-scrollbar:vertical { width: 12px; } .nav-tabs::-webkit-scrollbar:horizontal { height: 12px; } .nav-tabs::-webkit-scrollbar-thumb { background-color: rgba(0, 0, 0, .5); border-radius: 10px; border: 2px solid #ffffff; } .nav-tabs::-webkit-scrollbar-track { border-radius: 10px; background-color: #ffffff; }ola-0.10.5.nojsmin/javascript/new-src/package.json0000644000175000017500000000064413134123277021501 0ustar wouterwouter{ "name": "OLA", "license": "GPL-2.0+", "repository": "OpenLightingProject/ola", "devDependencies": { "olp-javascript-style": "OpenLightingProject/javascript-style", "grunt": "~0.4.5", "grunt-bower-task": "^0.4.0", "grunt-contrib-cssmin": "^0.11.0", "grunt-contrib-jshint": "^1.1.0", "grunt-contrib-uglify": "^0.7.0", "grunt-contrib-watch": "^0.6.1", "grunt-jscs": "^1.8.0" } } ola-0.10.5.nojsmin/javascript/new-src/src/0000755000175000017500000000000013134123611017766 5ustar wouterwouterola-0.10.5.nojsmin/javascript/new-src/src/constants.js0000644000175000017500000000173213023355232022346 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The new OLA web UI. * Copyright (C) 2015 Dave Olsthoorn */ /*jshint browser: true, jquery: true*/ /* global ola */ ola.constant('OLA', { 'MIN_CHANNEL_NUMBER': 1, 'MAX_CHANNEL_NUMBER': 512, 'MIN_CHANNEL_VALUE': 0, 'MAX_CHANNEL_VALUE': 255 });ola-0.10.5.nojsmin/javascript/new-src/src/controllers/0000755000175000017500000000000013155164170022344 5ustar wouterwouterola-0.10.5.nojsmin/javascript/new-src/src/controllers/fader_universe.js0000644000175000017500000000663413023355232025707 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The new OLA web UI. * Copyright (C) 2015 Dave Olsthoorn */ /*jshint browser: true, jquery: true*/ /* global ola */ ola.controller('faderUniverseCtrl', ['$scope', '$ola', '$routeParams', '$window', '$interval', 'OLA', function($scope, $ola, $routeParams, $window, $interval, OLA) { 'use strict'; $scope.get = []; $scope.list = []; $scope.last = 0; $scope.offset = 0; $scope.send = false; $scope.OLA = OLA; $scope.Universe = $routeParams.id; for (var i = 0; i < OLA.MAX_CHANNEL_NUMBER; i++) { $scope.list[i] = i; $scope.get[i] = OLA.MIN_CHANNEL_VALUE; } $scope.light = function(j) { for (var i = 0; i < OLA.MAX_CHANNEL_NUMBER; i++) { $scope.get[i] = j; } $scope.change(); }; var dmxGet = $interval(function() { $ola.get.Dmx($scope.Universe).then(function(data) { for (var i = 0; i < OLA.MAX_CHANNEL_NUMBER; i++) { if (i < data.dmx.length) { $scope.get[i] = data.dmx[i]; } else { $scope.get[i] = OLA.MIN_CHANNEL_VALUE; } } $scope.send = true; }); }, 1000); $scope.getColor = function(i) { if (i > 140) { return 'black'; } else { return 'white'; } }; $scope.ceil = function(i) { return $window.Math.ceil(i); }; $scope.change = function() { $ola.post.Dmx($scope.Universe, $scope.get); }; $scope.page = function(d) { if (d === 1) { var offsetLimit = $window.Math.ceil(OLA.MAX_CHANNEL_NUMBER / $scope.limit); if (($scope.offset + 1) !== offsetLimit) { $scope.offset++; } } else if (d === OLA.MIN_CHANNEL_VALUE) { if ($scope.offset !== OLA.MIN_CHANNEL_VALUE) { $scope.offset--; } } }; $scope.getWidth = function() { var width = $window.Math.floor(($window.innerWidth * 0.99) / $scope.limit); var amount = width - (52 / $scope.limit); return amount + 'px'; }; $scope.getLimit = function() { var width = ($window.innerWidth * 0.99) / 66; return $window.Math.floor(width); }; $scope.limit = $scope.getLimit(); $scope.width = { 'width': $scope.getWidth() }; $window.$($window).resize(function() { $scope.$apply(function() { $scope.limit = $scope.getLimit(); $scope.width = { width: $scope.getWidth() }; }); }); $scope.$on('$destroy', function() { $interval.cancel(dmxGet); }); } ]);ola-0.10.5.nojsmin/javascript/new-src/src/controllers/setting_universe.js0000644000175000017500000000633313023355232026277 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The new OLA web UI. * Copyright (C) 2015 Dave Olsthoorn */ /*jshint browser: true, jquery: true*/ /* global ola */ ola.controller('settingUniverseCtrl', ['$scope', '$ola', '$routeParams', function($scope, $ola, $routeParams) { 'use strict'; $scope.loadData = function() { $scope.Data = { old: {}, model: {}, Remove: [], Add: [] }; $scope.Data.old.id = $scope.Data.model.id = $routeParams.id; $ola.get.PortsId($routeParams.id).then(function(data) { $scope.DeactivePorts = data; }); $ola.get.UniverseInfo($routeParams.id).then(function(data) { $scope.Data.old.name = $scope.Data.model.name = data.name; $scope.Data.old.merge_mode = data.merge_mode; $scope.Data.model.merge_mode = data.merge_mode; $scope.ActivePorts = data.output_ports.concat(data.input_ports); $scope.Data.old.ActivePorts = data.output_ports.concat(data.input_ports); for (var i = 0; i < $scope.ActivePorts.length; ++i) { $scope.Data.Remove[i] = ''; } }); }; $scope.loadData(); $scope.Save = function() { var a = {}; a.id = $scope.Data.model.id; a.name = $scope.Data.model.name; a.merge_mode = $scope.Data.model.merge_mode; a.add_ports = $.grep($scope.Data.Add, Boolean).join(','); a.remove_ports = $.grep($scope.Data.Remove, Boolean).join(','); var modified = []; $scope.ActivePorts.forEach(function(element, index) { if ($scope.Data.Remove.indexOf($scope.ActivePorts[index].id) === -1) { var port = $scope.ActivePorts[index]; var port_old = $scope.Data.old.ActivePorts[index]; if (port.priority.current_mode === 'static') { if (0 < port.priority.value < 100) { a[port.id + '_priority_value'] = port.priority.value; if (modified.indexOf(port.id) === -1) { modified.push(port.id); } } } if (port_old.priority.current_mode !== port.priority.current_mode) { a[port.id + '_priority_mode'] = port.priority.current_mode; if (modified.indexOf(port.id) === -1) { modified.push(port.id); } } } }); a.modify_ports = $.grep(modified, Boolean).join(','); $ola.post.ModifyUniverse(a); $scope.loadData(); }; } ]);ola-0.10.5.nojsmin/javascript/new-src/src/controllers/overview.js0000644000175000017500000000260413023355232024545 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The new OLA web UI. * Copyright (C) 2015 Dave Olsthoorn */ /*jshint browser: true, jquery: true*/ /* global ola */ ola.controller('overviewCtrl', ['$scope', '$ola', '$location', function($scope, $ola, $location) { 'use strict'; $scope.Info = {}; $scope.Universes = {}; $ola.get.ItemList().then(function(data) { $scope.Universes = data.universes; }); $ola.get.ServerInfo().then(function(data) { $scope.Info = data; }); $scope.Shutdown = function() { $ola.action.Shutdown().then(); }; $scope.goUniverse = function(id) { $location.path('/universe/' + id); }; } ]);ola-0.10.5.nojsmin/javascript/new-src/src/controllers/header.js0000644000175000017500000000251213023355232024125 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The new OLA web UI. * Copyright (C) 2015 Dave Olsthoorn */ /*jshint browser: true, jquery: true */ /* global ola */ ola.controller('headerControl', ['$scope', '$ola', '$routeParams', '$window', function($scope, $ola, $routeParams, $window) { 'use strict'; $scope.header = { tab: '', id: $routeParams.id, name: '' }; $ola.get.UniverseInfo($routeParams.id) .then(function(data) { $scope.header.name = data.name; }); var hash = $window.location.hash; $scope.header.tab = hash.replace(/#\/universe\/[0-9]+\/?/, ''); } ]);ola-0.10.5.nojsmin/javascript/new-src/src/controllers/plugins.js0000644000175000017500000000340713023355232024362 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The new OLA web UI. * Copyright (C) 2015 Dave Olsthoorn */ /*jshint browser: true, jquery: true*/ /* global ola */ ola.controller('pluginsCtrl', ['$scope', '$ola', '$location', function($scope, $ola, $location) { 'use strict'; $scope.Items = {}; $scope.active = []; $scope.enabled = []; $scope.getInfo = function() { $ola.get.ItemList() .then(function(data) { $scope.Items = data; }); }; $scope.getInfo(); $scope.Reload = function() { $ola.action.Reload(); $scope.getInfo(); }; $scope.go = function(id) { $location.path('/plugin/' + id); }; $scope.changeStatus = function(id, current) { $ola.post.PluginState(id, current); $scope.getInfo(); }; $scope.getStyle = function(style) { if (style) { return { 'background-color': 'green' }; } else { return { 'background-color': 'red' }; } }; } ]); ola-0.10.5.nojsmin/javascript/new-src/src/controllers/plugin_info.js0000644000175000017500000000323213023355232025206 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The new OLA web UI. * Copyright (C) 2015 Dave Olsthoorn */ /*jshint browser: true, jquery: true*/ /* global ola */ ola.controller('pluginInfoCtrl', ['$scope', '$routeParams', '$ola', function($scope, $routeParams, $ola) { 'use strict'; $ola.get.InfoPlugin($routeParams.id).then(function(data) { $scope.active = data.active; $scope.enabled = data.enabled; $scope.name = data.name; //TODO(Dave_o): clean this up and use proper angular var description = document.getElementById('description'); description.textContent = data.description; description.innerHTML = description.innerHTML.replace(/\\n/g, '
'); }); $scope.stateColor = function(val) { if (val) { return { 'background-color': 'green' }; } else { return { 'background-color': 'red' }; } }; } ]);ola-0.10.5.nojsmin/javascript/new-src/src/controllers/keypad_universe.js0000644000175000017500000001003413023355232026070 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The new OLA web UI. * Copyright (C) 2015 Dave Olsthoorn */ /*jshint browser: true, jquery: true*/ /* global ola */ ola.controller('keypadUniverseCtrl', ['$scope', '$ola', '$routeParams', 'OLA', function($scope, $ola, $routeParams, OLA) { 'use strict'; $scope.Universe = $routeParams.id; var regexkeypad; /*jscs:disable maximumLineLength */ /*jshint ignore:start */ // The following regex doesn't fit in the 80 character limit so to avoid // errors from the linters they are disabled on this part regexkeypad = /^(?:([0-9]{1,3})(?:\s(THRU)\s(?:([0-9]{1,3}))?)?(?:\s(@)\s(?:([0-9]{1,3}|FULL))?)?)/; /*jscs:enable maximumLineLength */ /* jshint ignore:end */ var check = { channelValue: function(value) { return OLA.MIN_CHANNEL_VALUE <= value && value <= OLA.MAX_CHANNEL_VALUE; }, channelNumber: function(value) { return OLA.MIN_CHANNEL_NUMBER <= value && value <= OLA.MAX_CHANNEL_NUMBER; }, regexGroups: function(result) { if (result[1] !== undefined) { var check1 = this.channelNumber(parseInt(result[1], 10)); if (!check1) { return false; } } if (result[3] !== undefined) { var check2 = this.channelNumber(parseInt(result[3], 10)); if (!check2) { return false; } } if (result[5] !== undefined && result[5] !== 'FULL') { var check3 = this.channelValue(parseInt(result[5], 10)); if (!check3) { return false; } } return true; } }; $scope.field = ''; $scope.input = function(input) { var tmpField; if (input === 'backspace') { tmpField = $scope.field.substr(0, $scope.field.length - 1); } else { tmpField = $scope.field + input; } var fields = regexkeypad.exec(tmpField); if (fields === null) { $scope.field = ''; } else if (check.regexGroups(fields)) { $scope.field = fields[0]; } }; $scope.submit = function() { var dmx = []; var input = $scope.field; var result = regexkeypad.exec(input); if (result !== null && check.regexGroups(result)) { var begin = parseInt(result[1], 10); var end = result[3] ? parseInt(result[3], 10) : parseInt(result[1], 10); var value = (result[5] === 'FULL') ? OLA.MAX_CHANNEL_VALUE : parseInt(result[5], 10); if (begin <= end && check.channelValue(value)) { $ola.get.Dmx($scope.Universe).then(function(data) { for (var i = 0; i < OLA.MAX_CHANNEL_NUMBER; i++) { if (i < data.dmx.length) { dmx[i] = data.dmx[i]; } else { dmx[i] = OLA.MIN_CHANNEL_VALUE; } } for (var j = begin; j <= end; j++) { dmx[j - 1] = value; } $ola.post.Dmx($scope.Universe, dmx); $scope.field = ''; }); return true; } else { return false; } } else { return false; } }; } ]);ola-0.10.5.nojsmin/javascript/new-src/src/controllers/add_universe.js0000644000175000017500000000542613023355232025354 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The new OLA web UI. * Copyright (C) 2015 Dave Olsthoorn */ /*jshint browser: true, jquery: true*/ /* global ola */ ola.controller('addUniverseCtrl', ['$scope', '$ola', '$window', '$location', function($scope, $ola, $window, $location) { 'use strict'; $scope.Ports = {}; $scope.addPorts = []; $scope.Universes = []; $scope.Class = ''; $scope.Data = { id: 0, name: '', add_ports: '' }; $ola.get.ItemList().then(function(data) { for (var u in data.universes) { if (data.universes.hasOwnProperty(u)) { if ($scope.Data.id === parseInt(data.universes[u].id, 10)) { $scope.Data.id++; } $scope.Universes.push(parseInt(data.universes[u].id, 10)); } } }); $scope.Submit = function() { if (typeof $scope.Data.id === 'number' && $scope.Data.add_ports !== '' && $scope.Universes.indexOf($scope.Data.id) === -1) { if ($scope.Data.name === undefined || $scope.Data.name === '') { $scope.Data.name = 'Universe ' + $scope.Data.id; } $ola.post.AddUniverse($scope.Data); $location.path('/universe/' + $scope.Data.id); } else if ($scope.Universes.indexOf($scope.Data.id) !== -1) { $ola.error.modal('Universe ID already exists.'); } else if ($scope.Data.add_ports === undefined || $scope.Data.add_ports === '') { $ola.error.modal('There are no ports selected for the universe. ' + 'This is required.'); } }; $ola.get.Ports().then(function(data) { $scope.Ports = data; }); $scope.getDirection = function(direction) { if (direction) { return 'Output'; } else { return 'Input'; } }; $scope.updateId = function() { if ($scope.Universes.indexOf($scope.Data.id) !== -1) { $scope.Class = 'has-error'; } else { $scope.Class = ''; } }; $scope.TogglePort = function() { $scope.Data.add_ports = $window.$.grep($scope.addPorts, Boolean).join(','); }; } ]);ola-0.10.5.nojsmin/javascript/new-src/src/controllers/menu.js0000644000175000017500000000263313023355232023645 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The new OLA web UI. * Copyright (C) 2015 Dave Olsthoorn */ /*jshint browser: true, jquery: true*/ /* global ola */ ola.controller('menuCtrl', ['$scope', '$ola', '$interval', '$location', function($scope, $ola, $interval, $location) { 'use strict'; $scope.Items = {}; $scope.Info = {}; $scope.goTo = function(url) { $location.path(url); }; var getData = function() { $ola.get.ItemList().then(function(data) { $scope.Items = data; }); $ola.get.ServerInfo().then(function(data) { $scope.Info = data; document.title = data.instance_name + ' - ' + data.ip; }); }; getData(); $interval(getData, 10000); }]);ola-0.10.5.nojsmin/javascript/new-src/src/controllers/patch_universe.js0000644000175000017500000000206513023355232025717 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The new OLA web UI. * Copyright (C) 2015 Dave Olsthoorn */ /*jshint browser: true, jquery: true*/ /* global ola */ ola.controller('patchUniverseCtrl', ['$scope', '$ola', '$routeParams', function($scope, $ola, $routeParams) { 'use strict'; $scope.Universe = $routeParams.id; //TODO(Dave_o): implement me! } ]);ola-0.10.5.nojsmin/javascript/new-src/src/controllers/universe.js0000644000175000017500000000320513023355232024535 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The new OLA web UI. * Copyright (C) 2015 Dave Olsthoorn */ /*jshint browser: true, jquery: true*/ /* global ola */ ola.controller('universeCtrl', ['$scope', '$ola', '$routeParams', '$interval', 'OLA', function($scope, $ola, $routeParams, $interval, OLA) { 'use strict'; $scope.dmx = []; $scope.Universe = $routeParams.id; var interval = $interval(function() { $ola.get.Dmx($scope.Universe).then(function(data) { for (var i = 0; i < OLA.MAX_CHANNEL_NUMBER; i++) { $scope.dmx[i] = (typeof data.dmx[i] === 'number') ? data.dmx[i] : OLA.MIN_CHANNEL_VALUE; } }); }, 100); $scope.$on('$destroy', function() { $interval.cancel(interval); }); $scope.getColor = function(i) { if (i > 140) { return 'black'; } else { return 'white'; } }; } ]);ola-0.10.5.nojsmin/javascript/new-src/src/controllers/rdm_universe.js0000644000175000017500000000221313023355232025375 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The new OLA web UI. * Copyright (C) 2015 Dave Olsthoorn */ /*jshint browser: true, jquery: true*/ /* global ola */ ola.controller('rdmUniverseCtrl', ['$scope', '$ola', '$routeParams', function($scope, $ola, $routeParams) { 'use strict'; //get: // /json/rdm/set_section_info?id={{id}}&uid={{uid}}§ion={{section}}&hint={{hint}}&address={{address}} $scope.Universe = $routeParams.id; } ]);ola-0.10.5.nojsmin/javascript/new-src/src/factories/0000755000175000017500000000000013155164170021755 5ustar wouterwouterola-0.10.5.nojsmin/javascript/new-src/src/factories/ola.js0000644000175000017500000002500413023355232023062 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The new OLA web UI. * Copyright (C) 2015 Dave Olsthoorn */ /*jshint browser: true, jquery: true*/ /* global ola */ // TODO(Dave_o): split this up further ola.factory('$ola', ['$http', '$window', 'OLA', function($http, $window, OLA) { 'use strict'; // TODO(Dave_o): once olad supports json post data postEncode // can go away and the header in post requests too. var postEncode = function(data) { var PostData = []; for (var key in data) { if (data.hasOwnProperty(key)) { if (key === 'd' || key === 'remove_ports' || key === 'modify_ports' || key === 'add_ports') { // this is here so some posts don't get broken // because of removed comma's in arrays PostData.push(key + '=' + data[key]); } else { PostData.push(key + '=' + encodeURIComponent(data[key])); } } } return PostData.join('&'); }; var channelValueCheck = function(i) { i = parseInt(i, 10); if (i < OLA.MIN_CHANNEL_VALUE) { i = OLA.MIN_CHANNEL_VALUE; } else if (i > OLA.MAX_CHANNEL_VALUE) { i = OLA.MAX_CHANNEL_VALUE; } return i; }; var dmxConvert = function(dmx) { var strip = true; var integers = []; for (var i = OLA.MAX_CHANNEL_NUMBER; i >= OLA.MIN_CHANNEL_NUMBER; i--) { var value = channelValueCheck(dmx[i - 1]); if (value > OLA.MIN_CHANNEL_VALUE || !strip || i === OLA.MIN_CHANNEL_NUMBER) { integers[i - 1] = value; strip = false; } } return integers.join(','); }; return { get: { ItemList: function() { return $http.get('/json/universe_plugin_list') .then(function(response) { return response.data; }); }, ServerInfo: function() { return $http.get('/json/server_stats') .then(function(response) { return response.data; }); }, Ports: function() { return $http.get('/json/get_ports') .then(function(response) { return response.data; }); }, PortsId: function(id) { return $http({ method: 'GET', url: '/json/get_ports', params: { 'id': id } }) .then(function(response) { return response.data; }); }, InfoPlugin: function(id) { return $http({ method: 'GET', url: '/json/plugin_info', params: { 'id': id } }) .then(function(response) { return response.data; }); }, Dmx: function(id) { return $http({ method: 'GET', url: '/get_dmx', params: { 'u': id } }) .then(function(response) { return response.data; }); }, UniverseInfo: function(id) { return $http({ method: 'GET', url: '/json/universe_info', params: { 'id': id } }) .then(function(response) { return response.data; }); } }, post: { ModifyUniverse: function(data) { return $http({ method: 'POST', url: '/modify_universe', data: postEncode(data), headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).then(function(response) { return response.data; }); }, AddUniverse: function(data) { return $http({ method: 'POST', url: '/new_universe', data: postEncode(data), headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).then(function(response) { return response.data; }); }, Dmx: function(universe, dmx) { var data = { u: universe, d: dmxConvert(dmx) }; return $http({ method: 'POST', url: '/set_dmx', data: postEncode(data), headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).then(function(response) { return response.data; }); }, PluginState: function(pluginId, state) { var data = { state: state, plugin_id: pluginId }; return $http({ method: 'POST', url: '/set_plugin_state', data: postEncode(data), headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).then(function(response) { return response.data; }); } }, action: { Shutdown: function() { return $http.get('/quit') .then(function(response) { return response.data; }); }, Reload: function() { return $http.get('/reload') .then(function(response) { return response.data; }); }, ReloadPids: function() { return $http.get('/reload_pids') .then(function(response) { return response.data; }); } }, rdm: { // /json/rdm/section_info?id=[universe]&uid=[uid]§ion=[section] GetSectionInfo: function(universe, uid, section) { return $http({ method: 'GET', url: '/json/rdm/section_info', params: { 'id': universe, 'uid': uid, 'section': section } }) .then(function(response) { return response.data; }); }, // /json/rdm/set_section_info?id=[universe]&uid=[uid]§ion=[section] SetSection: function(universe, uid, section, hint, option) { return $http({ method: 'GET', url: '/json/rdm/set_section_info', params: { 'id': universe, 'uid': uid, 'section': section, 'hint': hint, 'int': option } }) .then(function(response) { return response.data; }); }, // /json/rdm/supported_pids?id=[universe]&uid=[uid] GetSupportedPids: function(universe, uid) { return $http({ method: 'GET', url: '/json/rdm/supported_pids', params: { 'id': universe, 'uid': uid } }) .then(function(response) { return response.data; }); }, // /json/rdm/supported_sections?id=[universe]&uid=[uid] GetSupportedSections: function(universe, uid) { return $http({ method: 'GET', url: '/json/rdm/supported_sections', params: { 'id': universe, 'uid': uid } }) .then(function(response) { return response.data; }); }, // /json/rdm/uid_identify_device?id=[universe]&uid=[uid] UidIdentifyDevice: function(universe, uid) { return $http({ method: 'GET', url: '/json/rdm/uid_identify_device', params: { 'id': universe, 'uid': uid } }) .then(function(response) { return response.data; }); }, // /json/rdm/uid_info?id=[universe]&uid=[uid] UidInfo: function(universe, uid) { return $http({ method: 'GET', url: '/json/rdm/uid_info', params: { 'id': universe, 'uid': uid } }) .then(function(response) { return response.data; }); }, // /json/rdm/uid_personalities?id=[universe]&uid=[uid] UidPersonalities: function(universe, uid) { return $http({ method: 'GET', url: '/json/rdm/uid_personalities', params: { 'id': universe, 'uid': uid } }) .then(function(response) { return response.data; }); }, // /json/rdm/uids?id=[universe] Uids: function(universe) { return $http({ method: 'GET', url: '/json/rdm/uids', params: { 'id': universe } }) .then(function(response) { return response.data; }); }, // /rdm/run_discovery?id=[universe]&incremental=true RunDiscovery: function(universe, incremental) { return $http({ method: 'GET', url: '/rdm/run_discovery', params: { 'id': universe, 'incremental': incremental } }) .then(function(response) { return response.data; }); } }, error: { modal: function(body, title) { if (typeof body !== 'undefined') { $('#errorModalBody').text(body); } else { $('#errorModalBody').text('There has been an error'); } if (typeof title !== 'undefined') { $('#errorModalLabel').text(title); } else { $('#errorModalLabel').text('Error'); } $('#errorModal').modal('show'); } } }; } ]);ola-0.10.5.nojsmin/javascript/new-src/src/filters/0000755000175000017500000000000013134123611021436 5ustar wouterwouterola-0.10.5.nojsmin/javascript/new-src/src/filters/start_form.js0000644000175000017500000000176313023355232024166 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The new OLA web UI. * Copyright (C) 2015 Dave Olsthoorn */ /*jshint browser: true, jquery: true*/ /* global ola */ ola.filter('startFrom', function() { 'use strict'; return function(input, start) { start = parseInt(start, 10); return input.slice(start); }; });ola-0.10.5.nojsmin/javascript/new-src/src/app.js0000644000175000017500000000447513023355232021121 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The new OLA web UI. * Copyright (C) 2015 Dave Olsthoorn */ /*jshint browser: true, jquery: true */ /* global angular */ var ola = angular.module('olaApp', ['ngRoute']); ola.config(['$routeProvider', function($routeProvider) { 'use strict'; $routeProvider.when('/', { templateUrl: '/new/views/overview.html', controller: 'overviewCtrl' }).when('/universes/', { templateUrl: '/new/views/universes.html', controller: 'overviewCtrl' }).when('/universe/add', { templateUrl: '/new/views/universe-add.html', controller: 'addUniverseCtrl' }).when('/universe/:id', { templateUrl: '/new/views/universe-overview.html', controller: 'universeCtrl' }).when('/universe/:id/keypad', { templateUrl: '/new/views/universe-keypad.html', controller: 'keypadUniverseCtrl' }).when('/universe/:id/faders', { templateUrl: '/new/views/universe-faders.html', controller: 'faderUniverseCtrl' }).when('/universe/:id/rdm', { templateUrl: '/new/views/universe-rdm.html', controller: 'rdmUniverseCtrl' }).when('/universe/:id/patch', { templateUrl: '/new/views/universe-patch.html', controller: 'patchUniverseCtrl' }).when('/universe/:id/settings', { templateUrl: '/new/views/universe-settings.html', controller: 'settingUniverseCtrl' }).when('/plugins', { templateUrl: '/new/views/plugins.html', controller: 'pluginsCtrl' }).when('/plugin/:id', { templateUrl: '/new/views/plugin-info.html', controller: 'pluginInfoCtrl' }).otherwise({ redirectTo: '/' }); } ]); ola-0.10.5.nojsmin/javascript/new-src/Gruntfile.js0000644000175000017500000001032713023355232021502 0ustar wouterwouter/*jshint node: true*/ module.exports = function(grunt) { 'use strict'; grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), bower: { dev: { options: { targetDir: '../../olad/www/new/libs', install: true, copy: true, cleanup: true, layout: 'byComponent' } } }, uglify: { build: { files: [{ dest: '../../olad/www/new/js/app.min.js', src: [ 'src/app.js', 'src/controllers/menu.js', 'src/controllers/patch_universe.js', 'src/controllers/rdm_universe.js', 'src/controllers/universe.js', 'src/controllers/fader_universe.js', 'src/controllers/keypad_universe.js', 'src/controllers/plugins.js', 'src/controllers/add_universe.js', 'src/controllers/plugin_info.js', 'src/controllers/setting_universe.js', 'src/controllers/header.js', 'src/controllers/overview.js', 'src/constants.js', 'src/factories/ola.js', 'src/filters/start_form.js' ] }], options: { mangle: true, sourceMap: true, sourceMapName: '../../olad/www/new/js/app.min.js.map' } } }, jshint: { dev: [ 'src/app.js', 'Gruntfile.js', 'src/controllers/menu.js', 'src/controllers/patch_universe.js', 'src/controllers/rdm_universe.js', 'src/controllers/universe.js', 'src/controllers/fader_universe.js', 'src/controllers/keypad_universe.js', 'src/controllers/plugins.js', 'src/controllers/add_universe.js', 'src/controllers/plugin_info.js', 'src/controllers/setting_universe.js', 'src/controllers/header.js', 'src/controllers/overview.js', 'src/constants.js', 'src/factories/ola.js', 'src/filters/start_form.js' ], options: { jshintrc: true } }, jscs: { src: [ 'src/app.js', 'Gruntfile.js', 'src/controllers/menu.js', 'src/controllers/patch_universe.js', 'src/controllers/rdm_universe.js', 'src/controllers/universe.js', 'src/controllers/fader_universe.js', 'src/controllers/keypad_universe.js', 'src/controllers/plugins.js', 'src/controllers/add_universe.js', 'src/controllers/plugin_info.js', 'src/controllers/setting_universe.js', 'src/controllers/header.js', 'src/controllers/overview.js', 'src/constants.js', 'src/factories/ola.js', 'src/filters/start_form.js' ], options: { config: true, verbose: true } }, watch: { build: { files: [ 'Gruntfile.js', 'src/controllers/menu.js', 'src/controllers/patch_universe.js', 'src/controllers/rdm_universe.js', 'src/controllers/universe.js', 'src/controllers/fader_universe.js', 'src/controllers/keypad_universe.js', 'src/controllers/plugins.js', 'src/controllers/add_universe.js', 'src/controllers/plugin_info.js', 'src/controllers/setting_universe.js', 'src/controllers/header.js', 'src/controllers/overview.js', 'src/constants.js', 'src/factories/ola.js', 'src/app.js', 'src/filters/start_form.js', 'css/style.css' ], tasks: ['test', 'uglify:build', 'cssmin:build'], options: { atBegin: true } } }, cssmin: { build: { files: [{ src: 'css/style.css', dest: '../../olad/www/new/css/style.min.css' }] } } }); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-watch'); grunt.loadNpmTasks('grunt-contrib-cssmin'); grunt.loadNpmTasks('grunt-bower-task'); grunt.loadNpmTasks('grunt-jscs'); grunt.registerTask('dev', ['watch:build']); grunt.registerTask('test', ['jshint:dev', 'jscs']); grunt.registerTask('build', ['test', 'uglify:build', 'cssmin:build']); }; ola-0.10.5.nojsmin/javascript/new-src/.jscsrc0000644000175000017500000000007213023355232020471 0ustar wouterwouter{ "plugins": ["olp-javascript-style"], "preset": "OLP" }ola-0.10.5.nojsmin/javascript/new-src/bower.json0000644000175000017500000000112313023355232021210 0ustar wouterwouter{ "name": "OLA", "authors": [ "Dave Olsthoorn " ], "description": "The new OLA web-ui", "license": "GPL", "private": true, "dependencies": { "angular": "~1.3.14", "bootstrap": "~3.3.1", "angular-route": "~1.3.14" }, "exportsOverride": { "angular": { "js": ["*.min.js"] }, "jquery": { "js": "dist/*.min.js" }, "bootstrap": { "js": "dist/js/bootstrap.min.js", "css": "dist/css/bootstrap.min.css", "fonts": "dist/fonts/" }, "angular-route": { "js": ["*.min.js"] } } } ola-0.10.5.nojsmin/javascript/new-src/.jshintrc0000644000175000017500000000054713023355232021035 0ustar wouterwouter{ "nonew": true, "curly": true, "latedef": true, "unused": true, "noarg": true, "indent": 2, "trailing": true, "forin": true, "noempty": true, "quotmark": "single", "eqeqeq": true, "strict": true, "undef": true, "bitwise": true, "newcap": true, "immed": true, "es3": true, "maxlen": 80, "nonbsp": true, "freeze": true }ola-0.10.5.nojsmin/javascript/README0000644000175000017500000000156513023355232016513 0ustar wouterwouterThis javascript uses the Google Closure library - http://closure-library.googlecode.com/ To build it you'll need a copy of closure checked out in the javascript directory. You can do this by running : svn checkout http://closure-library.googlecode.com/svn/trunk/ You'll also need the javascript compiler from http://code.google.com/closure/compiler/ Then to compile the javascript, run: trunk/closure/bin/build/closurebuilder.py --root=trunk/ --root=ola --namespace="ola.Setup" --output_mode=compiled --compiler_jar=compiler.jar --compiler_flags="--compilation_level=ADVANCED_OPTIMIZATIONS" > ../olad/www/ola.js To build the mobile version run: trunk/closure/bin/build/closurebuilder.py --root=trunk/ --root=ola --namespace="ola.mobile" --output_mode=compiled --compiler_jar=compiler.jar --compiler_flags="--compilation_level=ADVANCED_OPTIMIZATIONS" > ../olad/www/mobile.js ola-0.10.5.nojsmin/LGPL0000644000175000017500000006350413023355232014147 0ustar wouterwouter GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, 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 and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, 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 library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete 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 distribute a copy of this License along with the Library. 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 Library or any portion of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, 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 Library, 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 Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you 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. If distribution of 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 satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be 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. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library 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. 9. 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 Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library 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 with this License. 11. 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 Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library 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 Library. 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. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library 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. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser 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 Library 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 Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, 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 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. 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 library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ola-0.10.5.nojsmin/olad/0000755000175000017500000000000013155164170014402 5ustar wouterwouterola-0.10.5.nojsmin/olad/plugin_api/0000755000175000017500000000000013155164170016531 5ustar wouterwouterola-0.10.5.nojsmin/olad/plugin_api/DeviceManager.cpp0000644000175000017500000002215513023355232021727 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DeviceManager.cpp * Implementation of the Device Manager, this object tracks what devices are in * use. * Copyright (C) 2005 Simon Newton */ #include "olad/plugin_api/DeviceManager.h" #include #include #include #include #include #include #include "ola/Logging.h" #include "ola/StringUtils.h" #include "ola/stl/STLUtils.h" #include "olad/Port.h" #include "olad/plugin_api/PortManager.h" namespace ola { using std::map; using std::set; using std::string; using std::vector; const unsigned int DeviceManager::MISSING_DEVICE_ALIAS = 0; const char DeviceManager::PORT_PREFERENCES[] = "port"; const char DeviceManager::PRIORITY_VALUE_SUFFIX[] = "_priority_value"; const char DeviceManager::PRIORITY_MODE_SUFFIX[] = "_priority_mode"; bool operator <(const device_alias_pair& left, const device_alias_pair &right) { if (left.alias < right.alias) return true; return false; } DeviceManager::DeviceManager(PreferencesFactory *prefs_factory, PortManager *port_manager) : m_port_preferences(NULL), m_port_manager(port_manager), m_next_device_alias(FIRST_DEVICE_ALIAS) { if (prefs_factory) { m_port_preferences = prefs_factory->NewPreference(PORT_PREFERENCES); m_port_preferences->Load(); } } DeviceManager::~DeviceManager() { if (m_port_preferences) { m_port_preferences->Save(); } } bool DeviceManager::RegisterDevice(AbstractDevice *device) { if (!device) { return false; } const string device_id = device->UniqueId(); if (device_id.empty()) { OLA_WARN << "Device: " << device->Name() << " is missing UniqueId"; return false; } // See if we already have an alias for this device. unsigned int alias; DeviceIdMap::iterator iter = m_devices.find(device_id); if (iter != m_devices.end()) { if (iter->second.device) { // already registered OLA_INFO << "Device " << device_id << " is already registered"; return false; } else { // was previously registered, reuse alias alias = iter->second.alias; iter->second.device = device; } } else { alias = m_next_device_alias++; device_alias_pair pair(alias, device); STLReplace(&m_devices, device_id, pair); } STLReplace(&m_alias_map, alias, device); OLA_INFO << "Installed device: " << device->Name() << ":" << device->UniqueId(); vector input_ports; device->InputPorts(&input_ports); RestorePortSettings(input_ports); vector output_ports; device->OutputPorts(&output_ports); RestorePortSettings(output_ports); // look for timecode ports and add them to the set vector::const_iterator output_iter = output_ports.begin(); for (; output_iter != output_ports.end(); ++output_iter) { if ((*output_iter)->SupportsTimeCode()) { m_timecode_ports.insert(*output_iter); } } return true; } bool DeviceManager::UnregisterDevice(const string &device_id) { device_alias_pair *pair = STLFind(&m_devices, device_id); if (!pair || !pair->device) { OLA_WARN << "Device " << device_id << "not found"; return false; } ReleaseDevice(pair->device); STLRemove(&m_alias_map, pair->alias); pair->device = NULL; return true; } bool DeviceManager::UnregisterDevice(const AbstractDevice *device) { if (!device) { return false; } string device_id = device->UniqueId(); if (device_id.empty()) { return false; } return UnregisterDevice(device_id); } unsigned int DeviceManager::DeviceCount() const { return m_alias_map.size(); } vector DeviceManager::Devices() const { vector result; map::const_iterator iter; for (iter = m_devices.begin(); iter != m_devices.end(); ++iter) { if (iter->second.device) { result.push_back(iter->second); } } return result; } AbstractDevice *DeviceManager::GetDevice(unsigned int alias) const { return STLFindOrNull(m_alias_map, alias); } device_alias_pair DeviceManager::GetDevice(const string &unique_id) const { const device_alias_pair *result = STLFind(&m_devices, unique_id); if (result) { return *result; } else { return device_alias_pair(MISSING_DEVICE_ALIAS, NULL); } } void DeviceManager::UnregisterAllDevices() { DeviceIdMap::iterator iter; for (iter = m_devices.begin(); iter != m_devices.end(); ++iter) { ReleaseDevice(iter->second.device); iter->second.device = NULL; } m_alias_map.clear(); } void DeviceManager::SendTimeCode(const ola::timecode::TimeCode &timecode) { set::iterator iter = m_timecode_ports.begin(); for (; iter != m_timecode_ports.end(); iter++) { (*iter)->SendTimeCode(timecode); } } /* * Save the port universe patchings for a device * @param device the device to save the settings for */ void DeviceManager::ReleaseDevice(const AbstractDevice *device) { if (!m_port_preferences || !device) { return; } vector input_ports; vector output_ports; device->InputPorts(&input_ports); device->OutputPorts(&output_ports); SavePortPatchings(input_ports); SavePortPatchings(output_ports); vector::const_iterator input_iter = input_ports.begin(); for (; input_iter != input_ports.end(); ++input_iter) { SavePortPriority(**input_iter); } vector::const_iterator output_iter = output_ports.begin(); for (; output_iter != output_ports.end(); ++output_iter) { SavePortPriority(**output_iter); // remove from the timecode port set STLRemove(&m_timecode_ports, *output_iter); } } /* * Save the patching information for a list of ports. */ template void DeviceManager::SavePortPatchings(const vector &ports) const { typename vector::const_iterator iter = ports.begin(); while (iter != ports.end()) { string port_id = (*iter)->UniqueId(); if (port_id.empty()) { return; } if ((*iter)->GetUniverse()) { m_port_preferences->SetValue( port_id, IntToString((*iter)->GetUniverse()->UniverseId())); } else { m_port_preferences->RemoveValue(port_id); } iter++; } } /* * Save the priorities for all ports on this device */ void DeviceManager::SavePortPriority(const Port &port) const { if (port.PriorityCapability() == CAPABILITY_NONE) { return; } string port_id = port.UniqueId(); if (port_id.empty()) { return; } m_port_preferences->SetValue(port_id + PRIORITY_VALUE_SUFFIX, IntToString(port.GetPriority())); if (port.PriorityCapability() == CAPABILITY_FULL) { m_port_preferences->SetValue(port_id + PRIORITY_MODE_SUFFIX, IntToString(port.GetPriorityMode())); } } /* * Restore the priority settings for a port */ void DeviceManager::RestorePortPriority(Port *port) const { if (port->PriorityCapability() == CAPABILITY_NONE) { return; } string port_id = port->UniqueId(); if (port_id.empty()) { return; } string priority_str = m_port_preferences->GetValue( port_id + PRIORITY_VALUE_SUFFIX); string priority_mode_str = m_port_preferences->GetValue( port_id + PRIORITY_MODE_SUFFIX); if (priority_str.empty() && priority_mode_str.empty()) { return; } uint8_t priority, priority_mode; // setting the priority to overide mode first means we remember the over // value even if it's in inherit mode if (StringToInt(priority_str, &priority)) { m_port_manager->SetPriorityStatic(port, priority); } if (StringToInt(priority_mode_str, &priority_mode)) { if (priority_mode == PRIORITY_MODE_INHERIT) { m_port_manager->SetPriorityInherit(port); } } } /* * Restore the patching information for a port. */ template void DeviceManager::RestorePortSettings(const vector &ports) const { if (!m_port_preferences) { return; } typename vector::const_iterator iter = ports.begin(); while (iter != ports.end()) { RestorePortPriority(*iter); PortClass *port = *iter; iter++; string port_id = port->UniqueId(); if (port_id.empty()) continue; string uni_id = m_port_preferences->GetValue(port_id); if (uni_id.empty()) continue; errno = 0; int id = static_cast(strtol(uni_id.c_str(), NULL, 10)); if ((id == 0 && errno) || id < 0) continue; m_port_manager->PatchPort(port, id); } } } // namespace ola ola-0.10.5.nojsmin/olad/plugin_api/Port.cpp0000644000175000017500000001373013023355232020160 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Port.cpp * Base implementation of the Port class. * Copyright (C) 2005 Simon Newton * * Unfortunately this file contains a lot of code duplication. */ #include #include #include #include "ola/Logging.h" #include "ola/rdm/UIDSet.h" #include "olad/Device.h" #include "olad/Port.h" #include "olad/PortBroker.h" namespace ola { using std::auto_ptr; using std::string; using std::vector; BasicInputPort::BasicInputPort(AbstractDevice *parent, unsigned int port_id, const PluginAdaptor *plugin_adaptor, bool supports_rdm): m_port_id(port_id), m_priority(ola::dmx::SOURCE_PRIORITY_DEFAULT), m_priority_mode(PRIORITY_MODE_STATIC), m_port_string(""), m_universe(NULL), m_device(parent), m_plugin_adaptor(plugin_adaptor), m_supports_rdm(supports_rdm) { } bool BasicInputPort::SetUniverse(Universe *new_universe) { Universe *old_universe = GetUniverse(); if (old_universe == new_universe) return true; if (PreSetUniverse(old_universe, new_universe)) { m_universe = new_universe; PostSetUniverse(old_universe, new_universe); return true; } return false; } string BasicInputPort::UniqueId() const { if (m_port_string.empty()) { std::ostringstream str; if (m_device) str << m_device->UniqueId() << "-I-" << m_port_id; m_port_string = str.str(); } return m_port_string; } bool BasicInputPort::SetPriority(uint8_t priority) { if (priority > ola::dmx::SOURCE_PRIORITY_MAX) return false; m_priority = priority; return true; } void BasicInputPort::DmxChanged() { if (GetUniverse()) { const DmxBuffer &buffer = ReadDMX(); uint8_t priority = (PriorityCapability() == CAPABILITY_FULL && GetPriorityMode() == PRIORITY_MODE_INHERIT ? InheritedPriority() : GetPriority()); m_dmx_source.UpdateData(buffer, *m_plugin_adaptor->WakeUpTime(), priority); GetUniverse()->PortDataChanged(this); } } void BasicInputPort::HandleRDMRequest(ola::rdm::RDMRequest *request_ptr, ola::rdm::RDMCallback *callback) { auto_ptr request(request_ptr); if (m_universe) { m_plugin_adaptor->GetPortBroker()->SendRDMRequest( this, m_universe, request.release(), callback); } else { ola::rdm::RunRDMCallback(callback, ola::rdm::RDM_FAILED_TO_SEND); } } void BasicInputPort::TriggerRDMDiscovery( ola::rdm::RDMDiscoveryCallback *on_complete, bool full) { if (m_universe) { m_universe->RunRDMDiscovery(on_complete, full); } else { ola::rdm::UIDSet uids; on_complete->Run(uids); } } BasicOutputPort::BasicOutputPort(AbstractDevice *parent, unsigned int port_id, bool start_rdm_discovery_on_patch, bool supports_rdm): m_port_id(port_id), m_discover_on_patch(start_rdm_discovery_on_patch), m_priority(ola::dmx::SOURCE_PRIORITY_DEFAULT), m_priority_mode(PRIORITY_MODE_INHERIT), m_port_string(""), m_universe(NULL), m_device(parent), m_supports_rdm(supports_rdm) { } bool BasicOutputPort::SetUniverse(Universe *new_universe) { Universe *old_universe = GetUniverse(); if (old_universe == new_universe) return true; if (PreSetUniverse(old_universe, new_universe)) { m_universe = new_universe; PostSetUniverse(old_universe, new_universe); if (m_discover_on_patch) RunIncrementalDiscovery( NewSingleCallback(this, &BasicOutputPort::UpdateUIDs)); return true; } return false; } string BasicOutputPort::UniqueId() const { if (m_port_string.empty()) { std::ostringstream str; if (m_device) str << m_device->UniqueId() << "-O-" << m_port_id; m_port_string = str.str(); } return m_port_string; } bool BasicOutputPort::SetPriority(uint8_t priority) { if (priority > ola::dmx::SOURCE_PRIORITY_MAX) return false; m_priority = priority; return true; } void BasicOutputPort::SendRDMRequest(ola::rdm::RDMRequest *request_ptr, ola::rdm::RDMCallback *callback) { auto_ptr request(request_ptr); // broadcasts go to every port if (request->DestinationUID().IsBroadcast()) { ola::rdm::RunRDMCallback(callback, ola::rdm::RDM_WAS_BROADCAST); } else { OLA_WARN << "In base HandleRDMRequest, something has gone wrong with RDM" << " request routing"; ola::rdm::RunRDMCallback(callback, ola::rdm::RDM_FAILED_TO_SEND); } } void BasicOutputPort::RunFullDiscovery( ola::rdm::RDMDiscoveryCallback *on_complete) { ola::rdm::UIDSet uids; on_complete->Run(uids); } void BasicOutputPort::RunIncrementalDiscovery( ola::rdm::RDMDiscoveryCallback *on_complete) { ola::rdm::UIDSet uids; on_complete->Run(uids); } void BasicOutputPort::UpdateUIDs(const ola::rdm::UIDSet &uids) { Universe *universe = GetUniverse(); if (universe) universe->NewUIDList(this, uids); } template bool IsInputPort() { return true; } template<> bool IsInputPort() { return false; } template<> bool IsInputPort() { return true; } } // namespace ola ola-0.10.5.nojsmin/olad/plugin_api/PluginAdaptor.cpp0000644000175000017500000001015113023355232021777 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * PluginAdaptor.cpp * Provides a wrapper for the DeviceManager and SelectServer objects so that * the plugins can register devices and file handles for events * Copyright (C) 2005 Simon Newton */ #include #include "ola/Callback.h" #include "olad/PluginAdaptor.h" #include "olad/PortBroker.h" #include "olad/Preferences.h" #include "olad/plugin_api/DeviceManager.h" namespace ola { using ola::io::SelectServerInterface; using ola::thread::timeout_id; using std::string; PluginAdaptor::PluginAdaptor(DeviceManager *device_manager, SelectServerInterface *select_server, ExportMap *export_map, PreferencesFactory *preferences_factory, PortBrokerInterface *port_broker, const std::string *instance_name): m_device_manager(device_manager), m_ss(select_server), m_export_map(export_map), m_preferences_factory(preferences_factory), m_port_broker(port_broker), m_instance_name(instance_name) { } bool PluginAdaptor::AddReadDescriptor( ola::io::ReadFileDescriptor *descriptor) { return m_ss->AddReadDescriptor(descriptor); } bool PluginAdaptor::AddReadDescriptor( ola::io::ConnectedDescriptor *descriptor, bool delete_on_close) { return m_ss->AddReadDescriptor(descriptor, delete_on_close); } void PluginAdaptor::RemoveReadDescriptor( ola::io::ReadFileDescriptor *descriptor) { m_ss->RemoveReadDescriptor(descriptor); } void PluginAdaptor::RemoveReadDescriptor( ola::io::ConnectedDescriptor *descriptor) { m_ss->RemoveReadDescriptor(descriptor); } bool PluginAdaptor::AddWriteDescriptor( ola::io::WriteFileDescriptor *descriptor) { return m_ss->AddWriteDescriptor(descriptor); } void PluginAdaptor::RemoveWriteDescriptor( ola::io::WriteFileDescriptor *descriptor) { m_ss->RemoveWriteDescriptor(descriptor); } timeout_id PluginAdaptor::RegisterRepeatingTimeout( unsigned int ms, Callback0 *closure) { return m_ss->RegisterRepeatingTimeout(ms, closure); } timeout_id PluginAdaptor::RegisterRepeatingTimeout( const TimeInterval &interval, Callback0 *closure) { return m_ss->RegisterRepeatingTimeout(interval, closure); } timeout_id PluginAdaptor::RegisterSingleTimeout( unsigned int ms, SingleUseCallback0 *closure) { return m_ss->RegisterSingleTimeout(ms, closure); } timeout_id PluginAdaptor::RegisterSingleTimeout( const TimeInterval &interval, SingleUseCallback0 *closure) { return m_ss->RegisterSingleTimeout(interval, closure); } void PluginAdaptor::RemoveTimeout(timeout_id id) { m_ss->RemoveTimeout(id); } void PluginAdaptor::Execute(ola::BaseCallback0 *closure) { m_ss->Execute(closure); } void PluginAdaptor::DrainCallbacks() { m_ss->DrainCallbacks(); } bool PluginAdaptor::RegisterDevice(AbstractDevice *device) const { return m_device_manager->RegisterDevice(device); } bool PluginAdaptor::UnregisterDevice(AbstractDevice *device) const { return m_device_manager->UnregisterDevice(device); } Preferences *PluginAdaptor::NewPreference(const string &name) const { return m_preferences_factory->NewPreference(name); } const TimeStamp *PluginAdaptor::WakeUpTime() const { return m_ss->WakeUpTime(); } const std::string PluginAdaptor::InstanceName() { if (m_instance_name) { return *m_instance_name; } else { return ""; } } } // namespace ola ola-0.10.5.nojsmin/olad/plugin_api/Makefile.mk0000644000175000017500000000625413134123277020606 0ustar wouterwouter# This file is included directly in Makefile.am rather than via # olad/Makefile.mk due to the order of dependencies between them; we need to # build olad/plugin_api, then the plugins, then olad # HEADERS ################################################## noinst_HEADERS += olad/plugin_api/TestCommon.h # LIBRARIES ################################################## # lib olaserverplugininterface lib_LTLIBRARIES += olad/plugin_api/libolaserverplugininterface.la olad_plugin_api_libolaserverplugininterface_la_SOURCES = \ olad/plugin_api/Client.cpp \ olad/plugin_api/Client.h \ olad/plugin_api/Device.cpp \ olad/plugin_api/DeviceManager.cpp \ olad/plugin_api/DeviceManager.h \ olad/plugin_api/DmxSource.cpp \ olad/plugin_api/Plugin.cpp \ olad/plugin_api/PluginAdaptor.cpp \ olad/plugin_api/Port.cpp \ olad/plugin_api/PortBroker.cpp \ olad/plugin_api/PortManager.cpp \ olad/plugin_api/PortManager.h \ olad/plugin_api/Preferences.cpp \ olad/plugin_api/Universe.cpp \ olad/plugin_api/UniverseStore.cpp \ olad/plugin_api/UniverseStore.h olad_plugin_api_libolaserverplugininterface_la_CXXFLAGS = \ $(COMMON_PROTOBUF_CXXFLAGS) olad_plugin_api_libolaserverplugininterface_la_LIBADD = \ common/libolacommon.la \ common/web/libolaweb.la \ ola/libola.la # TESTS ################################################## test_programs += \ olad/plugin_api/ClientTester \ olad/plugin_api/DeviceTester \ olad/plugin_api/DmxSourceTester \ olad/plugin_api/PortTester \ olad/plugin_api/PreferencesTester \ olad/plugin_api/UniverseTester COMMON_OLAD_PLUGIN_API_TEST_LDADD = \ $(COMMON_TESTING_LIBS) \ $(libprotobuf_LIBS) \ olad/plugin_api/libolaserverplugininterface.la \ common/libolacommon.la olad_plugin_api_ClientTester_SOURCES = olad/plugin_api/ClientTest.cpp olad_plugin_api_ClientTester_CXXFLAGS = $(COMMON_TESTING_PROTOBUF_FLAGS) olad_plugin_api_ClientTester_LDADD = $(COMMON_OLAD_PLUGIN_API_TEST_LDADD) olad_plugin_api_DeviceTester_SOURCES = olad/plugin_api/DeviceManagerTest.cpp \ olad/plugin_api/DeviceTest.cpp olad_plugin_api_DeviceTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) olad_plugin_api_DeviceTester_LDADD = $(COMMON_OLAD_PLUGIN_API_TEST_LDADD) olad_plugin_api_DmxSourceTester_SOURCES = olad/plugin_api/DmxSourceTest.cpp olad_plugin_api_DmxSourceTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) olad_plugin_api_DmxSourceTester_LDADD = $(COMMON_OLAD_PLUGIN_API_TEST_LDADD) olad_plugin_api_PortTester_SOURCES = olad/plugin_api/PortTest.cpp \ olad/plugin_api/PortManagerTest.cpp olad_plugin_api_PortTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) olad_plugin_api_PortTester_LDADD = $(COMMON_OLAD_PLUGIN_API_TEST_LDADD) olad_plugin_api_PreferencesTester_SOURCES = olad/plugin_api/PreferencesTest.cpp olad_plugin_api_PreferencesTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) olad_plugin_api_PreferencesTester_LDADD = $(COMMON_OLAD_PLUGIN_API_TEST_LDADD) olad_plugin_api_UniverseTester_SOURCES = olad/plugin_api/UniverseTest.cpp olad_plugin_api_UniverseTester_CXXFLAGS = $(COMMON_TESTING_FLAGS) olad_plugin_api_UniverseTester_LDADD = $(COMMON_OLAD_PLUGIN_API_TEST_LDADD) ola-0.10.5.nojsmin/olad/plugin_api/Device.cpp0000644000175000017500000001151313023355232020430 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Device.cpp * Base implementation of the device class. * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include #include #include #include "common/rpc/RpcController.h" #include "common/rpc/RpcService.h" #include "ola/Logging.h" #include "ola/stl/STLUtils.h" #include "olad/Device.h" #include "olad/Plugin.h" #include "olad/Port.h" #include "olad/Universe.h" namespace ola { using std::map; using std::pair; using std::string; using std::vector; /* * Create a new device * @param owner the plugin that owns this device * @param name a nice name for this device */ Device::Device(AbstractPlugin *owner, const string &name) : AbstractDevice(), m_enabled(false), m_owner(owner), m_name(name) { } /* * Stop this device */ Device::~Device() { // we can't call stop from here because it uses virtual methods if (m_enabled) OLA_FATAL << "Device " << m_name << " wasn't stopped before deleting, " << "this represents a serious programming error."; } /* * Start the Device */ bool Device::Start() { if (m_enabled) return true; bool ret = StartHook(); if (ret) m_enabled = true; return ret; } /* * Stop this device */ bool Device::Stop() { if (!m_enabled) return true; PrePortStop(); DeleteAllPorts(); PostPortStop(); m_enabled = false; return true; } /* * Add a port to this device * @param port the port to add * @return true on success, false if the port already exists */ bool Device::AddPort(InputPort *port) { return GenericAddPort(port, &m_input_ports); } /* * Add a port to this device * @param port the port to add * @return 0 on success, non 0 on failure */ bool Device::AddPort(OutputPort *port) { return GenericAddPort(port, &m_output_ports); } void Device::InputPorts(vector *ports) const { STLValues(m_input_ports, ports); } void Device::OutputPorts(vector *ports) const { STLValues(m_output_ports, ports); } /* * Returns the InputPort with the id port_id */ InputPort *Device::GetInputPort(unsigned int port_id) const { return STLFindOrNull(m_input_ports, port_id); } /* * Returns the OutputPort with the id port_id */ OutputPort *Device::GetOutputPort(unsigned int port_id) const { return STLFindOrNull(m_output_ports, port_id); } /* * Delete all ports and clear the port list */ void Device::DeleteAllPorts() { map::iterator input_iter; map::iterator output_iter; for (input_iter = m_input_ports.begin(); input_iter != m_input_ports.end(); ++input_iter) { GenericDeletePort(input_iter->second); } for (output_iter = m_output_ports.begin(); output_iter != m_output_ports.end(); ++output_iter) { GenericDeletePort(output_iter->second); } m_input_ports.clear(); m_output_ports.clear(); } /* * Returns a unique id for this device */ string Device::UniqueId() const { if (m_unique_id.empty()) { if (!Owner()) { OLA_WARN << "Device: " << Name() << " missing owner"; return ""; } std::ostringstream str; str << Owner()->Id() << "-" << DeviceId(); m_unique_id = str.str(); } return m_unique_id; } /* * Device Config request */ void Device::Configure(ola::rpc::RpcController *controller, const string &request, string *response, ConfigureCallback *done) { controller->SetFailed("Not Implemented"); done->Run(); (void) request; (void) response; } template bool Device::GenericAddPort(PortClass *port, map *port_map) { if (!port) return false; if (!STLInsertIfNotPresent(port_map, port->PortId(), port)) { OLA_WARN << "Attempt to insert a port but this port id is already " << "associated with a different port."; } return true; } template void Device::GenericDeletePort(PortClass *port) { Universe *universe = port->GetUniverse(); if (universe) universe->RemovePort(port); delete port; } } // namespace ola ola-0.10.5.nojsmin/olad/plugin_api/DeviceTest.cpp0000644000175000017500000000665113023355232021277 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DeviceTest.cpp * Test fixture for the Device class. * Copyright (C) 2005 Simon Newton */ #include #include #include #include "olad/Device.h" #include "olad/Plugin.h" #include "olad/Port.h" #include "olad/Preferences.h" #include "olad/plugin_api/TestCommon.h" #include "ola/testing/TestUtils.h" using ola::AbstractDevice; using ola::AbstractPlugin; using ola::InputPort; using ola::OutputPort; using std::string; using std::vector; class DeviceTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(DeviceTest); CPPUNIT_TEST(testDevice); CPPUNIT_TEST_SUITE_END(); public: void testDevice(); private: void AddPortsToDeviceAndCheck(ola::Device *device); }; CPPUNIT_TEST_SUITE_REGISTRATION(DeviceTest); /* * Check that the base device class works correctly. */ void DeviceTest::testDevice() { string device_name = "test"; MockDevice orphaned_device(NULL, device_name); OLA_ASSERT_EQ(device_name, orphaned_device.Name()); OLA_ASSERT_EQ(static_cast(NULL), orphaned_device.Owner()); OLA_ASSERT_EQ(string(""), orphaned_device.UniqueId()); AddPortsToDeviceAndCheck(&orphaned_device); // Non orphaned device TestMockPlugin plugin(NULL, ola::OLA_PLUGIN_ARTNET); MockDevice device(&plugin, device_name); OLA_ASSERT_EQ(device.Name(), device_name); OLA_ASSERT_EQ(static_cast(&plugin), device.Owner()); OLA_ASSERT_EQ(string("2-test"), device.UniqueId()); AddPortsToDeviceAndCheck(&device); } void DeviceTest::AddPortsToDeviceAndCheck(ola::Device *device) { // check we don't have any ports yet. vector input_ports; device->InputPorts(&input_ports); OLA_ASSERT_EQ((size_t) 0, input_ports.size()); vector output_ports; device->OutputPorts(&output_ports); OLA_ASSERT_EQ((size_t) 0, output_ports.size()); // add two input ports and an output port TestMockInputPort input_port1(device, 1, NULL); TestMockInputPort input_port2(device, 2, NULL); TestMockOutputPort output_port1(device, 1); device->AddPort(&input_port1); device->AddPort(&input_port2); device->AddPort(&output_port1); device->InputPorts(&input_ports); OLA_ASSERT_EQ((size_t) 2, input_ports.size()); device->OutputPorts(&output_ports); OLA_ASSERT_EQ((size_t) 1, output_ports.size()); InputPort *input_port = device->GetInputPort(1); OLA_ASSERT(input_port); OLA_ASSERT_EQ((unsigned int) 1, input_port->PortId()); input_port = device->GetInputPort(2); OLA_ASSERT(input_port); OLA_ASSERT_EQ((unsigned int) 2, input_port->PortId()); OutputPort *output_port = device->GetOutputPort(1); OLA_ASSERT(output_port); OLA_ASSERT_EQ((unsigned int) 1, output_port->PortId()); } ola-0.10.5.nojsmin/olad/plugin_api/DeviceManager.h0000644000175000017500000001240113023355232021365 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DeviceManager.h * Interface to the DeviceManager class * Copyright (C) 2005 Simon Newton */ #ifndef OLAD_PLUGIN_API_DEVICEMANAGER_H_ #define OLAD_PLUGIN_API_DEVICEMANAGER_H_ #include #include #include #include #include "ola/base/Macro.h" #include "ola/timecode/TimeCode.h" #include "olad/Device.h" #include "olad/Preferences.h" namespace ola { // pair a device with it's alias class device_alias_pair { public: unsigned int alias; AbstractDevice *device; device_alias_pair(unsigned int alias, AbstractDevice *device) : alias(alias), device(device) {} }; bool operator <(const device_alias_pair& left, const device_alias_pair &right); /** * @brief Keeps track of OLA's devices. * * Devices can be identified in one of two ways, by device-id or by alias. * device-ids are strings and are persistent across restarting olad and reload * the plugins. device-ids are the keys used in preference containers to * identify devices. * * Device aliases are unsigned integers and are only valid for the lifetime of * the DeviceManager object. Device aliases are used by users when patching / * controlling a device. since '1' is easier to understand / type * than 5-02050016. If a device is registered, then unregistered, then * registered again, it'll have the same device alias. */ class DeviceManager { public: /** * @brief Create a new DeviceManager. * @param prefs_factory the PreferencesFactory to use, ownership is not * transferred. * @param port_manager the PortManager to use, ownership is not transferred. */ DeviceManager(PreferencesFactory *prefs_factory, class PortManager *port_manager); /** * @brief Destructor. */ ~DeviceManager(); /** * @brief Register a device. * @param device The device to register, ownership is not transferred. * @returns true on success, false on failure. * * During registration, any saved port patchings for this device are restored. */ bool RegisterDevice(AbstractDevice *device); /** * @brief Unregister a device by id. * @param device_id the id of the device to remove * @returns true on sucess, false on failure */ bool UnregisterDevice(const std::string &device_id); /** * @brief Unregister a device by pointer. * @param device a pointer to the device. * @returns true on sucess, false on failure */ bool UnregisterDevice(const AbstractDevice *device); /** * @brief Return the number of devices. * @returns the number of devices. */ unsigned int DeviceCount() const; /** * @brief Return a list of all devices and their aliases. * @returns a vector of device_alias_pairs. */ std::vector Devices() const; /** * @brief Lookup a device using the device alias. * @returns a pointer to the device or NULL if the device wasn't found. */ AbstractDevice *GetDevice(unsigned int alias) const; /** * @brief Lookup a device using the device id. * @param unique_id the device id of the device. * @returns a device_alias_pair, if the device isn't found the alias is set to * MISSING_DEVICE_ALIAS and the device pointer is NULL. */ device_alias_pair GetDevice(const std::string &unique_id) const; /** * @brief Remove all devices. */ void UnregisterAllDevices(); /** * @brief Send timecode to all ports which support timecode. * @param timecode the TimeCode information. */ void SendTimeCode(const ola::timecode::TimeCode &timecode); static const unsigned int MISSING_DEVICE_ALIAS; private: typedef std::map DeviceIdMap; typedef std::map DeviceAliasMap; Preferences *m_port_preferences; class PortManager *m_port_manager; DeviceIdMap m_devices; DeviceAliasMap m_alias_map; unsigned int m_next_device_alias; std::set m_timecode_ports; void ReleaseDevice(const AbstractDevice *device); void RestoreDevicePortSettings(AbstractDevice *device); template void SavePortPatchings(const std::vector &ports) const; void SavePortPriority(const Port &port) const; void RestorePortPriority(Port *port) const; template void RestorePortSettings(const std::vector &ports) const; static const char PORT_PREFERENCES[]; static const unsigned int FIRST_DEVICE_ALIAS = 1; static const char PRIORITY_VALUE_SUFFIX[]; static const char PRIORITY_MODE_SUFFIX[]; DISALLOW_COPY_AND_ASSIGN(DeviceManager); }; } // namespace ola #endif // OLAD_PLUGIN_API_DEVICEMANAGER_H_ ola-0.10.5.nojsmin/olad/plugin_api/DmxSourceTest.cpp0000644000175000017500000000531113023355232022001 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DmxSourceTest.cpp * Test fixture for the DmxSource classes * Copyright (C) 2005 Simon Newton */ #include #include #include #include "ola/Clock.h" #include "ola/DmxBuffer.h" #include "olad/DmxSource.h" #include "ola/testing/TestUtils.h" class DmxSourceTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(DmxSourceTest); CPPUNIT_TEST(testDmxSource); CPPUNIT_TEST(testIsActive); CPPUNIT_TEST_SUITE_END(); public: void testDmxSource(); void testIsActive(); private: ola::Clock m_clock; }; CPPUNIT_TEST_SUITE_REGISTRATION(DmxSourceTest); using ola::Clock; using ola::DmxBuffer; using ola::DmxSource; using ola::TimeInterval; using ola::TimeStamp; /* * Check that the base device class works correctly. */ void DmxSourceTest::testDmxSource() { DmxBuffer buffer("123456789"); TimeStamp timestamp; m_clock.CurrentTime(×tamp); DmxSource source(buffer, timestamp, 100); OLA_ASSERT(source.IsSet()); OLA_ASSERT(buffer == source.Data()); OLA_ASSERT_EQ(timestamp, source.Timestamp()); OLA_ASSERT_EQ((uint8_t) 100, source.Priority()); DmxBuffer buffer2("987654321"); TimeStamp timestamp2; m_clock.CurrentTime(×tamp2); OLA_ASSERT_TRUE(timestamp <= timestamp2); source.UpdateData(buffer2, timestamp2, 120); OLA_ASSERT(buffer2 == source.Data()); OLA_ASSERT_EQ(timestamp2, source.Timestamp()); OLA_ASSERT_EQ((uint8_t) 120, source.Priority()); DmxSource empty_source; OLA_ASSERT_FALSE(empty_source.IsSet()); } /* * Test the time based checks */ void DmxSourceTest::testIsActive() { DmxBuffer buffer("123456789"); TimeStamp timestamp; m_clock.CurrentTime(×tamp); DmxSource source(buffer, timestamp, 100); OLA_ASSERT(source.IsSet()); OLA_ASSERT(source.IsActive(timestamp)); TimeInterval interval(1000000); TimeStamp later = timestamp + interval; OLA_ASSERT(source.IsActive(later)); later = timestamp + TimeInterval(2500000); OLA_ASSERT_FALSE(source.IsActive(later)); } ola-0.10.5.nojsmin/olad/plugin_api/ClientTest.cpp0000644000175000017500000001067413023355232021316 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ClientTest.cpp * Test fixture for the Client class * Copyright (C) 2005 Simon Newton */ #include #include #include "common/protocol/Ola.pb.h" #include "common/protocol/OlaService.pb.h" #include "common/rpc/RpcController.h" #include "common/rpc/RpcService.h" #include "ola/Clock.h" #include "ola/Constants.h" #include "ola/DmxBuffer.h" #include "ola/rdm/UID.h" #include "ola/testing/TestUtils.h" #include "olad/DmxSource.h" #include "olad/plugin_api/Client.h" static unsigned int TEST_UNIVERSE = 1; static unsigned int TEST_UNIVERSE2 = 2; static const char TEST_DATA[] = "this is some test data"; static const char TEST_DATA2[] = "another set of test data"; using ola::Client; using ola::DmxBuffer; using std::string; class ClientTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(ClientTest); CPPUNIT_TEST(testSendDMX); CPPUNIT_TEST(testGetSetDMX); CPPUNIT_TEST_SUITE_END(); public: ClientTest() : m_test_uid(ola::OPEN_LIGHTING_ESTA_CODE, 0) {} void testSendDMX(); void testGetSetDMX(); private: ola::Clock m_clock; ola::rdm::UID m_test_uid; }; CPPUNIT_TEST_SUITE_REGISTRATION(ClientTest); /* * Mock out the ClientStub for testing */ class MockClientStub: public ola::proto::OlaClientService_Stub { public: MockClientStub(): ola::proto::OlaClientService_Stub(NULL) {} void UpdateDmxData(ola::rpc::RpcController *controller, const ola::proto::DmxData *request, ola::proto::Ack *response, ola::rpc::RpcService::CompletionCallback *done); }; void MockClientStub::UpdateDmxData( ola::rpc::RpcController* controller, const ola::proto::DmxData *request, OLA_UNUSED ola::proto::Ack *response, ola::rpc::RpcService::CompletionCallback *done) { OLA_ASSERT(controller); OLA_ASSERT_FALSE(controller->Failed()); OLA_ASSERT_EQ(TEST_UNIVERSE, (unsigned int) request->universe()); OLA_ASSERT(TEST_DATA == request->data()); done->Run(); } /* * Check that the SendDMX method works correctly. */ void ClientTest::testSendDMX() { // check we survive a null pointer const DmxBuffer buffer(TEST_DATA); uint8_t priority = 100; Client client(NULL, m_test_uid); client.SendDMX(TEST_UNIVERSE, priority, buffer); // check the stub is called correctly Client client2(new MockClientStub(), m_test_uid); client2.SendDMX(TEST_UNIVERSE, priority, buffer); } /* * Check that the DMX get/set works correctly. */ void ClientTest::testGetSetDMX() { DmxBuffer buffer(TEST_DATA); const DmxBuffer empty; Client client(NULL, m_test_uid); ola::TimeStamp timestamp; m_clock.CurrentTime(×tamp); ola::DmxSource source(buffer, timestamp, 100); // check get/set works client.DMXReceived(TEST_UNIVERSE, source); const ola::DmxSource &source2 = client.SourceData(TEST_UNIVERSE); OLA_ASSERT(source2.IsSet()); OLA_ASSERT(source2.Data() == buffer); OLA_ASSERT_EQ(timestamp, source2.Timestamp()); OLA_ASSERT_EQ((uint8_t) 100, source2.Priority()); // check update works ola::DmxBuffer old_data(buffer); buffer.Set(TEST_DATA2); OLA_ASSERT(source2.Data() == old_data); OLA_ASSERT_EQ(timestamp, source2.Timestamp()); OLA_ASSERT_EQ((uint8_t) 100, source2.Priority()); source.UpdateData(buffer, timestamp, 120); client.DMXReceived(TEST_UNIVERSE, source); const ola::DmxSource source3 = client.SourceData(TEST_UNIVERSE); OLA_ASSERT(source3.IsSet()); OLA_ASSERT(buffer == source3.Data()); OLA_ASSERT_EQ(timestamp, source3.Timestamp()); OLA_ASSERT_EQ((uint8_t) 120, source3.Priority()); // check fetching an unknown universe results in an empty buffer const ola::DmxSource source4 = client.SourceData(TEST_UNIVERSE2); OLA_ASSERT_FALSE(source4.IsSet()); OLA_ASSERT(empty == source4.Data()); } ola-0.10.5.nojsmin/olad/plugin_api/TestCommon.h0000644000175000017500000002251313023355232020770 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * TestCommon.h * Test fixture for various olad classes * Copyright (C) 2005 Simon Newton */ #ifndef OLAD_PLUGIN_API_TESTCOMMON_H_ #define OLAD_PLUGIN_API_TESTCOMMON_H_ #include #include #include #include #include #include "ola/Clock.h" #include "ola/DmxBuffer.h" #include "ola/rdm/RDMCommand.h" #include "ola/rdm/UIDSet.h" #include "olad/Device.h" #include "olad/Plugin.h" #include "olad/Port.h" #include "olad/plugin_api/PortManager.h" /* * Mock out an Input Port */ class TestMockInputPort: public ola::BasicInputPort { public: TestMockInputPort(ola::AbstractDevice *parent, unsigned int port_id, const ola::PluginAdaptor *plugin_adaptor) : ola::BasicInputPort(parent, port_id, plugin_adaptor) {} ~TestMockInputPort() {} std::string Description() const { return ""; } bool WriteDMX(const ola::DmxBuffer &buffer) { m_buffer = buffer; return true; } const ola::DmxBuffer &ReadDMX() const { return m_buffer; } private: ola::DmxBuffer m_buffer; }; /* * Same as above but this supports priorities */ class TestMockPriorityInputPort: public TestMockInputPort { public: TestMockPriorityInputPort(ola::AbstractDevice *parent, unsigned int port_id, const ola::PluginAdaptor *plugin_adaptor) : TestMockInputPort(parent, port_id, plugin_adaptor), m_inherited_priority(ola::dmx::SOURCE_PRIORITY_DEFAULT) { } uint8_t InheritedPriority() const { return m_inherited_priority; } void SetInheritedPriority(uint8_t priority) { m_inherited_priority = priority; } protected: bool SupportsPriorities() const { return true; } private: uint8_t m_inherited_priority; }; /* * Mock out an OutputPort */ class TestMockOutputPort: public ola::BasicOutputPort { public: TestMockOutputPort(ola::AbstractDevice *parent, unsigned int port_id, bool start_rdm_discovery_on_patch = false, bool supports_rdm = false) : ola::BasicOutputPort(parent, port_id, start_rdm_discovery_on_patch, supports_rdm) { } ~TestMockOutputPort() {} std::string Description() const { return ""; } bool WriteDMX(const ola::DmxBuffer &buffer, uint8_t priority) { m_buffer = buffer; (void) priority; return true; } const ola::DmxBuffer &ReadDMX() const { return m_buffer; } private: ola::DmxBuffer m_buffer; }; /* * Mock out an RDM OutputPort */ class TestMockRDMOutputPort: public TestMockOutputPort { public: typedef ola::BaseCallback2 RDMRequestHandler; TestMockRDMOutputPort(ola::AbstractDevice *parent, unsigned int port_id, ola::rdm::UIDSet *uids, bool start_rdm_discovery_on_patch = false, RDMRequestHandler *rdm_handler = NULL) : TestMockOutputPort(parent, port_id, start_rdm_discovery_on_patch, true), m_uids(uids), m_rdm_handler(rdm_handler) { } ~TestMockRDMOutputPort() {} void SetRDMHandler(RDMRequestHandler *handler) { m_rdm_handler.reset(handler); } void SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *callback) { // if a RDMRequestHandler was provided use that. if (m_rdm_handler.get()) { m_rdm_handler->Run(request, callback); return; } // otherwise just return a RDM_FAILED_TO_SEND delete request; RunRDMCallback(callback, ola::rdm::RDM_FAILED_TO_SEND); } void RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *on_complete) { on_complete->Run(*m_uids); } void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *on_complete) { on_complete->Run(*m_uids); } private: ola::rdm::UIDSet *m_uids; std::auto_ptr m_rdm_handler; }; /* * Same as above but this supports priorities */ class TestMockPriorityOutputPort: public TestMockOutputPort { public: TestMockPriorityOutputPort(ola::AbstractDevice *parent, unsigned int port_id): TestMockOutputPort(parent, port_id) {} protected: bool SupportsPriorities() const { return true; } }; /* * A mock device */ class MockDevice: public ola::Device { public: MockDevice(ola::AbstractPlugin *owner, const std::string &name) : Device(owner, name) {} std::string DeviceId() const { return Name(); } bool AllowLooping() const { return false; } bool AllowMultiPortPatching() const { return false; } }; /* * A mock device with looping and multiport patching enabled */ class MockDeviceLoopAndMulti: public ola::Device { public: MockDeviceLoopAndMulti(ola::AbstractPlugin *owner, const std::string &name) : Device(owner, name) {} std::string DeviceId() const { return Name(); } bool AllowLooping() const { return true; } bool AllowMultiPortPatching() const { return true; } }; /* * A mock plugin. */ class TestMockPlugin: public ola::Plugin { public: TestMockPlugin(ola::PluginAdaptor *plugin_adaptor, ola::ola_plugin_id plugin_id, bool enabled = true) : Plugin(plugin_adaptor), m_is_running(false), m_enabled(enabled), m_id(plugin_id) {} TestMockPlugin(ola::PluginAdaptor *plugin_adaptor, ola::ola_plugin_id plugin_id, const std::set &conflict_set, bool enabled = true) : Plugin(plugin_adaptor), m_is_running(false), m_enabled(enabled), m_id(plugin_id), m_conflict_set(conflict_set) {} void ConflictsWith(std::set *conflict_set) const { *conflict_set = m_conflict_set; } bool LoadPreferences() { m_preferences = m_plugin_adaptor->NewPreference(PluginPrefix()); return true; } std::string PreferencesSource() const { return ""; } bool IsEnabled() const { return m_enabled; } bool StartHook() { m_is_running = true; return true; } bool StopHook() { m_is_running = false; return true; } std::string Name() const { std::ostringstream str; str << m_id; return str.str(); } std::string Description() const { return "bar"; } ola::ola_plugin_id Id() const { return m_id; } std::string PluginPrefix() const { return "test"; } bool IsRunning() { return m_is_running; } private: bool m_is_running; bool m_enabled; ola::ola_plugin_id m_id; std::set m_conflict_set; }; /** * We mock this out so we can manipulate the wake up time. It was either this * or the mocking the plugin adaptor. */ class MockSelectServer: public ola::io::SelectServerInterface { public: explicit MockSelectServer(const ola::TimeStamp *wake_up) : SelectServerInterface(), m_wake_up(wake_up) {} ~MockSelectServer() {} bool AddReadDescriptor(ola::io::ReadFileDescriptor *descriptor) { (void) descriptor; return true; } bool AddReadDescriptor(ola::io::ConnectedDescriptor *descriptor, bool delete_on_close = false) { (void) descriptor; (void) delete_on_close; return true; } void RemoveReadDescriptor(ola::io::ReadFileDescriptor *descriptor) { (void) descriptor; } void RemoveReadDescriptor(ola::io::ConnectedDescriptor *descriptor) { (void) descriptor; } bool AddWriteDescriptor(ola::io::WriteFileDescriptor *descriptor) { (void) descriptor; return true; } void RemoveWriteDescriptor(ola::io::WriteFileDescriptor *descriptor) { (void) descriptor; } ola::thread::timeout_id RegisterRepeatingTimeout( unsigned int, ola::Callback0 *) { return ola::thread::INVALID_TIMEOUT; } ola::thread::timeout_id RegisterRepeatingTimeout( const ola::TimeInterval&, ola::Callback0*) { return ola::thread::INVALID_TIMEOUT; } ola::thread::timeout_id RegisterSingleTimeout( unsigned int, ola::SingleUseCallback0 *) { return ola::thread::INVALID_TIMEOUT; } ola::thread::timeout_id RegisterSingleTimeout( const ola::TimeInterval&, ola::SingleUseCallback0 *) { return ola::thread::INVALID_TIMEOUT; } void RemoveTimeout(ola::thread::timeout_id id) { (void) id; } const ola::TimeStamp *WakeUpTime() const { return m_wake_up; } void Execute(ola::BaseCallback0 *callback) { callback->Run(); } void DrainCallbacks() {} private: const ola::TimeStamp *m_wake_up; }; #endif // OLAD_PLUGIN_API_TESTCOMMON_H_ ola-0.10.5.nojsmin/olad/plugin_api/UniverseStore.cpp0000644000175000017500000001362713023355232022056 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * UniverseStore.cpp * The universe store class. This maintains the set of all active universes and * saves the settings. * Copyright (C) 2005 Simon Newton */ #include "olad/plugin_api/UniverseStore.h" #include #include #include #include #include #include #include "ola/ExportMap.h" #include "ola/Logging.h" #include "ola/StringUtils.h" #include "ola/stl/STLUtils.h" #include "olad/Preferences.h" #include "olad/Universe.h" namespace ola { using std::pair; using std::set; using std::string; using std::vector; const unsigned int UniverseStore::MINIMUM_RDM_DISCOVERY_INTERVAL = 30; UniverseStore::UniverseStore(Preferences *preferences, ExportMap *export_map) : m_preferences(preferences), m_export_map(export_map) { if (export_map) { export_map->GetStringMapVar(Universe::K_UNIVERSE_NAME_VAR, "universe"); export_map->GetStringMapVar(Universe::K_UNIVERSE_MODE_VAR, "universe"); const char *vars[] = { Universe::K_FPS_VAR, Universe::K_UNIVERSE_INPUT_PORT_VAR, Universe::K_UNIVERSE_OUTPUT_PORT_VAR, Universe::K_UNIVERSE_SINK_CLIENTS_VAR, Universe::K_UNIVERSE_SOURCE_CLIENTS_VAR, Universe::K_UNIVERSE_UID_COUNT_VAR, }; for (unsigned int i = 0; i < sizeof(vars) / sizeof(vars[0]); ++i) { export_map->GetUIntMapVar(string(vars[i]), "universe"); } } } UniverseStore::~UniverseStore() { DeleteAll(); } Universe *UniverseStore::GetUniverse(unsigned int universe_id) const { return STLFindOrNull(m_universe_map, universe_id); } Universe *UniverseStore::GetUniverseOrCreate(unsigned int universe_id) { UniverseMap::iterator iter = STLLookupOrInsertNull( &m_universe_map, universe_id); if (!iter->second) { iter->second = new Universe(universe_id, this, m_export_map, &m_clock); if (iter->second) { if (m_preferences) { RestoreUniverseSettings(iter->second); } } else { OLA_WARN << "Failed to create universe " << universe_id; } } return iter->second; } void UniverseStore::GetList(vector *universes) const { STLValues(m_universe_map, universes); } void UniverseStore::DeleteAll() { UniverseMap::iterator iter; for (iter = m_universe_map.begin(); iter != m_universe_map.end(); iter++) { SaveUniverseSettings(iter->second); delete iter->second; } m_deletion_candiates.clear(); m_universe_map.clear(); } void UniverseStore::AddUniverseGarbageCollection(Universe *universe) { m_deletion_candiates.insert(universe); } void UniverseStore::GarbageCollectUniverses() { set::iterator iter; UniverseMap::iterator map_iter; for (iter = m_deletion_candiates.begin(); iter != m_deletion_candiates.end(); iter++) { if (!(*iter)->IsActive()) { SaveUniverseSettings(*iter); m_universe_map.erase((*iter)->UniverseId()); delete *iter; } } m_deletion_candiates.clear(); } /* * Restore a universe's settings * @param uni the universe to update */ bool UniverseStore::RestoreUniverseSettings(Universe *universe) const { string key, value; std::ostringstream oss; if (!universe) return 0; oss << std::dec << universe->UniverseId(); // load name key = "uni_" + oss.str() + "_name"; value = m_preferences->GetValue(key); if (!value.empty()) universe->SetName(value); // load merge mode key = "uni_" + oss.str() + "_merge"; value = m_preferences->GetValue(key); if (!value.empty()) { if (value == "HTP") universe->SetMergeMode(Universe::MERGE_HTP); else universe->SetMergeMode(Universe::MERGE_LTP); } // load RDM discovery interval key = "uni_" + oss.str() + "_rdm_discovery_interval"; value = m_preferences->GetValue(key); if (!value.empty()) { unsigned int interval; if (StringToInt(value, &interval, true)) { if (interval != 0 && interval < MINIMUM_RDM_DISCOVERY_INTERVAL) { OLA_WARN << "RDM Discovery interval for universe " << universe->UniverseId() << " less than the minimum of " << MINIMUM_RDM_DISCOVERY_INTERVAL; interval = MINIMUM_RDM_DISCOVERY_INTERVAL; } OLA_DEBUG << "RDM Discovery interval for " << oss.str() << " is " << interval; TimeInterval discovery_interval(interval, 0); universe->SetRDMDiscoveryInterval(discovery_interval); } else { OLA_WARN << "Invalid RDM discovery interval for universe " << universe->UniverseId() << ", value was " << value; } } return 0; } /* * Save this universe's settings. * @param universe, the universe to save */ bool UniverseStore::SaveUniverseSettings(Universe *universe) const { string key, mode; std::ostringstream oss; if (!universe || !m_preferences) return 0; oss << std::dec << universe->UniverseId(); // save name key = "uni_" + oss.str() + "_name"; m_preferences->SetValue(key, universe->Name()); // save merge mode key = "uni_" + oss.str() + "_merge"; mode = (universe->MergeMode() == Universe::MERGE_HTP ? "HTP" : "LTP"); m_preferences->SetValue(key, mode); // We don't save the RDM Discovery interval since it can only be set in the // config files for now. m_preferences->Save(); return 0; } } // namespace ola ola-0.10.5.nojsmin/olad/plugin_api/Client.cpp0000644000175000017500000000530113023355232020445 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Client.cpp * Represents a connected client. * Copyright (C) 2005 Simon Newton */ #include #include #include "common/protocol/Ola.pb.h" #include "common/protocol/OlaService.pb.h" #include "ola/Callback.h" #include "ola/Logging.h" #include "ola/rdm/UID.h" #include "ola/stl/STLUtils.h" #include "olad/plugin_api/Client.h" namespace ola { using ola::rdm::UID; using ola::rpc::RpcController; using std::map; Client::Client(ola::proto::OlaClientService_Stub *client_stub, const ola::rdm::UID &uid) : m_client_stub(client_stub), m_uid(uid) { } Client::~Client() { m_data_map.clear(); } bool Client::SendDMX(unsigned int universe, uint8_t priority, const DmxBuffer &buffer) { if (!m_client_stub.get()) { OLA_FATAL << "client_stub is null"; return false; } RpcController *controller = new RpcController(); ola::proto::DmxData dmx_data; ola::proto::Ack *ack = new ola::proto::Ack(); dmx_data.set_priority(priority); dmx_data.set_universe(universe); dmx_data.set_data(buffer.Get()); m_client_stub->UpdateDmxData( controller, &dmx_data, ack, ola::NewSingleCallback(this, &ola::Client::SendDMXCallback, controller, ack)); return true; } void Client::DMXReceived(unsigned int universe, const DmxSource &source) { STLReplace(&m_data_map, universe, source); } const DmxSource Client::SourceData(unsigned int universe) const { map::const_iterator iter = m_data_map.find(universe); if (iter != m_data_map.end()) { return iter->second; } else { DmxSource source; return source; } } ola::rdm::UID Client::GetUID() const { return m_uid; } void Client::SetUID(const ola::rdm::UID &uid) { m_uid = uid; } /* * Called when UpdateDmxData completes. */ void Client::SendDMXCallback(RpcController *controller, ola::proto::Ack *reply) { delete controller; delete reply; } } // namespace ola ola-0.10.5.nojsmin/olad/plugin_api/PortBroker.cpp0000644000175000017500000000556113023355232021330 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * PortBroker.cpp * Acts as the glue between ports and the RDM request path. * Copyright (C) 2010 Simon Newton */ #include #include #include #include "ola/Callback.h" #include "ola/Logging.h" #include "olad/PortBroker.h" namespace ola { using std::pair; using std::set; using std::string; using std::vector; /** * Add a port to the broker */ void PortBroker::AddPort(const Port *port) { port_key key(port->UniqueId(), port); m_ports.insert(key); } /** * Remove a port from the broker */ void PortBroker::RemovePort(const Port *port) { port_key key(port->UniqueId(), port); m_ports.erase(key); } /** * Make an RDM call * @param port the OlaPortService that should exist when the call returns * @param universe the universe to send the RDM request on * @param request the RDM request * @param callback the callback to run when the request completes */ void PortBroker::SendRDMRequest(const Port *port, Universe *universe, ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *callback) { port_key key(port->UniqueId(), port); set::const_iterator iter = m_ports.find(key); if (iter == m_ports.end()) OLA_WARN << "Making an RDM call but the port doesn't exist in the broker!"; universe->SendRDMRequest( request, NewSingleCallback(this, &PortBroker::RequestComplete, key, callback)); } /** * Return from an RDM call * @param key the port associated with this request * @param callback the callback to run if the key still exists * @param status the status of the RDM request * @param response the RDM response */ void PortBroker::RequestComplete(port_key key, ola::rdm::RDMCallback *callback, ola::rdm::RDMReply *reply) { set::const_iterator iter = m_ports.find(key); if (iter == m_ports.end()) { OLA_INFO << "Port no longer exists, cleaning up from RDM response"; delete callback; } else { callback->Run(reply); } } } // namespace ola ola-0.10.5.nojsmin/olad/plugin_api/PreferencesTest.cpp0000644000175000017500000003177013023355232022341 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * PreferencesTest.cpp * Test fixture for the Preferences classes * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include "ola/Logging.h" #include "ola/StringUtils.h" #include "olad/Preferences.h" #include "ola/testing/TestUtils.h" using ola::BoolValidator; using ola::FileBackedPreferences; using ola::FileBackedPreferencesFactory; using ola::IntToString; using ola::IntValidator; using ola::UIntValidator; using ola::MemoryPreferencesFactory; using ola::Preferences; using ola::SetValidator; using ola::StringValidator; using ola::IPv4Validator; using std::string; using std::vector; class PreferencesTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(PreferencesTest); CPPUNIT_TEST(testValidators); CPPUNIT_TEST(testGetSetRemove); CPPUNIT_TEST(testBool); CPPUNIT_TEST(testFactory); CPPUNIT_TEST(testLoad); CPPUNIT_TEST(testSave); CPPUNIT_TEST_SUITE_END(); public: void setUp() { ola::InitLogging(ola::OLA_LOG_DEBUG, ola::OLA_LOG_STDERR); } void testValidators(); void testGetSetRemove(); void testBool(); void testFactory(); void testLoad(); void testSave(); }; CPPUNIT_TEST_SUITE_REGISTRATION(PreferencesTest); /* * Check the validators work */ void PreferencesTest::testValidators() { StringValidator string_validator; OLA_ASSERT(string_validator.IsValid("foo")); OLA_ASSERT_FALSE(string_validator.IsValid("")); std::set values; values.insert("one"); values.insert("two"); SetValidator set_validator(values); OLA_ASSERT(set_validator.IsValid("one")); OLA_ASSERT(set_validator.IsValid("two")); OLA_ASSERT_FALSE(set_validator.IsValid("zero")); OLA_ASSERT_FALSE(set_validator.IsValid("three")); std::set values2; values2.insert(1); values2.insert(3); SetValidator set_validator2(values2); OLA_ASSERT(set_validator2.IsValid("1")); OLA_ASSERT(set_validator2.IsValid("3")); OLA_ASSERT_FALSE(set_validator2.IsValid("0")); OLA_ASSERT_FALSE(set_validator2.IsValid("2")); OLA_ASSERT_FALSE(set_validator2.IsValid("4")); // a string validator that allows empty strings StringValidator string_validator2(true); OLA_ASSERT(string_validator2.IsValid("foo")); OLA_ASSERT(string_validator2.IsValid("")); BoolValidator bool_validator; OLA_ASSERT(bool_validator.IsValid("true")); OLA_ASSERT(bool_validator.IsValid("false")); OLA_ASSERT_FALSE(bool_validator.IsValid("")); IntValidator int_validator(-3, 4); OLA_ASSERT(int_validator.IsValid("-3")); OLA_ASSERT(int_validator.IsValid("0")); OLA_ASSERT(int_validator.IsValid("4")); OLA_ASSERT_FALSE(int_validator.IsValid("-4")); OLA_ASSERT_FALSE(int_validator.IsValid("5")); UIntValidator uint_validator(10, 14); OLA_ASSERT(uint_validator.IsValid("10")); OLA_ASSERT(uint_validator.IsValid("14")); OLA_ASSERT_FALSE(uint_validator.IsValid("0")); OLA_ASSERT_FALSE(uint_validator.IsValid("9")); OLA_ASSERT_FALSE(uint_validator.IsValid("15")); IPv4Validator ipv4_validator; // empty ok OLA_ASSERT(ipv4_validator.IsValid("")); OLA_ASSERT(ipv4_validator.IsValid("1.2.3.4")); OLA_ASSERT(ipv4_validator.IsValid("10.0.255.1")); OLA_ASSERT_FALSE(ipv4_validator.IsValid("foo")); OLA_ASSERT_FALSE(ipv4_validator.IsValid("1.2.3")); OLA_ASSERT_FALSE(ipv4_validator.IsValid("1.2.3.4.5")); OLA_ASSERT_FALSE(ipv4_validator.IsValid("1.f00.3.4")); IPv4Validator ipv4_validator2(false); // empty not ok OLA_ASSERT_FALSE(ipv4_validator2.IsValid("")); } /* * Check that we can get/set the preferences */ void PreferencesTest::testGetSetRemove() { MemoryPreferencesFactory factory; Preferences *preferences = factory.NewPreference("dummy"); string key1 = "foo"; string key2 = "bat"; string value1 = "bar"; string value2 = "baz"; unsigned int value3 = 1; unsigned int value4 = 2; int value5 = 3; int value6 = 4; const char value7[] = "bar"; const char value8[] = "baz"; // test get/set/has single values string OLA_ASSERT_EQ(string(""), preferences->GetValue(key1)); preferences->SetValue(key1, value1); OLA_ASSERT_EQ(value1, preferences->GetValue(key1)); OLA_ASSERT(preferences->HasKey(key1)); preferences->SetValue(key1, value2); OLA_ASSERT_EQ(value2, preferences->GetValue(key1)); preferences->RemoveValue(key1); OLA_ASSERT_EQ(string(""), preferences->GetValue(key1)); OLA_ASSERT_FALSE(preferences->HasKey(key1)); // test get/set/has single values uint OLA_ASSERT_EQ(string(""), preferences->GetValue(key1)); preferences->SetValue(key1, value3); OLA_ASSERT_EQ(IntToString(value3), preferences->GetValue(key1)); OLA_ASSERT(preferences->HasKey(key1)); preferences->SetValue(key1, value4); OLA_ASSERT_EQ(IntToString(value4), preferences->GetValue(key1)); preferences->RemoveValue(key1); OLA_ASSERT_EQ(string(""), preferences->GetValue(key1)); OLA_ASSERT_FALSE(preferences->HasKey(key1)); // test get/set/has single values int OLA_ASSERT_EQ(string(""), preferences->GetValue(key1)); preferences->SetValue(key1, value5); OLA_ASSERT_EQ(IntToString(value5), preferences->GetValue(key1)); OLA_ASSERT(preferences->HasKey(key1)); preferences->SetValue(key1, value6); OLA_ASSERT_EQ(IntToString(value6), preferences->GetValue(key1)); preferences->RemoveValue(key1); OLA_ASSERT_EQ(string(""), preferences->GetValue(key1)); OLA_ASSERT_FALSE(preferences->HasKey(key1)); vector values; // test get/set multiple value string values = preferences->GetMultipleValue(key2); OLA_ASSERT_EQ((size_t) 0, values.size()); preferences->SetMultipleValue(key2, value1); values = preferences->GetMultipleValue(key2); OLA_ASSERT(preferences->HasKey(key2)); OLA_ASSERT_EQ((size_t) 1, values.size()); OLA_ASSERT_EQ(value1, values.at(0)); preferences->SetMultipleValue(key2, value2); values = preferences->GetMultipleValue(key2); OLA_ASSERT_EQ((size_t) 2, values.size()); OLA_ASSERT_EQ(value1, values.at(0)); OLA_ASSERT_EQ(value2, values.at(1)); preferences->RemoveValue(key2); // test get/set multiple value uint values = preferences->GetMultipleValue(key2); OLA_ASSERT_EQ((size_t) 0, values.size()); preferences->SetMultipleValue(key2, value3); values = preferences->GetMultipleValue(key2); OLA_ASSERT(preferences->HasKey(key2)); OLA_ASSERT_EQ((size_t) 1, values.size()); OLA_ASSERT_EQ(IntToString(value3), values.at(0)); preferences->SetMultipleValue(key2, value4); values = preferences->GetMultipleValue(key2); OLA_ASSERT_EQ((size_t) 2, values.size()); OLA_ASSERT_EQ(IntToString(value3), values.at(0)); OLA_ASSERT_EQ(IntToString(value4), values.at(1)); preferences->RemoveValue(key2); // test get/set multiple value int values = preferences->GetMultipleValue(key2); OLA_ASSERT_EQ((size_t) 0, values.size()); preferences->SetMultipleValue(key2, value5); values = preferences->GetMultipleValue(key2); OLA_ASSERT(preferences->HasKey(key2)); OLA_ASSERT_EQ((size_t) 1, values.size()); OLA_ASSERT_EQ(IntToString(value5), values.at(0)); preferences->SetMultipleValue(key2, value6); values = preferences->GetMultipleValue(key2); OLA_ASSERT_EQ((size_t) 2, values.size()); OLA_ASSERT_EQ(IntToString(value5), values.at(0)); OLA_ASSERT_EQ(IntToString(value6), values.at(1)); preferences->RemoveValue(key2); // test SetDefaultValue String OLA_ASSERT(preferences->SetDefaultValue(key1, StringValidator(), value1)); OLA_ASSERT_EQ(value1, preferences->GetValue(key1)); OLA_ASSERT_FALSE(preferences->SetDefaultValue(key1, StringValidator(), value2)); OLA_ASSERT_EQ(value1, preferences->GetValue(key1)); OLA_ASSERT(preferences->HasKey(key1)); preferences->RemoveValue(key1); // test SetDefaultValue uint UIntValidator uint_validator(0, 3); OLA_ASSERT(preferences->SetDefaultValue(key1, uint_validator, value3)); OLA_ASSERT_EQ(IntToString(value3), preferences->GetValue(key1)); OLA_ASSERT_FALSE(preferences->SetDefaultValue(key1, uint_validator, value4)); OLA_ASSERT_EQ(IntToString(value3), preferences->GetValue(key1)); OLA_ASSERT(preferences->HasKey(key1)); preferences->RemoveValue(key1); // test SetDefaultValue int IntValidator int_validator(0, 5); OLA_ASSERT(preferences->SetDefaultValue(key1, int_validator, value5)); OLA_ASSERT_EQ(IntToString(value5), preferences->GetValue(key1)); OLA_ASSERT_FALSE(preferences->SetDefaultValue(key1, int_validator, value6)); OLA_ASSERT_EQ(IntToString(value5), preferences->GetValue(key1)); OLA_ASSERT(preferences->HasKey(key1)); preferences->RemoveValue(key1); // test SetDefaultValue char[] OLA_ASSERT(preferences->SetDefaultValue(key1, StringValidator(), value7)); OLA_ASSERT_EQ(string(value7), preferences->GetValue(key1)); OLA_ASSERT_FALSE(preferences->SetDefaultValue(key1, StringValidator(), value8)); OLA_ASSERT_EQ(string(value7), preferences->GetValue(key1)); OLA_ASSERT(preferences->HasKey(key1)); preferences->RemoveValue(key1); // test SetDefaultValue bool OLA_ASSERT(preferences->SetDefaultValue(key1, BoolValidator(), true)); OLA_ASSERT_EQ(string(BoolValidator::ENABLED), preferences->GetValue(key1)); OLA_ASSERT_FALSE(preferences->SetDefaultValue(key1, BoolValidator(), false)); OLA_ASSERT_EQ(string(BoolValidator::ENABLED), preferences->GetValue(key1)); OLA_ASSERT(preferences->HasKey(key1)); preferences->RemoveValue(key1); } /* * Check that we can get/set the preferences */ void PreferencesTest::testBool() { MemoryPreferencesFactory factory; Preferences *preferences = factory.NewPreference("dummy"); string key1 = "foo"; string value1 = "bar"; // test get/set single values OLA_ASSERT_EQ(false, preferences->GetValueAsBool(key1)); preferences->SetValueAsBool(key1, true); OLA_ASSERT_EQ(true, preferences->GetValueAsBool(key1)); preferences->SetValueAsBool(key1, false); OLA_ASSERT_EQ(false, preferences->GetValueAsBool(key1)); preferences->SetValue(key1, value1); OLA_ASSERT_EQ(false, preferences->GetValueAsBool(key1)); } /* * Check that the factory works as intended */ void PreferencesTest::testFactory() { MemoryPreferencesFactory factory; string preferences_name = "dummy"; Preferences *preferences = factory.NewPreference(preferences_name); Preferences *preferences2 = factory.NewPreference(preferences_name); OLA_ASSERT_EQ(preferences, preferences2); } /* * Check that we can load from a file */ void PreferencesTest::testLoad() { FileBackedPreferences *preferences = new FileBackedPreferences( "", "dummy", NULL); preferences->Clear(); preferences->SetValue("foo", "bad"); preferences->LoadFromFile( TEST_SRC_DIR "/olad/testdata/test_preferences.conf"); OLA_ASSERT_EQ(string("bar"), preferences->GetValue("foo")); OLA_ASSERT(preferences->HasKey("foo")); OLA_ASSERT_EQ(string("bat"), preferences->GetValue("baz")); OLA_ASSERT(preferences->HasKey("baz")); vector values = preferences->GetMultipleValue("multi"); OLA_ASSERT_EQ((size_t) 3, values.size()); OLA_ASSERT_EQ(string("1"), values.at(0)); OLA_ASSERT_EQ(string("2"), values.at(1)); OLA_ASSERT_EQ(string("3"), values.at(2)); delete preferences; } void PreferencesTest::testSave() { const string data_path = TEST_BUILD_DIR "/olad/ola-output.conf"; ola::FilePreferenceSaverThread saver_thread; saver_thread.Start(); FileBackedPreferences *preferences = new FileBackedPreferences( TEST_BUILD_DIR "/olad", "output", &saver_thread); preferences->Clear(); unlink(data_path.c_str()); string key1 = "foo"; string key2 = "bat"; string key3 = "/dev/ttyUSB0"; string value1 = "bar"; string value2 = "baz"; string value3 = "boo"; string multi_key = "multi"; preferences->SetValue(key1, value1); preferences->SetValue(key2, value2); preferences->SetValue(key3, value3); preferences->SetMultipleValue(multi_key, "1"); preferences->SetMultipleValue(multi_key, "2"); preferences->SetMultipleValue(multi_key, "3"); preferences->Save(); saver_thread.Syncronize(); FileBackedPreferences *input_preferences = new FileBackedPreferences("", "input", NULL); input_preferences->LoadFromFile(data_path); OLA_ASSERT(*preferences == *input_preferences); delete preferences; delete input_preferences; saver_thread.Join(); } ola-0.10.5.nojsmin/olad/plugin_api/PortManager.h0000644000175000017500000001040013023355232021107 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * PortManager.h * Provides a unified interface for controlling port patchings & priorities. * Copyright (C) 2005 Simon Newton */ #ifndef OLAD_PLUGIN_API_PORTMANAGER_H_ #define OLAD_PLUGIN_API_PORTMANAGER_H_ #include #include "olad/Device.h" #include "olad/PortBroker.h" #include "olad/plugin_api/DeviceManager.h" #include "olad/plugin_api/UniverseStore.h" #include "ola/base/Macro.h" namespace ola { /** * @brief Responsible for performing Port operations. */ class PortManager { public: /** * @brief Create a new PortManager. * @param universe_store the UniverseStore used to lookup / create Universes. * @param broker the PortBroker to update when Ports are added / removed. */ PortManager(UniverseStore *universe_store, PortBroker *broker) : m_universe_store(universe_store), m_broker(broker) { } /** * @brief Destructor. */ ~PortManager() {} /** * @brief Patch an InputPort to a universe. * @param port the port to patch * @param universe the universe-id to patch to. * @returns true is successful, false otherwise */ bool PatchPort(InputPort *port, unsigned int universe); /** * @brief Patch an OutputPort to a universe. * @param port the port to patch * @param universe the universe-id to patch to. * @returns true is successful, false otherwise */ bool PatchPort(OutputPort *port, unsigned int universe); /** * @brief UnPatch an InputPort. * @param port the port to unpatch * @returns true is successful, false otherwise */ bool UnPatchPort(InputPort *port); /** * @brief UnPatch an OutputPort. * @param port the port to unpatch * @returns true is successful, false otherwise */ bool UnPatchPort(OutputPort *port); /** * @brief Set a port to 'inherit' priority mode. * @param port the port to configure */ bool SetPriorityInherit(Port *port); /** * @brief Set a port to 'override' priority mode. * @param port the port to configure * @param value the new priority */ bool SetPriorityStatic(Port *port, uint8_t value); private: template bool GenericPatchPort(PortClass *port, unsigned int new_universe_id); template bool GenericUnPatchPort(PortClass *port); template bool CheckLooping(const AbstractDevice *device, unsigned int new_universe_id) const; template bool CheckMultiPort(const AbstractDevice *device, unsigned int new_universe_id) const; /** * Check if any input ports in this device are bound to the universe. * @returns true if there is a match, false otherwise. */ bool CheckInputPortsForUniverse(const AbstractDevice *device, unsigned int universe_id) const; /** * Check if any output ports in this device are bound to the universe. * @returns true if there is a match, false otherwise. */ bool CheckOutputPortsForUniverse(const AbstractDevice *device, unsigned int universe_id) const; /** * Check for any port in a list that's bound to this universe. * @returns true if there is a match, false otherwise. */ template bool CheckForPortMatchingUniverse(const std::vector &ports, unsigned int universe_id) const; UniverseStore * const m_universe_store; PortBroker *m_broker; DISALLOW_COPY_AND_ASSIGN(PortManager); }; } // namespace ola #endif // OLAD_PLUGIN_API_PORTMANAGER_H_ ola-0.10.5.nojsmin/olad/plugin_api/Preferences.cpp0000644000175000017500000002661613023355232021504 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Preferences.cpp * This class stores preferences in files * Copyright (C) 2005 Simon Newton */ #define __STDC_LIMIT_MACROS // for UINT8_MAX & friends #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ola/Logging.h" #include "ola/StringUtils.h" #include "ola/file/Util.h" #include "ola/network/IPV4Address.h" #include "ola/stl/STLUtils.h" #include "ola/thread/Thread.h" #include "olad/Preferences.h" namespace ola { using ola::thread::Mutex; using ola::thread::ConditionVariable; using std::ifstream; using std::ofstream; using std::map; using std::pair; using std::string; using std::vector; namespace { void SavePreferencesToFile( const string *filename_ptr, const FilePreferenceSaverThread::PreferencesMap *pref_map_ptr) { std::auto_ptr filename(filename_ptr); std::auto_ptr pref_map( pref_map_ptr); FilePreferenceSaverThread::PreferencesMap::const_iterator iter; ofstream pref_file(filename->data()); if (!pref_file.is_open()) { OLA_WARN << "Could not open " << *filename_ptr << ": " << strerror(errno); return; } for (iter = pref_map->begin(); iter != pref_map->end(); ++iter) { pref_file << iter->first << " = " << iter->second << std::endl; } pref_file.flush(); pref_file.close(); } } // namespace const char BoolValidator::ENABLED[] = "true"; const char BoolValidator::DISABLED[] = "false"; const char FileBackedPreferences::OLA_CONFIG_PREFIX[] = "ola-"; const char FileBackedPreferences::OLA_CONFIG_SUFFIX[] = ".conf"; // Validators //----------------------------------------------------------------------------- bool StringValidator::IsValid(const string &value) const { return m_empty_ok || !value.empty(); } bool BoolValidator::IsValid(const string &value) const { return (value == ENABLED || value == DISABLED); } bool UIntValidator::IsValid(const string &value) const { unsigned int output; if (!StringToInt(value, &output)) { return false; } return (output >= m_gt && output <= m_lt); } bool IntValidator::IsValid(const string &value) const { int output; if (!StringToInt(value, &output)) { return false; } return (output >= m_gt && output <= m_lt); } template <> bool SetValidator::IsValid(const string &value) const { return STLContains(m_values, value); } template <> bool SetValidator::IsValid(const string &value) const { unsigned int output; // It's an integer based set validator, so if we can't parse it to an // integer, it can't possibly match an integer and be valid if (!StringToInt(value, &output)) { return false; } return STLContains(m_values, output); } template <> bool SetValidator::IsValid(const string &value) const { int output; // It's an integer based set validator, so if we can't parse it to an // integer, it can't possibly match an integer and be valid if (!StringToInt(value, &output)) { return false; } return STLContains(m_values, output); } bool IPv4Validator::IsValid(const string &value) const { if (value.empty()) { return m_empty_ok; } vector tokens; StringSplit(value, &tokens, "."); if (tokens.size() != ola::network::IPV4Address::LENGTH) { return false; } for (unsigned int i = 0 ; i < 4; i++) { unsigned int octet; if (!StringToInt(tokens[i], &octet)) { return false; } if (octet > UINT8_MAX) { return false; } } return true; } // Prefs Factory //----------------------------------------------------------------------------- PreferencesFactory::~PreferencesFactory() { map::const_iterator iter; for (iter = m_preferences_map.begin(); iter != m_preferences_map.end(); ++iter) { delete iter->second; } m_preferences_map.clear(); } Preferences *PreferencesFactory::NewPreference(const string &name) { map::iterator iter = m_preferences_map.find(name); if (iter == m_preferences_map.end()) { Preferences *pref = Create(name); m_preferences_map.insert(make_pair(name, pref)); return pref; } else { return iter->second; } } // Memory Preferences //----------------------------------------------------------------------------- MemoryPreferences::~MemoryPreferences() { m_pref_map.clear(); } void MemoryPreferences::Clear() { m_pref_map.clear(); } void MemoryPreferences::SetValue(const string &key, const string &value) { m_pref_map.erase(key); m_pref_map.insert(make_pair(key, value)); } void MemoryPreferences::SetValue(const string &key, unsigned int value) { SetValue(key, IntToString(value)); } void MemoryPreferences::SetValue(const string &key, int value) { SetValue(key, IntToString(value)); } void MemoryPreferences::SetMultipleValue(const string &key, const string &value) { m_pref_map.insert(make_pair(key, value)); } void MemoryPreferences::SetMultipleValue(const string &key, unsigned int value) { SetMultipleValue(key, IntToString(value)); } void MemoryPreferences::SetMultipleValue(const string &key, int value) { SetMultipleValue(key, IntToString(value)); } bool MemoryPreferences::SetDefaultValue(const string &key, const Validator &validator, const string &value) { PreferencesMap::const_iterator iter; iter = m_pref_map.find(key); if (iter == m_pref_map.end() || !validator.IsValid(iter->second)) { SetValue(key, value); return true; } return false; } bool MemoryPreferences::SetDefaultValue(const string &key, const Validator &validator, const char value[]) { return SetDefaultValue(key, validator, string(value)); } bool MemoryPreferences::SetDefaultValue(const string &key, const Validator &validator, unsigned int value) { return SetDefaultValue(key, validator, IntToString(value)); } bool MemoryPreferences::SetDefaultValue(const string &key, const Validator &validator, int value) { return SetDefaultValue(key, validator, IntToString(value)); } bool MemoryPreferences::SetDefaultValue(const string &key, const Validator &validator, const bool value) { return SetDefaultValue( key, validator, value ? BoolValidator::ENABLED : BoolValidator::DISABLED); } string MemoryPreferences::GetValue(const string &key) const { PreferencesMap::const_iterator iter; iter = m_pref_map.find(key); if (iter != m_pref_map.end()) return iter->second; return ""; } vector MemoryPreferences::GetMultipleValue(const string &key) const { vector values; PreferencesMap::const_iterator iter; for (iter = m_pref_map.find(key); iter != m_pref_map.end() && iter->first == key; ++iter) { values.push_back(iter->second); } return values; } bool MemoryPreferences::HasKey(const string &key) const { return STLContains(m_pref_map, key); } void MemoryPreferences::RemoveValue(const string &key) { m_pref_map.erase(key); } bool MemoryPreferences::GetValueAsBool(const string &key) const { PreferencesMap::const_iterator iter; iter = m_pref_map.find(key); if (iter != m_pref_map.end()) return iter->second == BoolValidator::ENABLED; return false; } void MemoryPreferences::SetValueAsBool(const string &key, bool value) { m_pref_map.erase(key); m_pref_map.insert(make_pair(key, (value ? BoolValidator::ENABLED : BoolValidator::DISABLED))); } // FilePreferenceSaverThread //----------------------------------------------------------------------------- FilePreferenceSaverThread::FilePreferenceSaverThread() : Thread(Thread::Options("pref-saver")) { // set a long poll interval so we don't spin m_ss.SetDefaultInterval(TimeInterval(60, 0)); } void FilePreferenceSaverThread::SavePreferences( const string &file_name, const PreferencesMap &preferences) { const string *file_name_ptr = new string(file_name); const PreferencesMap *save_map = new PreferencesMap(preferences); SingleUseCallback0 *cb = NewSingleCallback(SavePreferencesToFile, file_name_ptr, save_map); m_ss.Execute(cb); } void *FilePreferenceSaverThread::Run() { m_ss.Run(); return NULL; } bool FilePreferenceSaverThread::Join(void *ptr) { m_ss.Terminate(); return Thread::Join(ptr); } void FilePreferenceSaverThread::Syncronize() { Mutex syncronize_mutex; ConditionVariable condition_var; syncronize_mutex.Lock(); m_ss.Execute(NewSingleCallback( this, &FilePreferenceSaverThread::CompleteSyncronization, &condition_var, &syncronize_mutex)); condition_var.Wait(&syncronize_mutex); } void FilePreferenceSaverThread::CompleteSyncronization( ConditionVariable *condition, Mutex *mutex) { // calling lock here forces us to block until Wait() is called on the // condition_var. mutex->Lock(); mutex->Unlock(); condition->Signal(); } // FileBackedPreferences //----------------------------------------------------------------------------- bool FileBackedPreferences::Load() { return LoadFromFile(FileName()); } bool FileBackedPreferences::Save() const { m_saver_thread->SavePreferences(FileName(), m_pref_map); return true; } const string FileBackedPreferences::FileName() const { return (m_directory + ola::file::PATH_SEPARATOR + OLA_CONFIG_PREFIX + m_preference_name + OLA_CONFIG_SUFFIX); } bool FileBackedPreferences::LoadFromFile(const string &filename) { ifstream pref_file(filename.data()); if (!pref_file.is_open()) { OLA_INFO << "Missing " << filename << ": " << strerror(errno) << " - this isn't an error, we'll just use the defaults"; return false; } m_pref_map.clear(); string line; while (getline(pref_file, line)) { StringTrim(&line); if (line.empty() || line.at(0) == '#') { continue; } vector tokens; StringSplit(line, &tokens, "="); if (tokens.size() != 2) { OLA_INFO << "Skipping line: " << line; continue; } string key = tokens[0]; string value = tokens[1]; StringTrim(&key); StringTrim(&value); m_pref_map.insert(make_pair(key, value)); } pref_file.close(); return true; } } // namespace ola ola-0.10.5.nojsmin/olad/plugin_api/Client.h0000644000175000017500000000641713023355232020123 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Client.h * Header file for the olad Client class. * Copyright (C) 2005 Simon Newton */ #ifndef OLAD_PLUGIN_API_CLIENT_H_ #define OLAD_PLUGIN_API_CLIENT_H_ #include #include #include "common/rpc/RpcController.h" #include "ola/base/Macro.h" #include "ola/rdm/UID.h" #include "olad/DmxSource.h" namespace ola { namespace proto { class OlaClientService_Stub; class Ack; } } namespace ola { /** * @brief Represents a connected OLA client on the OLA server side. * * This stores the state of the client (i.e. DMX data) and allows us to push * DMX updates to the client via the OlaClientService_Stub. */ class Client { public : /** * @brief Create a new client. * @param client_stub The OlaClientService_Stub to use to communicate with * the client. Ownership is transferred to the client. * @param uid The default UID to use for this client. The client may set its * own UID later. */ Client(ola::proto::OlaClientService_Stub *client_stub, const ola::rdm::UID &uid); virtual ~Client(); /** * @brief Push a DMX update to this client. * @param universe_id the universe the DMX data belongs to * @param priority the priority of the DMX data * @param buffer the DMX data. * @return true if the update was sent, false otherwise */ virtual bool SendDMX(unsigned int universe_id, uint8_t priority, const DmxBuffer &buffer); /** * @brief Called when this client sends us new data * @param universe the id of the universe for the new data * @param source the new DMX data. */ void DMXReceived(unsigned int universe, const DmxSource &source); /** * @brief Get the most recent DMX data received from this client. * @param universe the id of the universe we're interested in */ const DmxSource SourceData(unsigned int universe) const; /** * @brief Return the UID associated with this client. * @returns The client's UID. * * This is normally the UID passed in the constructor, unless the client * itself overrides the UID. */ ola::rdm::UID GetUID() const; /** * @brief Set the UID for the client. * @param uid the new UID to use for this client. */ void SetUID(const ola::rdm::UID &uid); private: void SendDMXCallback(ola::rpc::RpcController *controller, ola::proto::Ack *ack); std::auto_ptr m_client_stub; std::map m_data_map; ola::rdm::UID m_uid; DISALLOW_COPY_AND_ASSIGN(Client); }; } // namespace ola #endif // OLAD_PLUGIN_API_CLIENT_H_ ola-0.10.5.nojsmin/olad/plugin_api/Universe.cpp0000644000175000017500000006754113023355232021045 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Universe.cpp * Represents a universe of DMX data. * Copyright (C) 2005 Simon Newton * * Each universe has the following: * A human readable name * A DmxBuffer with the current dmx data * A MergeMode, either LTP (latest takes precedence) or HTP (highest takes * precedence) * A list of ports bound to this universe. If a port is an input, we use the * data to update the DmxBuffer according to the MergeMode. If a port is an * output, we notify the port whenever the DmxBuffer changes. * A list of source clients. which provide us with data for updating the * DmxBuffer per the merge mode. * A list of sink clients, which we update whenever the DmxBuffer changes. */ #include #include #include #include #include #include #include #include #include "ola/base/Array.h" #include "ola/Logging.h" #include "ola/MultiCallback.h" #include "ola/rdm/RDMCommand.h" #include "ola/rdm/RDMEnums.h" #include "ola/stl/STLUtils.h" #include "ola/strings/Format.h" #include "olad/Port.h" #include "olad/Universe.h" #include "olad/plugin_api/Client.h" #include "olad/plugin_api/UniverseStore.h" namespace ola { using ola::rdm::RDMDiscoveryCallback; using ola::rdm::RDMReply; using ola::rdm::RDMRequest; using ola::rdm::RunRDMCallback; using ola::rdm::UID; using ola::strings::ToHex; using std::auto_ptr; using std::map; using std::ostringstream; using std::set; using std::string; using std::vector; const char Universe::K_UNIVERSE_UID_COUNT_VAR[] = "universe-uids"; const char Universe::K_FPS_VAR[] = "universe-dmx-frames"; const char Universe::K_MERGE_HTP_STR[] = "htp"; const char Universe::K_MERGE_LTP_STR[] = "ltp"; const char Universe::K_UNIVERSE_INPUT_PORT_VAR[] = "universe-input-ports"; const char Universe::K_UNIVERSE_MODE_VAR[] = "universe-mode"; const char Universe::K_UNIVERSE_NAME_VAR[] = "universe-name"; const char Universe::K_UNIVERSE_OUTPUT_PORT_VAR[] = "universe-output-ports"; const char Universe::K_UNIVERSE_RDM_REQUESTS[] = "universe-rdm-requests"; const char Universe::K_UNIVERSE_SINK_CLIENTS_VAR[] = "universe-sink-clients"; const char Universe::K_UNIVERSE_SOURCE_CLIENTS_VAR[] = "universe-source-clients"; /* * Create a new universe * @param uid the universe id of this universe * @param store the store this universe came from * @param export_map the ExportMap that we update */ Universe::Universe(unsigned int universe_id, UniverseStore *store, ExportMap *export_map, Clock *clock) : m_universe_name(""), m_universe_id(universe_id), m_active_priority(ola::dmx::SOURCE_PRIORITY_MIN), m_merge_mode(Universe::MERGE_LTP), m_universe_store(store), m_export_map(export_map), m_clock(clock), m_rdm_discovery_interval(), m_last_discovery_time() { ostringstream universe_id_str, universe_name_str; universe_id_str << universe_id; m_universe_id_str = universe_id_str.str(); universe_name_str << "Universe " << universe_id; m_universe_name = universe_name_str.str(); UpdateName(); UpdateMode(); const char *vars[] = { K_FPS_VAR, K_UNIVERSE_INPUT_PORT_VAR, K_UNIVERSE_OUTPUT_PORT_VAR, K_UNIVERSE_RDM_REQUESTS, K_UNIVERSE_SINK_CLIENTS_VAR, K_UNIVERSE_SOURCE_CLIENTS_VAR, K_UNIVERSE_UID_COUNT_VAR, }; if (m_export_map) { for (unsigned int i = 0; i < arraysize(vars); ++i) { (*m_export_map->GetUIntMapVar(vars[i]))[m_universe_id_str] = 0; } } // We set the last discovery time to now, since most ports will trigger // discovery when they are patched. clock->CurrentTime(&m_last_discovery_time); } /* * Delete this universe */ Universe::~Universe() { const char *string_vars[] = { K_UNIVERSE_NAME_VAR, K_UNIVERSE_MODE_VAR, }; const char *uint_vars[] = { K_FPS_VAR, K_UNIVERSE_INPUT_PORT_VAR, K_UNIVERSE_OUTPUT_PORT_VAR, K_UNIVERSE_RDM_REQUESTS, K_UNIVERSE_SINK_CLIENTS_VAR, K_UNIVERSE_SOURCE_CLIENTS_VAR, K_UNIVERSE_UID_COUNT_VAR, }; if (m_export_map) { for (unsigned int i = 0; i < arraysize(string_vars); ++i) { m_export_map->GetStringMapVar(string_vars[i])->Remove(m_universe_id_str); } for (unsigned int i = 0; i < arraysize(uint_vars); ++i) { m_export_map->GetUIntMapVar(uint_vars[i])->Remove(m_universe_id_str); } } } /* * Set the universe name * @param name the new universe name */ void Universe::SetName(const string &name) { m_universe_name = name; UpdateName(); // notify ports vector::const_iterator iter; for (iter = m_output_ports.begin(); iter != m_output_ports.end(); ++iter) { (*iter)->UniverseNameChanged(name); } } /* * Set the universe merge mode * @param merge_mode the new merge_mode */ void Universe::SetMergeMode(enum merge_mode merge_mode) { m_merge_mode = merge_mode; UpdateMode(); } /* * Add an InputPort to this universe. * @param port the port to add */ bool Universe::AddPort(InputPort *port) { return GenericAddPort(port, &m_input_ports); } /* * Add an OutputPort to this universe. * @param port the port to add */ bool Universe::AddPort(OutputPort *port) { return GenericAddPort(port, &m_output_ports); } /* * Remove a port from this universe. * @param port the port to remove * @return true if the port was removed, false if it didn't exist */ bool Universe::RemovePort(InputPort *port) { return GenericRemovePort(port, &m_input_ports); } /* * Remove a port from this universe. * @param port the port to remove * @return true if the port was removed, false if it didn't exist */ bool Universe::RemovePort(OutputPort *port) { bool ret = GenericRemovePort(port, &m_output_ports, &m_output_uids); if (m_export_map) { (*m_export_map->GetUIntMapVar(K_UNIVERSE_UID_COUNT_VAR))[m_universe_id_str] = m_output_uids.size(); } return ret; } /* * Check if this port is bound to this universe * @param port the port to check for * @return true if the port exists in this universe, false otherwise */ bool Universe::ContainsPort(InputPort *port) const { return GenericContainsPort(port, m_input_ports); } /* * Check if this port is bound to this universe * @param port the port to check for * @return true if the port exists in this universe, false otherwise */ bool Universe::ContainsPort(OutputPort *port) const { return GenericContainsPort(port, m_output_ports); } /* * Get a list of input ports associated with this universe * @param ports, the vector to be populated */ void Universe::InputPorts(vector *ports) const { ports->clear(); std::copy(m_input_ports.begin(), m_input_ports.end(), std::back_inserter(*ports)); } /* * Get a list of output ports associated with this universe * @param ports, the vector to be populated */ void Universe::OutputPorts(vector *ports) const { ports->clear(); std::copy(m_output_ports.begin(), m_output_ports.end(), std::back_inserter(*ports)); } /* * @brief Add a client as a source for this universe * @param client the client to add * @return true */ bool Universe::AddSourceClient(Client *client) { // Check to see if it exists already. It doesn't make sense to have multiple // clients if (STLReplace(&m_source_clients, client, false)) { return true; } OLA_INFO << "Added source client, " << client << " to universe " << m_universe_id; SafeIncrement(K_UNIVERSE_SOURCE_CLIENTS_VAR); return true; } /* * @param Remove this client from the universe. * @note After the client is removed we internally check if this universe is * still in use, and if not delete it * @param client the client to remove * @return true is this client was removed, false if it didn't exist */ bool Universe::RemoveSourceClient(Client *client) { if (!STLRemove(&m_source_clients, client)) { return false; } SafeDecrement(K_UNIVERSE_SOURCE_CLIENTS_VAR); OLA_INFO << "Source client " << client << " has been removed from uni " << m_universe_id; if (!IsActive()) { m_universe_store->AddUniverseGarbageCollection(this); } return true; } /* * Check if this universe contains a client as a source * @param client the client to check for * @returns true if this universe contains the client, false otherwise */ bool Universe::ContainsSourceClient(Client *client) const { return STLContains(m_source_clients, client); } /* * @brief Add a client as a sink for this universe * @param client the client to add * @return true if client was added, and false if it was already a sink client */ bool Universe::AddSinkClient(Client *client) { if (!STLInsertIfNotPresent(&m_sink_clients, client)) { return false; } OLA_INFO << "Added sink client, " << client << " to universe " << m_universe_id; SafeIncrement(K_UNIVERSE_SINK_CLIENTS_VAR); return true; } /* * @param Remove this sink client from the universe. * @note After the client is removed we internally check if this universe is * still in use, and if not delete it * @param client the client to remove * @return true is this client was removed, false if it didn't exist */ bool Universe::RemoveSinkClient(Client *client) { if (!STLRemove(&m_sink_clients, client)) { return false; } SafeDecrement(K_UNIVERSE_SINK_CLIENTS_VAR); OLA_INFO << "Sink client " << client << " has been removed from uni " << m_universe_id; if (!IsActive()) { m_universe_store->AddUniverseGarbageCollection(this); } return true; } /* * Check if this universe contains a client as a sink * @param client the client to check for * @returns true if this universe contains the client, false otherwise */ bool Universe::ContainsSinkClient(Client *client) const { return STLContains(m_sink_clients, client); } /* * Set the dmx data for this universe, this overrides anything from the clients * or ports but will be overridden in the next update. * @param buffer the dmx buffer with the data * @return true is we updated all ports/clients, false otherwise */ bool Universe::SetDMX(const DmxBuffer &buffer) { if (!buffer.Size()) { OLA_INFO << "Trying to SetDMX with a 0 length dmx buffer, universe " << UniverseId(); return true; } m_buffer.Set(buffer); return UpdateDependants(); } /* * Call this when the dmx in a port that is part of this universe changes * @param port the port that has changed */ bool Universe::PortDataChanged(InputPort *port) { if (!ContainsPort(port)) { OLA_INFO << "Trying to update a port which isn't bound to universe: " << UniverseId(); return false; } if (MergeAll(port, NULL)) { UpdateDependants(); } return true; } /* * Called to indicate that data from a client has changed */ bool Universe::SourceClientDataChanged(Client *client) { if (!client) { return false; } AddSourceClient(client); // always add since this may be the first call if (MergeAll(NULL, client)) { UpdateDependants(); } return true; } /** * @brief Clean old source clients */ void Universe::CleanStaleSourceClients() { SourceClientMap::iterator iter = m_source_clients.begin(); while (iter != m_source_clients.end()) { if (iter->second) { // if stale remove it m_source_clients.erase(iter++); SafeDecrement(K_UNIVERSE_SOURCE_CLIENTS_VAR); OLA_INFO << "Removed Stale Client"; if (!IsActive()) { m_universe_store->AddUniverseGarbageCollection(this); } } else { // clear the stale flag iter->second = true; ++iter; } } } /* * Handle a RDM request for this universe, ownership of the request object is * transferred to this method. */ void Universe::SendRDMRequest(RDMRequest *request_ptr, ola::rdm::RDMCallback *callback) { auto_ptr request(request_ptr); OLA_INFO << "Universe " << UniverseId() << ", RDM request to " << request->DestinationUID() << ", SD: " << request->SubDevice() << ", CC " << ToHex(request->CommandClass()) << ", TN " << static_cast(request->TransactionNumber()) << ", PID " << ToHex(request->ParamId()) << ", PDL: " << request->ParamDataSize(); SafeIncrement(K_UNIVERSE_RDM_REQUESTS); if (request->DestinationUID().IsBroadcast()) { if (m_output_ports.empty()) { RunRDMCallback( callback, request->IsDUB() ? ola::rdm::RDM_TIMEOUT : ola::rdm::RDM_WAS_BROADCAST); return; } // send this request to all ports broadcast_request_tracker *tracker = new broadcast_request_tracker; tracker->expected_count = m_output_ports.size(); tracker->current_count = 0; tracker->status_code = (request->IsDUB() ? ola::rdm::RDM_PLUGIN_DISCOVERY_NOT_SUPPORTED : ola::rdm::RDM_WAS_BROADCAST); tracker->callback = callback; vector::iterator port_iter; for (port_iter = m_output_ports.begin(); port_iter != m_output_ports.end(); ++port_iter) { // because each port deletes the request, we need to copy it here if (request->IsDUB()) { (*port_iter)->SendRDMRequest( request->Duplicate(), NewSingleCallback(this, &Universe::HandleBroadcastDiscovery, tracker)); } else { (*port_iter)->SendRDMRequest( request->Duplicate(), NewSingleCallback(this, &Universe::HandleBroadcastAck, tracker)); } } } else { map::iterator iter = m_output_uids.find(request->DestinationUID()); if (iter == m_output_uids.end()) { OLA_WARN << "Can't find UID " << request->DestinationUID() << " in the output universe map, dropping request"; RunRDMCallback(callback, ola::rdm::RDM_UNKNOWN_UID); } else { iter->second->SendRDMRequest(request.release(), callback); } } } /* * Trigger RDM discovery for this universe */ void Universe::RunRDMDiscovery(RDMDiscoveryCallback *on_complete, bool full) { if (full) { OLA_INFO << "Full RDM discovery triggered for universe " << m_universe_id; } else { OLA_INFO << "Incremental RDM discovery triggered for universe " << m_universe_id; } m_clock->CurrentTime(&m_last_discovery_time); // we need to make a copy of the ports first, because the callback may run at // any time so we need to guard against the port list changing. vector output_ports(m_output_ports.size()); copy(m_output_ports.begin(), m_output_ports.end(), output_ports.begin()); // the multicallback that indicates when discovery is done BaseCallback0 *discovery_complete = NewMultiCallback( output_ports.size(), NewSingleCallback(this, &Universe::DiscoveryComplete, on_complete)); // Send Discovery requests to all ports, as each of these return they'll // update the UID map. When all ports callbacks have run, the MultiCallback // will trigger, running the DiscoveryCallback. vector::iterator iter; for (iter = output_ports.begin(); iter != output_ports.end(); ++iter) { if (full) { (*iter)->RunFullDiscovery( NewSingleCallback(this, &Universe::PortDiscoveryComplete, discovery_complete, *iter)); } else { (*iter)->RunIncrementalDiscovery( NewSingleCallback(this, &Universe::PortDiscoveryComplete, discovery_complete, *iter)); } } } /* * Update the UID : port mapping with this new data */ void Universe::NewUIDList(OutputPort *port, const ola::rdm::UIDSet &uids) { map::iterator iter = m_output_uids.begin(); while (iter != m_output_uids.end()) { if (iter->second == port && !uids.Contains(iter->first)) { m_output_uids.erase(iter++); } else { ++iter; } } ola::rdm::UIDSet::Iterator set_iter = uids.Begin(); for (; set_iter != uids.End(); ++set_iter) { iter = m_output_uids.find(*set_iter); if (iter == m_output_uids.end()) { m_output_uids[*set_iter] = port; } else if (iter->second != port) { OLA_WARN << "UID " << *set_iter << " seen on more than one port"; } } if (m_export_map) { (*m_export_map->GetUIntMapVar(K_UNIVERSE_UID_COUNT_VAR))[m_universe_id_str] = m_output_uids.size(); } } /* * Returns the complete UIDSet for this universe */ void Universe::GetUIDs(ola::rdm::UIDSet *uids) const { map::const_iterator iter = m_output_uids.begin(); for (; iter != m_output_uids.end(); ++iter) { uids->AddUID(iter->first); } } /** * Return the number of uids in the universe */ unsigned int Universe::UIDCount() const { return m_output_uids.size(); } /* * Return true if this universe is in use (has at least one port or client). */ bool Universe::IsActive() const { // any of the following means the port is active return !(m_output_ports.empty() && m_input_ports.empty() && m_source_clients.empty() && m_sink_clients.empty()); } // Private Methods //----------------------------------------------------------------------------- /* * Called when the dmx data for this universe changes, * updates everyone who needs to know (patched ports and network clients) */ bool Universe::UpdateDependants() { vector::const_iterator iter; set::const_iterator client_iter; // write to all ports assigned to this universe for (iter = m_output_ports.begin(); iter != m_output_ports.end(); ++iter) { (*iter)->WriteDMX(m_buffer, m_active_priority); } // write to all clients for (client_iter = m_sink_clients.begin(); client_iter != m_sink_clients.end(); ++client_iter) { (*client_iter)->SendDMX(m_universe_id, m_active_priority, m_buffer); } SafeIncrement(K_FPS_VAR); return true; } /* * Update the name in the export map. */ void Universe::UpdateName() { if (!m_export_map) { return; } StringMap *name_map = m_export_map->GetStringMapVar(K_UNIVERSE_NAME_VAR); (*name_map)[m_universe_id_str] = m_universe_name; } /* * Update the mode in the export map. */ void Universe::UpdateMode() { if (!m_export_map) { return; } StringMap *mode_map = m_export_map->GetStringMapVar(K_UNIVERSE_MODE_VAR); (*mode_map)[m_universe_id_str] = (m_merge_mode == Universe::MERGE_LTP ? K_MERGE_LTP_STR : K_MERGE_HTP_STR); } /* * HTP Merge all sources (clients/ports) * @pre sources.size >= 2 * @param sources the list of DmxSources to merge */ void Universe::HTPMergeSources(const vector &sources) { vector::const_iterator iter; m_buffer.Reset(); for (iter = sources.begin(); iter != sources.end(); ++iter) { m_buffer.HTPMerge(iter->Data()); } } /* * Merge all port/client sources. * This does a priority based merge as documented at: * https://wiki.openlighting.org/index.php/OLA_Merging_Algorithms * @param port the input port that changed or NULL * @param client the client that changed or NULL * @returns true if the data for this universe changed, false otherwise */ bool Universe::MergeAll(const InputPort *port, const Client *client) { vector active_sources; vector::const_iterator iter; SourceClientMap::const_iterator client_iter; m_active_priority = ola::dmx::SOURCE_PRIORITY_MIN; TimeStamp now; m_clock->CurrentTime(&now); bool changed_source_is_active = false; // Find the highest active ports for (iter = m_input_ports.begin(); iter != m_input_ports.end(); ++iter) { DmxSource source = (*iter)->SourceData(); if (!source.IsSet() || !source.IsActive(now) || !source.Data().Size()) { continue; } if (source.Priority() > m_active_priority) { changed_source_is_active = false; active_sources.clear(); m_active_priority = source.Priority(); } if (source.Priority() == m_active_priority) { active_sources.push_back(source); if (*iter == port) { changed_source_is_active = true; } } } // find the highest priority active clients for (client_iter = m_source_clients.begin(); client_iter != m_source_clients.end(); ++client_iter) { const DmxSource &source = client_iter->first->SourceData(UniverseId()); if (!source.IsSet() || !source.IsActive(now) || !source.Data().Size()) { continue; } if (source.Priority() > m_active_priority) { changed_source_is_active = false; active_sources.clear(); m_active_priority = source.Priority(); } if (source.Priority() == m_active_priority) { active_sources.push_back(source); if (client_iter->first == client) { changed_source_is_active = true; } } } if (active_sources.empty()) { OLA_WARN << "Something changed but we didn't find any active sources " << " for universe " << UniverseId(); return false; } if (!changed_source_is_active) { // this source didn't have any effect, skip return false; } // only one source at the active priority if (active_sources.size() == 1) { m_buffer.Set(active_sources[0].Data()); } else { // multi source merge if (m_merge_mode == Universe::MERGE_LTP) { vector::const_iterator source_iter = active_sources.begin(); DmxSource changed_source; if (port) { changed_source = port->SourceData(); } else { changed_source = client->SourceData(UniverseId()); } // check that the current port/client is newer than all other active // sources for (; source_iter != active_sources.end(); source_iter++) { if (changed_source.Timestamp() < source_iter->Timestamp()) { return false; } } // if we made it to here this is the newest source m_buffer.Set(changed_source.Data()); } else { HTPMergeSources(active_sources); } } return true; } /** * Called when discovery completes on a single ports. */ void Universe::PortDiscoveryComplete(BaseCallback0 *on_complete, OutputPort *output_port, const ola::rdm::UIDSet &uids) { NewUIDList(output_port, uids); on_complete->Run(); } /** * Called when discovery completes on all ports. */ void Universe::DiscoveryComplete(RDMDiscoveryCallback *on_complete) { ola::rdm::UIDSet uids; GetUIDs(&uids); if (on_complete) { on_complete->Run(uids); } } /** * Track fan-out responses for a broadcast request. * This increments the port counter until we reach the expected value, and * which point we run the callback for the client. */ void Universe::HandleBroadcastAck(broadcast_request_tracker *tracker, RDMReply *reply) { tracker->current_count++; if (reply->StatusCode() != ola::rdm::RDM_WAS_BROADCAST) { // propagate errors though tracker->status_code = reply->StatusCode(); } if (tracker->current_count == tracker->expected_count) { // all ports have completed RunRDMCallback(tracker->callback, tracker->status_code); delete tracker; } } /** * Handle the DUB responses. This is unique because unlike an RDM splitter can * can return the DUB responses from each port (485 line in the splitter * world). We do this by concatenating the vectors together. * * The response codes should be one of: * RDM_DUB_RESPONSE - got a DUB response * RDM_TIMEOUT - no response received * RDM_PLUGIN_DISCOVERY_NOT_SUPPORTED - the port doesn't support DUB * * The above list is ordered in highest to lowest precedence, i.e. if we get * any port with a RDM_DUB_RESPONSE, this overrides any other message. */ void Universe::HandleBroadcastDiscovery( broadcast_request_tracker *tracker, RDMReply *reply) { tracker->current_count++; if (reply->StatusCode() == ola::rdm::RDM_DUB_RESPONSE) { // RDM_DUB_RESPONSE is the highest priority tracker->status_code = ola::rdm::RDM_DUB_RESPONSE; } else if (reply->StatusCode() == ola::rdm::RDM_TIMEOUT && tracker->status_code != ola::rdm::RDM_DUB_RESPONSE) { // RDM_TIMEOUT is the second highest tracker->status_code = reply->StatusCode(); } else if (tracker->status_code != ola::rdm::RDM_DUB_RESPONSE && tracker->status_code != ola::rdm::RDM_TIMEOUT) { // everything else follows tracker->status_code = reply->StatusCode(); } // append any packets to the main packets vector tracker->frames.insert(tracker->frames.end(), reply->Frames().begin(), reply->Frames().end()); if (tracker->current_count == tracker->expected_count) { // all ports have completed RDMReply reply(tracker->status_code, NULL, tracker->frames); tracker->callback->Run(&reply); delete tracker; } } /* * Helper function to increment an Export Map variable */ void Universe::SafeIncrement(const string &name) { if (m_export_map) { (*m_export_map->GetUIntMapVar(name))[m_universe_id_str]++; } } /* * Helper function to decrement an Export Map variable */ void Universe::SafeDecrement(const string &name) { if (m_export_map) { (*m_export_map->GetUIntMapVar(name))[m_universe_id_str]--; } } /* * Add an Input or Output port to this universe. * @param port, the port to add * @param ports, the vector of ports to add to */ template bool Universe::GenericAddPort(PortClass *port, vector *ports) { if (find(ports->begin(), ports->end(), port) != ports->end()) { return true; } ports->push_back(port); if (m_export_map) { UIntMap *map = m_export_map->GetUIntMapVar( IsInputPort() ? K_UNIVERSE_INPUT_PORT_VAR : K_UNIVERSE_OUTPUT_PORT_VAR); (*map)[m_universe_id_str]++; } return true; } /* * Remove an Input or Output port from this universe. * @param port, the port to add * @param ports, the vector of ports to remove from */ template bool Universe::GenericRemovePort(PortClass *port, vector *ports, map *uid_map) { typename vector::iterator iter = find(ports->begin(), ports->end(), port); if (iter == ports->end()) { OLA_DEBUG << "Could not find port " << port->UniqueId() << " in universe " << UniverseId(); return true; } ports->erase(iter); if (m_export_map) { UIntMap *map = m_export_map->GetUIntMapVar( IsInputPort() ? K_UNIVERSE_INPUT_PORT_VAR : K_UNIVERSE_OUTPUT_PORT_VAR); (*map)[m_universe_id_str]--; } if (!IsActive()) { m_universe_store->AddUniverseGarbageCollection(this); } // Remove any uids that mapped to this port if (uid_map) { typename map::iterator uid_iter = uid_map->begin(); while (uid_iter != uid_map->end()) { if (uid_iter->second == port) { uid_map->erase(uid_iter++); } else { ++uid_iter; } } } return true; } /* * Check if this universe contains a particular port. * @param port, the port to add * @param ports, the vector of ports to remove from */ template bool Universe::GenericContainsPort(PortClass *port, const vector &ports) const { return find(ports.begin(), ports.end(), port) != ports.end(); } } // namespace ola ola-0.10.5.nojsmin/olad/plugin_api/PortTest.cpp0000644000175000017500000001151513023355232021017 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * PortTest.cpp * Test fixture for the Port classes * Copyright (C) 2005 Simon Newton */ #include #include #include #include "olad/PluginAdaptor.h" #include "olad/PortBroker.h" #include "olad/Preferences.h" #include "olad/plugin_api/TestCommon.h" #include "olad/plugin_api/UniverseStore.h" #include "ola/testing/TestUtils.h" using ola::Clock; using ola::TimeStamp; using std::string; class PortTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(PortTest); CPPUNIT_TEST(testOutputPortPriorities); CPPUNIT_TEST(testInputPortPriorities); CPPUNIT_TEST_SUITE_END(); public: void testOutputPortPriorities(); void testInputPortPriorities(); private: Clock m_clock; }; CPPUNIT_TEST_SUITE_REGISTRATION(PortTest); /* * Check that we can set the priority & mode of output ports */ void PortTest::testOutputPortPriorities() { TestMockOutputPort output_port(NULL, 1); OLA_ASSERT_EQ(ola::dmx::SOURCE_PRIORITY_DEFAULT, output_port.GetPriority()); OLA_ASSERT_EQ(ola::PRIORITY_MODE_INHERIT, output_port.GetPriorityMode()); // test the setting of priorities OLA_ASSERT(output_port.SetPriority(120)); OLA_ASSERT_EQ((uint8_t) 120, output_port.GetPriority()); OLA_ASSERT_FALSE(output_port.SetPriority(201)); OLA_ASSERT_EQ((uint8_t) 120, output_port.GetPriority()); OLA_ASSERT(output_port.SetPriority(0)); OLA_ASSERT_EQ((uint8_t) 0, output_port.GetPriority()); // test the setting of modes output_port.SetPriorityMode(ola::PRIORITY_MODE_STATIC); OLA_ASSERT_EQ(ola::PRIORITY_MODE_STATIC, output_port.GetPriorityMode()); output_port.SetPriorityMode(ola::PRIORITY_MODE_INHERIT); OLA_ASSERT_EQ(ola::PRIORITY_MODE_INHERIT, output_port.GetPriorityMode()); } /* * Test that we can set the priorities & modes of input ports */ void PortTest::testInputPortPriorities() { unsigned int universe_id = 1; ola::MemoryPreferences preferences("foo"); ola::UniverseStore store(&preferences, NULL); ola::PortBroker broker; ola::PortManager port_manager(&store, &broker); MockDevice device(NULL, "foo"); TimeStamp time_stamp; MockSelectServer ss(&time_stamp); ola::PluginAdaptor plugin_adaptor(NULL, &ss, NULL, NULL, NULL, NULL); // This port operates in static priority mode TestMockInputPort input_port(&device, 1, &plugin_adaptor); port_manager.PatchPort(&input_port, universe_id); ola::DmxBuffer buffer("foo bar baz"); m_clock.CurrentTime(&time_stamp); input_port.WriteDMX(buffer); input_port.DmxChanged(); ola::Universe *universe = store.GetUniverseOrCreate(universe_id); OLA_ASSERT(universe); OLA_ASSERT_EQ(ola::dmx::SOURCE_PRIORITY_DEFAULT, universe->ActivePriority()); // change the priority uint8_t new_priority = 120; port_manager.SetPriorityStatic(&input_port, new_priority); m_clock.CurrentTime(&time_stamp); input_port.WriteDMX(buffer); input_port.DmxChanged(); OLA_ASSERT_EQ(new_priority, universe->ActivePriority()); new_priority = 0; port_manager.SetPriorityStatic(&input_port, new_priority); m_clock.CurrentTime(&time_stamp); input_port.WriteDMX(buffer); input_port.DmxChanged(); OLA_ASSERT_EQ(new_priority, universe->ActivePriority()); port_manager.UnPatchPort(&input_port); // now try a port that supported priorities TestMockPriorityInputPort input_port2(&device, 2, &plugin_adaptor); port_manager.PatchPort(&input_port2, universe_id); // the default mode is static, lets change it to inherit input_port2.SetPriorityMode(ola::PRIORITY_MODE_INHERIT); input_port2.SetInheritedPriority(99); m_clock.CurrentTime(&time_stamp); input_port2.WriteDMX(buffer); input_port2.DmxChanged(); OLA_ASSERT_EQ((uint8_t) 99, universe->ActivePriority()); input_port2.SetInheritedPriority(123); m_clock.CurrentTime(&time_stamp); input_port2.WriteDMX(buffer); input_port2.DmxChanged(); OLA_ASSERT_EQ((uint8_t) 123, universe->ActivePriority()); // now try static mode new_priority = 108; port_manager.SetPriorityStatic(&input_port2, new_priority); m_clock.CurrentTime(&time_stamp); input_port2.WriteDMX(buffer); input_port2.DmxChanged(); OLA_ASSERT_EQ(new_priority, universe->ActivePriority()); } ola-0.10.5.nojsmin/olad/plugin_api/UniverseStore.h0000644000175000017500000000632413023355232021517 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * UniverseStore.h * The Universe Store class - this manages the universes * Copyright (C) 2005 Simon Newton */ #ifndef OLAD_PLUGIN_API_UNIVERSESTORE_H_ #define OLAD_PLUGIN_API_UNIVERSESTORE_H_ #include #include #include #include #include "ola/Clock.h" #include "ola/base/Macro.h" namespace ola { class Universe; /** * @brief Maintains a collection of Universe objects. */ class UniverseStore { public: /** * @brief Create a new UniverseStore. * @param preferences The Preferences store. * @param export_map the ExportMap to use for stats, may be NULL. */ UniverseStore(class Preferences *preferences, class ExportMap *export_map); /** * @brief Destructor. */ ~UniverseStore(); /** * @brief Lookup a universe from its universe-id. * @param universe_id the universe-id of the universe. * @return the universe, or NULL if the universe doesn't exist. */ Universe *GetUniverse(unsigned int universe_id) const; /** * @brief Lookup a universe, or create it if it does not exist. * @param universe_id the universe-id of the universe. * @return the universe, or NULL on error */ Universe *GetUniverseOrCreate(unsigned int universe_id); /** * @brief Return the number of universes. */ unsigned int UniverseCount() const { return m_universe_map.size(); } /** * @brief Returns a list of universes. This must be freed when you're * done with it. * @param[out] universes a pointer to a vector of Universes. */ void GetList(std::vector *universes) const; /** * @brief Delete all universes. */ void DeleteAll(); /** * @brief Mark a universe as a candiate for garbage collection. * @param universe the Universe which has no clients or ports bound. */ void AddUniverseGarbageCollection(Universe *universe); /** * @brief Garbage collect any pending universes. */ void GarbageCollectUniverses(); private: typedef std::map UniverseMap; Preferences *m_preferences; ExportMap *m_export_map; UniverseMap m_universe_map; std::set m_deletion_candiates; // list of universes we may be // able to delete Clock m_clock; bool RestoreUniverseSettings(Universe *universe) const; bool SaveUniverseSettings(Universe *universe) const; static const unsigned int MINIMUM_RDM_DISCOVERY_INTERVAL; DISALLOW_COPY_AND_ASSIGN(UniverseStore); }; } // namespace ola #endif // OLAD_PLUGIN_API_UNIVERSESTORE_H_ ola-0.10.5.nojsmin/olad/plugin_api/PortManager.cpp0000644000175000017500000001354513023355232021457 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * PortManager.cpp * Enables the Patching of Ports * Copyright (C) 2005 Simon Newton */ #include "olad/plugin_api/PortManager.h" #include #include "ola/Logging.h" #include "ola/StringUtils.h" #include "olad/Port.h" namespace ola { using std::vector; bool PortManager::PatchPort(InputPort *port, unsigned int universe) { return GenericPatchPort(port, universe); } bool PortManager::PatchPort(OutputPort *port, unsigned int universe) { return GenericPatchPort(port, universe); } bool PortManager::UnPatchPort(InputPort *port) { return GenericUnPatchPort(port); } bool PortManager::UnPatchPort(OutputPort *port) { return GenericUnPatchPort(port); } bool PortManager::SetPriorityInherit(Port *port) { if (port->PriorityCapability() != CAPABILITY_FULL) return true; if (port->GetPriorityMode() != PRIORITY_MODE_INHERIT) { port->SetPriorityMode(PRIORITY_MODE_INHERIT); } return true; } bool PortManager::SetPriorityStatic(Port *port, uint8_t value) { if (port->PriorityCapability() == CAPABILITY_NONE) return true; if (port->PriorityCapability() == CAPABILITY_FULL && port->GetPriorityMode() != PRIORITY_MODE_STATIC) port->SetPriorityMode(PRIORITY_MODE_STATIC); if (value > ola::dmx::SOURCE_PRIORITY_MAX) { OLA_WARN << "Priority " << static_cast(value) << " is greater than the max priority (" << static_cast(ola::dmx::SOURCE_PRIORITY_MAX) << ")"; value = ola::dmx::SOURCE_PRIORITY_MAX; } if (port->GetPriority() != value) port->SetPriority(value); return true; } template bool PortManager::GenericPatchPort(PortClass *port, unsigned int new_universe_id) { if (!port) return false; Universe *universe = port->GetUniverse(); if (universe && universe->UniverseId() == new_universe_id) return true; AbstractDevice *device = port->GetDevice(); if (device) { if (!device->AllowLooping()) { // check ports of the opposite type if (CheckLooping(device, new_universe_id)) return false; } if (!device->AllowMultiPortPatching()) { if (CheckMultiPort(device, new_universe_id)) return false; } } // unpatch if required if (universe) { OLA_DEBUG << "Port " << port->UniqueId() << " is bound to universe " << universe->UniverseId(); m_broker->RemovePort(port); universe->RemovePort(port); } universe = m_universe_store->GetUniverseOrCreate(new_universe_id); if (!universe) return false; if (port->SetUniverse(universe)) { OLA_INFO << "Patched " << port->UniqueId() << " to universe " << universe->UniverseId(); m_broker->AddPort(port); universe->AddPort(port); } else { if (!universe->IsActive()) m_universe_store->AddUniverseGarbageCollection(universe); } return true; } template bool PortManager::GenericUnPatchPort(PortClass *port) { if (!port) return false; Universe *universe = port->GetUniverse(); m_broker->RemovePort(port); if (universe) { universe->RemovePort(port); port->SetUniverse(NULL); OLA_INFO << "Unpatched " << port->UniqueId() << " from uni " << universe->UniverseId(); } return true; } template bool PortManager::CheckLooping(const AbstractDevice *device, unsigned int new_universe_id) const { return CheckOutputPortsForUniverse(device, new_universe_id); } template <> bool PortManager::CheckLooping( const AbstractDevice *device, unsigned int new_universe_id) const { return CheckInputPortsForUniverse(device, new_universe_id); } template bool PortManager::CheckMultiPort(const AbstractDevice *device, unsigned int new_universe_id) const { return CheckInputPortsForUniverse(device, new_universe_id); } template <> bool PortManager::CheckMultiPort( const AbstractDevice *device, unsigned int new_universe_id) const { return CheckOutputPortsForUniverse(device, new_universe_id); } bool PortManager::CheckInputPortsForUniverse(const AbstractDevice *device, unsigned int universe_id) const { vector ports; device->InputPorts(&ports); return CheckForPortMatchingUniverse(ports, universe_id); } bool PortManager::CheckOutputPortsForUniverse(const AbstractDevice *device, unsigned int universe_id) const { vector ports; device->OutputPorts(&ports); return CheckForPortMatchingUniverse(ports, universe_id); } template bool PortManager::CheckForPortMatchingUniverse( const vector &ports, unsigned int universe_id) const { typename vector::const_iterator iter; for (iter = ports.begin(); iter != ports.end(); ++iter) { if ((*iter)->GetUniverse() && (*iter)->GetUniverse()->UniverseId() == universe_id) { OLA_INFO << "Port " << (*iter)->PortId() << " is already patched to " << universe_id; return true; } } return false; } } // namespace ola ola-0.10.5.nojsmin/olad/plugin_api/DmxSource.cpp0000644000175000017500000000166013023355232021144 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DmxSource.cpp * The DmxSource class. * Copyright (C) 2005 Simon Newton */ #include namespace ola { const TimeInterval DmxSource::TIMEOUT_INTERVAL(2500000); // 2.5s } // namespace ola ola-0.10.5.nojsmin/olad/plugin_api/UniverseTest.cpp0000644000175000017500000006414313023355232021700 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * UniverseTest.cpp * Test fixture for the Universe and UniverseStore classes * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include "ola/Callback.h" #include "ola/Constants.h" #include "ola/Clock.h" #include "ola/DmxBuffer.h" #include "ola/rdm/RDMCommand.h" #include "ola/rdm/RDMReply.h" #include "ola/rdm/RDMResponseCodes.h" #include "ola/rdm/UID.h" #include "olad/DmxSource.h" #include "olad/PluginAdaptor.h" #include "olad/Port.h" #include "olad/PortBroker.h" #include "olad/Preferences.h" #include "olad/Universe.h" #include "olad/plugin_api/Client.h" #include "olad/plugin_api/PortManager.h" #include "olad/plugin_api/TestCommon.h" #include "olad/plugin_api/UniverseStore.h" #include "ola/testing/TestUtils.h" using ola::AbstractDevice; using ola::Clock; using ola::DmxBuffer; using ola::NewCallback; using ola::NewSingleCallback; using ola::TimeStamp; using ola::Universe; using ola::rdm::NewDiscoveryUniqueBranchRequest; using ola::rdm::RDMCallback; using ola::rdm::RDMReply; using ola::rdm::RDMRequest; using ola::rdm::RDMResponse; using ola::rdm::UID; using ola::rdm::UIDSet; using ola::rdm::RDMStatusCode; using std::string; using std::vector; static unsigned int TEST_UNIVERSE = 1; static const char TEST_DATA[] = "this is some test data"; class UniverseTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(UniverseTest); CPPUNIT_TEST(testLifecycle); CPPUNIT_TEST(testSetGetDmx); CPPUNIT_TEST(testSendDmx); CPPUNIT_TEST(testReceiveDmx); CPPUNIT_TEST(testSourceClients); CPPUNIT_TEST(testSinkClients); CPPUNIT_TEST(testLtpMerging); CPPUNIT_TEST(testHtpMerging); CPPUNIT_TEST(testRDMDiscovery); CPPUNIT_TEST(testRDMSend); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void tearDown(); void testLifecycle(); void testSetGetDmx(); void testSendDmx(); void testReceiveDmx(); void testSourceClients(); void testSinkClients(); void testLtpMerging(); void testHtpMerging(); void testRDMDiscovery(); void testRDMSend(); private: ola::MemoryPreferences *m_preferences; ola::UniverseStore *m_store; DmxBuffer m_buffer; ola::Clock m_clock; void ConfirmUIDs(UIDSet *expected, const UIDSet &uids); void ConfirmRDM(int line, RDMStatusCode expected_status_code, const RDMResponse *expected_response, RDMReply *reply); void ReturnRDMCode(RDMStatusCode status_code, const RDMRequest *request, RDMCallback *callback) { delete request; RunRDMCallback(callback, status_code); } }; class MockClient: public ola::Client { public: MockClient() : ola::Client(NULL, UID(ola::OPEN_LIGHTING_ESTA_CODE, 0)), m_dmx_set(false) { } bool SendDMX(unsigned int universe_id, uint8_t priority, const DmxBuffer &buffer) { OLA_ASSERT_EQ(TEST_UNIVERSE, universe_id); OLA_ASSERT_EQ(ola::dmx::SOURCE_PRIORITY_MIN, priority); OLA_ASSERT_EQ(string(TEST_DATA), buffer.Get()); m_dmx_set = true; return true; } bool m_dmx_set; }; CPPUNIT_TEST_SUITE_REGISTRATION(UniverseTest); void UniverseTest::setUp() { ola::InitLogging(ola::OLA_LOG_INFO, ola::OLA_LOG_STDERR); m_preferences = new ola::MemoryPreferences("foo"); m_store = new ola::UniverseStore(m_preferences, NULL); m_buffer.Set(TEST_DATA); } void UniverseTest::tearDown() { delete m_store; delete m_preferences; } /* * Test that we can create universes and save their settings */ void UniverseTest::testLifecycle() { Universe *universe = m_store->GetUniverse(TEST_UNIVERSE); OLA_ASSERT_FALSE(universe); universe = m_store->GetUniverseOrCreate(TEST_UNIVERSE); OLA_ASSERT(universe); OLA_ASSERT_EQ(TEST_UNIVERSE, universe->UniverseId()); OLA_ASSERT_EQ((unsigned int) 1, m_store->UniverseCount()); OLA_ASSERT_EQ(Universe::MERGE_LTP, universe->MergeMode()); OLA_ASSERT_FALSE(universe->IsActive()); string universe_name = "New Name"; universe->SetName(universe_name); universe->SetMergeMode(Universe::MERGE_HTP); OLA_ASSERT_EQ(universe_name, universe->Name()); OLA_ASSERT_EQ(Universe::MERGE_HTP, universe->MergeMode()); // delete it m_store->AddUniverseGarbageCollection(universe); m_store->GarbageCollectUniverses(); OLA_ASSERT_EQ((unsigned int) 0, m_store->UniverseCount()); universe = m_store->GetUniverse(TEST_UNIVERSE); OLA_ASSERT_FALSE(universe); // now re-create it universe = m_store->GetUniverseOrCreate(TEST_UNIVERSE); OLA_ASSERT(universe); OLA_ASSERT_EQ((unsigned int) 1, m_store->UniverseCount()); OLA_ASSERT_EQ(TEST_UNIVERSE, universe->UniverseId()); OLA_ASSERT_EQ(universe_name, universe->Name()); OLA_ASSERT_EQ(Universe::MERGE_HTP, universe->MergeMode()); m_store->DeleteAll(); OLA_ASSERT_EQ((unsigned int) 0, m_store->UniverseCount()); } /* * Check that SetDMX/GetDMX works */ void UniverseTest::testSetGetDmx() { Universe *universe = m_store->GetUniverseOrCreate(TEST_UNIVERSE); OLA_ASSERT(universe); // a new universe should be all 0s DmxBuffer empty_buffer; OLA_ASSERT(empty_buffer == universe->GetDMX()); // check that SetDMX works OLA_ASSERT(universe->SetDMX(m_buffer)); OLA_ASSERT(m_buffer == universe->GetDMX()); } /* * Check that SendDmx updates all ports */ void UniverseTest::testSendDmx() { Universe *universe = m_store->GetUniverseOrCreate(TEST_UNIVERSE); OLA_ASSERT(universe); TestMockOutputPort port(NULL, 1); // output port universe->AddPort(&port); OLA_ASSERT_EQ((unsigned int) 0, universe->InputPortCount()); OLA_ASSERT_EQ((unsigned int) 1, universe->OutputPortCount()); OLA_ASSERT(universe->IsActive()); // send some data to the universe and check the port gets it OLA_ASSERT(universe->SetDMX(m_buffer)); OLA_ASSERT(m_buffer == port.ReadDMX()); // remove the port from the universe universe->RemovePort(&port); OLA_ASSERT_EQ((unsigned int) 0, universe->InputPortCount()); OLA_ASSERT_EQ((unsigned int) 0, universe->OutputPortCount()); OLA_ASSERT_FALSE(universe->IsActive()); } /* * Check that we update when ports have new data */ void UniverseTest::testReceiveDmx() { ola::PortBroker broker; ola::PortManager port_manager(m_store, &broker); TimeStamp time_stamp; MockSelectServer ss(&time_stamp); ola::PluginAdaptor plugin_adaptor(NULL, &ss, NULL, NULL, NULL, NULL); MockDevice device(NULL, "foo"); TestMockInputPort port(&device, 1, &plugin_adaptor); // input port port_manager.PatchPort(&port, TEST_UNIVERSE); Universe *universe = m_store->GetUniverseOrCreate(TEST_UNIVERSE); OLA_ASSERT(universe); OLA_ASSERT_EQ((unsigned int) 1, universe->InputPortCount()); OLA_ASSERT_EQ((unsigned int) 0, universe->OutputPortCount()); OLA_ASSERT(universe->IsActive()); // Setup the port with some data, and check that signalling the universe // works. m_clock.CurrentTime(&time_stamp); port.WriteDMX(m_buffer); port.DmxChanged(); OLA_ASSERT_EQ(ola::dmx::SOURCE_PRIORITY_DEFAULT, universe->ActivePriority()); OLA_ASSERT_EQ(m_buffer.Size(), universe->GetDMX().Size()); OLA_ASSERT(m_buffer == universe->GetDMX()); // Remove the port from the universe universe->RemovePort(&port); OLA_ASSERT_FALSE(universe->IsActive()); OLA_ASSERT_EQ((unsigned int) 0, universe->InputPortCount()); OLA_ASSERT_EQ((unsigned int) 0, universe->OutputPortCount()); } /* * Check that we can add/remove source clients from this universes */ void UniverseTest::testSourceClients() { Universe *universe = m_store->GetUniverseOrCreate(TEST_UNIVERSE); OLA_ASSERT(universe); OLA_ASSERT_EQ((unsigned int) 0, universe->SourceClientCount()); OLA_ASSERT_EQ((unsigned int) 0, universe->SinkClientCount()); // test that we can add a source client MockClient client; universe->AddSourceClient(&client); OLA_ASSERT_EQ((unsigned int) 1, universe->SourceClientCount()); OLA_ASSERT_EQ((unsigned int) 0, universe->SinkClientCount()); OLA_ASSERT(universe->ContainsSourceClient(&client)); OLA_ASSERT_FALSE(universe->ContainsSinkClient(&client)); OLA_ASSERT(universe->IsActive()); // Setting DMX now does nothing OLA_ASSERT_FALSE(client.m_dmx_set); universe->SetDMX(m_buffer); OLA_ASSERT_FALSE(client.m_dmx_set); // now remove it universe->RemoveSourceClient(&client); OLA_ASSERT_EQ((unsigned int) 0, universe->SourceClientCount()); OLA_ASSERT_EQ((unsigned int) 0, universe->SinkClientCount()); OLA_ASSERT_FALSE(universe->ContainsSourceClient(&client)); OLA_ASSERT_FALSE(universe->ContainsSinkClient(&client)); OLA_ASSERT_FALSE(universe->IsActive()); // try to remove it again OLA_ASSERT_FALSE(universe->RemoveSourceClient(&client)); OLA_ASSERT_EQ((unsigned int) 0, universe->SourceClientCount()); OLA_ASSERT_EQ((unsigned int) 0, universe->SinkClientCount()); OLA_ASSERT_FALSE(universe->ContainsSourceClient(&client)); OLA_ASSERT_FALSE(universe->ContainsSinkClient(&client)); OLA_ASSERT_FALSE(universe->IsActive()); } /* * Check that we can add/remove sink clients from this universes */ void UniverseTest::testSinkClients() { Universe *universe = m_store->GetUniverseOrCreate(TEST_UNIVERSE); OLA_ASSERT(universe); OLA_ASSERT_EQ((unsigned int) 0, universe->SourceClientCount()); OLA_ASSERT_EQ((unsigned int) 0, universe->SinkClientCount()); // test that we can add a source client MockClient client; universe->AddSinkClient(&client); OLA_ASSERT_EQ((unsigned int) 1, universe->SinkClientCount()); OLA_ASSERT_EQ((unsigned int) 0, universe->SourceClientCount()); OLA_ASSERT(universe->ContainsSinkClient(&client)); OLA_ASSERT_FALSE(universe->ContainsSourceClient(&client)); OLA_ASSERT(universe->IsActive()); // Setting DMX now should update the client OLA_ASSERT_FALSE(client.m_dmx_set); universe->SetDMX(m_buffer); OLA_ASSERT(client.m_dmx_set); // now remove it universe->RemoveSinkClient(&client); OLA_ASSERT_EQ((unsigned int) 0, universe->SinkClientCount()); OLA_ASSERT_EQ((unsigned int) 0, universe->SourceClientCount()); OLA_ASSERT_FALSE(universe->ContainsSinkClient(&client)); OLA_ASSERT_FALSE(universe->ContainsSourceClient(&client)); OLA_ASSERT_FALSE(universe->IsActive()); // try to remove it again OLA_ASSERT_FALSE(universe->RemoveSinkClient(&client)); OLA_ASSERT_EQ((unsigned int) 0, universe->SinkClientCount()); OLA_ASSERT_EQ((unsigned int) 0, universe->SourceClientCount()); OLA_ASSERT_FALSE(universe->ContainsSinkClient(&client)); OLA_ASSERT_FALSE(universe->ContainsSourceClient(&client)); OLA_ASSERT_FALSE(universe->IsActive()); } /* * Check that LTP merging works correctly */ void UniverseTest::testLtpMerging() { DmxBuffer buffer1, buffer2, htp_buffer; buffer1.SetFromString("1,0,0,10"); buffer2.SetFromString("0,255,0,5,6,7"); ola::PortBroker broker; ola::PortManager port_manager(m_store, &broker); TimeStamp time_stamp; MockSelectServer ss(&time_stamp); ola::PluginAdaptor plugin_adaptor(NULL, &ss, NULL, NULL, NULL, NULL); MockDevice device(NULL, "foo"); MockDevice device2(NULL, "bar"); TestMockInputPort port(&device, 1, &plugin_adaptor); // input port TestMockInputPort port2(&device2, 1, &plugin_adaptor); // input port port_manager.PatchPort(&port, TEST_UNIVERSE); port_manager.PatchPort(&port2, TEST_UNIVERSE); Universe *universe = m_store->GetUniverseOrCreate(TEST_UNIVERSE); OLA_ASSERT(universe); universe->SetMergeMode(Universe::MERGE_LTP); OLA_ASSERT_EQ((unsigned int) 2, universe->InputPortCount()); OLA_ASSERT_EQ((unsigned int) 0, universe->OutputPortCount()); OLA_ASSERT(universe->IsActive()); OLA_ASSERT_EQ((unsigned int) 0, universe->GetDMX().Size()); // Setup the ports with some data, and check that signalling the universe // works. m_clock.CurrentTime(&time_stamp); port.WriteDMX(buffer1); port.DmxChanged(); OLA_ASSERT_EQ(ola::dmx::SOURCE_PRIORITY_DEFAULT, universe->ActivePriority()); OLA_ASSERT_EQ(buffer1.Size(), universe->GetDMX().Size()); OLA_ASSERT(buffer1 == universe->GetDMX()); // Now the second port gets data m_clock.CurrentTime(&time_stamp); port2.WriteDMX(buffer2); port2.DmxChanged(); OLA_ASSERT_EQ(ola::dmx::SOURCE_PRIORITY_DEFAULT, universe->ActivePriority()); OLA_ASSERT_EQ(buffer2.Size(), universe->GetDMX().Size()); OLA_ASSERT(buffer2 == universe->GetDMX()); // now resend the first port m_clock.CurrentTime(&time_stamp); port.WriteDMX(buffer1); port.DmxChanged(); OLA_ASSERT_EQ(ola::dmx::SOURCE_PRIORITY_DEFAULT, universe->ActivePriority()); OLA_ASSERT_EQ(buffer1.Size(), universe->GetDMX().Size()); OLA_ASSERT(buffer1 == universe->GetDMX()); // now check a client DmxBuffer client_buffer; client_buffer.SetFromString("255,0,0,255,10"); m_clock.CurrentTime(&time_stamp); ola::DmxSource source(client_buffer, time_stamp, ola::dmx::SOURCE_PRIORITY_DEFAULT); MockClient input_client; input_client.DMXReceived(TEST_UNIVERSE, source); universe->SourceClientDataChanged(&input_client); DmxBuffer client_htp_merge_result; client_htp_merge_result.SetFromString("255,255,0,255,10,7"); OLA_ASSERT_EQ(ola::dmx::SOURCE_PRIORITY_DEFAULT, universe->ActivePriority()); OLA_ASSERT_EQ(client_buffer.Size(), universe->GetDMX().Size()); OLA_ASSERT(client_buffer == universe->GetDMX()); // clean up universe->RemoveSourceClient(&input_client); universe->RemovePort(&port); universe->RemovePort(&port2); OLA_ASSERT_FALSE(universe->IsActive()); } /* * Check that HTP merging works correctly */ void UniverseTest::testHtpMerging() { DmxBuffer buffer1, buffer2, htp_buffer; buffer1.SetFromString("1,0,0,10"); buffer2.SetFromString("0,255,0,5,6,7"); htp_buffer.SetFromString("1,255,0,10,6,7"); ola::PortBroker broker; ola::PortManager port_manager(m_store, &broker); TimeStamp time_stamp; MockSelectServer ss(&time_stamp); ola::PluginAdaptor plugin_adaptor(NULL, &ss, NULL, NULL, NULL, NULL); MockDevice device(NULL, "foo"); MockDevice device2(NULL, "bar"); TestMockInputPort port(&device, 1, &plugin_adaptor); // input port TestMockInputPort port2(&device2, 1, &plugin_adaptor); // input port port_manager.PatchPort(&port, TEST_UNIVERSE); port_manager.PatchPort(&port2, TEST_UNIVERSE); Universe *universe = m_store->GetUniverseOrCreate(TEST_UNIVERSE); OLA_ASSERT(universe); universe->SetMergeMode(Universe::MERGE_HTP); OLA_ASSERT_EQ(universe->OutputPortCount(), (unsigned int) 0); OLA_ASSERT_EQ(universe->OutputPortCount(), (unsigned int) 0); OLA_ASSERT(universe->IsActive()); OLA_ASSERT_EQ((unsigned int) 0, universe->GetDMX().Size()); // Setup the ports with some data, and check that signalling the universe // works. m_clock.CurrentTime(&time_stamp); port.WriteDMX(buffer1); port.DmxChanged(); OLA_ASSERT_EQ(ola::dmx::SOURCE_PRIORITY_DEFAULT, universe->ActivePriority()); OLA_ASSERT_EQ(buffer1.Size(), universe->GetDMX().Size()); OLA_ASSERT(buffer1 == universe->GetDMX()); // Now the second port gets data m_clock.CurrentTime(&time_stamp); port2.WriteDMX(buffer2); port2.DmxChanged(); OLA_ASSERT_EQ(ola::dmx::SOURCE_PRIORITY_DEFAULT, universe->ActivePriority()); OLA_ASSERT_EQ(htp_buffer.Size(), universe->GetDMX().Size()); OLA_ASSERT(htp_buffer == universe->GetDMX()); // now raise the priority of the second port uint8_t new_priority = 120; port2.SetPriority(new_priority); m_clock.CurrentTime(&time_stamp); port2.DmxChanged(); OLA_ASSERT_EQ(new_priority, universe->ActivePriority()); OLA_ASSERT_EQ(buffer2.Size(), universe->GetDMX().Size()); OLA_ASSERT(buffer2 == universe->GetDMX()); // raise the priority of the first port port.SetPriority(new_priority); m_clock.CurrentTime(&time_stamp); port.DmxChanged(); OLA_ASSERT_EQ(new_priority, universe->ActivePriority()); OLA_ASSERT_EQ(htp_buffer.Size(), universe->GetDMX().Size()); OLA_ASSERT(htp_buffer == universe->GetDMX()); // now check a client DmxBuffer client_buffer; client_buffer.SetFromString("255,0,0,255,10"); m_clock.CurrentTime(&time_stamp); ola::DmxSource source(client_buffer, time_stamp, new_priority); MockClient input_client; input_client.DMXReceived(TEST_UNIVERSE, source); universe->SourceClientDataChanged(&input_client); DmxBuffer client_htp_merge_result; client_htp_merge_result.SetFromString("255,255,0,255,10,7"); OLA_ASSERT_EQ(new_priority, universe->ActivePriority()); OLA_ASSERT_EQ(client_htp_merge_result.Size(), universe->GetDMX().Size()); OLA_ASSERT(client_htp_merge_result == universe->GetDMX()); // clean up universe->RemoveSourceClient(&input_client); universe->RemovePort(&port); universe->RemovePort(&port2); OLA_ASSERT_FALSE(universe->IsActive()); } /** * Test RDM discovery for a universe/ */ void UniverseTest::testRDMDiscovery() { Universe *universe = m_store->GetUniverseOrCreate(TEST_UNIVERSE); OLA_ASSERT(universe); // check the uid set is initially empty UIDSet universe_uids; universe->GetUIDs(&universe_uids); OLA_ASSERT_EQ(0u, universe_uids.Size()); UID uid1(0x7a70, 1); UID uid2(0x7a70, 2); UID uid3(0x7a70, 3); UIDSet port1_uids, port2_uids; port1_uids.AddUID(uid1); port2_uids.AddUID(uid2); TestMockRDMOutputPort port1(NULL, 1, &port1_uids); // this port is configured to update the uids on patch TestMockRDMOutputPort port2(NULL, 2, &port2_uids, true); universe->AddPort(&port1); port1.SetUniverse(universe); universe->AddPort(&port2); port2.SetUniverse(universe); OLA_ASSERT_EQ((unsigned int) 0, universe->InputPortCount()); OLA_ASSERT_EQ((unsigned int) 2, universe->OutputPortCount()); universe->GetUIDs(&universe_uids); OLA_ASSERT_EQ(1u, universe_uids.Size()); OLA_ASSERT(universe_uids.Contains(uid2)); OLA_ASSERT(universe->IsActive()); // now trigger discovery UIDSet expected_uids; expected_uids.AddUID(uid1); expected_uids.AddUID(uid2); universe->RunRDMDiscovery( NewSingleCallback(this, &UniverseTest::ConfirmUIDs, &expected_uids), true); // now add a uid to one port, and remove a uid from another port1_uids.AddUID(uid3); port2_uids.RemoveUID(uid2); expected_uids.AddUID(uid3); expected_uids.RemoveUID(uid2); universe->RunRDMDiscovery( NewSingleCallback(this, &UniverseTest::ConfirmUIDs, &expected_uids), true); // remove the first port from the universe and confirm there are no more UIDs universe->RemovePort(&port1); expected_uids.Clear(); universe->RunRDMDiscovery( NewSingleCallback(this, &UniverseTest::ConfirmUIDs, &expected_uids), true); universe_uids.Clear(); universe->GetUIDs(&universe_uids); OLA_ASSERT_EQ(0u, universe_uids.Size()); universe->RemovePort(&port2); OLA_ASSERT_EQ((unsigned int) 0, universe->InputPortCount()); OLA_ASSERT_EQ((unsigned int) 0, universe->OutputPortCount()); OLA_ASSERT_FALSE(universe->IsActive()); } /** * test Sending an RDM request */ void UniverseTest::testRDMSend() { Universe *universe = m_store->GetUniverseOrCreate(TEST_UNIVERSE); OLA_ASSERT(universe); // setup the ports with a UID on each UID uid1(0x7a70, 1); UID uid2(0x7a70, 2); UID uid3(0x7a70, 3); UIDSet port1_uids, port2_uids; port1_uids.AddUID(uid1); port2_uids.AddUID(uid2); TestMockRDMOutputPort port1(NULL, 1, &port1_uids, true); TestMockRDMOutputPort port2(NULL, 2, &port2_uids, true); universe->AddPort(&port1); port1.SetUniverse(universe); universe->AddPort(&port2); port2.SetUniverse(universe); UID source_uid(0x7a70, 100); // first try a command to a uid we don't know about RDMRequest *request = new ola::rdm::RDMGetRequest( source_uid, uid3, 0, // transaction # 1, // port id 10, // sub device 296, // param id NULL, 0); universe->SendRDMRequest( request, NewSingleCallback(this, &UniverseTest::ConfirmRDM, __LINE__, ola::rdm::RDM_UNKNOWN_UID, reinterpret_cast(NULL))); // ok, now try something that returns a response from the port request = new ola::rdm::RDMGetRequest( source_uid, uid1, 0, // transaction # 1, // port id 10, // sub device 296, // param id NULL, 0); port1.SetRDMHandler( NewCallback(this, &UniverseTest::ReturnRDMCode, ola::rdm::RDM_TIMEOUT)); universe->SendRDMRequest( request, NewSingleCallback(this, &UniverseTest::ConfirmRDM, __LINE__, ola::rdm::RDM_TIMEOUT, reinterpret_cast(NULL))); // now try a broadcast fan out UID vendorcast_uid = UID::VendorcastAddress(0x7a70); request = new ola::rdm::RDMGetRequest( source_uid, vendorcast_uid, 0, // transaction # 1, // port id 10, // sub device 296, // param id NULL, 0); port1.SetRDMHandler( NewCallback(this, &UniverseTest::ReturnRDMCode, ola::rdm::RDM_WAS_BROADCAST)); port2.SetRDMHandler( NewCallback(this, &UniverseTest::ReturnRDMCode, ola::rdm::RDM_WAS_BROADCAST)); universe->SendRDMRequest( request, NewSingleCallback(this, &UniverseTest::ConfirmRDM, __LINE__, ola::rdm::RDM_WAS_BROADCAST, reinterpret_cast(NULL))); // now confirm that if one of the ports fails to send, we see this response request = new ola::rdm::RDMGetRequest( source_uid, vendorcast_uid, 0, // transaction # 1, // port id 10, // sub device 296, // param id NULL, 0); port2.SetRDMHandler( NewCallback(this, &UniverseTest::ReturnRDMCode, ola::rdm::RDM_FAILED_TO_SEND)); universe->SendRDMRequest( request, NewSingleCallback(this, &UniverseTest::ConfirmRDM, __LINE__, ola::rdm::RDM_FAILED_TO_SEND, reinterpret_cast(NULL))); // DUB responses are slightly different request = NewDiscoveryUniqueBranchRequest(source_uid, uid1, uid2, 0); port1.SetRDMHandler( NewCallback(this, &UniverseTest::ReturnRDMCode, ola::rdm::RDM_DUB_RESPONSE)); port2.SetRDMHandler( NewCallback(this, &UniverseTest::ReturnRDMCode, ola::rdm::RDM_DUB_RESPONSE)); universe->SendRDMRequest( request, NewSingleCallback(this, &UniverseTest::ConfirmRDM, __LINE__, ola::rdm::RDM_DUB_RESPONSE, reinterpret_cast(NULL))); // now check that we still get a RDM_DUB_RESPONSE even if one port returns an // RDM_TIMEOUT request = NewDiscoveryUniqueBranchRequest(source_uid, uid1, uid2, 0); port2.SetRDMHandler( NewCallback(this, &UniverseTest::ReturnRDMCode, ola::rdm::RDM_TIMEOUT)); universe->SendRDMRequest( request, NewSingleCallback(this, &UniverseTest::ConfirmRDM, __LINE__, ola::rdm::RDM_DUB_RESPONSE, reinterpret_cast(NULL))); // and the same again but the second port returns // RDM_PLUGIN_DISCOVERY_NOT_SUPPORTED request = NewDiscoveryUniqueBranchRequest(source_uid, uid1, uid2, 0); port2.SetRDMHandler( NewCallback(this, &UniverseTest::ReturnRDMCode, ola::rdm::RDM_PLUGIN_DISCOVERY_NOT_SUPPORTED)); universe->SendRDMRequest( request, NewSingleCallback(this, &UniverseTest::ConfirmRDM, __LINE__, ola::rdm::RDM_DUB_RESPONSE, reinterpret_cast(NULL))); // now the first port returns a RDM_TIMEOUT request = NewDiscoveryUniqueBranchRequest(source_uid, uid1, uid2, 0); port1.SetRDMHandler( NewCallback(this, &UniverseTest::ReturnRDMCode, ola::rdm::RDM_TIMEOUT)); universe->SendRDMRequest( request, NewSingleCallback(this, &UniverseTest::ConfirmRDM, __LINE__, ola::rdm::RDM_TIMEOUT, reinterpret_cast(NULL))); // finally if neither ports support the DUB, we should return that request = NewDiscoveryUniqueBranchRequest(source_uid, uid1, uid2, 0); port1.SetRDMHandler( NewCallback(this, &UniverseTest::ReturnRDMCode, ola::rdm::RDM_PLUGIN_DISCOVERY_NOT_SUPPORTED)); universe->SendRDMRequest( request, NewSingleCallback(this, &UniverseTest::ConfirmRDM, __LINE__, ola::rdm::RDM_PLUGIN_DISCOVERY_NOT_SUPPORTED, reinterpret_cast(NULL))); universe->RemovePort(&port1); universe->RemovePort(&port2); } /** * Check we got the uids we expect */ void UniverseTest::ConfirmUIDs(UIDSet *expected, const UIDSet &uids) { OLA_ASSERT_EQ(*expected, uids); } /** * Confirm an RDM response */ void UniverseTest::ConfirmRDM(int line, RDMStatusCode expected_status_code, const RDMResponse *expected_response, RDMReply *reply) { std::ostringstream str; str << "Line " << line; OLA_ASSERT_EQ_MSG(expected_status_code, reply->StatusCode(), str.str()); OLA_ASSERT_EQ_MSG(expected_response, reply->Response(), str.str()); } ola-0.10.5.nojsmin/olad/plugin_api/Plugin.cpp0000644000175000017500000000443613023355232020475 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Plugin.cpp * Base plugin class for ola * Copyright (C) 2005 Simon Newton */ #include #include "ola/Logging.h" #include "olad/Plugin.h" #include "olad/PluginAdaptor.h" #include "olad/Preferences.h" namespace ola { using std::string; const char Plugin::ENABLED_KEY[] = "enabled"; bool Plugin::LoadPreferences() { if (m_preferences) { return true; } if (PluginPrefix() == "") { OLA_WARN << Name() << ", no prefix provided"; return false; } m_preferences = m_plugin_adaptor->NewPreference(PluginPrefix()); if (!m_preferences) { return false; } m_preferences->Load(); bool save = m_preferences->SetDefaultValue( ENABLED_KEY, BoolValidator(), DefaultMode()); if (save) { m_preferences->Save(); } if (!SetDefaultPreferences()) { OLA_INFO << Name() << ", SetDefaultPreferences failed"; return false; } return true; } string Plugin::PreferenceConfigLocation() const { return m_preferences->ConfigLocation(); } bool Plugin::IsEnabled() const { return m_preferences->GetValueAsBool(ENABLED_KEY); } void Plugin::SetEnabledState(bool enable) { m_preferences->SetValueAsBool(ENABLED_KEY, enable); m_preferences->Save(); } bool Plugin::Start() { string enabled; if (m_enabled) { return false; } // setup prefs if (!LoadPreferences()) { return false; } if (!StartHook()) { return false; } m_enabled = true; return true; } bool Plugin::Stop() { if (!m_enabled) { return false; } bool ret = StopHook(); m_enabled = false; return ret; } } // namespace ola ola-0.10.5.nojsmin/olad/plugin_api/PortManagerTest.cpp0000644000175000017500000002512513023355232022314 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * PortManagerTest.cpp * Test fixture for the PortManager classes * Copyright (C) 2005 Simon Newton */ #include #include #include "olad/DmxSource.h" #include "olad/PortBroker.h" #include "olad/plugin_api/PortManager.h" #include "olad/plugin_api/TestCommon.h" #include "olad/plugin_api/UniverseStore.h" #include "ola/testing/TestUtils.h" using ola::DmxSource; using ola::PortManager; using ola::Port; using ola::Universe; using std::string; class PortManagerTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(PortManagerTest); CPPUNIT_TEST(testPortPatching); CPPUNIT_TEST(testPortPatchingLoopMulti); CPPUNIT_TEST(testInputPortSetPriority); CPPUNIT_TEST(testOutputPortSetPriority); CPPUNIT_TEST_SUITE_END(); public: void testPortPatching(); void testPortPatchingLoopMulti(); void testInputPortSetPriority(); void testOutputPortSetPriority(); }; CPPUNIT_TEST_SUITE_REGISTRATION(PortManagerTest); /* * Check that we can patch ports correctly. */ void PortManagerTest::testPortPatching() { ola::UniverseStore uni_store(NULL, NULL); ola::PortBroker broker; ola::PortManager port_manager(&uni_store, &broker); // mock device, this doesn't allow looping or multiport patching MockDevice device1(NULL, "test_device_1"); TestMockInputPort input_port(&device1, 1, NULL); TestMockInputPort input_port2(&device1, 2, NULL); TestMockOutputPort output_port(&device1, 1); TestMockOutputPort output_port2(&device1, 2); device1.AddPort(&input_port); device1.AddPort(&input_port2); device1.AddPort(&output_port); device1.AddPort(&output_port2); OLA_ASSERT_EQ(static_cast(NULL), input_port.GetUniverse()); OLA_ASSERT_EQ(static_cast(NULL), input_port2.GetUniverse()); OLA_ASSERT_EQ(static_cast(NULL), output_port.GetUniverse()); OLA_ASSERT_EQ(static_cast(NULL), output_port2.GetUniverse()); // simple patching OLA_ASSERT(port_manager.PatchPort(&input_port, 1)); OLA_ASSERT(port_manager.PatchPort(&output_port, 2)); OLA_ASSERT(input_port.GetUniverse()); OLA_ASSERT_EQ((unsigned int) 1, input_port.GetUniverse()->UniverseId()); OLA_ASSERT_EQ(static_cast(NULL), input_port2.GetUniverse()); OLA_ASSERT(output_port.GetUniverse()); OLA_ASSERT_EQ((unsigned int) 2, output_port.GetUniverse()->UniverseId()); OLA_ASSERT_EQ(static_cast(NULL), output_port2.GetUniverse()); // test looping OLA_ASSERT_FALSE(port_manager.PatchPort(&input_port2, 2)); OLA_ASSERT_FALSE(port_manager.PatchPort(&output_port2, 1)); OLA_ASSERT_EQ(static_cast(NULL), input_port2.GetUniverse()); OLA_ASSERT_EQ(static_cast(NULL), output_port2.GetUniverse()); // test multiport OLA_ASSERT_FALSE(port_manager.PatchPort(&input_port2, 1)); OLA_ASSERT_FALSE(port_manager.PatchPort(&output_port2, 2)); OLA_ASSERT_EQ(static_cast(NULL), input_port2.GetUniverse()); OLA_ASSERT_EQ(static_cast(NULL), output_port2.GetUniverse()); // test repatching OLA_ASSERT(port_manager.PatchPort(&input_port, 3)); OLA_ASSERT(port_manager.PatchPort(&output_port, 4)); OLA_ASSERT(input_port.GetUniverse()); OLA_ASSERT_EQ((unsigned int) 3, input_port.GetUniverse()->UniverseId()); OLA_ASSERT(output_port.GetUniverse()); OLA_ASSERT_EQ((unsigned int) 4, output_port.GetUniverse()->UniverseId()); // test unpatching OLA_ASSERT(port_manager.UnPatchPort(&input_port)); OLA_ASSERT(port_manager.UnPatchPort(&input_port2)); OLA_ASSERT(port_manager.UnPatchPort(&output_port)); OLA_ASSERT(port_manager.UnPatchPort(&output_port2)); OLA_ASSERT_EQ(static_cast(NULL), input_port.GetUniverse()); OLA_ASSERT_EQ(static_cast(NULL), input_port2.GetUniverse()); OLA_ASSERT_EQ(static_cast(NULL), output_port.GetUniverse()); OLA_ASSERT_EQ(static_cast(NULL), output_port2.GetUniverse()); } /* * test that patching works correctly for devices with looping and multiport * patching enabled. */ void PortManagerTest::testPortPatchingLoopMulti() { ola::UniverseStore uni_store(NULL, NULL); ola::PortBroker broker; ola::PortManager port_manager(&uni_store, &broker); // mock device that allows looping and multi port patching MockDeviceLoopAndMulti device1(NULL, "test_device_1"); TestMockInputPort input_port(&device1, 1, NULL); TestMockInputPort input_port2(&device1, 2, NULL); TestMockOutputPort output_port(&device1, 1); TestMockOutputPort output_port2(&device1, 2); device1.AddPort(&input_port); device1.AddPort(&input_port2); device1.AddPort(&output_port); device1.AddPort(&output_port2); OLA_ASSERT_EQ(static_cast(NULL), input_port.GetUniverse()); OLA_ASSERT_EQ(static_cast(NULL), input_port2.GetUniverse()); OLA_ASSERT_EQ(static_cast(NULL), output_port.GetUniverse()); OLA_ASSERT_EQ(static_cast(NULL), output_port2.GetUniverse()); // simple patching OLA_ASSERT(port_manager.PatchPort(&input_port, 1)); OLA_ASSERT(port_manager.PatchPort(&output_port, 2)); OLA_ASSERT(input_port.GetUniverse()); OLA_ASSERT_EQ((unsigned int) 1, input_port.GetUniverse()->UniverseId()); OLA_ASSERT_EQ(static_cast(NULL), input_port2.GetUniverse()); OLA_ASSERT(output_port.GetUniverse()); OLA_ASSERT_EQ((unsigned int) 2, output_port.GetUniverse()->UniverseId()); OLA_ASSERT_EQ(static_cast(NULL), output_port2.GetUniverse()); // test looping OLA_ASSERT(port_manager.PatchPort(&input_port2, 2)); OLA_ASSERT(port_manager.PatchPort(&output_port2, 1)); OLA_ASSERT(input_port2.GetUniverse()); OLA_ASSERT_EQ((unsigned int) 2, input_port2.GetUniverse()->UniverseId()); OLA_ASSERT(output_port2.GetUniverse()); OLA_ASSERT_EQ((unsigned int) 1, output_port2.GetUniverse()->UniverseId()); // test multiport OLA_ASSERT(port_manager.PatchPort(&input_port2, 1)); OLA_ASSERT(port_manager.PatchPort(&output_port2, 2)); OLA_ASSERT(input_port2.GetUniverse()); OLA_ASSERT_EQ((unsigned int) 1, input_port2.GetUniverse()->UniverseId()); OLA_ASSERT(output_port2.GetUniverse()); OLA_ASSERT_EQ((unsigned int) 2, output_port2.GetUniverse()->UniverseId()); } /* * Check that we can set priorities on an input port */ void PortManagerTest::testInputPortSetPriority() { // we're not testing patching so pass NULL here PortManager patcher(NULL, NULL); // Input port that doesn't support priorities TestMockInputPort input_port(NULL, 0, NULL); OLA_ASSERT_EQ(input_port.PriorityCapability(), ola::CAPABILITY_STATIC); OLA_ASSERT_EQ(input_port.GetPriorityMode(), ola::PRIORITY_MODE_STATIC); OLA_ASSERT_EQ(input_port.GetPriority(), ola::dmx::SOURCE_PRIORITY_DEFAULT); // this port doesn't support priorities so this is a noop OLA_ASSERT(patcher.SetPriorityInherit(&input_port)); OLA_ASSERT_EQ(input_port.GetPriorityMode(), ola::PRIORITY_MODE_STATIC); OLA_ASSERT_EQ(input_port.GetPriority(), ola::dmx::SOURCE_PRIORITY_DEFAULT); // set the static priority to 20 OLA_ASSERT(patcher.SetPriorityStatic(&input_port, 20)); OLA_ASSERT_EQ(input_port.GetPriorityMode(), ola::PRIORITY_MODE_STATIC); OLA_ASSERT_EQ(input_port.GetPriority(), (uint8_t) 20); // Now test an input port that does support priorities TestMockPriorityInputPort input_port2(NULL, 1, NULL); OLA_ASSERT_EQ(input_port2.PriorityCapability(), ola::CAPABILITY_FULL); OLA_ASSERT_EQ(input_port2.GetPriorityMode(), ola::PRIORITY_MODE_STATIC); OLA_ASSERT_EQ(input_port2.GetPriority(), ola::dmx::SOURCE_PRIORITY_DEFAULT); // try changing to static mode OLA_ASSERT(patcher.SetPriorityStatic(&input_port2, 20)); OLA_ASSERT_EQ(input_port2.GetPriorityMode(), ola::PRIORITY_MODE_STATIC); OLA_ASSERT_EQ(input_port2.GetPriority(), (uint8_t) 20); // bump priority OLA_ASSERT(patcher.SetPriorityStatic(&input_port2, 180)); OLA_ASSERT_EQ(input_port2.GetPriorityMode(), ola::PRIORITY_MODE_STATIC); OLA_ASSERT_EQ(input_port2.GetPriority(), (uint8_t) 180); // change to inherit mode OLA_ASSERT(patcher.SetPriorityInherit(&input_port2)); OLA_ASSERT_EQ(input_port2.GetPriorityMode(), ola::PRIORITY_MODE_INHERIT); OLA_ASSERT_EQ(input_port2.GetPriority(), (uint8_t) 180); } /* * Check that we can set priorities on an Output port */ void PortManagerTest::testOutputPortSetPriority() { // we're not testing patching so pass NULL here PortManager patcher(NULL, NULL); // Input port that doesn't support priorities TestMockOutputPort output_port(NULL, 0); OLA_ASSERT_EQ(output_port.PriorityCapability(), ola::CAPABILITY_NONE); OLA_ASSERT_EQ(output_port.GetPriorityMode(), ola::PRIORITY_MODE_INHERIT); OLA_ASSERT_EQ(output_port.GetPriority(), ola::dmx::SOURCE_PRIORITY_DEFAULT); // this port doesn't support priorities so these are all noops OLA_ASSERT(patcher.SetPriorityInherit(&output_port)); OLA_ASSERT(patcher.SetPriorityStatic(&output_port, 20)); OLA_ASSERT_EQ(output_port.GetPriorityMode(), ola::PRIORITY_MODE_INHERIT); OLA_ASSERT_EQ(output_port.GetPriority(), ola::dmx::SOURCE_PRIORITY_DEFAULT); // now test an output port that supports priorities TestMockPriorityOutputPort output_port2(NULL, 1); OLA_ASSERT_EQ(output_port2.PriorityCapability(), ola::CAPABILITY_FULL); OLA_ASSERT_EQ(output_port2.GetPriorityMode(), ola::PRIORITY_MODE_INHERIT); OLA_ASSERT_EQ(output_port2.GetPriority(), ola::dmx::SOURCE_PRIORITY_DEFAULT); // try changing to static mode OLA_ASSERT(patcher.SetPriorityStatic(&output_port2, 20)); OLA_ASSERT_EQ(output_port2.GetPriorityMode(), ola::PRIORITY_MODE_STATIC); OLA_ASSERT_EQ(output_port2.GetPriority(), (uint8_t) 20); // bump priority OLA_ASSERT(patcher.SetPriorityStatic(&output_port2, 180)); OLA_ASSERT_EQ(output_port2.GetPriorityMode(), ola::PRIORITY_MODE_STATIC); OLA_ASSERT_EQ(output_port2.GetPriority(), (uint8_t) 180); // change back to inherit mode OLA_ASSERT(patcher.SetPriorityInherit(&output_port2)); OLA_ASSERT_EQ(output_port2.GetPriorityMode(), ola::PRIORITY_MODE_INHERIT); OLA_ASSERT_EQ(output_port2.GetPriority(), (uint8_t) 180); } ola-0.10.5.nojsmin/olad/plugin_api/DeviceManagerTest.cpp0000644000175000017500000002635013023355232022570 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DeviceManagerTest.cpp * Test fixture for the DeviceManager class. * Copyright (C) 2005 Simon Newton */ #include #include #include #include "ola/Logging.h" #include "ola/DmxBuffer.h" #include "olad/Plugin.h" #include "olad/Port.h" #include "olad/PortBroker.h" #include "olad/Preferences.h" #include "olad/plugin_api/DeviceManager.h" #include "olad/plugin_api/PortManager.h" #include "olad/plugin_api/TestCommon.h" #include "olad/plugin_api/UniverseStore.h" #include "ola/testing/TestUtils.h" using ola::AbstractDevice; using ola::AbstractPlugin; using ola::DeviceManager; using ola::DmxBuffer; using ola::Port; using ola::PortManager; using ola::Universe; using ola::UniverseStore; using std::string; using std::vector; class DeviceManagerTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(DeviceManagerTest); CPPUNIT_TEST(testDeviceManager); CPPUNIT_TEST(testRestorePatchings); CPPUNIT_TEST(testRestorePriorities); CPPUNIT_TEST_SUITE_END(); public: void testDeviceManager(); void testRestorePatchings(); void testRestorePriorities(); }; CPPUNIT_TEST_SUITE_REGISTRATION(DeviceManagerTest); /* * Test that we can register devices and retrieve them. */ void DeviceManagerTest::testDeviceManager() { DeviceManager manager(NULL, NULL); OLA_ASSERT_EQ(0u, manager.DeviceCount()); TestMockPlugin plugin(NULL, ola::OLA_PLUGIN_ARTNET); MockDevice orphaned_device(NULL, "orphaned device"); MockDevice device1(&plugin, "test device 1"); MockDevice device2(&plugin, "test device 2"); // can't register NULL OLA_ASSERT_FALSE(manager.RegisterDevice(NULL)); // Can't register a device with no unique id OLA_ASSERT_FALSE(manager.RegisterDevice(&orphaned_device)); // register a device OLA_ASSERT(manager.RegisterDevice(&device1)); // the second time must fail OLA_ASSERT_FALSE(manager.RegisterDevice(&device1)); // register a second device OLA_ASSERT(manager.RegisterDevice(&device2)); OLA_ASSERT_EQ(2u, manager.DeviceCount()); vector devices = manager.Devices(); OLA_ASSERT_EQ(1u, devices[0].alias); OLA_ASSERT_EQ(static_cast(&device1), devices[0].device); OLA_ASSERT_EQ(2u, devices[1].alias); OLA_ASSERT_EQ(static_cast(&device2), devices[1].device); // test fetching a device by alias OLA_ASSERT_EQ(static_cast(&device1), manager.GetDevice(1)); OLA_ASSERT_EQ(static_cast(&device2), manager.GetDevice(2)); OLA_ASSERT_EQ(static_cast(NULL), manager.GetDevice(3)); // test fetching a device by id ola::device_alias_pair result = manager.GetDevice(device1.UniqueId()); OLA_ASSERT_EQ(1u, result.alias); OLA_ASSERT_EQ(static_cast(&device1), result.device); result = manager.GetDevice(device2.UniqueId()); OLA_ASSERT_EQ(2u, result.alias); OLA_ASSERT_EQ(static_cast(&device2), result.device); result = manager.GetDevice("foo"); OLA_ASSERT_EQ(DeviceManager::MISSING_DEVICE_ALIAS, result.alias); OLA_ASSERT_EQ(static_cast(NULL), result.device); result = manager.GetDevice(""); OLA_ASSERT_EQ(DeviceManager::MISSING_DEVICE_ALIAS, result.alias); OLA_ASSERT_EQ(static_cast(NULL), result.device); // test unregistering null or non-registered device OLA_ASSERT_FALSE(manager.UnregisterDevice(NULL)); OLA_ASSERT_FALSE(manager.UnregisterDevice(&orphaned_device)); // unregistering the first device doesn't change the ID of the second OLA_ASSERT(manager.UnregisterDevice(&device1)); OLA_ASSERT_EQ(1u, manager.DeviceCount()); OLA_ASSERT_EQ(static_cast(NULL), manager.GetDevice(1)); OLA_ASSERT_EQ(static_cast(&device2), manager.GetDevice(2)); devices = manager.Devices(); OLA_ASSERT_EQ((size_t) 1, devices.size()); OLA_ASSERT_EQ(2u, devices[0].alias); OLA_ASSERT_EQ(static_cast(&device2), devices[0].device); // unregister by id OLA_ASSERT_FALSE(manager.UnregisterDevice(device1.UniqueId())); OLA_ASSERT(manager.UnregisterDevice(device2.UniqueId())); OLA_ASSERT_EQ(0u, manager.DeviceCount()); manager.UnregisterAllDevices(); // add one back and check that ids reset OLA_ASSERT(manager.RegisterDevice(&device1)); OLA_ASSERT_EQ(1u, manager.DeviceCount()); devices = manager.Devices(); OLA_ASSERT_EQ(1u, devices[0].alias); OLA_ASSERT_EQ(static_cast(&device1), devices[0].device); OLA_ASSERT_EQ(static_cast(&device1), manager.GetDevice(1)); result = manager.GetDevice(device1.UniqueId()); OLA_ASSERT_EQ(1u, result.alias); OLA_ASSERT_EQ(static_cast(&device1), result.device); } /* * Check that we restore the port patchings */ void DeviceManagerTest::testRestorePatchings() { ola::MemoryPreferencesFactory prefs_factory; UniverseStore uni_store(NULL, NULL); ola::PortBroker broker; PortManager port_manager(&uni_store, &broker); DeviceManager manager(&prefs_factory, &port_manager); OLA_ASSERT_EQ(0u, manager.DeviceCount()); ola::Preferences *prefs = prefs_factory.NewPreference("port"); OLA_ASSERT(prefs); // Use a hyphen to confirm we can parse these correctly prefs->SetValue("2-test-device-1-I-1", "1"); prefs->SetValue("2-test-device-1-O-1", "3"); TestMockPlugin plugin(NULL, ola::OLA_PLUGIN_ARTNET); MockDevice device1(&plugin, "test-device-1"); TestMockInputPort input_port(&device1, 1, NULL); TestMockOutputPort output_port(&device1, 1); device1.AddPort(&input_port); device1.AddPort(&output_port); OLA_ASSERT(manager.RegisterDevice(&device1)); OLA_ASSERT_EQ(1u, manager.DeviceCount()); OLA_ASSERT(input_port.GetUniverse()); OLA_ASSERT_EQ(input_port.GetUniverse()->UniverseId(), 1u); OLA_ASSERT(output_port.GetUniverse()); OLA_ASSERT_EQ(output_port.GetUniverse()->UniverseId(), 3u); // Now check that patching a universe saves the settings Universe *uni = uni_store.GetUniverseOrCreate(10); OLA_ASSERT(uni); input_port.SetUniverse(uni); // unregister all manager.UnregisterAllDevices(); OLA_ASSERT_EQ(0u, manager.DeviceCount()); OLA_ASSERT_EQ(string("10"), prefs->GetValue("2-test-device-1-I-1")); OLA_ASSERT_EQ(string("3"), prefs->GetValue("2-test-device-1-O-1")); } /* * Test that port priorities are restored correctly. */ void DeviceManagerTest::testRestorePriorities() { ola::MemoryPreferencesFactory prefs_factory; UniverseStore uni_store(NULL, NULL); ola::PortBroker broker; PortManager port_manager(&uni_store, &broker); DeviceManager manager(&prefs_factory, &port_manager); OLA_ASSERT_EQ(0u, manager.DeviceCount()); ola::Preferences *prefs = prefs_factory.NewPreference("port"); OLA_ASSERT(prefs); prefs->SetValue("2-test_device_1-I-1_priority_mode", "0"); prefs->SetValue("2-test_device_1-I-1_priority_value", "120"); prefs->SetValue("2-test_device_1-O-1_priority_mode", "0"); prefs->SetValue("2-test_device_1-O-1_priority_value", "140"); prefs->SetValue("2-test_device_1-I-2_priority_mode", "1"); // override mode prefs->SetValue("2-test_device_1-I-2_priority_value", "160"); prefs->SetValue("2-test_device_1-O-2_priority_mode", "1"); // override mode prefs->SetValue("2-test_device_1-O-2_priority_value", "180"); prefs->SetValue("2-test_device_1-I-3_priority_mode", "0"); // inherit mode // invalid priority prefs->SetValue("2-test_device_1-I-3_priority_value", "210"); prefs->SetValue("2-test_device_1-O-3_priority_mode", "0"); // inherit mode prefs->SetValue("2-test_device_1-O-3_priority_value", "180"); TestMockPlugin plugin(NULL, ola::OLA_PLUGIN_ARTNET); MockDevice device1(&plugin, "test_device_1"); // these ports don't support priorities. TestMockInputPort input_port(&device1, 1, NULL); TestMockOutputPort output_port(&device1, 1); // these devices support priorities TestMockPriorityInputPort input_port2(&device1, 2, NULL); TestMockPriorityOutputPort output_port2(&device1, 2); TestMockPriorityInputPort input_port3(&device1, 3, NULL); TestMockPriorityOutputPort output_port3(&device1, 3); device1.AddPort(&input_port); device1.AddPort(&output_port); device1.AddPort(&input_port2); device1.AddPort(&output_port2); device1.AddPort(&input_port3); device1.AddPort(&output_port3); OLA_ASSERT(manager.RegisterDevice(&device1)); OLA_ASSERT_EQ(1u, manager.DeviceCount()); OLA_ASSERT_EQ(ola::CAPABILITY_STATIC, input_port.PriorityCapability()); OLA_ASSERT_EQ(ola::PRIORITY_MODE_STATIC, input_port.GetPriorityMode()); OLA_ASSERT_EQ((uint8_t) 120, input_port.GetPriority()); OLA_ASSERT_EQ(ola::CAPABILITY_NONE, output_port.PriorityCapability()); OLA_ASSERT_EQ(ola::PRIORITY_MODE_INHERIT, output_port.GetPriorityMode()); OLA_ASSERT_EQ((uint8_t) 100, output_port.GetPriority()); // these ports support priorities OLA_ASSERT_EQ(ola::CAPABILITY_FULL, input_port2.PriorityCapability()); OLA_ASSERT_EQ(ola::PRIORITY_MODE_STATIC, input_port2.GetPriorityMode()); OLA_ASSERT_EQ((uint8_t) 160, input_port2.GetPriority()); OLA_ASSERT_EQ(ola::CAPABILITY_FULL, output_port2.PriorityCapability()); OLA_ASSERT_EQ(ola::PRIORITY_MODE_STATIC, output_port2.GetPriorityMode()); OLA_ASSERT_EQ((uint8_t) 180, output_port2.GetPriority()); OLA_ASSERT_EQ(ola::CAPABILITY_FULL, input_port3.PriorityCapability()); OLA_ASSERT_EQ(ola::PRIORITY_MODE_INHERIT, input_port3.GetPriorityMode()); OLA_ASSERT_EQ((uint8_t) 200, input_port3.GetPriority()); OLA_ASSERT_EQ(ola::CAPABILITY_FULL, output_port3.PriorityCapability()); OLA_ASSERT_EQ(ola::PRIORITY_MODE_INHERIT, output_port3.GetPriorityMode()); OLA_ASSERT_EQ((uint8_t) 180, output_port3.GetPriority()); // Now make some changes input_port2.SetPriorityMode(ola::PRIORITY_MODE_INHERIT); output_port2.SetPriorityMode(ola::PRIORITY_MODE_INHERIT); input_port3.SetPriorityMode(ola::PRIORITY_MODE_STATIC); input_port3.SetPriority(40); output_port3.SetPriorityMode(ola::PRIORITY_MODE_STATIC); output_port3.SetPriority(60); // unregister all manager.UnregisterAllDevices(); OLA_ASSERT_EQ(0u, manager.DeviceCount()); OLA_ASSERT_EQ(string("0"), prefs->GetValue("2-test_device_1-I-2_priority_mode")); OLA_ASSERT_EQ(string("0"), prefs->GetValue("2-test_device_1-O-2_priority_mode")); OLA_ASSERT_EQ(string("1"), prefs->GetValue("2-test_device_1-I-3_priority_mode")); OLA_ASSERT_EQ(string("40"), prefs->GetValue("2-test_device_1-I-3_priority_value")); OLA_ASSERT_EQ(string("1"), prefs->GetValue("2-test_device_1-O-3_priority_mode")); OLA_ASSERT_EQ(string("60"), prefs->GetValue("2-test_device_1-O-3_priority_value")); } ola-0.10.5.nojsmin/olad/DynamicPluginLoader.cpp0000644000175000017500000001371613023355232021003 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DynamicPluginLoader.cpp * This class is responsible for loading and unloading the plugins * Copyright (C) 2005 Simon Newton */ #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #include "ola/stl/STLUtils.h" #include "olad/DynamicPluginLoader.h" #include "olad/Plugin.h" #ifdef USE_ARTNET #include "plugins/artnet/ArtNetPlugin.h" #endif // USE_ARTNET #ifdef USE_DUMMY #include "plugins/dummy/DummyPlugin.h" #endif // USE_DUMMY #ifdef USE_E131 #include "plugins/e131/E131Plugin.h" #endif // USE_E131 #ifdef USE_ESPNET #include "plugins/espnet/EspNetPlugin.h" #endif // USE_ESPNET #ifdef USE_GPIO #include "plugins/gpio/GPIOPlugin.h" #endif // USE_GPIO #ifdef USE_KARATE #include "plugins/karate/KaratePlugin.h" #endif // USE_KARATE #ifdef USE_KINET #include "plugins/kinet/KiNetPlugin.h" #endif // USE_KINET #ifdef USE_MILINST #include "plugins/milinst/MilInstPlugin.h" #endif // USE_MILINST #ifdef USE_OPENDMX #include "plugins/opendmx/OpenDmxPlugin.h" #endif // USE_OPENDMX #ifdef USE_OPENPIXELCONTROL #include "plugins/openpixelcontrol/OPCPlugin.h" #endif // USE_OPENPIXELCONTROL #ifdef USE_OSC #include "plugins/osc/OSCPlugin.h" #endif // USE_OSC #ifdef USE_PATHPORT #include "plugins/pathport/PathportPlugin.h" #endif // USE_PATHPORT #ifdef USE_RENARD #include "plugins/renard/RenardPlugin.h" #endif // USE_RENARD #ifdef USE_SANDNET #include "plugins/sandnet/SandNetPlugin.h" #endif // USE_SANDNET #ifdef USE_SHOWNET #include "plugins/shownet/ShowNetPlugin.h" #endif // USE_SHOWNET #ifdef USE_SPI #include "plugins/spi/SPIPlugin.h" #endif // USE_SPI #ifdef USE_STAGEPROFI #include "plugins/stageprofi/StageProfiPlugin.h" #endif // USE_STAGEPROFI #ifdef USE_USBPRO #include "plugins/usbpro/UsbSerialPlugin.h" #endif // USE_USBPRO #ifdef USE_LIBUSB #include "plugins/usbdmx/UsbDmxPlugin.h" #endif // USE_LIBUSB #ifdef USE_FTDI #include "plugins/ftdidmx/FtdiDmxPlugin.h" #endif // USE_FTDI #ifdef USE_UART #include "plugins/uartdmx/UartDmxPlugin.h" #endif // USE_UART #ifdef USE_DMX4LINUX #include "plugins/dmx4linux/Dmx4LinuxPlugin.h" #endif // USE_DMX4LINUX namespace ola { using std::vector; DynamicPluginLoader::~DynamicPluginLoader() { UnloadPlugins(); } vector DynamicPluginLoader::LoadPlugins() { if (m_plugins.empty()) { PopulatePlugins(); } return m_plugins; } /* * Setup the plugin list */ void DynamicPluginLoader::PopulatePlugins() { #ifdef USE_DMX4LINUX m_plugins.push_back( new ola::plugin::dmx4linux::Dmx4LinuxPlugin(m_plugin_adaptor)); #endif // USE_DMX4LINUX #ifdef USE_ARTNET m_plugins.push_back(new ola::plugin::artnet::ArtNetPlugin(m_plugin_adaptor)); #endif // USE_ARTNET #ifdef USE_DUMMY m_plugins.push_back(new ola::plugin::dummy::DummyPlugin(m_plugin_adaptor)); #endif // USE_DUMMY #ifdef USE_E131 m_plugins.push_back(new ola::plugin::e131::E131Plugin(m_plugin_adaptor)); #endif // USE_E131 #ifdef USE_ESPNET m_plugins.push_back(new ola::plugin::espnet::EspNetPlugin(m_plugin_adaptor)); #endif // USE_ESPNET #ifdef USE_GPIO m_plugins.push_back(new ola::plugin::gpio::GPIOPlugin(m_plugin_adaptor)); #endif // USE_GPIO #ifdef USE_KARATE m_plugins.push_back( new ola::plugin::karate::KaratePlugin(m_plugin_adaptor)); #endif // USE_KARATE #ifdef USE_KINET m_plugins.push_back(new ola::plugin::kinet::KiNetPlugin(m_plugin_adaptor)); #endif // USE_KINET #ifdef USE_MILINST m_plugins.push_back( new ola::plugin::milinst::MilInstPlugin(m_plugin_adaptor)); #endif // USE_MILINST #ifdef USE_OPENDMX m_plugins.push_back( new ola::plugin::opendmx::OpenDmxPlugin(m_plugin_adaptor)); #endif // USE_OPENDMX #ifdef USE_OPENPIXELCONTROL m_plugins.push_back( new ola::plugin::openpixelcontrol::OPCPlugin(m_plugin_adaptor)); #endif // USE_OPENPIXELCONTROL #ifdef USE_OSC m_plugins.push_back( new ola::plugin::osc::OSCPlugin(m_plugin_adaptor)); #endif // USE_OSC #ifdef USE_RENARD m_plugins.push_back( new ola::plugin::renard::RenardPlugin(m_plugin_adaptor)); #endif // USE_RENARD #ifdef USE_SANDNET m_plugins.push_back( new ola::plugin::sandnet::SandNetPlugin(m_plugin_adaptor)); #endif // USE_SANDNET #ifdef USE_SHOWNET m_plugins.push_back( new ola::plugin::shownet::ShowNetPlugin(m_plugin_adaptor)); #endif // USE_SHOWNET #ifdef USE_SPI m_plugins.push_back( new ola::plugin::spi::SPIPlugin(m_plugin_adaptor)); #endif // USE_SPI #ifdef USE_STAGEPROFI m_plugins.push_back( new ola::plugin::stageprofi::StageProfiPlugin(m_plugin_adaptor)); #endif // USE_STAGEPROFI #ifdef USE_USBPRO m_plugins.push_back( new ola::plugin::usbpro::UsbSerialPlugin(m_plugin_adaptor)); #endif // USE_USBPRO #ifdef USE_LIBUSB m_plugins.push_back(new ola::plugin::usbdmx::UsbDmxPlugin(m_plugin_adaptor)); #endif // USE_LIBUSB #ifdef USE_PATHPORT m_plugins.push_back( new ola::plugin::pathport::PathportPlugin(m_plugin_adaptor)); #endif // USE_PATHPORT #ifdef USE_FTDI m_plugins.push_back( new ola::plugin::ftdidmx::FtdiDmxPlugin(m_plugin_adaptor)); #endif // USE_FTDI #ifdef USE_UART m_plugins.push_back( new ola::plugin::uartdmx::UartDmxPlugin(m_plugin_adaptor)); #endif // USE_UART } void DynamicPluginLoader::UnloadPlugins() { STLDeleteElements(&m_plugins); } } // namespace ola ola-0.10.5.nojsmin/olad/HttpServerActions.cpp0000644000175000017500000000510213023355232020526 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * HttpServerActions.cpp * The actions the HTTP server uses to interact with the client. * Copyright (C) 2010 Simon Newton */ #include #include #include "ola/ActionQueue.h" #include "ola/Callback.h" #include "ola/Logging.h" #include "olad/HttpServerActions.h" namespace ola { using std::string; void BaseHttpAction::RequestComplete(bool failure) { m_failed = failure; m_on_done->Run(); } void BaseHttpAction::Perform(SingleUseCallback0 *on_done) { m_on_done = on_done; DoAction(); } void BaseHttpAction::CallbackComplete(const client::Result &result) { RequestComplete(!result.Success()); } void SetNameAction::DoAction() { m_client->SetUniverseName( m_universe, m_name, NewSingleCallback(static_cast(this), &SetNameAction::CallbackComplete)); } void SetMergeModeAction::DoAction() { m_client->SetUniverseMergeMode( m_universe, m_merge_mode, NewSingleCallback(static_cast(this), &SetMergeModeAction::CallbackComplete)); } void PatchPortAction::DoAction() { m_client->Patch( m_device_alias, m_port, m_direction, m_action, m_universe, NewSingleCallback(static_cast(this), &PatchPortAction::CallbackComplete)); } void PortPriorityInheritAction::DoAction() { m_client->SetPortPriorityInherit( m_device_alias, m_port, m_direction, NewSingleCallback(static_cast(this), &PortPriorityInheritAction::CallbackComplete)); } void PortPriorityStaticAction::DoAction() { m_client->SetPortPriorityOverride( m_device_alias, m_port, m_direction, m_override_value, NewSingleCallback(static_cast(this), &PortPriorityStaticAction::CallbackComplete)); } } // namespace ola ola-0.10.5.nojsmin/olad/Makefile.mk0000644000175000017500000000574613134123277016464 0ustar wouterwouterinclude olad/www/Makefile.mk dist_noinst_DATA += olad/testdata/test_preferences.conf # HEADERS ################################################## oladinclude_HEADERS += olad/OlaDaemon.h olad/OlaServer.h # LIBRARIES ################################################## ola_server_sources = \ olad/ClientBroker.cpp \ olad/ClientBroker.h \ olad/DiscoveryAgent.cpp \ olad/DiscoveryAgent.h \ olad/DynamicPluginLoader.cpp \ olad/DynamicPluginLoader.h \ olad/HttpServerActions.h \ olad/OlaServerServiceImpl.cpp \ olad/OlaServerServiceImpl.h \ olad/OladHTTPServer.h \ olad/PluginLoader.h \ olad/PluginManager.cpp \ olad/PluginManager.h \ olad/RDMHTTPModule.h ola_server_additional_libs = if HAVE_DNSSD ola_server_sources += olad/BonjourDiscoveryAgent.h \ olad/BonjourDiscoveryAgent.cpp endif if HAVE_AVAHI ola_server_sources += olad/AvahiDiscoveryAgent.h olad/AvahiDiscoveryAgent.cpp ola_server_additional_libs += $(avahi_LIBS) endif if HAVE_LIBMICROHTTPD ola_server_sources += olad/HttpServerActions.cpp \ olad/OladHTTPServer.cpp \ olad/RDMHTTPModule.cpp ola_server_additional_libs += common/http/libolahttp.la endif # lib olaserver lib_LTLIBRARIES += olad/libolaserver.la olad_libolaserver_la_SOURCES = $(ola_server_sources) \ olad/OlaServer.cpp \ olad/OlaDaemon.cpp olad_libolaserver_la_CXXFLAGS = $(COMMON_PROTOBUF_CXXFLAGS) \ -DHTTP_DATA_DIR=\"${www_datadir}\" olad_libolaserver_la_LIBADD = $(PLUGIN_LIBS) \ common/libolacommon.la \ common/web/libolaweb.la \ ola/libola.la \ olad/plugin_api/libolaserverplugininterface.la \ $(ola_server_additional_libs) # Simon: I'm not too sure about this but it seems that because PLUGIN_LIBS is # determined at configure time, we need to add them here. EXTRA_olad_libolaserver_la_DEPENDENCIES = $(PLUGIN_LIBS) # PROGRAMS ################################################## bin_PROGRAMS += olad/olad olad_olad_SOURCES = olad/Olad.cpp if SUPPORTS_RDYNAMIC olad_olad_LDFLAGS = -rdynamic endif olad_olad_LDADD = olad/libolaserver.la \ common/libolacommon.la \ ola/libola.la if USE_FTDI olad_olad_LDADD += -lftdi -lusb endif # TESTS ################################################## test_programs += \ olad/OlaTester COMMON_OLAD_TEST_LDADD = $(COMMON_TESTING_LIBS) $(libprotobuf_LIBS) \ olad/plugin_api/libolaserverplugininterface.la \ olad/libolaserver.la \ common/libolacommon.la olad_OlaTester_SOURCES = \ olad/PluginManagerTest.cpp \ olad/OlaServerServiceImplTest.cpp olad_OlaTester_CXXFLAGS = $(COMMON_TESTING_PROTOBUF_FLAGS) olad_OlaTester_LDADD = $(COMMON_OLAD_TEST_LDADD) CLEANFILES += olad/ola-output.conf ola-0.10.5.nojsmin/olad/OlaServerServiceImpl.cpp0000644000175000017500000010020613023355232021145 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OlaServerServiceImpl.cpp * Implementation of the OlaServerService interface. This is the class that * handles all the RPCs on the server side. * Copyright (C) 2005 Simon Newton */ #include #include #include #include "common/protocol/Ola.pb.h" #include "common/rpc/RpcSession.h" #include "ola/Callback.h" #include "ola/CallbackRunner.h" #include "ola/DmxBuffer.h" #include "ola/Logging.h" #include "ola/rdm/RDMCommand.h" #include "ola/rdm/UIDSet.h" #include "ola/strings/Format.h" #include "ola/timecode/TimeCode.h" #include "ola/timecode/TimeCodeEnums.h" #include "olad/ClientBroker.h" #include "olad/Device.h" #include "olad/DmxSource.h" #include "olad/OlaServerServiceImpl.h" #include "olad/Plugin.h" #include "olad/PluginManager.h" #include "olad/Port.h" #include "olad/Universe.h" #include "olad/plugin_api/Client.h" #include "olad/plugin_api/DeviceManager.h" #include "olad/plugin_api/PortManager.h" #include "olad/plugin_api/UniverseStore.h" namespace ola { using ola::CallbackRunner; using ola::proto::Ack; using ola::proto::DeviceConfigReply; using ola::proto::DeviceConfigRequest; using ola::proto::DeviceInfo; using ola::proto::DeviceInfoReply; using ola::proto::DeviceInfoRequest; using ola::proto::DmxData; using ola::proto::MergeModeRequest; using ola::proto::OptionalUniverseRequest; using ola::proto::PatchPortRequest; using ola::proto::PluginDescriptionReply; using ola::proto::PluginDescriptionRequest; using ola::proto::PluginInfo; using ola::proto::PluginListReply; using ola::proto::PluginListRequest; using ola::proto::PortInfo; using ola::proto::RegisterDmxRequest; using ola::proto::UniverseInfo; using ola::proto::UniverseInfoReply; using ola::proto::UniverseNameRequest; using ola::proto::UniverseRequest; using ola::rdm::RDMRequest; using ola::rdm::RDMResponse; using ola::rdm::UID; using ola::rdm::UIDSet; using ola::rpc::RpcController; using std::string; using std::vector; namespace { template RDMRequest::OverrideOptions RDMRequestOptionsFromProto( const RequestType &request) { RDMRequest::OverrideOptions options; if (!request.has_options()) { return options; } const ola::proto::RDMRequestOverrideOptions &proto_options = request.options(); if (proto_options.has_sub_start_code()) { options.sub_start_code = proto_options.sub_start_code(); } if (proto_options.has_message_length()) { options.SetMessageLength(proto_options.message_length()); } if (proto_options.has_message_count()) { options.message_count = proto_options.message_count(); } if (proto_options.has_checksum()) { options.SetChecksum(proto_options.checksum()); } return options; } } // namespace typedef CallbackRunner ClosureRunner; OlaServerServiceImpl::OlaServerServiceImpl( UniverseStore *universe_store, DeviceManager *device_manager, PluginManager *plugin_manager, PortManager *port_manager, ClientBroker *broker, const TimeStamp *wake_up_time, ReloadPluginsCallback *reload_plugins_callback) : m_universe_store(universe_store), m_device_manager(device_manager), m_plugin_manager(plugin_manager), m_port_manager(port_manager), m_broker(broker), m_wake_up_time(wake_up_time), m_reload_plugins_callback(reload_plugins_callback) { } void OlaServerServiceImpl::GetDmx( RpcController* controller, const UniverseRequest* request, DmxData* response, ola::rpc::RpcService::CompletionCallback* done) { ClosureRunner runner(done); Universe *universe = m_universe_store->GetUniverse(request->universe()); if (!universe) { return MissingUniverseError(controller); } const DmxBuffer buffer = universe->GetDMX(); response->set_data(buffer.Get()); response->set_universe(request->universe()); } void OlaServerServiceImpl::RegisterForDmx( RpcController* controller, const RegisterDmxRequest* request, Ack*, ola::rpc::RpcService::CompletionCallback* done) { ClosureRunner runner(done); Universe *universe = m_universe_store->GetUniverseOrCreate( request->universe()); if (!universe) { return MissingUniverseError(controller); } Client *client = GetClient(controller); if (request->action() == ola::proto::REGISTER) { universe->AddSinkClient(client); } else { universe->RemoveSinkClient(client); } } void OlaServerServiceImpl::UpdateDmxData( RpcController* controller, const DmxData* request, Ack*, ola::rpc::RpcService::CompletionCallback* done) { ClosureRunner runner(done); Universe *universe = m_universe_store->GetUniverse(request->universe()); if (!universe) { return MissingUniverseError(controller); } Client *client = GetClient(controller); DmxBuffer buffer; buffer.Set(request->data()); uint8_t priority = ola::dmx::SOURCE_PRIORITY_DEFAULT; if (request->has_priority()) { priority = request->priority(); priority = std::max(static_cast(ola::dmx::SOURCE_PRIORITY_MIN), priority); priority = std::min(static_cast(ola::dmx::SOURCE_PRIORITY_MAX), priority); } DmxSource source(buffer, *m_wake_up_time, priority); client->DMXReceived(request->universe(), source); universe->SourceClientDataChanged(client); } void OlaServerServiceImpl::StreamDmxData( RpcController *controller, const ola::proto::DmxData* request, ola::proto::STREAMING_NO_RESPONSE*, ola::rpc::RpcService::CompletionCallback*) { Universe *universe = m_universe_store->GetUniverse(request->universe()); if (!universe) { return; } Client *client = GetClient(controller); DmxBuffer buffer; buffer.Set(request->data()); uint8_t priority = ola::dmx::SOURCE_PRIORITY_DEFAULT; if (request->has_priority()) { priority = request->priority(); priority = std::max(static_cast(ola::dmx::SOURCE_PRIORITY_MIN), priority); priority = std::min(static_cast(ola::dmx::SOURCE_PRIORITY_MAX), priority); } DmxSource source(buffer, *m_wake_up_time, priority); client->DMXReceived(request->universe(), source); universe->SourceClientDataChanged(client); } void OlaServerServiceImpl::SetUniverseName( RpcController* controller, const UniverseNameRequest* request, Ack*, ola::rpc::RpcService::CompletionCallback* done) { ClosureRunner runner(done); Universe *universe = m_universe_store->GetUniverse(request->universe()); if (!universe) { return MissingUniverseError(controller); } universe->SetName(request->name()); } void OlaServerServiceImpl::SetMergeMode( RpcController* controller, const MergeModeRequest* request, Ack*, ola::rpc::RpcService::CompletionCallback* done) { ClosureRunner runner(done); Universe *universe = m_universe_store->GetUniverse(request->universe()); if (!universe) { return MissingUniverseError(controller); } Universe::merge_mode mode = request->merge_mode() == ola::proto::HTP ? Universe::MERGE_HTP : Universe::MERGE_LTP; universe->SetMergeMode(mode); } void OlaServerServiceImpl::PatchPort( RpcController* controller, const PatchPortRequest* request, Ack*, ola::rpc::RpcService::CompletionCallback* done) { ClosureRunner runner(done); AbstractDevice *device = m_device_manager->GetDevice(request->device_alias()); if (!device) { return MissingDeviceError(controller); } bool result; if (request->is_output()) { OutputPort *port = device->GetOutputPort(request->port_id()); if (!port) { return MissingPortError(controller); } if (request->action() == ola::proto::PATCH) { result = m_port_manager->PatchPort(port, request->universe()); } else { result = m_port_manager->UnPatchPort(port); } } else { InputPort *port = device->GetInputPort(request->port_id()); if (!port) { return MissingPortError(controller); } if (request->action() == ola::proto::PATCH) { result = m_port_manager->PatchPort(port, request->universe()); } else { result = m_port_manager->UnPatchPort(port); } } if (!result) { controller->SetFailed("Patch port request failed"); } } void OlaServerServiceImpl::SetPortPriority( RpcController* controller, const ola::proto::PortPriorityRequest* request, Ack*, ola::rpc::RpcService::CompletionCallback* done) { ClosureRunner runner(done); AbstractDevice *device = m_device_manager->GetDevice(request->device_alias()); if (!device) { return MissingDeviceError(controller); } bool status; bool inherit_mode = true; uint8_t value = 0; if (request->priority_mode() == PRIORITY_MODE_STATIC) { if (request->has_priority()) { inherit_mode = false; value = request->priority(); } else { OLA_INFO << "In Set Port Priority, override mode was set but the value " "wasn't specified"; controller->SetFailed( "Invalid SetPortPriority request, see logs for more info"); return; } } if (request->is_output()) { OutputPort *port = device->GetOutputPort(request->port_id()); if (!port) { return MissingPortError(controller); } if (inherit_mode) { status = m_port_manager->SetPriorityInherit(port); } else { status = m_port_manager->SetPriorityStatic(port, value); } } else { InputPort *port = device->GetInputPort(request->port_id()); if (!port) { return MissingPortError(controller); } if (inherit_mode) { status = m_port_manager->SetPriorityInherit(port); } else { status = m_port_manager->SetPriorityStatic(port, value); } } if (!status) { controller->SetFailed( "Invalid SetPortPriority request, see logs for more info"); } } void OlaServerServiceImpl::AddUniverse( const Universe * universe, ola::proto::UniverseInfoReply *universe_info_reply) const { UniverseInfo *universe_info = universe_info_reply->add_universe(); universe_info->set_universe(universe->UniverseId()); universe_info->set_name(universe->Name()); universe_info->set_merge_mode(universe->MergeMode() == Universe::MERGE_HTP ? ola::proto::HTP : ola::proto::LTP); universe_info->set_input_port_count(universe->InputPortCount()); universe_info->set_output_port_count(universe->OutputPortCount()); universe_info->set_rdm_devices(universe->UIDCount()); std::vector input_ports; std::vector::const_iterator input_it; universe->InputPorts(&input_ports); for (input_it = input_ports.begin(); input_it != input_ports.end(); input_it++) { PortInfo *pi = universe_info->add_input_ports(); PopulatePort(**input_it, pi); } std::vector output_ports; std::vector::const_iterator output_it; universe->OutputPorts(&output_ports); for (output_it = output_ports.begin(); output_it != output_ports.end(); output_it++) { PortInfo *pi = universe_info->add_output_ports(); PopulatePort(**output_it, pi); } } void OlaServerServiceImpl::GetUniverseInfo( RpcController* controller, const OptionalUniverseRequest* request, UniverseInfoReply* response, ola::rpc::RpcService::CompletionCallback* done) { ClosureRunner runner(done); if (request->has_universe()) { // return info for a single universe Universe *universe = m_universe_store->GetUniverse(request->universe()); if (!universe) { return MissingUniverseError(controller); } AddUniverse(universe, response); } else { // return all vector uni_list; m_universe_store->GetList(&uni_list); vector::const_iterator iter; for (iter = uni_list.begin(); iter != uni_list.end(); ++iter) { AddUniverse(*iter, response); } } } void OlaServerServiceImpl::GetPlugins( RpcController*, const PluginListRequest*, PluginListReply* response, ola::rpc::RpcService::CompletionCallback* done) { ClosureRunner runner(done); vector plugin_list; vector::const_iterator iter; m_plugin_manager->Plugins(&plugin_list); for (iter = plugin_list.begin(); iter != plugin_list.end(); ++iter) { PluginInfo *plugin_info = response->add_plugin(); AddPlugin(*iter, plugin_info); } } void OlaServerServiceImpl::ReloadPlugins( RpcController*, const ::ola::proto::PluginReloadRequest*, Ack*, ola::rpc::RpcService::CompletionCallback* done) { ClosureRunner runner(done); if (m_reload_plugins_callback.get()) { m_reload_plugins_callback->Run(); } else { OLA_WARN << "No plugin reload callback provided!"; } } void OlaServerServiceImpl::GetPluginDescription( RpcController* controller, const ola::proto::PluginDescriptionRequest* request, ola::proto::PluginDescriptionReply* response, ola::rpc::RpcService::CompletionCallback* done) { ClosureRunner runner(done); AbstractPlugin *plugin = m_plugin_manager->GetPlugin((ola_plugin_id) request->plugin_id()); if (plugin) { response->set_name(plugin->Name()); response->set_description(plugin->Description()); } else { controller->SetFailed("Plugin not loaded"); } } void OlaServerServiceImpl::GetPluginState( RpcController* controller, const ola::proto::PluginStateRequest* request, ola::proto::PluginStateReply* response, ola::rpc::RpcService::CompletionCallback* done) { ClosureRunner runner(done); ola_plugin_id plugin_id = (ola_plugin_id) request->plugin_id(); AbstractPlugin *plugin = m_plugin_manager->GetPlugin(plugin_id); if (plugin) { response->set_name(plugin->Name()); response->set_enabled(plugin->IsEnabled()); response->set_active(m_plugin_manager->IsActive(plugin_id)); response->set_preferences_source(plugin->PreferenceConfigLocation()); vector conflict_list; m_plugin_manager->GetConflictList(plugin_id, &conflict_list); vector::const_iterator iter = conflict_list.begin(); for (; iter != conflict_list.end(); ++iter) { PluginInfo *plugin_info = response->add_conflicts_with(); AddPlugin(*iter, plugin_info); } } else { controller->SetFailed("Plugin not loaded"); } } void OlaServerServiceImpl::SetPluginState( RpcController *controller, const ola::proto::PluginStateChangeRequest* request, Ack*, ola::rpc::RpcService::CompletionCallback* done) { ClosureRunner runner(done); ola_plugin_id plugin_id = (ola_plugin_id) request->plugin_id(); AbstractPlugin *plugin = m_plugin_manager->GetPlugin(plugin_id); if (plugin) { OLA_DEBUG << "SetPluginState to " << request->enabled() << " for plugin " << plugin->Name(); if (request->enabled()) { if (!m_plugin_manager->EnableAndStartPlugin(plugin_id)) { controller->SetFailed("Failed to start plugin: " + plugin->Name()); } } else { m_plugin_manager->DisableAndStopPlugin(plugin_id); } } } void OlaServerServiceImpl::GetDeviceInfo( RpcController*, const DeviceInfoRequest* request, DeviceInfoReply* response, ola::rpc::RpcService::CompletionCallback* done) { ClosureRunner runner(done); vector device_list = m_device_manager->Devices(); vector::const_iterator iter; for (iter = device_list.begin(); iter != device_list.end(); ++iter) { if (request->has_plugin_id()) { if (iter->device->Owner()->Id() == request->plugin_id() || request->plugin_id() == ola::OLA_PLUGIN_ALL) { AddDevice(iter->device, iter->alias, response); } } else { AddDevice(iter->device, iter->alias, response); } } } void OlaServerServiceImpl::GetCandidatePorts( RpcController* controller, const ola::proto::OptionalUniverseRequest* request, ola::proto::DeviceInfoReply* response, ola::rpc::RpcService::CompletionCallback* done) { ClosureRunner runner(done); vector device_list = m_device_manager->Devices(); vector::const_iterator iter; Universe *universe = NULL; if (request->has_universe()) { universe = m_universe_store->GetUniverse(request->universe()); if (!universe) { return MissingUniverseError(controller); } } vector input_ports; vector output_ports; vector::const_iterator input_iter; vector::const_iterator output_iter; for (iter = device_list.begin(); iter != device_list.end(); ++iter) { AbstractDevice *device = iter->device; input_ports.clear(); output_ports.clear(); device->InputPorts(&input_ports); device->OutputPorts(&output_ports); bool seen_input_port = false; bool seen_output_port = false; unsigned int unpatched_input_ports = 0; unsigned int unpatched_output_ports = 0; if (universe) { for (input_iter = input_ports.begin(); input_iter != input_ports.end(); input_iter++) { if ((*input_iter)->GetUniverse() == universe) { seen_input_port = true; } else if (!(*input_iter)->GetUniverse()) { unpatched_input_ports++; } } for (output_iter = output_ports.begin(); output_iter != output_ports.end(); output_iter++) { if ((*output_iter)->GetUniverse() == universe) { seen_output_port = true; } else if (!(*output_iter)->GetUniverse()) { unpatched_output_ports++; } } } else { unpatched_input_ports = input_ports.size(); unpatched_output_ports = output_ports.size(); } bool can_bind_more_input_ports = ( (!seen_output_port || device->AllowLooping()) && (!seen_input_port || device->AllowMultiPortPatching())); bool can_bind_more_output_ports = ( (!seen_input_port || device->AllowLooping()) && (!seen_output_port || device->AllowMultiPortPatching())); if ((unpatched_input_ports == 0 || !can_bind_more_input_ports) && (unpatched_output_ports == 0 || !can_bind_more_output_ports)) { continue; } // go ahead and create the device at this point DeviceInfo *device_info = response->add_device(); device_info->set_device_alias(iter->alias); device_info->set_device_name(device->Name()); device_info->set_device_id(device->UniqueId()); if (device->Owner()) { device_info->set_plugin_id(device->Owner()->Id()); } for (input_iter = input_ports.begin(); input_iter != input_ports.end(); ++input_iter) { if ((*input_iter)->GetUniverse()) { continue; } if (!can_bind_more_input_ports) { break; } PortInfo *port_info = device_info->add_input_port(); PopulatePort(**input_iter, port_info); if (!device->AllowMultiPortPatching()) { break; } } for (output_iter = output_ports.begin(); output_iter != output_ports.end(); ++output_iter) { if ((*output_iter)->GetUniverse()) { continue; } if (!can_bind_more_output_ports) { break; } PortInfo *port_info = device_info->add_output_port(); PopulatePort(**output_iter, port_info); if (!device->AllowMultiPortPatching()) { break; } } } } void OlaServerServiceImpl::ConfigureDevice( RpcController* controller, const DeviceConfigRequest* request, DeviceConfigReply* response, ola::rpc::RpcService::CompletionCallback* done) { AbstractDevice *device = m_device_manager->GetDevice(request->device_alias()); if (!device) { MissingDeviceError(controller); done->Run(); return; } device->Configure(controller, request->data(), response->mutable_data(), done); } void OlaServerServiceImpl::GetUIDs( RpcController* controller, const ola::proto::UniverseRequest* request, ola::proto::UIDListReply* response, ola::rpc::RpcService::CompletionCallback* done) { ClosureRunner runner(done); Universe *universe = m_universe_store->GetUniverse(request->universe()); if (!universe) { return MissingUniverseError(controller); } response->set_universe(universe->UniverseId()); UIDSet uid_set; universe->GetUIDs(&uid_set); UIDSet::Iterator iter = uid_set.Begin(); for (; iter != uid_set.End(); ++iter) { ola::proto::UID *uid = response->add_uid(); SetProtoUID(*iter, uid); } } void OlaServerServiceImpl::ForceDiscovery( RpcController* controller, const ola::proto::DiscoveryRequest* request, ola::proto::UIDListReply *response, ola::rpc::RpcService::CompletionCallback* done) { Universe *universe = m_universe_store->GetUniverse(request->universe()); if (universe) { unsigned int universe_id = request->universe(); m_broker->RunRDMDiscovery( GetClient(controller), universe, request->full(), NewSingleCallback(this, &OlaServerServiceImpl::RDMDiscoveryComplete, universe_id, done, response)); } else { ClosureRunner runner(done); MissingUniverseError(controller); } } void OlaServerServiceImpl::RDMCommand( RpcController* controller, const ola::proto::RDMRequest* request, ola::proto::RDMResponse* response, ola::rpc::RpcService::CompletionCallback* done) { Universe *universe = m_universe_store->GetUniverse(request->universe()); if (!universe) { MissingUniverseError(controller); done->Run(); return; } Client *client = GetClient(controller); UID source_uid = client->GetUID(); UID destination(request->uid().esta_id(), request->uid().device_id()); RDMRequest::OverrideOptions options = RDMRequestOptionsFromProto(*request); ola::rdm::RDMRequest *rdm_request = NULL; if (request->is_set()) { rdm_request = new ola::rdm::RDMSetRequest( source_uid, destination, 0, // transaction # 1, // port id request->sub_device(), request->param_id(), reinterpret_cast(request->data().data()), request->data().size(), options); } else { rdm_request = new ola::rdm::RDMGetRequest( source_uid, destination, 0, // transaction # 1, // port id request->sub_device(), request->param_id(), reinterpret_cast(request->data().data()), request->data().size(), options); } ola::rdm::RDMCallback *callback = NewSingleCallback( this, &OlaServerServiceImpl::HandleRDMResponse, response, done, request->include_raw_response()); m_broker->SendRDMRequest(client, universe, rdm_request, callback); } void OlaServerServiceImpl::RDMDiscoveryCommand( RpcController* controller, const ola::proto::RDMDiscoveryRequest* request, ola::proto::RDMResponse* response, ola::rpc::RpcService::CompletionCallback* done) { Universe *universe = m_universe_store->GetUniverse(request->universe()); if (!universe) { MissingUniverseError(controller); done->Run(); return; } Client *client = GetClient(controller); UID source_uid = client->GetUID(); UID destination(request->uid().esta_id(), request->uid().device_id()); RDMRequest::OverrideOptions options = RDMRequestOptionsFromProto(*request); ola::rdm::RDMRequest *rdm_request = new ola::rdm::RDMDiscoveryRequest( source_uid, destination, 0, // transaction # 1, // port id request->sub_device(), request->param_id(), reinterpret_cast(request->data().data()), request->data().size(), options); ola::rdm::RDMCallback *callback = NewSingleCallback( this, &OlaServerServiceImpl::HandleRDMResponse, response, done, request->include_raw_response()); m_broker->SendRDMRequest(client, universe, rdm_request, callback); } void OlaServerServiceImpl::SetSourceUID( RpcController *controller, const ola::proto::UID* request, Ack*, ola::rpc::RpcService::CompletionCallback* done) { ClosureRunner runner(done); UID source_uid(request->esta_id(), request->device_id()); GetClient(controller)->SetUID(source_uid); } void OlaServerServiceImpl::SendTimeCode( RpcController* controller, const ola::proto::TimeCode* request, Ack*, ola::rpc::RpcService::CompletionCallback* done) { ClosureRunner runner(done); ola::timecode::TimeCode time_code( static_cast(request->type()), request->hours(), request->minutes(), request->seconds(), request->frames()); if (time_code.IsValid()) { m_device_manager->SendTimeCode(time_code); } else { controller->SetFailed("Invalid TimeCode"); } } // Private methods //----------------------------------------------------------------------------- /* * Handle an RDM Response, this includes broadcast messages, messages that * timed out and normal response messages. */ void OlaServerServiceImpl::HandleRDMResponse( ola::proto::RDMResponse* response, ola::rpc::RpcService::CompletionCallback* done, bool include_raw_packets, ola::rdm::RDMReply *reply) { ClosureRunner runner(done); response->set_response_code( static_cast(reply->StatusCode())); if (reply->StatusCode() == ola::rdm::RDM_COMPLETED_OK) { if (!reply->Response()) { // No response returned. OLA_WARN << "RDM code was ok but response was NULL"; response->set_response_code(static_cast( ola::rdm::RDM_INVALID_RESPONSE)); } else if (reply->Response()->ResponseType() <= ola::rdm::RDM_NACK_REASON) { // Valid RDM Response code. SetProtoUID(reply->Response()->SourceUID(), response->mutable_source_uid()); SetProtoUID(reply->Response()->DestinationUID(), response->mutable_dest_uid()); response->set_transaction_number(reply->Response()->TransactionNumber()); response->set_response_type(static_cast( reply->Response()->ResponseType())); response->set_message_count(reply->Response()->MessageCount()); response->set_sub_device(reply->Response()->SubDevice()); switch (reply->Response()->CommandClass()) { case ola::rdm::RDMCommand::DISCOVER_COMMAND_RESPONSE: response->set_command_class(ola::proto::RDM_DISCOVERY_RESPONSE); break; case ola::rdm::RDMCommand::GET_COMMAND_RESPONSE: response->set_command_class(ola::proto::RDM_GET_RESPONSE); break; case ola::rdm::RDMCommand::SET_COMMAND_RESPONSE: response->set_command_class(ola::proto::RDM_SET_RESPONSE); break; default: OLA_WARN << "Unknown command class " << strings::ToHex(static_cast( reply->Response()->CommandClass())); } response->set_param_id(reply->Response()->ParamId()); if (reply->Response()->ParamData() && reply->Response()->ParamDataSize()) { response->set_data( reinterpret_cast(reply->Response()->ParamData()), reply->Response()->ParamDataSize()); } } else { // Invalid RDM Response code. OLA_WARN << "RDM response present, but response type is invalid, was " << strings::ToHex(reply->Response()->ResponseType()); response->set_response_code(ola::proto::RDM_INVALID_RESPONSE); } } if (include_raw_packets) { vector::const_iterator iter = reply->Frames().begin(); for (; iter != reply->Frames().end(); ++iter) { ola::proto::RDMFrame *frame = response->add_raw_frame(); frame->set_raw_response(iter->data.data(), iter->data.size()); ola::proto::RDMFrameTiming *timing = frame->mutable_timing(); timing->set_response_delay(iter->timing.response_time); timing->set_break_time(iter->timing.break_time); timing->set_mark_time(iter->timing.mark_time); timing->set_data_time(iter->timing.data_time); } } } /** * Called when RDM discovery completes */ void OlaServerServiceImpl::RDMDiscoveryComplete( unsigned int universe_id, ola::rpc::RpcService::CompletionCallback* done, ola::proto::UIDListReply *response, const UIDSet &uids) { ClosureRunner runner(done); response->set_universe(universe_id); UIDSet::Iterator iter = uids.Begin(); for (; iter != uids.End(); ++iter) { ola::proto::UID *uid = response->add_uid(); SetProtoUID(*iter, uid); } } void OlaServerServiceImpl::MissingUniverseError(RpcController* controller) { controller->SetFailed("Universe doesn't exist"); } void OlaServerServiceImpl::MissingDeviceError(RpcController* controller) { controller->SetFailed("Device doesn't exist"); } void OlaServerServiceImpl::MissingPluginError(RpcController* controller) { controller->SetFailed("Plugin doesn't exist"); } void OlaServerServiceImpl::MissingPortError(RpcController* controller) { controller->SetFailed("Port doesn't exist"); } /* * Add this device to the DeviceInfo response */ void OlaServerServiceImpl::AddPlugin(AbstractPlugin *plugin, PluginInfo* plugin_info) const { plugin_info->set_plugin_id(plugin->Id()); plugin_info->set_name(plugin->Name()); plugin_info->set_active(m_plugin_manager->IsActive(plugin->Id())); plugin_info->set_enabled(m_plugin_manager->IsEnabled(plugin->Id())); } /* * Add this device to the DeviceInfo response */ void OlaServerServiceImpl::AddDevice(AbstractDevice *device, unsigned int alias, DeviceInfoReply* response) const { DeviceInfo *device_info = response->add_device(); device_info->set_device_alias(alias); device_info->set_device_name(device->Name()); device_info->set_device_id(device->UniqueId()); if (device->Owner()) { device_info->set_plugin_id(device->Owner()->Id()); } vector input_ports; device->InputPorts(&input_ports); vector::const_iterator input_iter; for (input_iter = input_ports.begin(); input_iter != input_ports.end(); ++input_iter) { PortInfo *port_info = device_info->add_input_port(); PopulatePort(**input_iter, port_info); } vector output_ports; device->OutputPorts(&output_ports); vector::const_iterator output_iter; for (output_iter = output_ports.begin(); output_iter != output_ports.end(); ++output_iter) { PortInfo *port_info = device_info->add_output_port(); PopulatePort(**output_iter, port_info); } } template void OlaServerServiceImpl::PopulatePort(const PortClass &port, PortInfo *port_info) const { port_info->set_port_id(port.PortId()); port_info->set_priority_capability(port.PriorityCapability()); port_info->set_description(port.Description()); if (port.GetUniverse()) { port_info->set_active(true); port_info->set_universe(port.GetUniverse()->UniverseId()); } else { port_info->set_active(false); } if (port.PriorityCapability() != CAPABILITY_NONE) { port_info->set_priority_mode(port.GetPriorityMode()); if (port.GetPriorityMode() == PRIORITY_MODE_STATIC) { port_info->set_priority(port.GetPriority()); } } port_info->set_supports_rdm(port.SupportsRDM()); } void OlaServerServiceImpl::SetProtoUID(const ola::rdm::UID &uid, ola::proto::UID *pb_uid) { pb_uid->set_esta_id(uid.ManufacturerId()); pb_uid->set_device_id(uid.DeviceId()); } Client* OlaServerServiceImpl::GetClient(ola::rpc::RpcController *controller) { return reinterpret_cast(controller->Session()->GetData()); } } // namespace ola ola-0.10.5.nojsmin/olad/OladHTTPServer.cpp0000644000175000017500000011634713023355232017663 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OladHTTPServer.cpp * Ola HTTP class * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include "ola/ActionQueue.h" #include "ola/Callback.h" #include "ola/DmxBuffer.h" #include "ola/Logging.h" #include "ola/StringUtils.h" #include "ola/base/Version.h" #include "ola/dmx/SourcePriorities.h" #include "ola/network/NetworkUtils.h" #include "ola/web/Json.h" #include "olad/DmxSource.h" #include "olad/HttpServerActions.h" #include "olad/OladHTTPServer.h" #include "olad/OlaServer.h" #include "olad/Preferences.h" namespace ola { using ola::client::OlaDevice; using ola::client::OlaInputPort; using ola::client::OlaOutputPort; using ola::client::OlaPlugin; using ola::client::OlaPort; using ola::client::OlaUniverse; using ola::http::HTTPRequest; using ola::http::HTTPResponse; using ola::http::HTTPServer; using ola::io::ConnectedDescriptor; using ola::web::JsonArray; using ola::web::JsonObject; using std::cout; using std::endl; using std::ostringstream; using std::string; using std::vector; const char OladHTTPServer::HELP_PARAMETER[] = "help"; const char OladHTTPServer::HELP_REDIRECTION[] = "?help=1"; const char OladHTTPServer::K_BACKEND_DISCONNECTED_ERROR[] = "Failed to send request, client isn't connected"; const char OladHTTPServer::K_PRIORITY_VALUE_SUFFIX[] = "_priority_value"; const char OladHTTPServer::K_PRIORITY_MODE_SUFFIX[] = "_priority_mode"; /** * @brief Create a new OLA HTTP server * @param export_map the ExportMap to display when /debug is called * @param options the OladHTTPServerOptions for the OLA HTTP server * @param client_socket A ConnectedDescriptor which is used to communicate with * the server. * @param ola_server the OlaServer to use * @param iface the network interface to bind to */ OladHTTPServer::OladHTTPServer(ExportMap *export_map, const OladHTTPServerOptions &options, ConnectedDescriptor *client_socket, OlaServer *ola_server, const ola::network::Interface &iface) : OlaHTTPServer(options, export_map), m_client_socket(client_socket), m_client(client_socket), m_ola_server(ola_server), m_enable_quit(options.enable_quit), m_interface(iface), m_rdm_module(&m_server, &m_client) { // The main handlers RegisterHandler("/quit", &OladHTTPServer::DisplayQuit); RegisterHandler("/reload", &OladHTTPServer::ReloadPlugins); RegisterHandler("/reload_pids", &OladHTTPServer::ReloadPidStore); RegisterHandler("/new_universe", &OladHTTPServer::CreateNewUniverse); RegisterHandler("/modify_universe", &OladHTTPServer::ModifyUniverse); RegisterHandler("/set_plugin_state", &OladHTTPServer::SetPluginState); RegisterHandler("/set_dmx", &OladHTTPServer::HandleSetDmx); RegisterHandler("/get_dmx", &OladHTTPServer::GetDmx); // json endpoints for the new UI RegisterHandler("/json/server_stats", &OladHTTPServer::JsonServerStats); RegisterHandler("/json/universe_plugin_list", &OladHTTPServer::JsonUniversePluginList); RegisterHandler("/json/plugin_info", &OladHTTPServer::JsonPluginInfo); RegisterHandler("/json/get_ports", &OladHTTPServer::JsonAvailablePorts); RegisterHandler("/json/universe_info", &OladHTTPServer::JsonUniverseInfo); // these are the static files for the old UI m_server.RegisterFile("/blank.gif", HTTPServer::CONTENT_TYPE_GIF); m_server.RegisterFile("/button-bg.png", HTTPServer::CONTENT_TYPE_PNG); m_server.RegisterFile("/custombutton.css", HTTPServer::CONTENT_TYPE_CSS); m_server.RegisterFile("/editortoolbar.png", HTTPServer::CONTENT_TYPE_PNG); m_server.RegisterFile("/expander.png", HTTPServer::CONTENT_TYPE_PNG); m_server.RegisterFile("/handle.vertical.png", HTTPServer::CONTENT_TYPE_PNG); m_server.RegisterFile("/loader.gif", HTTPServer::CONTENT_TYPE_GIF); m_server.RegisterFile("/loader-mini.gif", HTTPServer::CONTENT_TYPE_GIF); m_server.RegisterFile("/logo.png", HTTPServer::CONTENT_TYPE_PNG); m_server.RegisterFile("/logo-mini.png", HTTPServer::CONTENT_TYPE_PNG); m_server.RegisterFile("/mobile.html", HTTPServer::CONTENT_TYPE_HTML); m_server.RegisterFile("/mobile.js", HTTPServer::CONTENT_TYPE_JS); m_server.RegisterFile("/ola.html", HTTPServer::CONTENT_TYPE_HTML); m_server.RegisterFile("/ola.js", HTTPServer::CONTENT_TYPE_JS); m_server.RegisterFile("/tick.gif", HTTPServer::CONTENT_TYPE_GIF); m_server.RegisterFile("/toolbar-bg.png", HTTPServer::CONTENT_TYPE_PNG); m_server.RegisterFile("/toolbar.css", HTTPServer::CONTENT_TYPE_CSS); m_server.RegisterFile("/toolbar_sprites.png", HTTPServer::CONTENT_TYPE_PNG); m_server.RegisterFile("/vertical.gif", HTTPServer::CONTENT_TYPE_GIF); m_server.RegisterFile("/warning.png", HTTPServer::CONTENT_TYPE_PNG); m_server.RegisterFile("/", "landing.html", HTTPServer::CONTENT_TYPE_HTML); // these are the static files for the new UI m_server.RegisterFile( "/new/", "/new/index.html", HTTPServer::CONTENT_TYPE_HTML); m_server.RegisterFile( "/new/views/overview.html", HTTPServer::CONTENT_TYPE_HTML); m_server.RegisterFile( "/new/views/plugins.html", HTTPServer::CONTENT_TYPE_HTML); m_server.RegisterFile( "/new/views/plugin-info.html", HTTPServer::CONTENT_TYPE_HTML); m_server.RegisterFile( "/new/views/universe-overview.html", HTTPServer::CONTENT_TYPE_HTML); m_server.RegisterFile( "/new/views/universe-add.html", HTTPServer::CONTENT_TYPE_HTML); m_server.RegisterFile( "/new/views/universe-header.html", HTTPServer::CONTENT_TYPE_HTML); m_server.RegisterFile( "/new/views/universe-keypad.html", HTTPServer::CONTENT_TYPE_HTML); m_server.RegisterFile( "/new/views/universe-patch.html", HTTPServer::CONTENT_TYPE_HTML); m_server.RegisterFile( "/new/views/universe-settings.html", HTTPServer::CONTENT_TYPE_HTML); m_server.RegisterFile( "/new/views/universe-faders.html", HTTPServer::CONTENT_TYPE_HTML); m_server.RegisterFile( "/new/views/universes.html", HTTPServer::CONTENT_TYPE_HTML); m_server.RegisterFile( "/new/views/universe-rdm.html", HTTPServer::CONTENT_TYPE_HTML); m_server.RegisterFile( "/new/js/app.min.js", HTTPServer::CONTENT_TYPE_JS); m_server.RegisterFile( "/new/js/app.min.js.map", HTTPServer::CONTENT_TYPE_OCT); m_server.RegisterFile( "/new/libs/jquery/js/jquery.min.js", HTTPServer::CONTENT_TYPE_JS); m_server.RegisterFile( "/new/libs/angular-route/js/angular-route.min.js", HTTPServer::CONTENT_TYPE_JS); m_server.RegisterFile( "/new/libs/angular/js/angular.min.js", HTTPServer::CONTENT_TYPE_JS); m_server.RegisterFile( "/new/libs/bootstrap/js/bootstrap.min.js", HTTPServer::CONTENT_TYPE_JS); m_server.RegisterFile( "/new/libs/bootstrap/fonts/glyphicons-halflings-regular.woff", HTTPServer::CONTENT_TYPE_OCT); m_server.RegisterFile( "/new/libs/bootstrap/fonts/glyphicons-halflings-regular.svg", HTTPServer::CONTENT_TYPE_OCT); m_server.RegisterFile( "/new/libs/bootstrap/fonts/glyphicons-halflings-regular.ttf", HTTPServer::CONTENT_TYPE_OCT); m_server.RegisterFile( "/new/libs/bootstrap/fonts/glyphicons-halflings-regular.eot", HTTPServer::CONTENT_TYPE_OCT); m_server.RegisterFile( "/new/libs/bootstrap/fonts/glyphicons-halflings-regular.woff2", HTTPServer::CONTENT_TYPE_OCT); m_server.RegisterFile( "/new/css/style.min.css", HTTPServer::CONTENT_TYPE_CSS); m_server.RegisterFile( "/new/libs/bootstrap/css/bootstrap.min.css", HTTPServer::CONTENT_TYPE_CSS); m_server.RegisterFile( "/new/img/logo.png", HTTPServer::CONTENT_TYPE_PNG); m_server.RegisterFile( "/new/img/light_bulb.png", HTTPServer::CONTENT_TYPE_PNG); m_server.RegisterFile( "/new/img/light_bulb_off.png", HTTPServer::CONTENT_TYPE_PNG); m_server.RegisterFile( "/new/img/logo-mini.png", HTTPServer::CONTENT_TYPE_PNG); m_start_time_t = time(NULL); } /* * @brief Teardown */ OladHTTPServer::~OladHTTPServer() { if (m_client_socket) { m_server.SelectServer()->RemoveReadDescriptor(m_client_socket); } m_client.Stop(); if (m_client_socket) { delete m_client_socket; } } /** * @brief Setup the OLA HTTP server * @return true if this worked, false otherwise. */ bool OladHTTPServer::Init() { if (!OlaHTTPServer::Init()) { return false; } if (!m_client.Setup()) { return false; } /* Setup disconnect notifications. m_socket->SetOnClose( ola::NewSingleCallback(this, &SimpleClient::SocketClosed)); */ m_server.SelectServer()->AddReadDescriptor(m_client_socket); return true; } /** * @brief Can be called while the HTTP server is running */ void OladHTTPServer::SetPidStore(const ola::rdm::RootPidStore *pid_store) { m_rdm_module.SetPidStore(pid_store); } /** * @brief Print the server stats JSON * @param request the HTTPRequest * @param response the HTTPResponse * @returns MHD_NO or MHD_YES */ int OladHTTPServer::JsonServerStats(const HTTPRequest*, HTTPResponse *response) { char start_time_str[50]; #ifdef _WIN32 strftime(start_time_str, sizeof(start_time_str), "%c", localtime(&m_start_time_t)); #else struct tm start_time; localtime_r(&m_start_time_t, &start_time); strftime(start_time_str, sizeof(start_time_str), "%c", &start_time); #endif // _WIN32 JsonObject json; json.Add("hostname", ola::network::FQDN()); json.Add("instance_name", m_ola_server->InstanceName()); json.Add("config_dir", m_ola_server->GetPreferencesFactory()->ConfigLocation()); json.Add("ip", m_interface.ip_address.ToString()); json.Add("broadcast", m_interface.bcast_address.ToString()); json.Add("subnet", m_interface.subnet_mask.ToString()); json.Add("hw_address", m_interface.hw_address.ToString()); json.Add("version", ola::base::Version::GetVersion()); json.Add("up_since", start_time_str); json.Add("quit_enabled", m_enable_quit); response->SetNoCache(); response->SetContentType(HTTPServer::CONTENT_TYPE_PLAIN); int r = response->SendJson(json); delete response; return r; } /** * @brief Print the list of universes / plugins as a json string * @param request the HTTPRequest * @param response the HTTPResponse * @returns MHD_NO or MHD_YES */ int OladHTTPServer::JsonUniversePluginList(const HTTPRequest*, HTTPResponse *response) { m_client.FetchPluginList( NewSingleCallback(this, &OladHTTPServer::HandlePluginList, response)); return MHD_YES; } /** * @brief Print the plugin info as a JSON string * @param request the HTTPRequest * @param response the HTTPResponse * @returns MHD_NO or MHD_YES */ int OladHTTPServer::JsonPluginInfo(const HTTPRequest *request, HTTPResponse *response) { if (request->CheckParameterExists(HELP_PARAMETER)) { return ServeUsage(response, "?id=[plugin]"); } string val = request->GetParameter("id"); int plugin_id; if (!StringToInt(val, &plugin_id)) { return ServeHelpRedirect(response); } m_client.FetchPluginDescription( (ola_plugin_id) plugin_id, NewSingleCallback(this, &OladHTTPServer::HandlePartialPluginInfo, response, plugin_id)); return MHD_YES; } /** * @brief Return information about a universe * @param request the HTTPRequest * @param response the HTTPResponse * @returns MHD_NO or MHD_YES */ int OladHTTPServer::JsonUniverseInfo(OLA_UNUSED const HTTPRequest *request, HTTPResponse *response) { if (request->CheckParameterExists(HELP_PARAMETER)) { return ServeUsage(response, "?id=[universe]"); } string uni_id = request->GetParameter("id"); unsigned int universe_id; if (!StringToInt(uni_id, &universe_id)) { return ServeHelpRedirect(response); } m_client.FetchUniverseInfo( universe_id, NewSingleCallback(this, &OladHTTPServer::HandleUniverseInfo, response)); return MHD_YES; } /** * @brief Return a list of unbound ports * @param request the HTTPRequest * @param response the HTTPResponse * @returns MHD_NO or MHD_YES */ int OladHTTPServer::JsonAvailablePorts(const HTTPRequest *request, HTTPResponse *response) { if (request->CheckParameterExists(HELP_PARAMETER)) { return ServeUsage(response, "? or ?id=[universe]"); } string uni_id = request->GetParameter("id"); if (uni_id.empty()) { // get all available ports m_client.FetchCandidatePorts( NewSingleCallback(this, &OladHTTPServer::HandleCandidatePorts, response)); } else { unsigned int universe_id; if (!StringToInt(uni_id, &universe_id)) { return ServeHelpRedirect(response); } m_client.FetchCandidatePorts( universe_id, NewSingleCallback(this, &OladHTTPServer::HandleCandidatePorts, response)); } return MHD_YES; } /** * @brief Create a new universe by binding one or more ports. * @param request the HTTPRequest * @param response the HTTPResponse * @returns MHD_NO or MHD_YES */ int OladHTTPServer::CreateNewUniverse(const HTTPRequest *request, HTTPResponse *response) { if (request->CheckParameterExists(HELP_PARAMETER)) { return ServeUsage(response, "POST id=[universe], name=[name], add_ports=[a comma " "separated list of port ids]"); } string uni_id = request->GetPostParameter("id"); string name = request->GetPostParameter("name"); if (name.size() > K_UNIVERSE_NAME_LIMIT) { name = name.substr(K_UNIVERSE_NAME_LIMIT); } unsigned int universe_id; if (!StringToInt(uni_id, &universe_id)) { return ServeHelpRedirect(response); } ActionQueue *action_queue = new ActionQueue( NewSingleCallback(this, &OladHTTPServer::CreateUniverseComplete, response, universe_id, !name.empty())); // add patch actions here string add_port_ids = request->GetPostParameter("add_ports"); AddPatchActions(action_queue, add_port_ids, universe_id, ola::client::PATCH); if (!name.empty()) { action_queue->AddAction( new SetNameAction(&m_client, universe_id, name, false)); } action_queue->NextAction(); return MHD_YES; } /** * @brief Modify an existing universe. * @param request the HTTPRequest * @param response the HTTPResponse * @returns MHD_NO or MHD_YES */ int OladHTTPServer::ModifyUniverse(const HTTPRequest *request, HTTPResponse *response) { if (request->CheckParameterExists(HELP_PARAMETER)) { return ServeUsage(response, "POST id=[universe], name=[name], merge_mode=[HTP|LTP], " "add_ports=[a comma separated list of port ids], " "remove_ports=[a comma separated list of port ids]"); } string uni_id = request->GetPostParameter("id"); string name = request->GetPostParameter("name"); string merge_mode = request->GetPostParameter("merge_mode"); unsigned int universe_id; if (!StringToInt(uni_id, &universe_id)) { return ServeHelpRedirect(response); } if (name.empty()) { return m_server.ServeError(response, "No name supplied"); } if (name.size() > K_UNIVERSE_NAME_LIMIT) { name = name.substr(K_UNIVERSE_NAME_LIMIT); } ActionQueue *action_queue = new ActionQueue( NewSingleCallback(this, &OladHTTPServer::ModifyUniverseComplete, response)); action_queue->AddAction( new SetNameAction(&m_client, universe_id, name, true)); if (merge_mode == "LTP" || merge_mode == "HTP") { OlaUniverse::merge_mode mode = ( merge_mode == "LTP" ? OlaUniverse::MERGE_LTP : OlaUniverse::MERGE_HTP); action_queue->AddAction( new SetMergeModeAction(&m_client, universe_id, mode)); } string remove_port_ids = request->GetPostParameter("remove_ports"); AddPatchActions(action_queue, remove_port_ids, universe_id, client::UNPATCH); string add_port_ids = request->GetPostParameter("add_ports"); AddPatchActions(action_queue, add_port_ids, universe_id, client::PATCH); AddPriorityActions(action_queue, request); action_queue->NextAction(); return MHD_YES; } /** * @brief Set plugin state. * @param request the HTTPRequest * @param response the HTTPResponse * @returns MHD_NO or MHD_YES */ int OladHTTPServer::SetPluginState(const HTTPRequest *request, HTTPResponse *response) { if (request->CheckParameterExists(HELP_PARAMETER)) { return ServeUsage(response, "POST state=[enable|disable], " "plugin_id=[a plugin id]"); } string state_string = request->GetPostParameter("state"); bool state; if (!StringToBoolTolerant(state_string, &state)) { OLA_INFO << "Invalid state " << state_string; return ServeHelpRedirect(response); } string plugin_id_string = request->GetPostParameter("plugin_id"); unsigned int plugin_id; if (!StringToInt(plugin_id_string, &plugin_id)) { OLA_INFO << "Invalid plugin id " << plugin_id_string; return ServeHelpRedirect(response); } m_client.SetPluginState( (ola_plugin_id) plugin_id, state, NewSingleCallback(this, &OladHTTPServer::HandleBoolResponse, response)); return MHD_YES; } /** * @brief Handle the get DMX command * @param request the HTTPRequest * @param response the HTTPResponse * @returns MHD_NO or MHD_YES */ int OladHTTPServer::GetDmx(const HTTPRequest *request, HTTPResponse *response) { if (request->CheckParameterExists(HELP_PARAMETER)) { return ServeUsage(response, "?u=[universe]"); } string uni_id = request->GetParameter("u"); unsigned int universe_id; if (!StringToInt(uni_id, &universe_id)) { return ServeHelpRedirect(response); } m_client.FetchDMX( universe_id, NewSingleCallback(this, &OladHTTPServer::HandleGetDmx, response)); return MHD_YES; } /** * @brief Handle the set DMX command * @param request the HTTPRequest * @param response the HTTPResponse * @returns MHD_NO or MHD_YES */ int OladHTTPServer::HandleSetDmx(const HTTPRequest *request, HTTPResponse *response) { if (request->CheckParameterExists(HELP_PARAMETER)) { return ServeUsage(response, "POST u=[universe], d=[DMX data (a comma separated list of values)]"); } string dmx_data_str = request->GetPostParameter("d"); string uni_id = request->GetPostParameter("u"); unsigned int universe_id; if (!StringToInt(uni_id, &universe_id)) { return ServeHelpRedirect(response); } DmxBuffer buffer; buffer.SetFromString(dmx_data_str); if (!buffer.Size()) { return m_server.ServeError(response, "Invalid DMX string"); } ola::client::SendDMXArgs args( NewSingleCallback(this, &OladHTTPServer::HandleBoolResponse, response)); m_client.SendDMX(universe_id, buffer, args); return MHD_YES; } /** * @brief Cause the server to shutdown * @param request the HTTPRequest * @param response the HTTPResponse * @returns MHD_NO or MHD_YES */ int OladHTTPServer::DisplayQuit(OLA_UNUSED const HTTPRequest *request, HTTPResponse *response) { if (m_enable_quit) { response->SetContentType(HTTPServer::CONTENT_TYPE_PLAIN); response->Append("ok"); m_ola_server->StopServer(); } else { response->SetStatus(403); response->SetContentType(HTTPServer::CONTENT_TYPE_HTML); response->Append("403 Unauthorized"); } response->SetNoCache(); int r = response->Send(); delete response; return r; } /** * @brief Reload all plugins * @param request the HTTPRequest * @param response the HTTPResponse * @returns MHD_NO or MHD_YES */ int OladHTTPServer::ReloadPlugins(const HTTPRequest*, HTTPResponse *response) { m_client.ReloadPlugins( NewSingleCallback(this, &OladHTTPServer::HandleBoolResponse, response)); return MHD_YES; } /** * @brief Reload the PID Store. * @param request the HTTPRequest * @param response the HTTPResponse * @returns MHD_NO or MHD_YES */ int OladHTTPServer::ReloadPidStore(OLA_UNUSED const HTTPRequest *request, HTTPResponse *response) { m_ola_server->ReloadPidStore(); response->SetNoCache(); response->SetContentType(HTTPServer::CONTENT_TYPE_PLAIN); response->Append("ok"); int r = response->Send(); delete response; return r; } /** * @brief Handle the plugin list callback * @param response the HTTPResponse that is associated with the request. * @param result the result of the API call * @param plugins a list of plugins */ void OladHTTPServer::HandlePluginList(HTTPResponse *response, const client::Result &result, const vector &plugins) { if (!result.Success()) { m_server.ServeError(response, result.Error()); return; } JsonObject *json = new JsonObject(); // fire off the universe request now. the main server is running in a // separate thread. m_client.FetchUniverseList( NewSingleCallback(this, &OladHTTPServer::HandleUniverseList, response, json)); JsonArray *plugins_json = json->AddArray("plugins"); vector::const_iterator iter; for (iter = plugins.begin(); iter != plugins.end(); ++iter) { JsonObject *plugin = plugins_json->AppendObject(); plugin->Add("name", iter->Name()); plugin->Add("id", iter->Id()); plugin->Add("active", iter->IsActive()); plugin->Add("enabled", iter->IsEnabled()); } } /** * @brief Handle the universe list callback * @param response the HTTPResponse that is associated with the request. * @param json the JsonObject to add the data to * @param result the result of the API call * @param universes the vector of OlaUniverse */ void OladHTTPServer::HandleUniverseList(HTTPResponse *response, JsonObject *json, const client::Result &result, const vector &universes) { if (result.Success()) { JsonArray *universe_json = json->AddArray("universes"); vector::const_iterator iter; for (iter = universes.begin(); iter != universes.end(); ++iter) { JsonObject *universe = universe_json->AppendObject(); universe->Add("id", iter->Id()); universe->Add("input_ports", iter->InputPortCount()); universe->Add("name", iter->Name()); universe->Add("output_ports", iter->OutputPortCount()); universe->Add("rdm_devices", iter->RDMDeviceCount()); } } response->SetNoCache(); response->SetContentType(HTTPServer::CONTENT_TYPE_PLAIN); response->SendJson(*json); delete response; delete json; } /** * @brief Handle the plugin description response. * @param response the HTTPResponse that is associated with the request. * @param plugin_id the plugin id. * @param result the result of the API call. * @param description the plugin description. */ void OladHTTPServer::HandlePartialPluginInfo(HTTPResponse *response, int plugin_id, const client::Result &result, const string &description) { if (!result.Success()) { m_server.ServeError(response, result.Error()); return; } m_client.FetchPluginState( (ola_plugin_id) plugin_id, NewSingleCallback(this, &OladHTTPServer::HandlePluginInfo, response, description)); } /** * @brief Handle the plugin description response. * @param response the HTTPResponse that is associated with the request. * @param description the plugin description * @param result the result of the API call. * @param state the state of the plugin. */ void OladHTTPServer::HandlePluginInfo(HTTPResponse *response, string description, const client::Result &result, const ola::client::PluginState &state) { if (!result.Success()) { m_server.ServeError(response, result.Error()); return; } string escaped_description = description; // Replace \n before passing in so we get \\n out the far end ReplaceAll(&escaped_description, "\n", "\\n"); JsonObject json; json.Add("description", escaped_description); json.Add("name", state.name); json.Add("enabled", state.enabled); json.Add("active", state.active); json.Add("preferences_source", state.preferences_source); JsonArray *plugins = json.AddArray("conflicts_with"); vector::const_iterator iter = state.conflicting_plugins.begin(); for (; iter != state.conflicting_plugins.end(); ++iter) { JsonObject *plugin = plugins->AppendObject(); plugin->Add("active", iter->IsActive()); plugin->Add("id", iter->Id()); plugin->Add("name", iter->Name()); } response->SetNoCache(); response->SetContentType(HTTPServer::CONTENT_TYPE_PLAIN); response->SendJson(json); delete response; } /** * @brief Handle the universe info * @param response the HTTPResponse that is associated with the request. * @param result the result of the API call * @param universe the OlaUniverse object */ void OladHTTPServer::HandleUniverseInfo(HTTPResponse *response, const client::Result &result, const OlaUniverse &universe) { if (!result.Success()) { m_server.ServeError(response, result.Error()); return; } JsonObject *json = new JsonObject(); // fire off the device/port request now. the main server is running in a // separate thread. m_client.FetchDeviceInfo( ola::OLA_PLUGIN_ALL, NewSingleCallback(this, &OladHTTPServer::HandlePortsForUniverse, response, json, universe.Id())); json->Add("id", universe.Id()); json->Add("name", universe.Name()); json->Add("merge_mode", (universe.MergeMode() == OlaUniverse::MERGE_HTP ? "HTP" : "LTP")); } void OladHTTPServer::HandlePortsForUniverse( HTTPResponse *response, JsonObject *json, unsigned int universe_id, const client::Result &result, const vector &devices) { if (result.Success()) { vector::const_iterator iter = devices.begin(); vector::const_iterator input_iter; vector::const_iterator output_iter; JsonArray *output_ports_json = json->AddArray("output_ports"); JsonArray *input_ports_json = json->AddArray("input_ports"); for (; iter != devices.end(); ++iter) { const vector &input_ports = iter->InputPorts(); for (input_iter = input_ports.begin(); input_iter != input_ports.end(); ++input_iter) { if (input_iter->IsActive() && input_iter->Universe() == universe_id) { JsonObject *obj = input_ports_json->AppendObject(); PortToJson(obj, *iter, *input_iter, false); } } const vector &output_ports = iter->OutputPorts(); for (output_iter = output_ports.begin(); output_iter != output_ports.end(); ++output_iter) { if (output_iter->IsActive() && output_iter->Universe() == universe_id) { JsonObject *obj = output_ports_json->AppendObject(); PortToJson(obj, *iter, *output_iter, true); } } } } response->SetNoCache(); response->SetContentType(HTTPServer::CONTENT_TYPE_PLAIN); response->SendJson(*json); delete json; delete response; } /** * @brief Handle the list of candidate ports * @param response the HTTPResponse that is associated with the request. * @param result the result of the API call * @param devices the possbile devices & ports */ void OladHTTPServer::HandleCandidatePorts( HTTPResponse *response, const client::Result &result, const vector &devices) { if (!result.Success()) { m_server.ServeError(response, result.Error()); return; } vector::const_iterator iter = devices.begin(); vector::const_iterator input_iter; vector::const_iterator output_iter; JsonArray json; for (; iter != devices.end(); ++iter) { const vector &input_ports = iter->InputPorts(); for (input_iter = input_ports.begin(); input_iter != input_ports.end(); ++input_iter) { JsonObject *obj = json.AppendObject(); PortToJson(obj, *iter, *input_iter, false); } const vector &output_ports = iter->OutputPorts(); for (output_iter = output_ports.begin(); output_iter != output_ports.end(); ++output_iter) { JsonObject *obj = json.AppendObject(); PortToJson(obj, *iter, *output_iter, true); } } response->SetNoCache(); response->SetContentType(HTTPServer::CONTENT_TYPE_PLAIN); response->SendJson(json); delete response; } /* * @brief Schedule a callback to send the new universe response to the client */ void OladHTTPServer::CreateUniverseComplete(HTTPResponse *response, unsigned int universe_id, bool included_name, class ActionQueue *action_queue) { // this is a trick to unwind the stack and return control to a method outside // the Action m_server.SelectServer()->RegisterSingleTimeout( 0, NewSingleCallback(this, &OladHTTPServer::SendCreateUniverseResponse, response, universe_id, included_name, action_queue)); } /* * @brief Send the response to a new universe request */ void OladHTTPServer::SendCreateUniverseResponse( HTTPResponse *response, unsigned int universe_id, bool included_name, class ActionQueue *action_queue) { unsigned int action_count = action_queue->ActionCount(); if (included_name) { action_count--; } bool failed = true; // it only takes one port patch to pass for (unsigned int i = 0; i < action_count; i++) { failed &= action_queue->GetAction(i)->Failed(); } JsonObject json; json.Add("ok", !failed); json.Add("universe", universe_id); json.Add("message", (failed ? "Failed to patch any ports" : "")); response->SetNoCache(); response->SetContentType(HTTPServer::CONTENT_TYPE_PLAIN); response->SendJson(json); delete action_queue; delete response; } /* * @brief Schedule a callback to send the modify universe response to the client */ void OladHTTPServer::ModifyUniverseComplete(HTTPResponse *response, ActionQueue *action_queue) { // this is a trick to unwind the stack and return control to a method outside // the Action m_server.SelectServer()->RegisterSingleTimeout( 0, NewSingleCallback(this, &OladHTTPServer::SendModifyUniverseResponse, response, action_queue)); } /* * @brief Send the response to a modify universe request. */ void OladHTTPServer::SendModifyUniverseResponse(HTTPResponse *response, ActionQueue *action_queue) { if (!action_queue->WasSuccessful()) { delete action_queue; m_server.ServeError(response, "Update failed"); } else { response->SetContentType(HTTPServer::CONTENT_TYPE_PLAIN); response->Append("ok"); response->Send(); delete action_queue; delete response; } } /** * @brief Serve usage information. * @param response the reponse to use. * @param details the usage information */ int OladHTTPServer::ServeUsage(HTTPResponse *response, const string &details) { response->SetContentType(HTTPServer::CONTENT_TYPE_HTML); response->Append("Usage:"); if (!details.empty()) { response->Append("

"); response->Append(details); response->Append("

"); } int r = response->Send(); delete response; return r; } /** * @brief Callback for m_client.FetchDmx called by GetDmx * @param response the HTTPResponse * @param result the result of the API call * @param buffer the DmxBuffer */ void OladHTTPServer::HandleGetDmx(HTTPResponse *response, const client::Result &result, const client::DMXMetadata &, const DmxBuffer &buffer) { // rather than adding 512 JsonValue we cheat and use raw here ostringstream str; str << "[" << buffer.ToString() << "]"; JsonObject json; json.AddRaw("dmx", str.str()); json.Add("error", result.Error()); response->SetNoCache(); response->SetContentType(HTTPServer::CONTENT_TYPE_PLAIN); response->SendJson(json); delete response; } /** * @brief Handle the set DMX response. * @param response the HTTPResponse that is associated with the request. * @param result the result of the API call */ void OladHTTPServer::HandleBoolResponse(HTTPResponse *response, const client::Result &result) { if (!result.Success()) { m_server.ServeError(response, result.Error()); return; } response->SetContentType(HTTPServer::CONTENT_TYPE_PLAIN); response->Append("ok"); response->Send(); delete response; } /** * @brief Add the json representation of this port to the ostringstream */ void OladHTTPServer::PortToJson(JsonObject *json, const OlaDevice &device, const OlaPort &port, bool is_output) { ostringstream str; str << device.Alias() << "-" << (is_output ? "O" : "I") << "-" << port.Id(); json->Add("device", device.Name()); json->Add("description", port.Description()); json->Add("id", str.str()); json->Add("is_output", is_output); JsonObject *priority_json = json->AddObject("priority"); if (port.PriorityCapability() != CAPABILITY_NONE) { // This can be used as the default value for the priority input and because // inherit ports can return a 0 priority we shall set it to the default // here uint8_t priority = port.Priority(); if (priority == 0) { // We check here because 0 is an invalid priority outside of Olad priority = dmx::SOURCE_PRIORITY_DEFAULT; } priority_json->Add("value", static_cast(priority)); priority_json->Add( "current_mode", (port.PriorityMode() == PRIORITY_MODE_INHERIT ? "inherit" : "static")); priority_json->Add("priority_capability", (port.PriorityCapability() == CAPABILITY_STATIC ? "static" : "full")); } } /** * @brief Add the Patch Actions to the ActionQueue. * @param action_queue the ActionQueue to add the actions to. * @param port_id_string a string to ports to add/remove. * @param universe the universe id to add these ports if * @param port_action either PATCH or UNPATCH. */ void OladHTTPServer::AddPatchActions(ActionQueue *action_queue, const string port_id_string, unsigned int universe, client::PatchAction port_action) { vector ports; vector::const_iterator iter; DecodePortIds(port_id_string, &ports); for (iter = ports.begin(); iter != ports.end(); ++iter) { action_queue->AddAction(new PatchPortAction( &m_client, iter->device_alias, iter->port, iter->direction, universe, port_action)); } } /** * @brief Add the Priority Actions to the ActionQueue. * @param action_queue the ActionQueue to add the actions to. * @param request the HTTPRequest to read the url params from. */ void OladHTTPServer::AddPriorityActions(ActionQueue *action_queue, const HTTPRequest *request) { string port_ids = request->GetPostParameter("modify_ports"); vector ports; vector::const_iterator iter; DecodePortIds(port_ids, &ports); for (iter = ports.begin(); iter != ports.end(); ++iter) { string priority_mode_id = iter->string_id + K_PRIORITY_MODE_SUFFIX; string priority_id = iter->string_id + K_PRIORITY_VALUE_SUFFIX; string mode = request->GetPostParameter(priority_mode_id); if (mode == "inherit") { action_queue->AddAction(new PortPriorityInheritAction( &m_client, iter->device_alias, iter->port, iter->direction)); } else if (mode == "static" || mode == "") { // an empty mode param means this is a static port string value = request->GetPostParameter(priority_id); uint8_t priority_value; if (StringToInt(value, &priority_value)) { action_queue->AddAction(new PortPriorityStaticAction( &m_client, iter->device_alias, iter->port, iter->direction, priority_value)); } } } } /** * @brief Decode port ids in a string. * * This converts a string like "4-I-1,2-O-3" into a vector of port identifiers. * @param port_ids the port ids in a , separated string * @param ports a vector of port_identifiers that will be filled. */ void OladHTTPServer::DecodePortIds(const string &port_ids, vector *ports) { vector port_strings; StringSplit(port_ids, &port_strings, ","); vector::const_iterator iter; vector tokens; for (iter = port_strings.begin(); iter != port_strings.end(); ++iter) { if (iter->empty()) { continue; } tokens.clear(); StringSplit(*iter, &tokens, "-"); if (tokens.size() != 3 || (tokens[1] != "I" && tokens[1] != "O")) { OLA_INFO << "Not a valid port id " << *iter; continue; } unsigned int device_alias, port; if (!StringToInt(tokens[0], &device_alias) || !StringToInt(tokens[2], &port)) { OLA_INFO << "Not a valid port id " << *iter; continue; } client::PortDirection direction = ( tokens[1] == "I" ? client::INPUT_PORT : client::OUTPUT_PORT); port_identifier port_id = {device_alias, port, direction, *iter}; ports->push_back(port_id); } } /** * @brief Register a handler */ inline void OladHTTPServer::RegisterHandler( const string &path, int (OladHTTPServer::*method)(const HTTPRequest*, HTTPResponse*)) { m_server.RegisterHandler( path, NewCallback( this, method)); } } // namespace ola ola-0.10.5.nojsmin/olad/OlaServerServiceImpl.h0000644000175000017500000002601413023355232020616 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OlaServerServiceImpl.h * Implementation of the OlaService interface * Copyright (C) 2005 Simon Newton */ #include #include #include #include "common/protocol/Ola.pb.h" #include "common/protocol/OlaService.pb.h" #include "ola/Callback.h" #include "ola/rdm/RDMCommand.h" #include "ola/rdm/RDMControllerInterface.h" #include "ola/rdm/UID.h" #include "ola/rdm/UIDSet.h" #ifndef OLAD_OLASERVERSERVICEIMPL_H_ #define OLAD_OLASERVERSERVICEIMPL_H_ namespace ola { class Universe; /** * @brief The OLA Server RPC methods. * * After the RPC system un-marshalls the data, it invokes the methods of this * class. This therefore contains all the methods a client can invoke on the * server. * * There is no client specific member data, so a single OlaServerServiceImpl * is created. Any OLA client data is passed via the user data in the * ola::rpc::RpcSession object, accessible via the ola::rpc::RpcController. */ class OlaServerServiceImpl : public ola::proto::OlaServerService { public: /** * @brief A Callback used to reload all the plugins. */ typedef Callback0 ReloadPluginsCallback; /** * @brief Create a new OlaServerServiceImpl. */ OlaServerServiceImpl(class UniverseStore *universe_store, class DeviceManager *device_manager, class PluginManager *plugin_manager, class PortManager *port_manager, class ClientBroker *broker, const class TimeStamp *wake_up_time, ReloadPluginsCallback *reload_plugins_callback); ~OlaServerServiceImpl() {} /** * @brief Returns the current DMX values for a particular universe. */ void GetDmx(ola::rpc::RpcController* controller, const ola::proto::UniverseRequest* request, ola::proto::DmxData* response, ola::rpc::RpcService::CompletionCallback* done); /** * @brief Register a client to receive DMX data. */ void RegisterForDmx(ola::rpc::RpcController* controller, const ola::proto::RegisterDmxRequest* request, ola::proto::Ack* response, ola::rpc::RpcService::CompletionCallback* done); /** * @brief Update the DMX values for a single universe. */ void UpdateDmxData(ola::rpc::RpcController* controller, const ola::proto::DmxData* request, ola::proto::Ack* response, ola::rpc::RpcService::CompletionCallback* done); /** * @brief Handle a streaming DMX update, no response is sent. */ void StreamDmxData(ola::rpc::RpcController* controller, const ::ola::proto::DmxData* request, ::ola::proto::STREAMING_NO_RESPONSE* response, ola::rpc::RpcService::CompletionCallback* done); /** * @brief Sets the name of a universe. */ void SetUniverseName(ola::rpc::RpcController* controller, const ola::proto::UniverseNameRequest* request, ola::proto::Ack* response, ola::rpc::RpcService::CompletionCallback* done); /** * @brief Set the merge mode for a universe. */ void SetMergeMode(ola::rpc::RpcController* controller, const ola::proto::MergeModeRequest* request, ola::proto::Ack* response, ola::rpc::RpcService::CompletionCallback* done); /** * @brief Patch a port to a universe. */ void PatchPort(ola::rpc::RpcController* controller, const ola::proto::PatchPortRequest* request, ola::proto::Ack* response, ola::rpc::RpcService::CompletionCallback* done); /** * @brief Set the priority of one or more ports. */ void SetPortPriority(ola::rpc::RpcController* controller, const ola::proto::PortPriorityRequest* request, ola::proto::Ack* response, ola::rpc::RpcService::CompletionCallback* done); /** * @brief Returns information on the active universes. */ void GetUniverseInfo(ola::rpc::RpcController* controller, const ola::proto::OptionalUniverseRequest* request, ola::proto::UniverseInfoReply* response, ola::rpc::RpcService::CompletionCallback* done); /** * @brief Return info on available plugins. */ void GetPlugins(ola::rpc::RpcController* controller, const ola::proto::PluginListRequest* request, ola::proto::PluginListReply* response, ola::rpc::RpcService::CompletionCallback* done); /** * @brief Reload the plugins. */ void ReloadPlugins(ola::rpc::RpcController* controller, const ola::proto::PluginReloadRequest* request, ola::proto::Ack* response, ola::rpc::RpcService::CompletionCallback* done); /** * @brief Return the description for a plugin. */ void GetPluginDescription( ola::rpc::RpcController* controller, const ola::proto::PluginDescriptionRequest* request, ola::proto::PluginDescriptionReply* response, ola::rpc::RpcService::CompletionCallback* done); /** * @brief Return the state for a plugin. */ void GetPluginState( ola::rpc::RpcController* controller, const ola::proto::PluginStateRequest* request, ola::proto::PluginStateReply* response, ola::rpc::RpcService::CompletionCallback* done); /** * @brief Change the state of plugins. */ void SetPluginState( ola::rpc::RpcController* controller, const ola::proto::PluginStateChangeRequest* request, ola::proto::Ack* response, ola::rpc::RpcService::CompletionCallback* done); /** * @brief Return information on available devices. */ void GetDeviceInfo(ola::rpc::RpcController* controller, const ola::proto::DeviceInfoRequest* request, ola::proto::DeviceInfoReply* response, ola::rpc::RpcService::CompletionCallback* done); /** * @brief Handle a GetCandidatePorts request. */ void GetCandidatePorts(ola::rpc::RpcController* controller, const ola::proto::OptionalUniverseRequest* request, ola::proto::DeviceInfoReply* response, ola::rpc::RpcService::CompletionCallback* done); /** * @brief Handle a ConfigureDevice request. */ void ConfigureDevice(ola::rpc::RpcController* controller, const ola::proto::DeviceConfigRequest* request, ola::proto::DeviceConfigReply* response, ola::rpc::RpcService::CompletionCallback* done); /** * @brief Fetch the UID list for a universe. */ void GetUIDs(ola::rpc::RpcController* controller, const ola::proto::UniverseRequest* request, ola::proto::UIDListReply* response, ola::rpc::RpcService::CompletionCallback* done); /** * @brief Force RDM discovery for a universe. */ void ForceDiscovery(ola::rpc::RpcController* controller, const ola::proto::DiscoveryRequest* request, ola::proto::UIDListReply* response, ola::rpc::RpcService::CompletionCallback* done); /** * @brief Handle an RDM Command. */ void RDMCommand(ola::rpc::RpcController* controller, const ::ola::proto::RDMRequest* request, ola::proto::RDMResponse* response, ola::rpc::RpcService::CompletionCallback* done); /** * @brief Handle an RDM Discovery Command. * * This is used by the RDM responder tests. Normally clients don't need to * send raw discovery packets and can just use the GetUIDs method. */ void RDMDiscoveryCommand(ola::rpc::RpcController* controller, const ::ola::proto::RDMDiscoveryRequest* request, ola::proto::RDMResponse* response, ola::rpc::RpcService::CompletionCallback* done); /** * @brief Set this client's source UID. */ void SetSourceUID(ola::rpc::RpcController* controller, const ::ola::proto::UID* request, ola::proto::Ack* response, ola::rpc::RpcService::CompletionCallback* done); /** * @brief Send Timecode */ void SendTimeCode(ola::rpc::RpcController* controller, const ::ola::proto::TimeCode* request, ::ola::proto::Ack* response, ola::rpc::RpcService::CompletionCallback* done); private: void HandleRDMResponse(ola::proto::RDMResponse* response, ola::rpc::RpcService::CompletionCallback* done, bool include_raw_packets, ola::rdm::RDMReply *reply); void RDMDiscoveryComplete(unsigned int universe, ola::rpc::RpcService::CompletionCallback* done, ola::proto::UIDListReply *response, const ola::rdm::UIDSet &uids); void MissingUniverseError(ola::rpc::RpcController* controller); void MissingPluginError(ola::rpc::RpcController* controller); void MissingDeviceError(ola::rpc::RpcController* controller); void MissingPortError(ola::rpc::RpcController* controller); void AddPlugin(class AbstractPlugin *plugin, ola::proto::PluginInfo *plugin_info) const; void AddDevice(class AbstractDevice *device, unsigned int alias, ola::proto::DeviceInfoReply* response) const; void AddUniverse(const Universe *universe, ola::proto::UniverseInfoReply *universe_info_reply) const; template void PopulatePort(const PortClass &port, ola::proto::PortInfo *port_info) const; void SetProtoUID(const ola::rdm::UID &uid, ola::proto::UID *pb_uid); class Client* GetClient(ola::rpc::RpcController *controller); UniverseStore *m_universe_store; DeviceManager *m_device_manager; class PluginManager *m_plugin_manager; class PortManager *m_port_manager; class ClientBroker *m_broker; const class TimeStamp *m_wake_up_time; std::auto_ptr m_reload_plugins_callback; }; } // namespace ola #endif // OLAD_OLASERVERSERVICEIMPL_H_ ola-0.10.5.nojsmin/olad/RDMHTTPModule.h0000644000175000017500000007417713023355232017056 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RDMHTTPModule.h * This module acts as the HTTP -> olad gateway for RDM commands. * Copyright (C) 2010 Simon Newton */ #ifndef OLAD_RDMHTTPMODULE_H_ #define OLAD_RDMHTTPMODULE_H_ #include #include #include #include #include #include "ola/base/Macro.h" #include "ola/client/ClientRDMAPIShim.h" #include "ola/client/OlaClient.h" #include "ola/http/HTTPServer.h" #include "ola/rdm/PidStore.h" #include "ola/rdm/RDMAPI.h" #include "ola/rdm/UID.h" #include "ola/thread/Mutex.h" #include "ola/web/JsonSections.h" namespace ola { /* * The module that deals with RDM requests. */ class RDMHTTPModule { public: RDMHTTPModule(ola::http::HTTPServer *http_server, ola::client::OlaClient *client); ~RDMHTTPModule(); void SetPidStore(const ola::rdm::RootPidStore *pid_store); int RunRDMDiscovery(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response); int JsonUIDs(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response); // these are used by the RDM Patcher int JsonUIDInfo(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response); int JsonUIDIdentifyDevice(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response); int JsonUIDPersonalities(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response); // these are used by the RDM Attributes Panel int JsonSupportedPIDs(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response); int JsonSupportedSections(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response); int JsonSectionInfo(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response); int JsonSaveSectionInfo(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response); void PruneUniverseList(const std::vector &universes); private: typedef struct { std::string manufacturer; std::string device; bool active; } resolved_uid; typedef enum { RESOLVE_MANUFACTURER, RESOLVE_DEVICE, } uid_resolve_action; typedef struct { std::map resolved_uids; std::queue > pending_uids; bool uid_resolution_running; bool active; } uid_resolution_state; ola::http::HTTPServer *m_server; ola::client::OlaClient *m_client; ola::client::ClientRDMAPIShim m_shim; ola::rdm::RDMAPI m_rdm_api; std::map m_universe_uids; ola::thread::Mutex m_pid_store_mu; const ola::rdm::RootPidStore *m_pid_store; // GUARDED_BY(m_pid_store_mu); typedef struct { std::string id; std::string name; std::string hint; } section_info; struct lt_section_info { bool operator()(const section_info &left, const section_info &right) { return left.name < right.name; } }; typedef struct { unsigned int universe_id; const ola::rdm::UID uid; std::string hint; std::string device_model; std::string software_version; } device_info; typedef struct { unsigned int universe_id; const ola::rdm::UID *uid; bool include_descriptions; bool return_as_section; unsigned int active; unsigned int next; unsigned int total; std::vector > personalities; } personality_info; // UID resolution methods void HandleUIDList(ola::http::HTTPResponse *response, unsigned int universe_id, const client::Result &result, const ola::rdm::UIDSet &uids); void ResolveNextUID(unsigned int universe_id); void UpdateUIDManufacturerLabel(unsigned int universe, ola::rdm::UID uid, const ola::rdm::ResponseStatus &status, const std::string &device_label); void UpdateUIDDeviceLabel(unsigned int universe, ola::rdm::UID uid, const ola::rdm::ResponseStatus &status, const std::string &device_label); uid_resolution_state *GetUniverseUids(unsigned int universe); uid_resolution_state *GetUniverseUidsOrCreate(unsigned int universe); // uid info handler void UIDInfoHandler(ola::http::HTTPResponse *response, const ola::rdm::ResponseStatus &status, const ola::rdm::DeviceDescriptor &device); // uid identify handler void UIDIdentifyDeviceHandler(ola::http::HTTPResponse *response, const ola::rdm::ResponseStatus &status, bool value); // personality handler void SendPersonalityResponse(ola::http::HTTPResponse *response, personality_info *info); // supported params / sections void SupportedParamsHandler(ola::http::HTTPResponse *response, const ola::rdm::ResponseStatus &status, const std::vector &pids); void SupportedSectionsHandler(ola::http::HTTPResponse *response, unsigned int universe, ola::rdm::UID uid, const ola::rdm::ResponseStatus &status, const std::vector &pids); void SupportedSectionsDeviceInfoHandler( ola::http::HTTPResponse *response, const std::vector pids, const ola::rdm::ResponseStatus &status, const ola::rdm::DeviceDescriptor &device); // section methods std::string GetCommStatus(ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); void CommStatusHandler(ola::http::HTTPResponse *response, const ola::rdm::ResponseStatus &status, uint16_t short_messages, uint16_t length_mismatch, uint16_t checksum_fail); std::string ClearCommsCounters(ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); std::string GetProxiedDevices(ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); void ProxiedDevicesHandler(ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::ResponseStatus &status, const std::vector &uids); std::string GetDeviceInfo(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); void GetSoftwareVersionHandler(ola::http::HTTPResponse *response, device_info dev_info, const ola::rdm::ResponseStatus &status, const std::string &software_version); void GetDeviceModelHandler(ola::http::HTTPResponse *response, device_info dev_info, const ola::rdm::ResponseStatus &status, const std::string &device_model); void GetDeviceInfoHandler(ola::http::HTTPResponse *response, device_info dev_info, const ola::rdm::ResponseStatus &status, const ola::rdm::DeviceDescriptor &device); std::string GetProductIds(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); void GetProductIdsHandler(ola::http::HTTPResponse *response, const ola::rdm::ResponseStatus &status, const std::vector &ids); std::string GetManufacturerLabel(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); void GetManufacturerLabelHandler(ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID uid, const ola::rdm::ResponseStatus &status, const std::string &label); std::string GetDeviceLabel(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); void GetDeviceLabelHandler(ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID uid, const ola::rdm::ResponseStatus &status, const std::string &label); std::string SetDeviceLabel(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); std::string GetFactoryDefaults(ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); void FactoryDefaultsHandler(ola::http::HTTPResponse *response, const ola::rdm::ResponseStatus &status, bool defaults); std::string SetFactoryDefault(ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); std::string GetLanguage(ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); void GetSupportedLanguagesHandler( ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID uid, const ola::rdm::ResponseStatus &status, const std::vector &languages); void GetLanguageHandler(ola::http::HTTPResponse *response, std::vector languages, const ola::rdm::ResponseStatus &status, const std::string &language); std::string SetLanguage(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); std::string GetBootSoftware(ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); void GetBootSoftwareLabelHandler(ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID uid, const ola::rdm::ResponseStatus &status, const std::string &label); void GetBootSoftwareVersionHandler( ola::http::HTTPResponse *response, std::string label, const ola::rdm::ResponseStatus &status, uint32_t version); std::string GetPersonalities(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid, bool return_as_section, bool include_description = false); void GetPersonalityHandler( ola::http::HTTPResponse *response, personality_info *info, const ola::rdm::ResponseStatus &status, uint8_t current, uint8_t total); void GetNextPersonalityDescription(ola::http::HTTPResponse *response, personality_info *info); void GetPersonalityLabelHandler( ola::http::HTTPResponse *response, personality_info *info, const ola::rdm::ResponseStatus &status, uint8_t personality, uint16_t slot_count, const std::string &label); void SendSectionPersonalityResponse(ola::http::HTTPResponse *response, personality_info *info); std::string SetPersonality(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); std::string GetStartAddress(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); void GetStartAddressHandler(ola::http::HTTPResponse *response, const ola::rdm::ResponseStatus &status, uint16_t address); std::string SetStartAddress(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); std::string GetSensor(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); void SensorDefinitionHandler(ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID uid, uint8_t sensor_id, const ola::rdm::ResponseStatus &status, const ola::rdm::SensorDescriptor &definition); void SensorValueHandler(ola::http::HTTPResponse *response, ola::rdm::SensorDescriptor *definition, const ola::rdm::ResponseStatus &status, const ola::rdm::SensorValueDescriptor &value); std::string RecordSensor(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); std::string GetDeviceHours(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); std::string SetDeviceHours(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); std::string GetLampHours(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); std::string SetLampHours(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); std::string GetLampStrikes(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); std::string SetLampStrikes(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); std::string GetLampState(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); void LampStateHandler(ola::http::HTTPResponse *response, const ola::rdm::ResponseStatus &status, uint8_t state); std::string SetLampState(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); std::string GetLampMode(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); void LampModeHandler(ola::http::HTTPResponse *response, const ola::rdm::ResponseStatus &status, uint8_t mode); std::string SetLampMode(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); std::string GetPowerCycles(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); std::string SetPowerCycles(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); std::string GetDisplayInvert(ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); void DisplayInvertHandler(ola::http::HTTPResponse *response, const ola::rdm::ResponseStatus &status, uint8_t value); std::string SetDisplayInvert(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); std::string GetDisplayLevel(ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); void DisplayLevelHandler(ola::http::HTTPResponse *response, const ola::rdm::ResponseStatus &status, uint8_t value); std::string SetDisplayLevel(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); std::string GetPanInvert(ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); std::string SetPanInvert(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); std::string GetTiltInvert(ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); std::string SetTiltInvert(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); std::string GetPanTiltSwap(ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); std::string SetPanTiltSwap(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); std::string GetClock(ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); void ClockHandler(ola::http::HTTPResponse *response, const ola::rdm::ResponseStatus &status, const ola::rdm::ClockValue &clock); std::string SyncClock(ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); std::string GetIdentifyDevice(ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); std::string SetIdentifyDevice(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); std::string GetPowerState(ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); void PowerStateHandler(ola::http::HTTPResponse *response, const ola::rdm::ResponseStatus &status, uint8_t value); std::string SetPowerState(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); std::string GetResetDevice(ola::http::HTTPResponse *response); std::string SetResetDevice(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); std::string GetDnsHostname(ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); void GetDnsHostnameHandler(ola::http::HTTPResponse *response, const ola::rdm::ResponseStatus &status, const std::string &label); std::string SetDnsHostname(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); std::string GetDnsDomainName(ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); void GetDnsDomainNameHandler(ola::http::HTTPResponse *response, const ola::rdm::ResponseStatus &status, const std::string &label); std::string SetDnsDomainName(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response, unsigned int universe_id, const ola::rdm::UID &uid); // util methods bool CheckForInvalidId(const ola::http::HTTPRequest *request, unsigned int *universe_id); bool CheckForInvalidUid(const ola::http::HTTPRequest *request, ola::rdm::UID **uid); uint16_t SubDeviceOrRoot(const ola::http::HTTPRequest *request); void SetHandler(ola::http::HTTPResponse *response, const ola::rdm::ResponseStatus &status); void GenericUIntHandler(ola::http::HTTPResponse *response, std::string description, const ola::rdm::ResponseStatus &status, uint32_t value); void GenericUInt8BoolHandler(ola::http::HTTPResponse *response, std::string description, const ola::rdm::ResponseStatus &status, uint8_t value); void GenericBoolHandler(ola::http::HTTPResponse *response, std::string description, const ola::rdm::ResponseStatus &status, bool value); bool CheckForRDMError(ola::http::HTTPResponse *response, const ola::rdm::ResponseStatus &status); int RespondWithError(ola::http::HTTPResponse *response, const std::string &error); void RespondWithSection(ola::http::HTTPResponse *response, const ola::web::JsonSection §ion); bool CheckForRDMSuccess(const ola::rdm::ResponseStatus &status); bool CheckForRDMSuccessWithError(const ola::rdm::ResponseStatus &status, std::string *error); void HandleBoolResponse(ola::http::HTTPResponse *response, const std::string &error); void AddSection(std::vector *sections, const std::string §ion_id, const std::string §ion_name, const std::string &hint = ""); static const uint32_t INVALID_PERSONALITY = 0xffff; static const char BACKEND_DISCONNECTED_ERROR[]; static const char HINT_KEY[]; static const char ID_KEY[]; static const char SECTION_KEY[]; static const char UID_KEY[]; static const char ADDRESS_FIELD[]; static const char DISPLAY_INVERT_FIELD[]; static const char GENERIC_BOOL_FIELD[]; static const char GENERIC_STRING_FIELD[]; static const char GENERIC_UINT_FIELD[]; static const char IDENTIFY_DEVICE_FIELD[]; static const char LABEL_FIELD[]; static const char LANGUAGE_FIELD[]; static const char RECORD_SENSOR_FIELD[]; static const char SUB_DEVICE_FIELD[]; static const char BOOT_SOFTWARE_SECTION[]; static const char CLOCK_SECTION[]; static const char COMMS_STATUS_SECTION[]; static const char DEVICE_HOURS_SECTION[]; static const char DEVICE_INFO_SECTION[]; static const char DEVICE_LABEL_SECTION[]; static const char DISPLAY_INVERT_SECTION[]; static const char DISPLAY_LEVEL_SECTION[]; static const char DMX_ADDRESS_SECTION[]; static const char DNS_DOMAIN_NAME_SECTION[]; static const char DNS_HOSTNAME_SECTION[]; static const char FACTORY_DEFAULTS_SECTION[]; static const char IDENTIFY_DEVICE_SECTION[]; static const char LAMP_HOURS_SECTION[]; static const char LAMP_MODE_SECTION[]; static const char LAMP_STATE_SECTION[]; static const char LAMP_STRIKES_SECTION[]; static const char LANGUAGE_SECTION[]; static const char MANUFACTURER_LABEL_SECTION[]; static const char PAN_INVERT_SECTION[]; static const char PAN_TILT_SWAP_SECTION[]; static const char PERSONALITY_SECTION[]; static const char POWER_CYCLES_SECTION[]; static const char POWER_STATE_SECTION[]; static const char PRODUCT_DETAIL_SECTION[]; static const char PROXIED_DEVICES_SECTION[]; static const char RESET_DEVICE_SECTION[]; static const char SENSOR_SECTION[]; static const char TILT_INVERT_SECTION[]; static const char BOOT_SOFTWARE_SECTION_NAME[]; static const char CLOCK_SECTION_NAME[]; static const char COMMS_STATUS_SECTION_NAME[]; static const char DEVICE_HOURS_SECTION_NAME[]; static const char DEVICE_INFO_SECTION_NAME[]; static const char DEVICE_LABEL_SECTION_NAME[]; static const char DISPLAY_INVERT_SECTION_NAME[]; static const char DISPLAY_LEVEL_SECTION_NAME[]; static const char DMX_ADDRESS_SECTION_NAME[]; static const char DNS_DOMAIN_NAME_SECTION_NAME[]; static const char DNS_HOSTNAME_SECTION_NAME[]; static const char FACTORY_DEFAULTS_SECTION_NAME[]; static const char IDENTIFY_DEVICE_SECTION_NAME[]; static const char LAMP_HOURS_SECTION_NAME[]; static const char LAMP_MODE_SECTION_NAME[]; static const char LAMP_STATE_SECTION_NAME[]; static const char LAMP_STRIKES_SECTION_NAME[]; static const char LANGUAGE_SECTION_NAME[]; static const char MANUFACTURER_LABEL_SECTION_NAME[]; static const char PAN_INVERT_SECTION_NAME[]; static const char PAN_TILT_SWAP_SECTION_NAME[]; static const char PERSONALITY_SECTION_NAME[]; static const char POWER_CYCLES_SECTION_NAME[]; static const char POWER_STATE_SECTION_NAME[]; static const char PRODUCT_DETAIL_SECTION_NAME[]; static const char PROXIED_DEVICES_SECTION_NAME[]; static const char RESET_DEVICE_SECTION_NAME[]; static const char TILT_INVERT_SECTION_NAME[]; DISALLOW_COPY_AND_ASSIGN(RDMHTTPModule); }; } // namespace ola #endif // OLAD_RDMHTTPMODULE_H_ ola-0.10.5.nojsmin/olad/OlaServerServiceImplTest.cpp0000644000175000017500000004121513023355232022011 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OlaServerServiceImplTest.cpp * Test fixture for the OlaServerServiceImpl class * Copyright (C) 2005 Simon Newton * * How this file is organized: * We test each rpc method in OlaServerServiceImpl, for each method, we have a * series of Check objects which validate the rpc response. */ #include #include #include "common/rpc/RpcController.h" #include "common/rpc/RpcSession.h" #include "ola/Callback.h" #include "ola/Clock.h" #include "ola/Constants.h" #include "ola/DmxBuffer.h" #include "ola/ExportMap.h" #include "ola/Logging.h" #include "ola/rdm/UID.h" #include "ola/testing/TestUtils.h" #include "olad/OlaServerServiceImpl.h" #include "olad/PluginLoader.h" #include "olad/Universe.h" #include "olad/plugin_api/Client.h" #include "olad/plugin_api/DeviceManager.h" #include "olad/plugin_api/UniverseStore.h" using ola::Client; using ola::NewSingleCallback; using ola::SingleUseCallback0; using ola::DmxBuffer; using ola::OlaServerServiceImpl; using ola::Universe; using ola::UniverseStore; using ola::rpc::RpcController; using ola::rpc::RpcSession; using std::string; class OlaServerServiceImplTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(OlaServerServiceImplTest); CPPUNIT_TEST(testGetDmx); CPPUNIT_TEST(testRegisterForDmx); CPPUNIT_TEST(testUpdateDmxData); CPPUNIT_TEST(testSetUniverseName); CPPUNIT_TEST(testSetMergeMode); CPPUNIT_TEST_SUITE_END(); public: OlaServerServiceImplTest(): m_uid(ola::OPEN_LIGHTING_ESTA_CODE, 0) { } void setUp() { ola::InitLogging(ola::OLA_LOG_INFO, ola::OLA_LOG_STDERR); } void testGetDmx(); void testRegisterForDmx(); void testUpdateDmxData(); void testSetUniverseName(); void testSetMergeMode(); private: ola::rdm::UID m_uid; ola::Clock m_clock; void CallGetDmx(OlaServerServiceImpl *service, int universe_id, class GetDmxCheck *check); void CallRegisterForDmx(OlaServerServiceImpl *service, int universe_id, ola::proto::RegisterAction action, class RegisterForDmxCheck *check); void CallUpdateDmxData(OlaServerServiceImpl *service, Client *client, int universe_id, const DmxBuffer &data, class UpdateDmxDataCheck *check); void CallSetUniverseName(OlaServerServiceImpl *service, int universe_id, const string &name, class SetUniverseNameCheck *check); void CallSetMergeMode(OlaServerServiceImpl *service, int universe_id, ola::proto::MergeMode merge_mode, class SetMergeModeCheck *check); }; CPPUNIT_TEST_SUITE_REGISTRATION(OlaServerServiceImplTest); static const uint8_t SAMPLE_DMX_DATA[] = {1, 2, 3, 4, 5}; /* * The GetDmx Checks */ class GetDmxCheck { public: virtual ~GetDmxCheck() {} virtual void Check(RpcController *controller, ola::proto::DmxData *reply) = 0; }; /* * Assert that the data is all 0 */ class GetDmxNoDataCheck: public GetDmxCheck { public: void Check(RpcController *controller, ola::proto::DmxData *reply) { DmxBuffer empty_buffer; OLA_ASSERT_FALSE(controller->Failed()); OLA_ASSERT_EQ(empty_buffer, DmxBuffer(reply->data())); } }; /* * Assert that the data matches the test data. */ class GetDmxValidDataCheck: public GetDmxCheck { public: void Check(RpcController *controller, ola::proto::DmxData *reply) { OLA_ASSERT_FALSE(controller->Failed()); OLA_ASSERT_EQ( DmxBuffer(SAMPLE_DMX_DATA, sizeof(SAMPLE_DMX_DATA)), DmxBuffer(reply->data())); } }; /* * RegisterForDmxChecks */ class RegisterForDmxCheck { public: virtual ~RegisterForDmxCheck() {} virtual void Check(RpcController *controller, ola::proto::Ack *reply) = 0; }; /* * UpdateDmxDataCheck */ class UpdateDmxDataCheck { public: virtual ~UpdateDmxDataCheck() {} virtual void Check(RpcController *controller, ola::proto::Ack *reply) = 0; }; /* * SetUniverseNameCheck */ class SetUniverseNameCheck { public: virtual ~SetUniverseNameCheck() {} virtual void Check(RpcController *controller, ola::proto::Ack *reply) = 0; }; /* * SetMergeModeCheck */ class SetMergeModeCheck { public: virtual ~SetMergeModeCheck() {} virtual void Check(RpcController *controller, ola::proto::Ack *reply) = 0; }; /* * Assert that we got a missing universe error */ template class GenericMissingUniverseCheck: public parent { public: void Check(RpcController *controller, OLA_UNUSED reply *r) { OLA_ASSERT(controller->Failed()); OLA_ASSERT_EQ(string("Universe doesn't exist"), controller->ErrorText()); } }; /* * Assert that we got an ack */ template class GenericAckCheck: public parent { public: void Check(RpcController *controller, OLA_UNUSED ola::proto::Ack *r) { OLA_ASSERT_FALSE(controller->Failed()); } }; /* * Check that the GetDmx method works */ void OlaServerServiceImplTest::testGetDmx() { UniverseStore store(NULL, NULL); OlaServerServiceImpl service(&store, NULL, NULL, NULL, NULL, NULL, NULL); GenericMissingUniverseCheck missing_universe_check; GetDmxNoDataCheck empty_data_check; GetDmxValidDataCheck valid_data_check; // test a universe that doesn't exist unsigned int universe_id = 0; CallGetDmx(&service, universe_id, &missing_universe_check); // test a new universe Universe *universe = store.GetUniverseOrCreate(universe_id); OLA_ASSERT_NOT_NULL(universe); CallGetDmx(&service, universe_id, &empty_data_check); // Set the universe data DmxBuffer buffer(SAMPLE_DMX_DATA, sizeof(SAMPLE_DMX_DATA)); universe->SetDMX(buffer); CallGetDmx(&service, universe_id, &valid_data_check); // remove the universe and try again store.AddUniverseGarbageCollection(universe); store.GarbageCollectUniverses(); CallGetDmx(&service, universe_id, &missing_universe_check); } /* * Call the GetDmx method * @param impl the OlaServerServiceImpl to use * @param universe_id the universe_id in the request * @param check the GetDmxCheck class to use for the callback check */ void OlaServerServiceImplTest::CallGetDmx(OlaServerServiceImpl *service, int universe_id, GetDmxCheck *check) { RpcSession session(NULL); RpcController controller(&session); ola::proto::UniverseRequest request; ola::proto::DmxData response; SingleUseCallback0 *closure = NewSingleCallback( check, &GetDmxCheck::Check, &controller, &response); request.set_universe(universe_id); service->GetDmx(&controller, &request, &response, closure); } /* * Check the RegisterForDmx method works */ void OlaServerServiceImplTest::testRegisterForDmx() { UniverseStore store(NULL, NULL); OlaServerServiceImpl service(&store, NULL, NULL, NULL, NULL, NULL, NULL); // Register for a universe that doesn't exist unsigned int universe_id = 0; unsigned int second_universe_id = 99; GenericAckCheck ack_check; CallRegisterForDmx(&service, universe_id, ola::proto::REGISTER, &ack_check); // The universe should exist now and the client should be bound Universe *universe = store.GetUniverse(universe_id); OLA_ASSERT_NOT_NULL(universe); OLA_ASSERT(universe->ContainsSinkClient(NULL)); OLA_ASSERT_EQ((unsigned int) 1, universe->SinkClientCount()); // Try to register again CallRegisterForDmx(&service, universe_id, ola::proto::REGISTER, &ack_check); OLA_ASSERT(universe->ContainsSinkClient(NULL)); OLA_ASSERT_EQ((unsigned int) 1, universe->SinkClientCount()); // Register a second universe CallRegisterForDmx(&service, second_universe_id, ola::proto::REGISTER, &ack_check); Universe *second_universe = store.GetUniverse(universe_id); OLA_ASSERT(second_universe->ContainsSinkClient(NULL)); OLA_ASSERT_EQ((unsigned int) 1, second_universe->SinkClientCount()); // Unregister the first universe CallRegisterForDmx(&service, universe_id, ola::proto::UNREGISTER, &ack_check); OLA_ASSERT_FALSE(universe->ContainsSinkClient(NULL)); OLA_ASSERT_EQ((unsigned int) 0, universe->SinkClientCount()); // Unregister the second universe CallRegisterForDmx(&service, second_universe_id, ola::proto::UNREGISTER, &ack_check); OLA_ASSERT_FALSE(second_universe->ContainsSinkClient(NULL)); OLA_ASSERT_EQ((unsigned int) 0, second_universe->SinkClientCount()); // Unregister again CallRegisterForDmx(&service, universe_id, ola::proto::UNREGISTER, &ack_check); OLA_ASSERT_FALSE(universe->ContainsSinkClient(NULL)); OLA_ASSERT_EQ((unsigned int) 0, universe->SinkClientCount()); } /* * Call the RegisterForDmx method * @param impl the OlaServerServiceImpl to use * @param universe_id the universe_id in the request * @param action the action to use REGISTER or UNREGISTER * @param check the RegisterForDmxCheck to use for the callback check */ void OlaServerServiceImplTest::CallRegisterForDmx( OlaServerServiceImpl *service, int universe_id, ola::proto::RegisterAction action, RegisterForDmxCheck *check) { RpcSession session(NULL); RpcController controller(&session); ola::proto::RegisterDmxRequest request; ola::proto::Ack response; SingleUseCallback0 *closure = NewSingleCallback( check, &RegisterForDmxCheck::Check, &controller, &response); request.set_universe(universe_id); request.set_action(action); service->RegisterForDmx(&controller, &request, &response, closure); } /* * Check the UpdateDmxData method works */ void OlaServerServiceImplTest::testUpdateDmxData() { UniverseStore store(NULL, NULL); ola::TimeStamp time1; ola::Client client1(NULL, m_uid); ola::Client client2(NULL, m_uid); OlaServerServiceImpl service(&store, NULL, NULL, NULL, NULL, &time1, NULL); GenericMissingUniverseCheck missing_universe_check; GenericAckCheck ack_check; unsigned int universe_id = 0; DmxBuffer dmx_data("this is a test"); DmxBuffer dmx_data2("different data hmm"); // Update a universe that doesn't exist m_clock.CurrentTime(&time1); CallUpdateDmxData(&service, &client1, universe_id, dmx_data, &missing_universe_check); Universe *universe = store.GetUniverse(universe_id); OLA_ASSERT_FALSE(universe); // Update a universe that exists m_clock.CurrentTime(&time1); universe = store.GetUniverseOrCreate(universe_id); CallUpdateDmxData(&service, &client1, universe_id, dmx_data, &ack_check); OLA_ASSERT_EQ(dmx_data, universe->GetDMX()); // Update a second client with an older timestamp // make sure we're in ltp mode OLA_ASSERT_EQ(universe->MergeMode(), Universe::MERGE_LTP); time1 = time1 - ola::TimeInterval(1000000); CallUpdateDmxData(&service, &client2, universe_id, dmx_data2, &ack_check); OLA_ASSERT_EQ(dmx_data.Size(), universe->GetDMX().Size()); // Should continue to hold the old data OLA_ASSERT_EQ(dmx_data, universe->GetDMX()); // Now send a new update m_clock.CurrentTime(&time1); CallUpdateDmxData(&service, &client2, universe_id, dmx_data2, &ack_check); OLA_ASSERT_EQ(dmx_data2, universe->GetDMX()); } /* * Call the UpdateDmxDataCheck method * @param impl the OlaServerServiceImpl to use * @param universe_id the universe_id in the request * @param data the DmxBuffer to use as data * @param check the SetUniverseNameCheck to use for the callback check */ void OlaServerServiceImplTest::CallUpdateDmxData( OlaServerServiceImpl *service, Client *client, int universe_id, const DmxBuffer &data, UpdateDmxDataCheck *check) { RpcSession session(NULL); session.SetData(client); RpcController controller(&session); ola::proto::DmxData request; ola::proto::Ack response; SingleUseCallback0 *closure = NewSingleCallback( check, &UpdateDmxDataCheck::Check, &controller, &response); request.set_universe(universe_id); request.set_data(data.Get()); service->UpdateDmxData(&controller, &request, &response, closure); } /* * Check the SetUniverseName method works */ void OlaServerServiceImplTest::testSetUniverseName() { UniverseStore store(NULL, NULL); OlaServerServiceImpl service(&store, NULL, NULL, NULL, NULL, NULL, NULL); unsigned int universe_id = 0; string universe_name = "test 1"; string universe_name2 = "test 1-2"; GenericAckCheck ack_check; GenericMissingUniverseCheck missing_universe_check; // Check we get an error for a missing universe CallSetUniverseName(&service, universe_id, universe_name, &missing_universe_check); Universe *universe = store.GetUniverse(universe_id); OLA_ASSERT_FALSE(universe); // Check SetUniverseName works on an existing universe universe = store.GetUniverseOrCreate(universe_id); CallSetUniverseName(&service, universe_id, universe_name, &ack_check); OLA_ASSERT_EQ(universe_name, universe->Name()); // Run it again with a new name CallSetUniverseName(&service, universe_id, universe_name2, &ack_check); OLA_ASSERT_EQ(universe_name2, universe->Name()); } /* * Call the SetUniverseName method * @param impl the OlaServerServiceImpl to use * @param universe_id the universe_id in the request * @param name the name to use * @param check the SetUniverseNameCheck to use for the callback check */ void OlaServerServiceImplTest::CallSetUniverseName( OlaServerServiceImpl *service, int universe_id, const string &name, SetUniverseNameCheck *check) { RpcSession session(NULL); RpcController controller(&session); ola::proto::UniverseNameRequest request; ola::proto::Ack response; SingleUseCallback0 *closure = NewSingleCallback( check, &SetUniverseNameCheck::Check, &controller, &response); request.set_universe(universe_id); request.set_name(name); service->SetUniverseName(&controller, &request, &response, closure); } /* * Check the SetMergeMode method works */ void OlaServerServiceImplTest::testSetMergeMode() { UniverseStore store(NULL, NULL); OlaServerServiceImpl service(&store, NULL, NULL, NULL, NULL, NULL, NULL); unsigned int universe_id = 0; GenericAckCheck ack_check; GenericMissingUniverseCheck missing_universe_check; // Check we get an error for a missing universe CallSetMergeMode(&service, universe_id, ola::proto::HTP, &missing_universe_check); Universe *universe = store.GetUniverse(universe_id); OLA_ASSERT_FALSE(universe); // Check SetUniverseName works universe = store.GetUniverseOrCreate(universe_id); CallSetMergeMode(&service, universe_id, ola::proto::HTP, &ack_check); OLA_ASSERT_EQ(Universe::MERGE_HTP, universe->MergeMode()); // Run it again CallSetMergeMode(&service, universe_id, ola::proto::LTP, &ack_check); OLA_ASSERT_EQ(Universe::MERGE_LTP, universe->MergeMode()); } /* * Call the SetMergeMode method * @param impl the OlaServerServiceImpl to use * @param universe_id the universe_id in the request * @param mode the merge_mode to use * @param check the SetMergeModeCheck to use for the callback check */ void OlaServerServiceImplTest::CallSetMergeMode( OlaServerServiceImpl *service, int universe_id, ola::proto::MergeMode merge_mode, SetMergeModeCheck *check) { RpcSession session(NULL); RpcController controller(&session); ola::proto::MergeModeRequest request; ola::proto::Ack response; ola::SingleUseCallback0 *closure = NewSingleCallback( check, &SetMergeModeCheck::Check, &controller, &response); request.set_universe(universe_id); request.set_merge_mode(merge_mode); service->SetMergeMode(&controller, &request, &response, closure); } ola-0.10.5.nojsmin/olad/www/0000755000175000017500000000000013134123605015221 5ustar wouterwouterola-0.10.5.nojsmin/olad/www/hide_sections.png0000644000175000017500000000572013023355232020553 0ustar wouterwouter‰PNG  IHDR(-S pHYs  ÒÝ~ü OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFiPLTEÿÿÿÿÿÿT¦&n³'n´LDe````”Ç`”Ȭ ÿ2ÿ5ÿ6ÿ;ÿ<ÿB ÿDÿKÿMÿTÿVÿ\"ÿš€ÿœƒÿ …ÿ¤‰ÿ©Œÿ­ÿ¯‘ÿ±“ÿ²”ÿµ–ÿÿÿ¿îí6tRNS¬U¢fIDATÓmË‚0;ô"ŸŠ ðÿ鯖r`v™ENâmq€€} Šñ#Gh“v©0“™ÐQ ŸîݾžMߺº]NGEÿ¸_Ï¥÷k™4Ûq@(‹¥ë_o§ü+ Ôtã×IEND®B`‚ola-0.10.5.nojsmin/olad/www/Makefile.mk0000644000175000017500000000601713023355232017273 0ustar wouterwouterwwwdir = $(www_datadir) newdir = $(www_datadir)/new viewsdir = $(www_datadir)/new/views jsdir = $(www_datadir)/new/js cssdir = $(www_datadir)/new/css imgdir = $(www_datadir)/new/img jquerydir = $(www_datadir)/new/libs/jquery/js angularroutedir = $(www_datadir)/new/libs/angular-route/js angulardir = $(www_datadir)/new/libs/angular/js bootcssdir = $(www_datadir)/new/libs/bootstrap/css bootjsdir = $(www_datadir)/new/libs/bootstrap/js bootfontsdir = $(www_datadir)/new/libs/bootstrap/fonts dist_www_DATA = \ olad/www/back.png \ olad/www/blank.gif \ olad/www/button-bg.png \ olad/www/console_values.html \ olad/www/custombutton.css \ olad/www/discovery.png \ olad/www/editortoolbar.png \ olad/www/expander.png \ olad/www/forward.png \ olad/www/handle.vertical.png \ olad/www/hide_sections.png \ olad/www/incremental-discovery.png \ olad/www/landing.html \ olad/www/light_bulb_off.png \ olad/www/light_bulb.png \ olad/www/loader-mini.gif \ olad/www/loader.gif \ olad/www/logo-mini.png \ olad/www/logo.png \ olad/www/mobile.html \ olad/www/mobile.js \ olad/www/ola.html \ olad/www/ola.js \ olad/www/refresh.png \ olad/www/show_sections.png \ olad/www/tick.gif \ olad/www/toolbar-bg.png \ olad/www/toolbar.css \ olad/www/toolbar_sprites.png \ olad/www/vertical.gif \ olad/www/wand.png \ olad/www/warning.png dist_new_DATA = \ olad/www/new/index.html dist_views_DATA = \ olad/www/new/views/overview.html \ olad/www/new/views/plugin-info.html \ olad/www/new/views/plugins.html \ olad/www/new/views/universe-add.html \ olad/www/new/views/universe-faders.html \ olad/www/new/views/universe-header.html \ olad/www/new/views/universe-keypad.html \ olad/www/new/views/universe-overview.html \ olad/www/new/views/universe-patch.html \ olad/www/new/views/universe-rdm.html \ olad/www/new/views/universe-settings.html \ olad/www/new/views/universes.html dist_js_DATA = \ olad/www/new/js/app.min.js \ olad/www/new/js/app.min.js.map dist_css_DATA = \ olad/www/new/css/style.min.css dist_img_DATA = \ olad/www/new/img/light_bulb_off.png \ olad/www/new/img/light_bulb.png \ olad/www/new/img/logo-mini.png \ olad/www/new/img/logo.png dist_jquery_DATA = \ olad/www/new/libs/jquery/js/jquery.min.js dist_angularroute_DATA = \ olad/www/new/libs/angular-route/js/angular-route.min.js dist_angular_DATA = \ olad/www/new/libs/angular/js/angular.min.js dist_bootjs_DATA = \ olad/www/new/libs/bootstrap/js/bootstrap.min.js dist_bootfonts_DATA = \ olad/www/new/libs/bootstrap/fonts/glyphicons-halflings-regular.eot \ olad/www/new/libs/bootstrap/fonts/glyphicons-halflings-regular.svg \ olad/www/new/libs/bootstrap/fonts/glyphicons-halflings-regular.ttf \ olad/www/new/libs/bootstrap/fonts/glyphicons-halflings-regular.woff \ olad/www/new/libs/bootstrap/fonts/glyphicons-halflings-regular.woff2 dist_bootcss_DATA = \ olad/www/new/libs/bootstrap/css/bootstrap.min.css ola-0.10.5.nojsmin/olad/www/loader-mini.gif0000644000175000017500000000347113023355232020115 0ustar wouterwouterGIF89aôúúú*/ÿîîúšœûàáúbfüü*/ÿqtüGKý¶¸ûÅÆû9>ý©«û,1ýVZý~ü!ÿ NETSCAPE2.0!þCreated with ajaxload.info!ù ,w  !å¨DBÇA«H‰àȬ³Áa°¦D‚Âæ@ ^¶AéXøP¤@ñ¸"Uƒ‚³Q# ÎáB\;ŸÍ Ã1ª oÏ:2$v@ $|,3 ‚_# d€53—" s5 e!!ù ,v i@e9ŽDAÉAŒ²ŠÄñÀ/«`ph$Ca%@ ŒÇépH©°x½FÂuS‰ƒx#… Â.¿Ý„†YfŽL_" p 3BƒW ˆ]|L \6’{|zš87[7!!ù ,x Ù e9ŽDE"²Š„ƒÀ2r,« qPć€j´Â`ð8ëÂ@8bH, *Ñâ0-¦ ðmFWîä9½LP¤E3+ (‚B"  f{ˆ*BW_/‰ @_$‰‚~Kr7Ar7!!ù ,v Ù4e9Ž„!Hñ"Ë* ÐQ/@ƒ±ˆ-4€ép4ŒR+÷¼-Ÿèµp­ȧ`ÑP(–6ƒá ðU/ü  *,„)(+/]"lO…/†*Ak‘“Š K”ŒŠ]A~66 6!!ù ,l ie9Ž"ÇñË*‡ ½¾-Ö80H‚±€=N;¡ ÐÊT„Eìн®îqè¤í±ež êUoK2_WZòÝŒV‰´1jgWe@tuH//w`?…‰f~#’‰–6”“#!!ù ,~ ¹,e9Ž‚"ƒñÄ* †; pR³%„°#0¤š`¡ À'Ãc™(¤”J@@¿Áµ/1Ái4ˆÂ`½V­‰Bâ¾V u}„"caNi/ ] ))-Lel  mi} me[+!!ù ,y Ie9ŽÂ"Mó6Ä*¨"7EÍ–„@G((L&Ôpqj@Z…§‰ùº „ï%@­w¬Z) „pl( ‡Ô­Žqõu*R&c `))( s_Jˆ>_\'Gm7Œ$+!!ù ,w Ie9Ž*,‹ (Ä*¾(üB5[1² ¥Z²ÓIah!G—ªexz²ìJ0ˆe¿6ÀÂ@V|U«ñ4º¶Dm²…%$Í›ëp \Gx }@+| =+ 1“- Ea5l)+!!ù ,y )œä¨ž'AœK©’¯àÚ,¢¶ý“‰E\(lƒœ©&;5 à5D‰Ä€0è³3‚a¬0-‹µ-Ñ¡À”ŽÃƒpH4V % i p[R"| Œ‘# ™ 6iZwcw*!!ù ,y )œä¨ž,K”*ù¶Ä‹¨0Ÿ aš;׋аY8b`4én¤ ¨Bb‚b»x¾,±ÁÔ¾‘ ±Ë¾ÍäÑ( Ƚ°  % >  2*Ši* /:™+$v*!!ù ,u )œä¨žl[ª$á ²Jq[£Âq 3™`Q[ø5ø:Š•ðIX!0ÀrAD8 Cv«ÉÜHPfi¾äiQ”ƒAP@pC %D PQ46 Š iciNj0w „)#!!ù ,y )œä¨. q¾¨ ,G ®Jr(¯J8 ‡Cðä*Ї†B´,™Ž…ê&< …Œ´Ûh± W~-¼‘`Ñ, ‡–õ¤,ì>; 8RN<, …<1T] ˜c‘—' qk$ @)#!;ola-0.10.5.nojsmin/olad/www/show_sections.png0000644000175000017500000000604713023355232020625 0ustar wouterwouter‰PNG  IHDR(-S pHYs  ÒÝ~ü OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFŸPLTEÿÿÿÿÿÿb[x#m```b[xr¼ x¿ y¿§ ÃĂÂĪÃĂÂĬ"¯#m%±*µ-¸.ŒÈ/ŒÈ3¼7¾!<Â$@Å(D—ÎD˜ÎFÉ+JÌ.TÒ4‹Ó†ŒÔ†ŽÕˆ‘ØŠ•ۚޞᒣ䖨蘬ëœëëóîîõÿÿÿ‡’¿¦ tRNSÙõõõ¹$—IDATÓ]ÏGÂ@CÑߨ0=dh“sÎÙ÷? ›*Æo©…JB ?ÂÌjHÅç }ªø4‡”èG>}g°˜È§Ÿ ¢jªêF9Ú€;_®·ûãùB  ¸Ó`<]®÷ pÇFw8Y¬vˆj«ØaîHÂ`‹…K™[òßH·_×[ͶúºIEND®B`‚ola-0.10.5.nojsmin/olad/www/button-bg.png0000644000175000017500000000064613023355232017636 0ustar wouterwouter‰PNG  IHDRôÆýÇâÀPLTEÿÿÿàßàèèèþþþÚÙÙãäãïïïÈÇÇïïðÇÇÇÞÞÞüüýÛÛÛö÷ööö÷ßßßáááýýüÙÙÚÿÿÿøøùíííêêêòñò½¼½ÎÎÎÊÊÊ¿¿¿ôôô×××ÄÄÄäãäÁÁÁååæçèèàààæååæææáâá÷ö÷÷÷öþýþÜÜÛæåæÛÜÜßààÑÑÑââáÙÙÙÜÛÛÚÚÙäääåææÈÈÇÛÜÛããäææåðïï»»»âááâáâÔÔÔýüýúûû$@i>tRNS@æØf”IDATx^íÅUBQCÑÞçn¨»»»ÌV@š0>ÎêNŠa¢ëßà§©Ÿ>}¼yB8£0¡N(,ëâXŽƒ¡HÐ4­ûúó`ÖÙÃ4ÍÖîÔÂ0I’ûêµPqO)xžÂ?B!„B!®ôû2¡Fhšûຶk£J¨–„¡A0 c›­3Á|3 ŽoæyëéEtIEND®B`‚ola-0.10.5.nojsmin/olad/www/toolbar.css0000644000175000017500000002455613023355232017411 0ustar wouterwouter/* * Copyright 2009 The Closure Library Authors. All Rights Reserved. * * Use of this source code is governed by an Apache 2.0 License. * See the COPYING file for details. */ /* * Standard styling for toolbars and toolbar items. * * @author attila@google.com (Attila Bodis) */ /* * Styles used by goog.ui.ToolbarRenderer. */ .goog-toolbar { background: #fafafa url(/toolbar-bg.png) repeat-x bottom left; border-bottom: 1px solid #d5d5d5; cursor: default; font: normal 12px Arial, sans-serif; margin: 0; outline: none; padding: 2px; position: relative; zoom: 1; /* The toolbar element must have layout on IE. */ } /* * Styles used by goog.ui.ToolbarButtonRenderer. */ .goog-toolbar-button { margin: 0 2px; border: 0; padding: 0; font-family: Arial, sans-serif; color: #333; text-decoration: none; list-style: none; vertical-align: middle; cursor: default; outline: none; } /* Pseudo-rounded corners. */ .goog-toolbar-button-outer-box, .goog-toolbar-button-inner-box { border: 0; vertical-align: top; } .goog-toolbar-button-outer-box { margin: 0; padding: 1px 0; } .goog-toolbar-button-inner-box { margin: 0 -1px; padding: 3px 4px; } /* Pre-IE7 IE hack; ignored by IE7 and all non-IE browsers. */ * html .goog-toolbar-button-inner-box { /* IE6 needs to have the box shifted to make the borders line up. */ left: -1px; } /* Pre-IE7 BiDi fixes. */ * html .goog-toolbar-button-rtl .goog-toolbar-button-outer-box { /* @noflip */ left: -1px; } * html .goog-toolbar-button-rtl .goog-toolbar-button-inner-box { /* @noflip */ right: auto; } /* IE7-only hack; ignored by all other browsers. */ *:first-child+html .goog-toolbar-button-inner-box { /* IE7 needs to have the box shifted to make the borders line up. */ left: -1px; } /* IE7 BiDi fix. */ *:first-child+html .goog-toolbar-button-rtl .goog-toolbar-button-inner-box { /* @noflip */ left: 1px; /* @noflip */ right: auto; } /* Safari-only hacks. */ ::root .goog-toolbar-button, ::root .goog-toolbar-button-outer-box { /* Required to make pseudo-rounded corners work on Safari. */ line-height: 0; } ::root .goog-toolbar-button-inner-box { /* Required to make pseudo-rounded corners work on Safari. */ line-height: normal; } /* Disabled styles. */ .goog-toolbar-button-disabled { opacity: 0.3; -moz-opacity: 0.3; filter: alpha(opacity=30); } .goog-toolbar-button-disabled .goog-toolbar-button-outer-box, .goog-toolbar-button-disabled .goog-toolbar-button-inner-box { /* Disabled text/border color trumps everything else. */ color: #333 !important; border-color: #999 !important; } /* Pre-IE7 IE hack; ignored by IE7 and all non-IE browsers. */ * html .goog-toolbar-button-disabled { /* IE can't apply alpha to an element with a transparent background... */ background-color: #f0f0f0; margin: 0 1px; padding: 0 1px; } /* IE7-only hack; ignored by all other browsers. */ *:first-child+html .goog-toolbar-button-disabled { /* IE can't apply alpha to an element with a transparent background... */ background-color: #f0f0f0; margin: 0 1px; padding: 0 1px; } /* Only draw borders when in a non-default state. */ .goog-toolbar-button-hover .goog-toolbar-button-outer-box, .goog-toolbar-button-active .goog-toolbar-button-outer-box, .goog-toolbar-button-checked .goog-toolbar-button-outer-box, .goog-toolbar-button-selected .goog-toolbar-button-outer-box { border-width: 1px 0; border-style: solid; padding: 0; } .goog-toolbar-button-hover .goog-toolbar-button-inner-box, .goog-toolbar-button-active .goog-toolbar-button-inner-box, .goog-toolbar-button-checked .goog-toolbar-button-inner-box, .goog-toolbar-button-selected .goog-toolbar-button-inner-box { border-width: 0 1px; border-style: solid; padding: 3px; } /* Hover styles. */ .goog-toolbar-button-hover .goog-toolbar-button-outer-box, .goog-toolbar-button-hover .goog-toolbar-button-inner-box { /* Hover border style wins over active/checked/selected. */ border-color: #a1badf !important; } /* Active/checked/selected styles. */ .goog-toolbar-button-active, .goog-toolbar-button-checked, .goog-toolbar-button-selected { /* Active/checked/selected background color always wins. */ background-color: #dde1eb !important; } .goog-toolbar-button-active .goog-toolbar-button-outer-box, .goog-toolbar-button-active .goog-toolbar-button-inner-box, .goog-toolbar-button-checked .goog-toolbar-button-outer-box, .goog-toolbar-button-checked .goog-toolbar-button-inner-box, .goog-toolbar-button-selected .goog-toolbar-button-outer-box, .goog-toolbar-button-selected .goog-toolbar-button-inner-box { border-color: #729bd1; } /* Pill (collapsed border) styles. */ .goog-toolbar-button-collapse-right, .goog-toolbar-button-collapse-right .goog-toolbar-button-outer-box, .goog-toolbar-button-collapse-right .goog-toolbar-button-inner-box { margin-right: 0; } .goog-toolbar-button-collapse-left, .goog-toolbar-button-collapse-left .goog-toolbar-button-outer-box, .goog-toolbar-button-collapse-left .goog-toolbar-button-inner-box { margin-left: 0; } /* Pre-IE7 IE hack; ignored by IE7 and all non-IE browsers. */ * html .goog-toolbar-button-collapse-left .goog-toolbar-button-inner-box { left: 0; } /* IE7-only hack; ignored by all other browsers. */ *:first-child+html .goog-toolbar-button-collapse-left .goog-toolbar-button-inner-box { left: 0; } /* * Styles used by goog.ui.ToolbarMenuButtonRenderer. */ .goog-toolbar-menu-button { margin: 0 2px; border: 0; padding: 0; font-family: Arial, sans-serif; color: #333; text-decoration: none; list-style: none; vertical-align: middle; cursor: default; outline: none; } /* Pseudo-rounded corners. */ .goog-toolbar-menu-button-outer-box, .goog-toolbar-menu-button-inner-box { border: 0; vertical-align: top; } .goog-toolbar-menu-button-outer-box { margin: 0; padding: 1px 0; } .goog-toolbar-menu-button-inner-box { margin: 0 -1px; padding: 3px 4px; } /* Pre-IE7 IE hack; ignored by IE7 and all non-IE browsers. */ * html .goog-toolbar-menu-button-inner-box { /* IE6 needs to have the box shifted to make the borders line up. */ left: -1px; } /* Pre-IE7 BiDi fixes. */ * html .goog-toolbar-menu-button-rtl .goog-toolbar-menu-button-outer-box { /* @noflip */ left: -1px; } * html .goog-toolbar-menu-button-rtl .goog-toolbar-menu-button-inner-box { /* @noflip */ right: auto; } /* IE7-only hack; ignored by all other browsers. */ *:first-child+html .goog-toolbar-menu-button-inner-box { /* IE7 needs to have the box shifted to make the borders line up. */ left: -1px; } /* IE7 BiDi fix. */ *:first-child+html .goog-toolbar-menu-button-rtl .goog-toolbar-menu-button-inner-box { /* @noflip */ left: 1px; /* @noflip */ right: auto; } /* Safari-only hacks. */ ::root .goog-toolbar-menu-button, ::root .goog-toolbar-menu-button-outer-box, ::root .goog-toolbar-menu-button-inner-box { /* Required to make pseudo-rounded corners work on Safari. */ line-height: 0; } ::root .goog-toolbar-menu-button-caption, ::root .goog-toolbar-menu-button-dropdown { /* Required to make pseudo-rounded corners work on Safari. */ line-height: normal; } /* Disabled styles. */ .goog-toolbar-menu-button-disabled { opacity: 0.3; -moz-opacity: 0.3; filter: alpha(opacity=30); } .goog-toolbar-menu-button-disabled .goog-toolbar-menu-button-outer-box, .goog-toolbar-menu-button-disabled .goog-toolbar-menu-button-inner-box { /* Disabled text/border color trumps everything else. */ color: #333 !important; border-color: #999 !important; } /* Pre-IE7 IE hack; ignored by IE7 and all non-IE browsers. */ * html .goog-toolbar-menu-button-disabled { /* IE can't apply alpha to an element with a transparent background... */ background-color: #f0f0f0; margin: 0 1px; padding: 0 1px; } /* IE7-only hack; ignored by all other browsers. */ *:first-child+html .goog-toolbar-menu-button-disabled { /* IE can't apply alpha to an element with a transparent background... */ background-color: #f0f0f0; margin: 0 1px; padding: 0 1px; } /* Only draw borders when in a non-default state. */ .goog-toolbar-menu-button-hover .goog-toolbar-menu-button-outer-box, .goog-toolbar-menu-button-active .goog-toolbar-menu-button-outer-box, .goog-toolbar-menu-button-open .goog-toolbar-menu-button-outer-box { border-width: 1px 0; border-style: solid; padding: 0; } .goog-toolbar-menu-button-hover .goog-toolbar-menu-button-inner-box, .goog-toolbar-menu-button-active .goog-toolbar-menu-button-inner-box, .goog-toolbar-menu-button-open .goog-toolbar-menu-button-inner-box { border-width: 0 1px; border-style: solid; padding: 3px; } /* Hover styles. */ .goog-toolbar-menu-button-hover .goog-toolbar-menu-button-outer-box, .goog-toolbar-menu-button-hover .goog-toolbar-menu-button-inner-box { /* Hover border color trumps active/open style. */ border-color: #a1badf !important; } /* Active/open styles. */ .goog-toolbar-menu-button-active, .goog-toolbar-menu-button-open { /* Active/open background color wins. */ background-color: #dde1eb !important; } .goog-toolbar-menu-button-active .goog-toolbar-menu-button-outer-box, .goog-toolbar-menu-button-active .goog-toolbar-menu-button-inner-box, .goog-toolbar-menu-button-open .goog-toolbar-menu-button-outer-box, .goog-toolbar-menu-button-open .goog-toolbar-menu-button-inner-box { border-color: #729bd1; } /* Menu button caption style. */ .goog-toolbar-menu-button-caption { padding: 0 4px 0 0; vertical-align: middle; } /* Dropdown style. */ .goog-toolbar-menu-button-dropdown { width: 7px; /* Client apps may override the URL at which they serve the sprite. */ background: url(/editortoolbar.png) no-repeat -388px 0; vertical-align: middle; } /* * Styles used by goog.ui.ToolbarSeparatorRenderer. */ .goog-toolbar-separator { margin: 0 2px; border-left: 1px solid #d6d6d6; border-right: 1px solid #f7f7f7; padding: 0; width: 0; text-decoration: none; list-style: none; outline: none; vertical-align: middle; line-height: normal; font-size: 120%; overflow: hidden; } /* * Additional styling for toolbar select controls, which always have borders. */ .goog-toolbar-select .goog-toolbar-menu-button-outer-box { border-width: 1px 0; border-style: solid; padding: 0; } .goog-toolbar-select .goog-toolbar-menu-button-inner-box { border-width: 0 1px; border-style: solid; padding: 3px; } .goog-toolbar-select .goog-toolbar-menu-button-outer-box, .goog-toolbar-select .goog-toolbar-menu-button-inner-box { border-color: #bfcbdf; } ola-0.10.5.nojsmin/olad/www/landing.html0000644000175000017500000000440713023355232017530 0ustar wouterwouter Full Version Mobile Version ola-0.10.5.nojsmin/olad/www/vertical.gif0000644000175000017500000000006613023355232017523 0ustar wouterwouterGIF89a‘œ™œ´²´ÅÂÅæææ!ù,œ"€_;ola-0.10.5.nojsmin/olad/www/expander.png0000644000175000017500000000564513023355232017547 0ustar wouterwouter‰PNG  IHDRQ ŸQ EiCCPICC ProfilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüºÇhbKGDÿÿÿ ½§“ pHYs  šœtIMEÚ!+nÂÑáIDATHÇcd```pNYÂ@Ø;'l 1꜒Wÿ'Fݾ¹¡ŒÄ¨ìîctNYB¬åĨ%ÖÄ:t°»‰aP †d :%¯þOjŠ"”ڈͺØËh:" ÜKpFØ…=Œ,Ä”äÆ.}ä¦"t}0>µÜã£Û³tbCtþ4 ýK'f1hkôŒ–‰Äm %Æ¥³° #Fv¦¤\ fŠ#”r(M¸R2>÷jk(1^½qïtþ4”-ÉH‘WoÜû€C62Ç àh;‘J€q´ÛG¹ûóÚ‚-ÿáûõIEND®B`‚ola-0.10.5.nojsmin/olad/www/blank.gif0000644000175000017500000000006113023355232016774 0ustar wouterwouterGIF89a‘ÿÿÿÿÀÀÀ!ù,T;ola-0.10.5.nojsmin/olad/www/refresh.png0000644000175000017500000000076613023355232017376 0ustar wouterwouter‰PNG  IHDRóÿa½IDAT8R¿kSQ=ç|÷¹ú†´‹KÒA$`}±BŸkè앤N:5ÝÄ%¾EÜ ¸8m];»uJº˜‚ƒB@üÁCtÈ–ÿà9Ä®¯!zà.ßwÏùÎwîE–eȲ ËPª ë¥Úð_ËyÌÉ$/W¶‡ñŸzD‹dcò~³— ¸,Pª}ˆAvHÆ $§+?oOsž V[$ûc3œæÇ9ƒs e:ð9s+Ûç1‰¾¤”b™Le36)F$¡Ü Xùz´ž€›+‘{ö''›]ÂÚƒÑň"H¾¬§8š ö°?9¹›ƒ´À" ‰îç77§ÅþÒWX†…!ú¨>‡ÕÇãð_B®X¸þð¢,c‡Dd¥Ø¿—üˆN¤€·Beg™Óž9µ\`°@£‹W76|òÖó_mÍÁÓk9ÏwЧÊ9Â9…wž|æ®\ «æ¬.Ç2ÉÆÂÌ”H|)#Ì9•eìÈ .dÚ=m¯ö|yˆßÞÞêJH³¯;s"X ˜©'ÓýÓöêáÒeÚ%ù‰äà㋵Fñò"üõŒã×ÕTÆÈÎþ‡ ¿lñ{ aºÓœIEND®B`‚ola-0.10.5.nojsmin/olad/www/forward.png0000644000175000017500000000070413023355232017374 0ustar wouterwouter‰PNG  IHDRóÿasBIT|dˆtEXtSoftwarewww.inkscape.org›î<VIDAT8¥’½/CQÆï¹÷jÓR´*±Y ’Џ‚`ñH$b‘ØúˆÙ$ƒÄJR“Ï´j°ˆÕ`²!tÐÞ´z¡4âã¶å™NÎyžßÉû!Zkþ#åõ(™E= ÿ@sómmû2žêüMCD[dò"^?@0º‰D“2u9ñÝ2vÁïQˆ(U>£ç …F+îbñ™§ì²Þ‹o}\™˜Æ±Ž*¥”eYaZÂ2sÝ®“=«e€ë*œ\Mùwù6¬ÈôU;ù%·T/@pK½XfÌäÕ1x¹¯=ª‚µCÁ7¯ÓƒY1î(Û€€T>@DPÒ‡%]•°KÇX#o%ôE¿¯U–ÉÌ.~c€WýH^úÐÞüì1«”ZÞ“¢¾!' úØ>ûê¨ptмÌéSûö'‡7À!MAÖõ¹ýë˜<{P‹ÞÈc´@€çIEND®B`‚ola-0.10.5.nojsmin/olad/www/toolbar-bg.png0000644000175000017500000000024613023355232017761 0ustar wouterwouter‰PNG  IHDR gè9PLTEøøøîîîóóóèèèúúúõõõööö÷÷÷ñññïïïùùùòòòëëëêêêéééíííçççæææåååYÞvJ(IDATx^%Á… ±Ã]÷–OhñT¾D$`µ‘)]t§›Ã} C²íÎ;IEND®B`‚ola-0.10.5.nojsmin/olad/www/incremental-discovery.png0000644000175000017500000000114013023355232022231 0ustar wouterwouter‰PNG  IHDRóÿa'IDATxÚc`À´´´Ø’òòòVWVVî/++[TPPàË@ ðôô”‰ŒŒ¼àììüÏÌÁý«½OÈGwÏŸaaaÿnòññá§ŸÅßßÿ¬©ƒ×÷Ú•gRVÞÚÿŸáÿò[ŸÎ7.Ù|Ï70øwZZÚ"œº¶FØ8zü°©Úr$dƹýékî€ X}÷ëùMOŸqøÒа?@Wja5ÀÎÎn¾~pÍ-›ú}û§žÛŸº â‚¥7?ŸÝðè'ØüÆî7¡¡¡ùX 055ݬ5í4H.ܺtËooïF¬èéé­Õj¹bP¸m¿së¡ý¡3.€]P·÷é‘ßž_péýùâîÙÏ€Õa5ÀÜܼQÉÈýuɶ#æ•»ö»w²ìÆÉ‡Ÿœ›¸ÿþEßÀŸâââáX úMÝÄÄ䯾{ÊSך]Ç­«÷€ ð™pjÅŠ‹çB“ó>hjj¾*åÅÐ\ 'NÜÕÛÛû è•?–Îþ_¬#«X%vÞ°‹©|èýÃÐÐ𛤤d6Í@ÛÿüOJJjJNNúó‚®®î_##£ÿ:::¿544NmwÁÐ\XXØòO__ÿ?¿‹‹3ƒ¦Hv`rV¦@kwwwPòÆÐœŸŸß Ö tö‡˜˜b¥¥ešŸŸX3ЉœHœœœVÒÒÒŸ€þúäêêêÆ@`tº39zKYþRŸ*_ÇIEND®B`‚ola-0.10.5.nojsmin/olad/www/mobile.html0000644000175000017500000002634413134123277017374 0ustar wouterwouter OLA
Hostname
Primary IP
Primary Broadcast Address
Primary MAC Address
Instance Name
Version
Started
ola-0.10.5.nojsmin/olad/www/editortoolbar.png0000644000175000017500000000530713023355232020605 0ustar wouterwouter‰PNG  IHDRp¡¦²âÐPLTED! H'N,R-S.T™333"8\39C,Be2Eg0Gt1Hu4Hm@GT8Ll7LrÿD=G#¯ùÜÞ›³Ÿ0gÎ廲ï7ÕÙÂH¤P‡·…ë··ÑPõÜ’£Œ¦wšþçQ–Là¬V¸ý'¶î'ÿÚ œø¨]Ê4ç¨c@ùÈNÐãÜbíÚ+V¬Ý¸|ùòüfæ1TÏcÐáỷcÁÉC2z+W`u›? yõ›3ôM9ç“ájÚ,È´‡pUY¬ÆmYX”·¾õ-ndØî±Á‹¬H´ôt]àDè|mV8«¤pˆ8Fá<ð•è§Öç²Ùø=róÞfsùj¥F à «!¤‰k‚°‰:ðE‚fL_à0oä>ElñâÅ Pr˜KL×gGNI0yFw@ºÂùÒÑðî)võÛT2¢ßpçtÂ/1&“®Êó¥Ð ²"jâò0oé[Œx£'¨bJ·9]ßÀäȨ;È*\ž)[:2ò¥*Ý¢Ò'NJâ½ð†i«pУ\VP ê‹í6'ï²—7ãÍåvï´Ù'׃Êy¼ðGêæ«à*&tjãÔÇ ˆ8 ¸Þ~mûöƒ‡¿ùhc 8.%¨‘Ib²×ãm+<)ö8z4{JZJ·‡fôNék8¿?p~ ¸ˆ„³Â Ëë­Qó¶Á·hÆM'JJdÃÒî.* ‡I‹F5ÀAEákur@ü0æV¸?cÀ ´ñ—Nw¦]½,ïªÇ'ê]ãƒÁ¥|šsúÒ| ¸Íj…S¡ õTÕYî¸DvŽ<ÒÒòýºGÞoÛ&†Eæ[[â*œ¹Nw4J`O&|cg[¯´€ÕpºrnME_ø§iêÔ½ ì®7_Z P”L¨Nd ÞÜ|ØÒbœO1lê|Úã 0)û("Z…Ó Û?Âé•êŒU8Ž1Ýò“òp­ûÿÔí …Bßµ"à<ÐC2ªŸ‘æ¬ËQÍVP.íN9Ó2(àT5ܺÔ'H‚.м!â¤xy½Á ¾¼kÆÜ4iö\tªãb…Y!&EáfÁ®©©©ÿ€'n~ðÚÜ »wOØ dà€.pRCÄ‘x »˜¾hKô°q>E¸1õ[£Ì›AÖpbdÌ(“RéÉ©©á`LäÌ+Ü_ºPè­ÿÀÀ¡Õ¤'v8WF/·x, 8(»{e¸xÜfVá üPµ²‚Õh{©:2‚¼$ó&7ßX¼è޼‘£òóÇ”²«T}ßüÆ•¹Ž PÃ?©Ø*p6}øÛ|vo¬·~8©%Œˆ#¼‡#ŒIÜ3³ ÷C f½Ð¨^¦R«Ró«Tý ¥£pšE »J•·¼¨Uj¬f:5©á~ì ½÷ó±Ï1pxKÄƒ× §U2[1ûÜÅ6Ò ·§©žr‘ŸÛ 8 œ ÆIÍ|ý-ƒçç_9È}Ý 8;{´¯-“¯pØ*$Þ@ÓW|õÒX~h“,ì¨"¼‡»/GZjæ&؃ &o´h0©pÚmØ®}8«î›†'NüØññ±_B!œ@©œ òŽAì§Òa¶ë™™é™™™;²²ÜƒLÜÏü›†öÕpr Q8rõÞ>ýrH“yà0q˜7 n‹ÀjZ:o¿7ᛆ„ —N[GÞ4Xu_m Ãøú·ŸÞ‘€ždonu`ÉhâeŽf?X:cž`}“‰›úø­ÕI»qyKôjËèMƒ¹ÈòÖà¬mémêš8ë݇K’U |Z!æTÐ|YÙéâí´GÆgú¯E¬ÖøÈÖHöî,³3ÿ’:ÅÔ¿”ý B0ÕñK IEND®B`‚ola-0.10.5.nojsmin/olad/www/light_bulb_off.png0000644000175000017500000000122413023355232020673 0ustar wouterwouter‰PNG  IHDRóÿatEXtSoftwareAdobe ImageReadyqÉe<6IDATxÚ”SKkQ¾3“É$ÉÃÒ$Š‚©&Ð…Z•d)J®\¹sÓ…  â(]¸q©¸qÕ ¡‹‚u!HLì#D%uJÚIMÀÒ´vÚæa2Ï;×3jJÒv8Ü3s¾ï»çžs/EA]}òQe…ñî…¼õ£ «hšfŸ=8ä8P¿Yà›‰è™«“c×Çâ‘ÐP£­«bíçöLæsN¬I!È/‚îJòèóÉÛ’±pc´uXÜé»÷.E‚7 ’˽„>(/ñp"5®é¦i`S¥á<†bÚŠ¡”w~íßOßÌÈ @<¼¨èfÇ$ˆÈ:ÖZ²®b“Í Úp$ßîå8ŽPm+µºÒ´ÎÙ’ u»®ªš¦xŽ,>¦U°ÿqµ"€³¾ÕjlîudhñŸbÙ°Ïå]Z¯TA`ÏV’_^ÌgóÑëôyXÎçq:Â~Žò¹<~žáž¾y_LÞVìÇÎAóëÔëù·W.Î ºø—sÇ‚îðãW³ï¶¤z¦PµPU†±6* ¥òTÁ» ÷¡¸Vʬˆßa÷Œ®ëÈVÀJ‚[*Ì-[åXÆÎÏ-­” ?Ëø¯!Û)ÀîݰšÊÜzHr†Ä :ÁúÎc©vä|v·¸xmDE´93õÉ™H·ÿG•À“ÉÒ4çŸoYÈžÄ?6…>“$ 5»ƒ Ç^c讀M¥Òw ŒÂè¦íp¿v.1Ýœx™IEND®B`‚ola-0.10.5.nojsmin/olad/www/logo-mini.png0000644000175000017500000000134413023355232017623 0ustar wouterwouter‰PNG  IHDR3mÀ¤¯«IDATxÚå–MHTQÇ{%:cQ––9H„R´ú\´pU³‰> #Œ ŒvÑ¢Má"ERFaQ%-ÄÚØ¢Dƒ ú± …ù5&“óú/þ‹?¹½ûîLô‡Ì=ïœóÞysî»gÖÿ¢Ù nƒ/ r`Ü ˜ä“B”dŽÀY;À[à ?ÁtÀöìü‹ÅÜaŽ>—`œ9IÒªÄgm¯äϯÈŬYÉÓ"é §Àaà…žŒ¹PäbÎ_èŠÚZ90 ¶[m?xÃ}E*fgü¨äÚ`<¼c@3ˆª½Œý âE(æcs|±ß¸¾i¼›Îýl=gŽtÅ”‚aÆÞ§í×Y°2,ÁC:®ÚÏ ,æ ãfÀZÚb`ˆö¶°£c|±R LÛA‚¿+¤Õ\‹ñÀãnÕÚǹ§òªJn£­“ëz`ÒBöôS±eç9Ó í´:Oû}äõ“¦µrãÚÖãü׌b[n“õ(ó”9ÓŘk†ëM¼>lš>brã àªri—6[/‡µ iS¢OyNÙèøÃüÕ e½…9z‹¹N[Þ˜¾¼mt¸*¶à¨A•qt‹í"sœr(f˜¶[–˘³+ŸC=˜ÑǶ©ŸËà¬kÀ"þ®Æ'Š9Kß÷À‹0€ö˜Úé0ÀB‚z ^¹Ï"3ŒÐ·Øh³äOš6p?ž¥–3ÔƼåÅ´Î[õ1î®Éa xI§NÑ›¸GTÕ|ˆ!ƒ*¦æð™~í ŠɤPkrŠƒ:ù˜T}:Ù*Aù!$Á(ë@ÅÁwÛ±\’϶2®ðp¥¬‹ÑÏw/×ÝÀE­ŒÏ€Å¶AsA‚Ìÿ¤~° =™IIEND®B`‚ola-0.10.5.nojsmin/olad/www/mobile.js0000644000175000017500000026372513023355232017045 0ustar wouterwouterfunction e(a){throw a;}var k=void 0,m=null;function aa(){return function(){}}function ba(a){return function(b){this[a]=b}}function p(a){return function(){return this[a]}}function r(a){return function(){return a}}var s,ca=ca||{},u=this;function da(a){for(var a=a.split("."),b=u,c;c=a.shift();)if(b[c]!=m)b=b[c];else return m;return b}function v(){}function y(a){a.p=function(){return a.Ke||(a.Ke=new a)}} function ea(a){var b=typeof a;if(b=="object")if(a){if(a instanceof Array)return"array";else if(a instanceof Object)return b;var c=Object.prototype.toString.call(a);if(c=="[object Window]")return"object";if(c=="[object Array]"||typeof a.length=="number"&&typeof a.splice!="undefined"&&typeof a.propertyIsEnumerable!="undefined"&&!a.propertyIsEnumerable("splice"))return"array";if(c=="[object Function]"||typeof a.call!="undefined"&&typeof a.propertyIsEnumerable!="undefined"&&!a.propertyIsEnumerable("call"))return"function"}else return"null"; else if(b=="function"&&typeof a.call=="undefined")return"object";return b}function fa(a){return a!==k}function ga(a){return ea(a)=="array"}function ha(a){var b=ea(a);return b=="array"||b=="object"&&typeof a.length=="number"}function z(a){return typeof a=="string"}function ia(a){return typeof a=="number"}function ja(a){return ea(a)=="function"}function ka(a){a=ea(a);return a=="object"||a=="array"||a=="function"}function la(a){return a[ma]||(a[ma]=++na)} var ma="closure_uid_"+Math.floor(Math.random()*2147483648).toString(36),na=0;function oa(a,b,c){return a.call.apply(a.bind,arguments)}function pa(a,b,c){a||e(Error());if(arguments.length>2){var d=Array.prototype.slice.call(arguments,2);return function(){var c=Array.prototype.slice.call(arguments);Array.prototype.unshift.apply(c,d);return a.apply(b,c)}}else return function(){return a.apply(b,arguments)}} function qa(a,b,c){qa=Function.prototype.bind&&Function.prototype.bind.toString().indexOf("native code")!=-1?oa:pa;return qa.apply(m,arguments)}function ra(a,b){var c=Array.prototype.slice.call(arguments,1);return function(){var b=Array.prototype.slice.call(arguments);b.unshift.apply(b,c);return a.apply(this,b)}}var sa=Date.now||function(){return+new Date};function A(a,b){function c(){}c.prototype=b.prototype;a.a=b.prototype;a.prototype=new c;a.prototype.constructor=a};function ta(a,b){for(var c=1;c")!=-1&&(a=a.replace(Aa,">"));a.indexOf('"')!=-1&&(a=a.replace(Ba,"""));return a}var ya=/&/g,za=//g,Ba=/\"/g,xa=/[&<>\"]/; function Ca(a,b){for(var c=0,d=String(a).replace(/^[\s\xa0]+|[\s\xa0]+$/g,"").split("."),h=String(b).replace(/^[\s\xa0]+|[\s\xa0]+$/g,"").split("."),g=Math.max(d.length,h.length),j=0;c==0&&jb)return 1;return 0};var Ea,Fa,Ga,Ha,Ia,Ja;function Ka(){return u.navigator?u.navigator.userAgent:m}function La(){return u.navigator}Ia=Ha=Ga=Fa=Ea=!1;var Ma;if(Ma=Ka()){var Na=La();Ea=Ma.indexOf("Opera")==0;Fa=!Ea&&Ma.indexOf("MSIE")!=-1;Ha=(Ga=!Ea&&Ma.indexOf("WebKit")!=-1)&&Ma.indexOf("Mobile")!=-1;Ia=!Ea&&!Ga&&Na.product=="Gecko"}var Oa=Ea,C=Fa,D=Ia,E=Ga,Pa=Ha,Qa=La();Ja=(Qa&&Qa.platform||"").indexOf("Mac")!=-1;var Ra=!!La()&&(La().appVersion||"").indexOf("X11")!=-1,Sa; a:{var Ta="",Ua;if(Oa&&u.opera)var Va=u.opera.version,Ta=typeof Va=="function"?Va():Va;else if(D?Ua=/rv\:([^\);]+)(\)|;)/:C?Ua=/MSIE\s+([^\);]+)(\)|;)/:E&&(Ua=/WebKit\/(\S+)/),Ua)var Wa=Ua.exec(Ka()),Ta=Wa?Wa[1]:"";if(C){var Xa,Ya=u.document;Xa=Ya?Ya.documentMode:k;if(Xa>parseFloat(Ta)){Sa=String(Xa);break a}}Sa=Ta}var Za={};function F(a){return Za[a]||(Za[a]=Ca(Sa,a)>=0)}var $a={};function ab(){return $a[9]||($a[9]=C&&document.documentMode&&document.documentMode>=9)};function bb(a,b,c){for(var d in a)b.call(c,a[d],d,a)}function cb(a){var b=[],c=0,d;for(d in a)b[c++]=a[d];return b}function db(a){var b=[],c=0,d;for(d in a)b[c++]=d;return b}var eb="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",");function fb(a,b){for(var c,d,h=1;h=0} function qb(a){if(!ga(a))for(var b=a.length-1;b>=0;b--)delete a[b];a.length=0}function rb(a,b){var c=jb(a,b);c>=0&&G.splice.call(a,c,1)}function sb(a){return G.concat.apply(G,arguments)}function tb(a){if(ga(a))return sb(a);else{for(var b=[],c=0,d=a.length;c=112&&a.keyCode<=123)a.keyCode=-1}catch(b){}};s.xe=p("V");s.e=function(){Db.a.e.call(this);this.relatedTarget=this.currentTarget=this.target=this.V=m};function Gb(){}var Hb=0;s=Gb.prototype;s.key=0;s.fb=!1;s.Gd=!1;s.Rb=function(a,b,c,d,h,g){ja(a)?this.Ud=!0:a&&a.handleEvent&&ja(a.handleEvent)?this.Ud=!1:e(Error("Invalid listener argument"));this.xb=a;this.ge=b;this.src=c;this.type=d;this.capture=!!h;this.wc=g;this.Gd=!1;this.key=++Hb;this.fb=!1};s.handleEvent=function(a){return this.Ud?this.xb.call(this.wc||this.src,a):this.xb.handleEvent.call(this.xb,a)};var Ib,Jb=(Ib="ScriptEngine"in u&&u.ScriptEngine()=="JScript")?u.ScriptEngineMajorVersion()+"."+u.ScriptEngineMinorVersion()+"."+u.ScriptEngineBuildVersion():"0";function Kb(a,b){this.ab=b;this.B=[];a>this.ab&&e(Error("[goog.structs.SimplePool] Initial cannot be greater than max"));for(var c=0;c=0),j;Qb=function(a){j=a};if(g){Lb=function(){return l.getObject()};Mb=function(a){l.eb(a)};Nb=function(){return n.getObject()};Ob=function(a){n.eb(a)};Pb=function(){return o.getObject()};Rb=function(){o.eb(c())};Sb=function(){return w.getObject()};Tb=function(a){w.eb(a)};Ub=function(){return t.getObject()}; Vb=function(a){t.eb(a)};var l=new Kb(0,600);l.Ta=a;var n=new Kb(0,600);n.Ta=b;var o=new Kb(0,600);o.Ta=c;var w=new Kb(0,600);w.Ta=d;var t=new Kb(0,600);t.Ta=h}else Lb=a,Mb=v,Nb=b,Ob=v,Pb=c,Rb=v,Sb=d,Tb=v,Ub=h,Vb=v})();var Wb={},J={},Xb={},Yb={}; function K(a,b,c,d,h){if(b)if(ga(b)){for(var g=0;g=0;g--){var h=a[g];if(d||b==h.capture)ac(h.key),c++}});else if(a=la(a),Xb[a])for(var a=Xb[a],h=a.length-1;h>=0;h--){var g=a[h];if(d||b==g.capture)ac(g.key),c++}}function $b(a,b,c){var d=J;return b in d&&(d=d[b],c in d&&(d=d[c],a=la(a),d[a]))?d[a]:m} function dc(a,b,c,d,h){var g=1,b=la(b);if(a[b]){a.ga--;a=a[b];a.Dc?a.Dc++:a.Dc=1;try{for(var j=a.length,l=0;l=0&&j.ga;L--)o.currentTarget= t[L],g&=dc(j,t[L],d,!0,o);if(n){j=h[!1];j.ga=j.v;for(L=0;!o.cb&&L=this.left&&a.right<=this.right&&a.top>=this.top&&a.bottom<=this.bottom:a.x>=this.left&&a.x<=this.right&&a.y>=this.top&&a.y<=this.bottom};function hc(a,b){this.width=a;this.height=b}s=hc.prototype;s.ba=function(){return new hc(this.width,this.height)};s.toString=function(){return"("+this.width+" x "+this.height+")"};s.ua=function(){return!(this.width*this.height)};s.floor=function(){this.width=Math.floor(this.width);this.height=Math.floor(this.height);return this};s.round=function(){this.width=Math.round(this.width);this.height=Math.round(this.height);return this};function ic(a,b,c,d){this.left=a;this.top=b;this.width=c;this.height=d}ic.prototype.ba=function(){return new ic(this.left,this.top,this.width,this.height)};ic.prototype.toString=function(){return"("+this.left+", "+this.top+" - "+this.width+"w x "+this.height+"h)"}; ic.prototype.Td=function(a){var b=Math.max(this.left,a.left),c=Math.min(this.left+this.width,a.left+a.width);if(b<=c){var d=Math.max(this.top,a.top),a=Math.min(this.top+this.height,a.top+a.height);if(d<=a)return this.left=b,this.top=d,this.width=c-b,this.height=a-d,!0}return!1}; ic.prototype.contains=function(a){return a instanceof ic?this.left<=a.left&&this.left+this.width>=a.left+a.width&&this.top<=a.top&&this.top+this.height>=a.top+a.height:a.x>=this.left&&a.x<=this.left+this.width&&a.y>=this.top&&a.y<=this.top+this.height};var jc;function kc(a){return(a=a.className)&&typeof a.split=="function"?a.split(/\s+/):[]}function lc(a,b){var c=kc(a),d=wb(arguments,1),h;h=c;for(var g=0,j=0;j0)){var j;a:{if(g&&typeof g.length=="number")if(ka(g)){j=typeof g.item=="function"||typeof g.item=="string";break a}else if(ja(g)){j=typeof g.item=="function";break a}j=!1}kb(j?tb(g):g,d)}else d(g)}}function Q(a){return document.createElement(a)}function tc(a){return a.compatMode=="CSS1Compat"}function uc(a){for(var b;b=a.firstChild;)a.removeChild(b)} function vc(a){a&&a.parentNode&&a.parentNode.removeChild(a)}function wc(a){for(;a&&a.nodeType!=1;)a=a.nextSibling;return a}function xc(a,b){if(a.contains&&b.nodeType==1)return a==b||a.contains(b);if(typeof a.compareDocumentPosition!="undefined")return a==b||Boolean(a.compareDocumentPosition(b)&16);for(;b&&a!=b;)b=b.parentNode;return b==a}function O(a){return a.nodeType==9?a:a.ownerDocument||a.document} function yc(a,b){if("textContent"in a)a.textContent=b;else if(a.firstChild&&a.firstChild.nodeType==3){for(;a.lastChild!=a.firstChild;)a.removeChild(a.lastChild);a.firstChild.data=b}else uc(a),a.appendChild(O(a).createTextNode(b))}var zc={SCRIPT:1,STYLE:1,HEAD:1,IFRAME:1,OBJECT:1},Ac={IMG:" ",BR:"\n"};function Bc(a){var b=a.getAttributeNode("tabindex");return b&&b.specified?(a=a.tabIndex,ia(a)&&a>=0&&a<32768):!1} function Cc(a){if(oc&&"innerText"in a)a=a.innerText.replace(/(\r\n|\r|\n)/g,"\n");else{var b=[];Dc(a,b,!0);a=b.join("")}a=a.replace(/ \xAD /g," ").replace(/\xAD/g,"");a=a.replace(/\u200B/g,"");oc||(a=a.replace(/ +/g," "));a!=" "&&(a=a.replace(/^\s*/,""));return a}function Ec(a){var b=[];Dc(a,b,!1);return b.join("")} function Dc(a,b,c){if(!(a.nodeName in zc))if(a.nodeType==3)c?b.push(String(a.nodeValue).replace(/(\r\n|\r|\n)/g,"")):b.push(a.nodeValue);else if(a.nodeName in Ac)b.push(Ac[a.nodeName]);else for(a=a.firstChild;a;)Dc(a,b,c),a=a.nextSibling}function pc(a){this.o=a||u.document||document}s=pc.prototype;s.S=N;function Fc(a){return a.o}s.b=function(a){return z(a)?this.o.getElementById(a):a}; function Gc(a,b){var c;c=a.o;var d=b&&b!="*"?b.toUpperCase():"";c=c.querySelectorAll&&c.querySelector&&(!E||tc(document)||F("528"))&&d?c.querySelectorAll(d+""):c.getElementsByTagName(d||"*");return c} s.d=function(a,b,c){var d=this.o,h=arguments,g=h[0],j=h[1];if(!nc&&j&&(j.name||j.type)){g=["<",g];j.name&&g.push(' name="',wa(j.name),'"');if(j.type){g.push(' type="',wa(j.type),'"');var l={};fb(l,j);j=l;delete j.type}g.push(">");g=g.join("")}g=d.createElement(g);if(j)z(j)?g.className=j:ga(j)?lc.apply(m,[g].concat(j)):qc(g,j);h.length>2&&sc(d,g,h);return g};s.createElement=function(a){return this.o.createElement(a)};s.createTextNode=function(a){return this.o.createTextNode(a)}; function Hc(a){return tc(a.o)}function Ic(a){var b=a.o,a=!E&&tc(b)?b.documentElement:b.body,b=b.parentWindow||b.defaultView;return new M(b.pageXOffset||a.scrollLeft,b.pageYOffset||a.scrollTop)}s.appendChild=function(a,b){a.appendChild(b)};s.contains=xc;function R(a,b){var c=O(a);return c.defaultView&&c.defaultView.getComputedStyle&&(c=c.defaultView.getComputedStyle(a,m))?c[b]||c.getPropertyValue(b):""}function Jc(a,b){return R(a,b)||(a.currentStyle?a.currentStyle[b]:m)||a.style[b]}function Kc(a){var b=a.getBoundingClientRect();if(C)a=a.ownerDocument,b.left-=a.documentElement.clientLeft+a.body.clientLeft,b.top-=a.documentElement.clientTop+a.body.clientTop;return b} function Lc(a){if(C)return a.offsetParent;for(var b=O(a),c=Jc(a,"position"),d=c=="fixed"||c=="absolute",a=a.parentNode;a&&a!=b;a=a.parentNode)if(c=Jc(a,"position"),d=d&&c=="static"&&a!=b.documentElement&&a!=b.body,!d&&(a.scrollWidth>a.clientWidth||a.scrollHeight>a.clientHeight||c=="fixed"||c=="absolute"||c=="relative"))return a;return m} function Mc(a){for(var b=new gc(0,Infinity,Infinity,0),c=N(a),d=c.o.body,h=c.o.documentElement,g=!E&&tc(c.o)?c.o.documentElement:c.o.body;a=Lc(a);)if((!C||a.clientWidth!=0)&&(!E||a.clientHeight!=0||a!=d)&&a!=d&&a!=h&&Jc(a,"overflow")!="visible"){var j=Nc(a),l;l=a;if(D&&!F("1.9")){var n=parseFloat(R(l,"borderLeftWidth"));if(Qc(l)){var o=l.offsetWidth-l.clientWidth-n-parseFloat(R(l,"borderRightWidth"));n+=o}l=new M(n,parseFloat(R(l,"borderTopWidth")))}else l=new M(l.clientLeft,l.clientTop);j.x+=l.x; j.y+=l.y;b.top=Math.max(b.top,j.y);b.right=Math.min(b.right,j.x+a.clientWidth);b.bottom=Math.min(b.bottom,j.y+a.clientHeight);b.left=Math.max(b.left,j.x)}d=g.scrollLeft;g=g.scrollTop;b.left=Math.max(b.left,d);b.top=Math.max(b.top,g);c=c.o.parentWindow||c.o.defaultView||window;h=c.document;E&&!F("500")&&!Pa?(typeof c.innerHeight=="undefined"&&(c=window),h=c.innerHeight,a=c.document.documentElement.scrollHeight,c==c.top&&a=0&&b.left>=0&&b.bottom>b.top&&b.right>b.left?b:m} function Nc(a){var b,c=O(a),d=Jc(a,"position"),h=D&&c.getBoxObjectFor&&!a.getBoundingClientRect&&d=="absolute"&&(b=c.getBoxObjectFor(a))&&(b.screenX<0||b.screenY<0),g=new M(0,0),j;b=c?c.nodeType==9?c:O(c):document;j=C&&!ab()&&!Hc(N(b))?b.body:b.documentElement;if(a==j)return g;if(a.getBoundingClientRect)b=Kc(a),a=Ic(N(c)),g.x=b.left+a.x,g.y=b.top+a.y;else if(c.getBoxObjectFor&&!h)b=c.getBoxObjectFor(a),a=c.getBoxObjectFor(j),g.x=b.screenX-a.screenX,g.y=b.screenY-a.screenY;else{b=a;do{g.x+=b.offsetLeft; g.y+=b.offsetTop;b!=a&&(g.x+=b.clientLeft||0,g.y+=b.clientTop||0);if(E&&Jc(b,"position")=="fixed"){g.x+=c.body.scrollLeft;g.y+=c.body.scrollTop;break}b=b.offsetParent}while(b&&b!=a);if(Oa||E&&d=="absolute")g.y-=c.body.offsetTop;for(b=a;(b=Lc(b))&&b!=c.body&&b!=j;)if(g.x-=b.scrollLeft,!Oa||b.tagName!="TR")g.y-=b.scrollTop}return g}function Rc(a,b){typeof a=="number"&&(a=(b?Math.round(a):a)+"px");return a} function Sc(a){if(Jc(a,"display")!="none")return Tc(a);var b=a.style,c=b.display,d=b.visibility,h=b.position;b.visibility="hidden";b.position="absolute";b.display="inline";a=Tc(a);b.display=c;b.position=h;b.visibility=d;return a}function Tc(a){var b=a.offsetWidth,c=a.offsetHeight,d=E&&!b&&!c;return(!fa(b)||d)&&a.getBoundingClientRect?(a=Kc(a),new hc(a.right-a.left,a.bottom-a.top)):new hc(b,c)}function Uc(a){var b=Nc(a),a=Sc(a);return new ic(b.x,b.y,a.width,a.height)} function Vc(a,b){a.style.display=b?"":"none"}function Wc(a){C?a.cssText=".goog-tabpane-clear { clear: both; height: 0px; overflow: hidden }":a[E?"innerText":"innerHTML"]=".goog-tabpane-clear { clear: both; height: 0px; overflow: hidden }"}function Qc(a){return"rtl"==Jc(a,"direction")}var Xc=D?"MozUserSelect":E?"WebkitUserSelect":m; function Yc(a,b,c){c=!c?a.getElementsByTagName("*"):m;if(Xc){if(b=b?"none":"",a.style[Xc]=b,c)for(var a=0,d;d=c[a];a++)d.style[Xc]=b}else if(C||Oa)if(b=b?"on":"",a.setAttribute("unselectable",b),c)for(a=0;d=c[a];a++)d.setAttribute("unselectable",b)}function Zc(a,b){if(/^\d+px?$/.test(b))return parseInt(b,10);else{var c=a.style.left,d=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;a.style.left=b;var h=a.style.pixelLeft;a.style.left=c;a.runtimeStyle.left=d;return h}} function $c(a,b){return Zc(a,a.currentStyle?a.currentStyle[b]:m)}var ad={thin:2,medium:4,thick:6};function bd(a,b){if((a.currentStyle?a.currentStyle[b+"Style"]:m)=="none")return 0;var c=a.currentStyle?a.currentStyle[b+"Width"]:m;return c in ad?ad[c]:Zc(a,c)};function cd(a){this.Rd=a;this.r=[]}A(cd,Ab);var dd=[];s=cd.prototype;s.g=function(a,b,c,d,h){ga(b)||(dd[0]=b,b=dd);for(var g=0;g=0&&g.ga;j--)a.currentTarget=h[j],d&=dc(g,h[j],a.type,!0,a)&&a.$b!=!1}if(!1 in c)if(g=c[!1],g.ga=g.v,b)for(j=0;!a.cb&&jpd(this))&&e(Error("Child component index out of bounds"));if(!this.qa||!this.A)this.qa={},this.A=[];if(a.getParent()==this)this.qa[kd(a)]=a,rb(this.A,a);else{var d=this.qa,h=kd(a);h in d&&e(Error('The object already contains the key "'+h+'"'));d[h]=a}md(a,this);vb(this.A,b,0,a);a.k&&this.k&&a.getParent()==this?(c=this.w(),c.insertBefore(a.b(),c.childNodes[b]||m)):c?(this.m||this.d(),b=T(this,b+1),S(a,this.w(), b?b.m:m)):this.k&&!a.k&&a.m&&a.i()};s.w=p("m");function qd(a){if(a.ac==m)a.ac=Qc(a.k?a.m:a.ca.o.body);return a.ac}s.Ab=function(a){this.k&&e(Error("Component already rendered"));this.ac=a};function pd(a){return a.A?a.A.length:0}function nd(a,b){return a.qa&&b?(b in a.qa?a.qa[b]:k)||m:m}function T(a,b){return a.A?a.A[b]||m:m}function od(a,b,c){a.A&&kb(a.A,b,c)}function rd(a,b){return a.A&&b?jb(a.A,b):-1} s.removeChild=function(a,b){if(a){var c=z(a)?a:kd(a),a=nd(this,c);if(c&&a){var d=this.qa;c in d&&delete d[c];rb(this.A,a);b&&(a.ja(),a.m&&vc(a.m));md(a,m)}}a||e(Error("Child is not in parent component"));return a};function sd(a,b){a.setAttribute("role",b);a.zf=b}function U(a,b,c){a.setAttribute("aria-"+b,c)};function td(){}var ud;y(td);s=td.prototype;s.la=aa();s.d=function(a){var b=a.S().d("div",this.Va(a).join(" "),a.Ca);this.ud(a,b);return b};s.w=function(a){return a};s.Nb=function(a,b,c){if(a=a.b?a.b():a)if(C&&!F("7")){var d=vd(kc(a),b);d.push(b);ra(c?lc:mc,a).apply(m,d)}else c?lc(a,b):mc(a,b)};s.tb=function(a){qd(a)&&this.Ab(a.b(),!0);a.isEnabled()&&this.gb(a,a.s)};s.ud=function(a,b){a.isEnabled()||this.T(b,1,!0);a.n&8&&this.T(b,8,!0);a.u&16&&this.T(b,16,a.vb());a.u&64&&this.T(b,64,!!(a.n&64))}; s.Jc=function(a,b){Yc(a,!b,!C&&!Oa)};s.Ab=function(a,b){this.Nb(a,this.j()+"-rtl",b)};s.Za=function(a){var b;return a.u&32&&(b=a.C())?Bc(b):!1};s.gb=function(a,b){var c;if(a.u&32&&(c=a.C())){if(!b&&a.n&32){try{c.blur()}catch(d){}a.n&32&&a.Wa(m)}if(Bc(c)!=b)b?c.tabIndex=0:(c.tabIndex=-1,c.removeAttribute("tabIndex"))}};s.Z=function(a,b){Vc(a,b)};s.O=function(a,b,c){var d=a.b();if(d){var h=this.nc(b);h&&this.Nb(a,h,c);this.T(d,b,c)}}; s.T=function(a,b,c){ud||(ud={1:"disabled",8:"selected",16:"checked",64:"expanded"});(b=ud[b])&&U(a,b,c)};s.N=function(a,b){var c=this.w(a);if(c&&(uc(c),b))if(z(b))yc(c,b);else{var d=function(a){if(a){var b=O(c);c.appendChild(z(a)?b.createTextNode(a):a)}};ga(b)?kb(b,d):ha(b)&&!("nodeType"in b)?kb(tb(b),d):d(b)}};s.C=function(a){return a.b()};s.j=r("goog-control"); s.Va=function(a){var b=this.j(),c=[b],d=this.j();d!=b&&c.push(d);b=a.n;for(d=[];b;){var h=b&-b;d.push(this.nc(h));b&=~h}c.push.apply(c,d);(a=a.ka)&&c.push.apply(c,a);C&&!F("7")&&c.push.apply(c,vd(c));return c};function vd(a,b){var c=[];b&&(a=a.concat([b]));kb([],function(d){ob(d,ra(pb,a))&&(!b||pb(d,b))&&c.push(d.join("_"))});return c}s.nc=function(a){if(!this.Id){var b=this.j();this.Id={1:b+"-disabled",2:b+"-hover",4:b+"-active",8:b+"-selected",16:b+"-checked",32:b+"-focused",64:b+"-open"}}return this.Id[a]};function wd(a,b){a||e(Error("Invalid class name "+a));ja(b)||e(Error("Invalid decorator function "+b))}var xd={};function yd(a,b,c,d,h){if(!C&&(!E||!F("525")))return!0;if(Ja&&h)return zd(a);if(h&&!d)return!1;if(!c&&(b==17||b==18))return!1;if(C&&d&&b==a)return!1;switch(a){case 13:return!(C&&ab());case 27:return!E}return zd(a)} function zd(a){if(a>=48&&a<=57)return!0;if(a>=96&&a<=106)return!0;if(a>=65&&a<=90)return!0;if(E&&a==0)return!0;switch(a){case 32:case 63:case 107:case 109:case 110:case 111:case 186:case 189:case 187:case 188:case 190:case 191:case 192:case 222:case 219:case 220:case 221:return!0;default:return!1}};function Ad(a,b){a&&Bd(this,a,b)}A(Ad,gd);s=Ad.prototype;s.m=m;s.Bc=m;s.kd=m;s.Cc=m;s.Ja=-1;s.Ha=-1; var Cd={3:13,12:144,63232:38,63233:40,63234:37,63235:39,63236:112,63237:113,63238:114,63239:115,63240:116,63241:117,63242:118,63243:119,63244:120,63245:121,63246:122,63247:123,63248:44,63272:46,63273:36,63275:35,63276:33,63277:34,63289:144,63302:45},Dd={Up:38,Down:40,Left:37,Right:39,Enter:13,F1:112,F2:113,F3:114,F4:115,F5:116,F6:117,F7:118,F8:119,F9:120,F10:121,F11:122,F12:123,"U+007F":46,Home:36,End:35,PageUp:33,PageDown:34,Insert:45},Ed={61:187,59:186},Fd=C||E&&F("525");s=Ad.prototype; s.De=function(a){if(E&&(this.Ja==17&&!a.ctrlKey||this.Ja==18&&!a.altKey))this.Ha=this.Ja=-1;Fd&&!yd(a.keyCode,this.Ja,a.shiftKey,a.ctrlKey,a.altKey)?this.handleEvent(a):this.Ha=D&&a.keyCode in Ed?Ed[a.keyCode]:a.keyCode};s.Ee=function(){this.Ha=this.Ja=-1}; s.handleEvent=function(a){var b=a.V,c,d;C&&a.type=="keypress"?(c=this.Ha,d=c!=13&&c!=27?b.keyCode:0):E&&a.type=="keypress"?(c=this.Ha,d=b.charCode>=0&&b.charCode<63232&&zd(c)?b.charCode:0):Oa?(c=this.Ha,d=zd(c)?b.keyCode:0):(c=b.keyCode||this.Ha,d=b.charCode||0,Ja&&d==63&&!c&&(c=191));var h=c,g=b.keyIdentifier;c?c>=63232&&c in Cd?h=Cd[c]:c==25&&a.shiftKey&&(h=9):g&&g in Dd&&(h=Dd[g]);a=h==this.Ja;this.Ja=h;b=new Gd(h,d,a,b);try{this.dispatchEvent(b)}finally{b.F()}};s.b=p("m"); function Bd(a,b,c){a.Cc&&a.detach();a.m=b;a.Bc=K(a.m,"keypress",a,c);a.kd=K(a.m,"keydown",a.De,c,a);a.Cc=K(a.m,"keyup",a.Ee,c,a)}s.detach=function(){if(this.Bc)ac(this.Bc),ac(this.kd),ac(this.Cc),this.Cc=this.kd=this.Bc=m;this.m=m;this.Ha=this.Ja=-1};s.e=function(){Ad.a.e.call(this);this.detach()};function Gd(a,b,c,d){d&&this.Rb(d,k);this.type="key";this.keyCode=a;this.charCode=b;this.repeat=c}A(Gd,Db);function V(a,b,c){hd.call(this,c);if(!b){for(var b=this.constructor,d;b;){d=la(b);if(d=xd[d])break;b=b.a?b.a.constructor:m}b=d?ja(d.p)?d.p():new d:m}this.f=b;this.Ca=a}A(V,hd);s=V.prototype;s.Ca=m;s.n=0;s.u=39;s.Fd=255;s.zd=0;s.s=!0;s.ka=m;s.sc=!0;s.Tc=!1;s.qd=m;function Hd(a,b){a.k&&b!=a.sc&&Id(a,b);a.sc=b}s.C=function(){return this.f.C(this)};s.oc=function(){return this.W||(this.W=new Ad)};function Jd(a,b){if(b)a.ka?pb(a.ka,b)||a.ka.push(b):a.ka=[b],a.f.Nb(a,b,!0)} s.Nb=function(a,b){if(b)Jd(this,a);else if(a&&this.ka){rb(this.ka,a);if(this.ka.length==0)this.ka=m;this.f.Nb(this,a,!1)}};s.d=function(){var a=this.f.d(this);this.m=a;var b=this.qd||this.f.la();b&&sd(a,b);this.Tc||this.f.Jc(a,!1);this.s||this.f.Z(a,!1)};s.w=function(){return this.f.w(this.b())};s.i=function(){V.a.i.call(this);this.f.tb(this);if(this.u&-2&&(this.sc&&Id(this,!0),this.u&32)){var a=this.C();if(a){var b=this.oc();Bd(b,a);ld(this).g(b,"key",this.sa).g(a,"focus",this.rc).g(a,"blur",this.Wa)}}}; function Id(a,b){var c=ld(a),d=a.b();b?(c.g(d,"mouseover",a.uc).g(d,"mousedown",a.Ea).g(d,"mouseup",a.Fa).g(d,"mouseout",a.tc),C&&c.g(d,"dblclick",a.Qd)):(c.ha(d,"mouseover",a.uc).ha(d,"mousedown",a.Ea).ha(d,"mouseup",a.Fa).ha(d,"mouseout",a.tc),C&&c.ha(d,"dblclick",a.Qd))}s.ja=function(){V.a.ja.call(this);this.W&&this.W.detach();this.s&&this.isEnabled()&&this.f.gb(this,!1)};s.e=function(){V.a.e.call(this);this.W&&(this.W.F(),delete this.W);delete this.f;this.ka=this.Ca=m}; s.N=function(a){this.f.N(this.b(),a);this.Ca=a};s.Ob=function(){var a=this.Ca;if(!a)return"";a=z(a)?a:ga(a)?lb(a,Ec).join(""):Cc(a);return ua(a)};s.Ab=function(a){V.a.Ab.call(this,a);var b=this.b();b&&this.f.Ab(b,a)};s.Jc=function(a){this.Tc=a;var b=this.b();b&&this.f.Jc(b,a)};s.Z=function(a,b){if(b||this.s!=a&&this.dispatchEvent(a?"show":"hide")){var c=this.b();c&&this.f.Z(c,a);this.isEnabled()&&this.f.gb(this,a);this.s=a;return!0}return!1};s.isEnabled=function(){return!(this.n&1)}; s.wa=function(a){Kd(this,2,a)&&this.O(2,a)};s.ub=function(){return!!(this.n&4)};s.setActive=function(a){Kd(this,4,a)&&this.O(4,a)};s.xd=function(a){Kd(this,8,a)&&this.O(8,a)};s.vb=function(){return!!(this.n&16)};s.bc=function(a){Kd(this,16,a)&&this.O(16,a)};s.t=function(a){Kd(this,64,a)&&this.O(64,a)};s.O=function(a,b){if(this.u&a&&b!=!!(this.n&a))this.f.O(this,a,b),this.n=b?this.n|a:this.n&~a}; function Ld(a,b,c){a.k&&a.n&b&&!c&&e(Error("Component already rendered"));!c&&a.n&b&&a.O(b,!1);a.u=c?a.u|b:a.u&~b}function W(a,b){return!!(a.Fd&b)&&!!(a.u&b)}function Kd(a,b,c){return!!(a.u&b)&&!!(a.n&b)!=c&&(!(a.zd&b)||a.dispatchEvent(jd(b,c)))&&!a.Lb}s.uc=function(a){(!a.relatedTarget||!xc(this.b(),a.relatedTarget))&&this.dispatchEvent("enter")&&this.isEnabled()&&W(this,2)&&this.wa(!0)}; s.tc=function(a){if((!a.relatedTarget||!xc(this.b(),a.relatedTarget))&&this.dispatchEvent("leave"))W(this,4)&&this.setActive(!1),W(this,2)&&this.wa(!1)};s.Ea=function(a){if(this.isEnabled()&&(W(this,2)&&this.wa(!0),Fb(a)&&(!E||!Ja||!a.ctrlKey)))W(this,4)&&this.setActive(!0),this.f.Za(this)&&this.C().focus();!this.Tc&&Fb(a)&&(!E||!Ja||!a.ctrlKey)&&a.preventDefault()};s.Fa=function(a){this.isEnabled()&&(W(this,2)&&this.wa(!0),this.ub()&&this.bb(a)&&W(this,4)&&this.setActive(!1))}; s.Qd=function(a){this.isEnabled()&&this.bb(a)};s.bb=function(a){W(this,16)&&this.bc(!this.vb());W(this,8)&&this.xd(!0);W(this,64)&&this.t(!(this.n&64));var b=new H("action",this);if(a)for(var c=["altKey","ctrlKey","metaKey","shiftKey","platformModifierKey"],d,h=0;d=c[h];h++)b[d]=a[d];return this.dispatchEvent(b)};s.rc=function(){W(this,32)&&Kd(this,32,!0)&&this.O(32,!0)};s.Wa=function(){W(this,4)&&this.setActive(!1);W(this,32)&&Kd(this,32,!1)&&this.O(32,!1)}; s.sa=function(a){return this.s&&this.isEnabled()&&this.Xa(a)?(a.preventDefault(),a.stopPropagation(),!0):!1};s.Xa=function(a){return a.keyCode==13&&this.bb(a)};ja(V)||e(Error("Invalid component class "+V));ja(td)||e(Error("Invalid renderer class "+td));var Md=la(V);xd[Md]=td;wd("goog-control",function(){return new V(m)});var Nd={};function Od(){}Od.prototype.id=v;Od.prototype.Kb=function(a){if(this.id()>a.id())return 1;else if(this.id()a.lb)return 1;else if(this.lba.oa?1:0};function Wd(a,b,c,d){X.call(this,a,b,c,d);this.N(a.toString())}A(Wd,X);Wd.prototype.i=function(){Xd.a.i.call(this);this.b().title=this.item().toString()};Wd.prototype.update=function(a){this.N(a.toString())};function Yd(a){this.U=a}Yd.prototype.Ub=function(a){return new Wd(a,this.U)};function Zd(){}A(Zd,td);y(Zd);s=Zd.prototype;s.la=r("button");s.T=function(a,b,c){b==16?U(a,"pressed",c):Zd.a.T.call(this,a,b,c)};s.d=function(a){var b=Zd.a.d.call(this,a),c=a.qc();c&&this.yd(b,c);(c=a.ea())&&this.Oa(b,c);a.u&16&&this.T(b,16,a.vb());return b};s.ea=v;s.Oa=v;s.qc=function(a){return a.title};s.yd=function(a,b){if(a)a.title=b||""};s.j=r("goog-button");function $d(){}A($d,Zd);y($d);s=$d.prototype;s.la=aa();s.d=function(a){Hd(a,!1);a.Fd&=-256;Ld(a,32,!1);return a.S().d("button",{"class":this.Va(a).join(" "),disabled:!a.isEnabled(),title:a.qc()||"",value:a.ea()||""},a.Ob()||"")};s.tb=function(a){ld(a).g(a.b(),"click",a.bb)};s.Jc=v;s.Ab=v;s.Za=function(a){return a.isEnabled()};s.gb=v;s.O=function(a,b,c){$d.a.O.call(this,a,b,c);if((a=a.b())&&b==1)a.disabled=c};s.ea=function(a){return a.value};s.Oa=function(a,b){if(a)a.value=b};s.T=v;function Y(a,b,c){V.call(this,a,b||$d.p(),c)}A(Y,V);s=Y.prototype;s.ea=p("gc");s.Oa=function(a){this.gc=a;this.f.Oa(this.b(),a)};s.qc=p("le");s.yd=function(a){this.le=a;this.f.yd(this.b(),a)};s.e=function(){Y.a.e.call(this);delete this.gc;delete this.le};s.i=function(){Y.a.i.call(this);if(this.u&32){var a=this.C();a&&ld(this).g(a,"keyup",this.Xa)}};s.Xa=function(a){return a.keyCode==13&&a.type=="key"||a.keyCode==32&&a.type=="keyup"?this.bb(a):a.keyCode==32};wd("goog-button",function(){return new Y(m)});function ae(a){this.element=P(a)}function be(a){a.element.style.display="block"}function ce(a){a.element.style.display="none"}function ee(a){a.element.innerHTML='
'}function fe(a){a.element.innerHTML=""};function ge(a){if(typeof a.ra=="function")return a.ra();if(z(a))return a.split("");if(ha(a)){for(var b=[],c=a.length,d=0;d0&&a1){c%2&&e(Error("Uneven number of arguments"));for(var d=0;d2*this.v&&oe(this),!0):!1}; function oe(a){if(a.v!=a.r.length){for(var b=0,c=0;b0&&c.push(", ");var g;g=d[h];switch(typeof g){case "object":g=g?"object":"null";break;case "string":break;case "number":g=String(g);break;case "boolean":g=g?"true":"false";break;case "function":g=(g=te(g))?g:"[fn]";break;default:g=typeof g}g.length>40&&(g=g.substr(0,40)+"...");c.push(g)}b.push(a);c.push(")\n");try{c.push(se(a.caller,b))}catch(j){c.push("[exception trying to get caller]\n")}}else a? c.push("[...long stack...]"):c.push("[end]");return c.join("")}function te(a){if(ue[a])return ue[a];a=String(a);if(!ue[a]){var b=/function ([^\(]+)/.exec(a);ue[a]=b?b[1]:"[Anonymous]"}return ue[a]}var ue={};function ve(a,b,c,d,h){this.reset(a,b,c,d,h)}ve.prototype.$e=0;ve.prototype.Od=m;ve.prototype.Nd=m;var we=0;ve.prototype.reset=function(a,b,c,d,h){this.$e=typeof h=="number"?h:we++;this.Bf=d||sa();this.Tb=a;this.Me=b;this.xf=c;delete this.Od;delete this.Nd};ve.prototype.je=ba("Tb");function xe(a){this.Ne=a}xe.prototype.q=m;xe.prototype.Tb=m;xe.prototype.A=m;xe.prototype.Sd=m;function ye(a,b){this.name=a;this.value=b}ye.prototype.toString=p("name");var ze=new ye("SEVERE",1E3),Ae=new ye("WARNING",900),Be=new ye("INFO",800),Ce=new ye("CONFIG",700),De=new ye("FINE",500),Ee=new ye("FINEST",300);s=xe.prototype;s.getParent=p("q");s.je=ba("Tb");function Fe(a){if(a.Tb)return a.Tb;if(a.q)return Fe(a.q);ib("Root logger has no level set.");return m} s.log=function(a,b,c){if(a.value>=Fe(this).value){a=this.ye(a,b,c);b="log:"+a.Me;u.console&&(u.console.timeStamp?u.console.timeStamp(b):u.console.markTimeline&&u.console.markTimeline(b));u.msWriteProfilerMark&&u.msWriteProfilerMark(b);for(b=this;b;){var c=b,d=a;if(c.Sd)for(var h=0,g=k;g=c.Sd[h];h++)g(d);b=b.getParent()}}}; s.ye=function(a,b,c){var d=new ve(a,String(b),this.Ne);if(c){d.Od=c;var h;var g=arguments.callee.caller;try{var j;var l=da("window.location.href");if(z(c))j={message:c,name:"Unknown error",lineNumber:"Not available",fileName:l,stack:"Not available"};else{var n,o,w=!1;try{n=c.lineNumber||c.vf||"Not available"}catch(t){n="Not available",w=!0}try{o=c.fileName||c.filename||c.sourceURL||l}catch(B){o="Not available",w=!0}j=w||!c.lineNumber||!c.fileName||!c.stack?{message:c.message,name:c.name,lineNumber:n, fileName:o,stack:c.stack||"Not available"}:c}h="Message: "+wa(j.message)+'\nUrl: '+j.fileName+"\nLine: "+j.lineNumber+"\n\nBrowser stack:\n"+wa(j.stack+"-> ")+"[end]\n\nJS stack traversal:\n"+wa(re(g)+"-> ")}catch(L){h="Exception trying to expose exception! You win, we lose. "+L}d.Nd=h}return d};s.info=function(a,b){this.log(Be,a,b)};function Ge(a,b){a.log(De,b,k)}s.cc=ba("q");var He={},Ie=m; function Je(a){Ie||(Ie=new xe(""),He[""]=Ie,Ie.je(Ce));var b;if(!(b=He[a])){b=new xe(a);var c=a.lastIndexOf("."),d=a.substr(c+1),c=Je(a.substr(0,c));if(!c.A)c.A={};c.A[d]=b;b.cc(c);He[a]=b}return b};function Ke(){if(D)this.Sa={},this.Pc={},this.Lc=[]}Ke.prototype.D=Je("goog.net.xhrMonitor");Ke.prototype.da=D;function Le(a){var b=Me;if(b.da){var c=z(a)?a:ka(a)?la(a):"";b.D.log(Ee,"Pushing context: "+a+" ("+c+")",k);b.Lc.push(c)}}function Ne(){var a=Me;if(a.da){var b=a.Lc.pop();a.D.log(Ee,"Popping context: "+b,k);Oe(a,b)}}function Pe(a){var b=Me;if(b.da){a=la(a);Ge(b.D,"Opening XHR : "+a);for(var c=0;c0)Ge(this.D,$e(this,"Will abort after "+this.Mc+"ms if incomplete")),this.jb=ke.setTimeout(qa(this.cf, this),this.Mc);Ge(this.D,$e(this,"Sending request"));this.yc=!0;this.h.send(a);this.yc=!1}catch(j){Ge(this.D,$e(this,"Send error: "+j.message)),af(this,j)}};s.dispatchEvent=function(a){if(this.h){Le(this.h);try{return Ye.a.dispatchEvent.call(this,a)}finally{Ne()}}else return Ye.a.dispatchEvent.call(this,a)};s.cf=function(){if(typeof ca!="undefined"&&this.h)this.Ia="Timed out after "+this.Mc+"ms, aborting",this.Sb=8,Ge(this.D,$e(this,this.Ia)),this.dispatchEvent("timeout"),this.abort(8)}; function af(a,b){a.ya=!1;if(a.h)a.Ya=!0,a.h.abort(),a.Ya=!1;a.Ia=b;a.Sb=5;bf(a);cf(a)}function bf(a){if(!a.$c)a.$c=!0,a.dispatchEvent("complete"),a.dispatchEvent("error")}s.abort=function(a){if(this.h&&this.ya)Ge(this.D,$e(this,"Aborting")),this.ya=!1,this.Ya=!0,this.h.abort(),this.Ya=!1,this.Sb=a||7,this.dispatchEvent("complete"),this.dispatchEvent("abort"),cf(this)};s.e=function(){if(this.h){if(this.ya)this.ya=!1,this.Ya=!0,this.h.abort(),this.Ya=!1;cf(this,!0)}Ye.a.e.call(this)}; s.ce=function(){!this.jd&&!this.yc&&!this.Ya?this.Pe():df(this)};s.Pe=function(){df(this)}; function df(a){if(a.ya&&typeof ca!="undefined")if(a.Oc[1]&&ef(a)==4&&ff(a)==2)Ge(a.D,$e(a,"Local request error detected and ignored"));else if(a.yc&&ef(a)==4)ke.setTimeout(qa(a.ce,a),0);else if(a.dispatchEvent("readystatechange"),ef(a)==4){Ge(a.D,$e(a,"Request complete"));a.ya=!1;var b;a:switch(ff(a)){case 0:b=z(a.wb)?a.wb.match(ie)[1]||m:a.wb.uf();b=!(b?Ze.test(b):self.location?Ze.test(self.location.protocol):1);break a;case 200:case 201:case 202:case 204:case 304:case 1223:b=!0;break a;default:b= !1}if(b)a.dispatchEvent("complete"),a.dispatchEvent("success");else{a.Sb=6;var c;try{c=ef(a)>2?a.h.statusText:""}catch(d){Ge(a.D,"Can not get status: "+d.message),c=""}a.Ia=c+" ["+ff(a)+"]";bf(a)}cf(a)}} function cf(a,b){if(a.h){var c=a.h,d=a.Oc[0]?v:m;a.h=m;a.Oc=m;if(a.jb)ke.clearTimeout(a.jb),a.jb=m;b||(Le(c),a.dispatchEvent("ready"),Ne());var h=Me;if(h.da){var g=la(c);Ge(h.D,"Closing XHR : "+g);delete h.Pc[g];for(var j in h.Sa)rb(h.Sa[j],g),h.Sa[j].length==0&&delete h.Sa[j]}try{c.onreadystatechange=d}catch(l){a.D.log(ze,"Problem encountered resetting onreadystatechange: "+l.message,k)}}}s.ub=function(){return!!this.h};function ef(a){return a.h?a.h.readyState:0} function ff(a){try{return ef(a)>2?a.h.status:-1}catch(b){return a.D.log(Ae,"Can not get status: "+b.message,k),-1}}function gf(a){if(a.h)return Re(a.h.responseText)}function $e(a,b){return b+" ["+a.Wd+" "+a.wb+" "+ff(a)+"]"};function hf(){this.Da=[]}s=hf.prototype;s.ta=0;s.ib=0;s.mc=function(a){this.Da[this.ib++]=a};s.pb=function(){if(this.ta!=this.ib){var a=this.Da[this.ta];delete this.Da[this.ta];this.ta++;return a}};s.L=function(){return this.ib-this.ta};s.ua=function(){return this.ib-this.ta==0};s.clear=function(){this.ib=this.ta=this.Da.length=0};s.contains=function(a){return pb(this.Da,a)};s.remove=function(a){a=jb(this.Da,a);if(a<0)return!1;a==this.ta?this.pb():(G.splice.call(this.Da,a,1),this.ib--);return!0}; s.ra=function(){return this.Da.slice(this.ta,this.ib)};function jf(a,b){this.Xd=a||0;this.ab=b||10;this.Xd>this.ab&&e(Error(kf));this.B=new hf;this.Ga=new pe;this.Zc=0;this.md=m;this.jc()}A(jf,Ab);var kf="[goog.structs.Pool] Min can not be greater than max";s=jf.prototype;s.getObject=function(){var a=sa();if(!(this.md!=m&&a-this.md0;)if(b=this.B.pb(),this.pd(b))break;else this.jc();!b&&this.L()this.ab&&this.B.L()>0;)this.Ua(a.pb())};s.ob=function(){return{}};s.Ua=function(a){if(typeof a.F=="function")a.F();else for(var b in a)a[b]=m};s.pd=function(a){return typeof a.se=="function"?a.se():!0};s.contains=function(a){return this.B.contains(a)||this.Ga.contains(a)};s.L=function(){return this.B.L()+this.Ga.L()}; s.ua=function(){return this.B.ua()&&this.Ga.ua()};s.e=function(){jf.a.e.call(this);this.Ga.L()>0&&e(Error("[goog.structs.Pool] Objects not released"));delete this.Ga;for(var a=this.B;!a.ua();)this.Ua(a.pb());delete this.B};function lf(a,b){this.va=a;this.gc=b}lf.prototype.ea=p("gc");lf.prototype.ba=function(){return new lf(this.va,this.gc)};function mf(a){this.fa=[];if(a)a:{var b,c;if(a instanceof mf){if(b=a.Qb(),c=a.ra(),a.L()<=0){for(var a=this.fa,d=0;d0;)if(d=b-1>>1,a[d].va>c.va)a[b]=a[d],b=d;else break;a[b]=c}s=mf.prototype; s.remove=function(){var a=this.fa,b=a.length,c=a[0];if(!(b<=0)){if(b==1)qb(a);else{a[0]=a.pop();for(var a=0,b=this.fa,d=b.length,h=b[a];a>1;){var g=a*2+1,j=a*2+2,g=jh.va)break;b[a]=b[g];a=g}b[a]=h}return c.ea()}};s.ra=function(){for(var a=this.fa,b=[],c=a.length,d=0;d0;){var b=this.getObject();if(b)a.pb().apply(this,[b]);else break}};s.Rc=function(a){pf.a.Rc.call(this,a);this.vc()};s.jc=function(){pf.a.jc.call(this);this.vc()}; s.e=function(){pf.a.e.call(this);u.clearTimeout(this.ue);this.Hc.clear();this.Hc=m};function qf(a,b,c){pf.call(this,b,c);this.Ie=a}A(qf,pf);qf.prototype.ob=function(){var a=new Ye,b=this.Ie;b&&he(b,function(b,d){a.headers.set(d,b)});return a};qf.prototype.Ua=function(a){a.F()};qf.prototype.pd=function(a){return!a.Lb&&!a.ub()};function rf(a,b,c,d){this.url=a;this.U=b;this.Te=c;this.Se=d}function sf(){this.fe=new qf({},1);this.xa={};this.Ic=[]}A(sf,gd);y(sf);function tf(a){H.call(this,"server_info_change");this.Ma=a}A(tf,H);function uf(a){H.call(this,"plugin_list_change");this.plugins=a}A(uf,H);function vf(a){H.call(this,"universe_list_change");this.xa=a}A(uf,H);function wf(a){H.call(this,"plugin_change");this.We=a}A(wf,H); function xf(a){yf(a,"json/server_stats",function(a){a=gf(a.target);this.dispatchEvent(new tf(a))})}function zf(a){yf(a,"json/universe_plugin_list",function(a){if(ff(a.target)!=200)Nd.wf.info("Request failed: "+String(a.target.wb)+" : "+(z(a.target.Ia)?a.target.Ia:String(a.target.Ia)));else{a=gf(a.target);this.xa={};for(var c=0;c=30?(b=Nd.ne.p(),b.Af(ed.ne.kf.of),yc(b.Mb,"Failed to Communicate with Server"),b.N("The request pool was empty, the server is probably down."),b.Z(!0)):(a.Ic.push(new rf(b,c,d,h)),a.fe.getObject(function(b){if(a.Ic.length){var c=a.Ic.shift();c.U&&K(b,"complete",c.U,!1,a);K(b,"ready",a.te,!1,a);b.send(c.url,c.Te,c.Se)}},1))}sf.prototype.te=function(a){a=a.target;cc(a);this.fe.eb(a)};function Hf(a,b,c,d,h,g,j,l){var n,o=c.offsetParent;if(o){var w=o.tagName=="HTML"||o.tagName=="BODY";if(!w||Jc(o,"position")!="static")n=Nc(o),w||(n=fc(n,new M(o.scrollLeft,o.scrollTop)))}o=Uc(a);(w=Mc(a))&&o.Td(new ic(w.left,w.top,w.right-w.left,w.bottom-w.top));var w=N(a),t=N(c);if(w.o!=t.o){var B=w.o.body,t=t.o.parentWindow||t.o.defaultView,L=new M(0,0),nb=O(B)?O(B).parentWindow||O(B).defaultView:window,de=B;do{var va;if(nb==t)va=Nc(de);else{var I=de;va=new M;if(I.nodeType==1)if(I.getBoundingClientRect)I= Kc(I),va.x=I.left,va.y=I.top;else{var Oc=Ic(N(I)),I=Nc(I);va.x=I.x-Oc.x;va.y=I.y-Oc.y}else{var Oc=ja(I.xe),Pc=I;I.targetTouches?Pc=I.targetTouches[0]:Oc&&I.V.targetTouches&&(Pc=I.V.targetTouches[0]);va.x=Pc.clientX;va.y=Pc.clientY}}L.x+=va.x;L.y+=va.y}while(nb&&nb!=t&&(de=nb.frameElement)&&(nb=nb.parent));B=fc(L,Nc(B));C&&!Hc(w)&&(B=fc(B,Ic(w)));o.left+=B.x;o.top+=B.y}a=(b&4&&Qc(a)?b^2:b)&-5;b=new M(a&2?o.left+o.width:o.left,a&1?o.top+o.height:o.top);n&&(b=fc(b,n));h&&(b.x+=(a&2?-1:1)*h.x,b.y+=(a& 1?-1:1)*h.y);var q;if(j&&(q=Mc(c))&&n)q.top-=n.y,q.right-=n.x,q.bottom-=n.y,q.left-=n.x;a:{n=b.ba();h=0;a=(d&4&&Qc(c)?d^2:d)&-5;d=Sc(c);l=l?l.ba():d.ba();if(g||a!=0)a&2?n.x-=l.width+(g?g.right:0):g&&(n.x+=g.left),a&1?n.y-=l.height+(g?g.bottom:0):g&&(n.y+=g.top);if(j){if(q){g=n;h=0;if((j&65)==65&&(g.x=q.right))j&=-2;if((j&132)==132&&(g.y=q.bottom))j&=-5;if(g.xq.right&&j&16&&(l.width-=g.x+l.width-q.right,h|=4);if(g.x+l.width> q.right&&j&1)g.x=Math.max(q.right-l.width,q.left),h|=1;j&2&&(h|=(g.xq.right?32:0));if(g.y=q.top&&g.y+l.height>q.bottom&&j&32&&(l.height-=g.y+l.height-q.bottom,h|=8);if(g.y+l.height>q.bottom&&j&4)g.y=Math.max(q.bottom-l.height,q.top),h|=2;j&8&&(h|=(g.yq.bottom?128:0));j=h}else j=256;h=j;if(h&496){c=h;break a}}g=D&&(Ja||Ra)&&F("1.9");n instanceof M?(j=n.x,n=n.y):(j=n,n=k);c.style.left=Rc(j,g);c.style.top=Rc(n,g);if(!(d== l||(!d||!l?0:d.width==l.width&&d.height==l.height)))g=Hc(N(O(c))),C&&(!g||!F("8"))?(j=c.style,g?(C?(g=$c(c,"paddingLeft"),d=$c(c,"paddingRight"),n=$c(c,"paddingTop"),q=$c(c,"paddingBottom"),g=new gc(n,d,q,g)):(g=R(c,"paddingLeft"),d=R(c,"paddingRight"),n=R(c,"paddingTop"),q=R(c,"paddingBottom"),g=new gc(parseFloat(n),parseFloat(d),parseFloat(q),parseFloat(g))),C?(d=bd(c,"borderLeft"),n=bd(c,"borderRight"),q=bd(c,"borderTop"),c=bd(c,"borderBottom"),c=new gc(q,n,c,d)):(d=R(c,"borderLeftWidth"),n=R(c, "borderRightWidth"),q=R(c,"borderTopWidth"),c=R(c,"borderBottomWidth"),c=new gc(parseFloat(q),parseFloat(n),parseFloat(c),parseFloat(d))),j.pixelWidth=l.width-c.left-g.left-g.right-c.right,j.pixelHeight=l.height-c.top-g.top-g.bottom-c.bottom):(j.pixelWidth=l.width,j.pixelHeight=l.height)):(c=c.style,D?c.MozBoxSizing="border-box":E?c.WebkitBoxSizing="border-box":c.boxSizing="border-box",c.width=l.width+"px",c.height=l.height+"px");c=h}return c};function If(){}If.prototype.sd=aa();function Jf(a,b){this.element=a;this.Wc=b}A(Jf,If);Jf.prototype.sd=function(a,b,c){Hf(this.element,this.Wc,a,b,k,c)};function Kf(a,b,c){Jf.call(this,a,b);this.pe=c}A(Kf,Jf);Kf.prototype.Pd=r(5);Kf.prototype.sd=function(a,b,c,d){var h=Hf(this.element,this.Wc,a,b,m,c,10,d);if(h&496){var g=Lf(h,this.Wc),b=Lf(h,b),h=Hf(this.element,g,a,b,m,c,10,d);h&496&&(g=Lf(h,g),b=Lf(h,b),this.pe?Hf(this.element,g,a,b,m,c,this.Pd(),d):Hf(this.element,g,a,b,m,c,0,d))}};function Lf(a,b){a&48&&(b^=2);a&192&&(b^=1);return b};function Mf(a,b,c,d){Kf.call(this,a,b,c||d);this.Ze=d}A(Mf,Kf);Mf.prototype.Pd=function(){return 65|(this.Ze?32:132)};var Nf,Of;Of=Nf=!1;var Pf=Ka();Pf&&(Pf.indexOf("Firefox")!=-1||Pf.indexOf("Camino")!=-1||(Pf.indexOf("iPhone")!=-1||Pf.indexOf("iPod")!=-1?Nf=!0:Pf.indexOf("iPad")!=-1&&(Of=!0)));var Qf=Nf,Rf=Of;function Sf(){}A(Sf,td);y(Sf);Sf.prototype.d=function(a){return a.S().d("div",this.j())};Sf.prototype.N=aa();Sf.prototype.j=r("goog-menuseparator");function Tf(a,b){V.call(this,m,a||Sf.p(),b);Ld(this,1,!1);Ld(this,2,!1);Ld(this,4,!1);Ld(this,32,!1);this.n=1}A(Tf,V);Tf.prototype.i=function(){Tf.a.i.call(this);sd(this.b(),"separator")};wd("goog-menuseparator",function(){return new Tf});function Uf(){}y(Uf);s=Uf.prototype;s.la=aa();s.d=function(a){return a.S().d("div",this.Va(a).join(" "))};s.w=function(a){return a};s.tb=function(a){a=a.b();Yc(a,!0,D);if(C)a.hideFocus=!0;var b=this.la();b&&sd(a,b)};s.C=function(a){return a.b()};s.j=r("goog-container");s.Va=function(a){var b=this.j(),c=[b,a.yb==Vf?b+"-horizontal":b+"-vertical"];a.isEnabled()||c.push(b+"-disabled");return c};function Wf(){}A(Wf,Uf);y(Wf);Wf.prototype.la=r("menu");Wf.prototype.Ra=function(a,b){return xc(a.b(),b)};Wf.prototype.j=r("goog-menu");Wf.prototype.tb=function(a){Wf.a.tb.call(this,a);U(a.b(),"haspopup","true")};wd("goog-menuseparator",function(){return new Tf});function Xf(){this.Jd=[]}A(Xf,td);y(Xf);function Yf(a,b){var c=a.Jd[b];if(!c){switch(b){case 0:c=a.j()+"-highlight";break;case 1:c=a.j()+"-checkbox";break;case 2:c=a.j()+"-content"}a.Jd[b]=c}return c}s=Xf.prototype;s.la=r("menuitem");s.d=function(a){var b=a.S().d("div",this.Va(a).join(" "),Zf(this,a.Ca,a.S()));$f(this,a,b,!!(a.u&8)||!!(a.u&16));return b};s.w=function(a){return a&&a.firstChild}; s.N=function(a,b){var c=this.w(a),d=ag(this,a)?c.firstChild:m;Xf.a.N.call(this,a,b);d&&!ag(this,a)&&c.insertBefore(d,c.firstChild||m)};function Zf(a,b,c){a=Yf(a,2);return c.d("div",a,b)}s.wd=function(a,b,c){b&&(sd(b,c?"menuitemradio":this.la()),$f(this,a,b,c))};function ag(a,b){var c=a.w(b);if(c){var c=c.firstChild,d=Yf(a,1);return!!c&&!!c.className&&c.className.indexOf(d)!=-1}return!1} function $f(a,b,c,d){d!=ag(a,c)&&(d?lc(c,"goog-option"):mc(c,"goog-option"),c=a.w(c),d?(a=Yf(a,1),c.insertBefore(b.S().d("div",a),c.firstChild||m)):c.removeChild(c.firstChild))}s.nc=function(a){switch(a){case 2:return Yf(this,0);case 16:case 8:return"goog-option-selected";default:return Xf.a.nc.call(this,a)}};s.j=r("goog-menuitem");function bg(a,b,c,d){V.call(this,a,d||Xf.p(),c);this.Oa(b)}A(bg,V);s=bg.prototype;s.ea=function(){var a=this.od;return a!=m?a:this.Ob()};s.Oa=ba("od");s.wd=function(a){Ld(this,8,a);this.vb()&&!a&&this.bc(!1);var b=this.b();b&&this.f.wd(this,b,a)};s.Ob=function(){var a=this.Ca;return ga(a)?(a=lb(a,function(a){return pb(kc(a),"goog-menuitem-accel")?"":Ec(a)}).join(""),ua(a)):bg.a.Ob.call(this)}; s.Fa=function(a){var b=this.getParent();if(b){var c=b.de;b.de=m;if(b=c&&ia(a.clientX))b=new M(a.clientX,a.clientY),b=c==b?!0:!c||!b?!1:c.x==b.x&&c.y==b.y;if(b)return}bg.a.Fa.call(this,a)};wd("goog-menuitem",function(){return new bg(m)});function Z(a,b,c){hd.call(this,c);this.f=b||Uf.p();this.yb=a||cg}A(Z,hd);var Vf="horizontal",cg="vertical";s=Z.prototype;s.ld=m;s.W=m;s.f=m;s.yb=m;s.s=!0;s.da=!0;s.ad=!0;s.I=-1;s.z=m;s.Ka=!1;s.qe=!1;s.Re=!0;s.pa=m;s.C=function(){return this.ld||this.f.C(this)};s.oc=function(){return this.W||(this.W=new Ad(this.C()))};s.d=function(){this.m=this.f.d(this)};s.w=function(){return this.f.w(this.b())}; s.i=function(){Z.a.i.call(this);od(this,function(a){a.k&&dg(this,a)},this);var a=this.b();this.f.tb(this);this.Z(this.s,!0);ld(this).g(this,"enter",this.dd).g(this,"highlight",this.ed).g(this,"unhighlight",this.gd).g(this,"open",this.Ge).g(this,"close",this.Ae).g(a,"mousedown",this.Ea).g(O(a),"mouseup",this.Ce).g(a,["mousedown","mouseup","mouseover","mouseout"],this.ze);this.Za()&&eg(this,!0)}; function eg(a,b){var c=ld(a),d=a.C();b?c.g(d,"focus",a.rc).g(d,"blur",a.Wa).g(a.oc(),"key",a.sa):c.ha(d,"focus",a.rc).ha(d,"blur",a.Wa).ha(a.oc(),"key",a.sa)}s.ja=function(){fg(this,-1);this.z&&this.z.t(!1);this.Ka=!1;Z.a.ja.call(this)};s.e=function(){Z.a.e.call(this);if(this.W)this.W.F(),this.W=m;this.f=this.z=this.pa=this.ld=m};s.dd=r(!0); s.ed=function(a){var b=rd(this,a.target);if(b>-1&&b!=this.I){var c=T(this,this.I);c&&c.wa(!1);this.I=b;c=T(this,this.I);this.Ka&&c.setActive(!0);this.Re&&this.z&&c!=this.z&&(c.u&64?c.t(!0):this.z.t(!1))}U(this.b(),"activedescendant",a.target.b().id)};s.gd=function(a){if(a.target==T(this,this.I))this.I=-1;U(this.b(),"activedescendant","")};s.Ge=function(a){if((a=a.target)&&a!=this.z&&a.getParent()==this)this.z&&this.z.t(!1),this.z=a};s.Ae=function(a){if(a.target==this.z)this.z=m}; s.Ea=function(a){if(this.da)this.Ka=!0;var b=this.C();b&&Bc(b)?b.focus():a.preventDefault()};s.Ce=function(){this.Ka=!1};s.ze=function(a){var b;a:{b=a.target;if(this.pa)for(var c=this.b();b&&b!==c;){var d=b.id;if(d in this.pa){b=this.pa[d];break a}b=b.parentNode}b=m}if(b)switch(a.type){case "mousedown":b.Ea(a);break;case "mouseup":b.Fa(a);break;case "mouseover":b.uc(a);break;case "mouseout":b.tc(a)}};s.rc=aa();s.Wa=function(){fg(this,-1);this.Ka=!1;this.z&&this.z.t(!1)}; s.sa=function(a){return this.isEnabled()&&this.s&&(pd(this)!=0||this.ld)&&this.Xa(a)?(a.preventDefault(),a.stopPropagation(),!0):!1}; s.Xa=function(a){var b=T(this,this.I);if(b&&typeof b.sa=="function"&&b.sa(a))return!0;if(this.z&&this.z!=b&&typeof this.z.sa=="function"&&this.z.sa(a))return!0;if(a.shiftKey||a.ctrlKey||a.metaKey||a.altKey)return!1;switch(a.keyCode){case 27:if(this.Za())this.C().blur();else return!1;break;case 36:gg(this);break;case 35:hg(this);break;case 38:if(this.yb==cg)ig(this);else return!1;break;case 37:if(this.yb==Vf)qd(this)?jg(this):ig(this);else return!1;break;case 40:if(this.yb==cg)jg(this);else return!1; break;case 39:if(this.yb==Vf)qd(this)?ig(this):jg(this);else return!1;break;default:return!1}return!0};function dg(a,b){var c=b.b(),c=c.id||(c.id=kd(b));if(!a.pa)a.pa={};a.pa[c]=b}s.Jb=function(a,b){Z.a.Jb.call(this,a,b)};s.mb=function(a,b,c){a.zd|=2;a.zd|=64;(this.Za()||!this.qe)&&Ld(a,32,!1);Hd(a,!1);Z.a.mb.call(this,a,b,c);c&&this.k&&dg(this,a);b<=this.I&&this.I++}; s.removeChild=function(a,b){if(a=z(a)?nd(this,a):a){var c=rd(this,a);c!=-1&&(c==this.I?a.wa(!1):c-1&&T(a,a.I).wa(!1)}s.wa=function(a){fg(this,rd(this,a))};function gg(a){kg(a,function(a,c){return(a+1)%c},pd(a)-1)}function hg(a){kg(a,function(a,c){a--;return a<0?c-1:a},0)}function jg(a){kg(a,function(a,c){return(a+1)%c},a.I)}function ig(a){kg(a,function(a,c){a--;return a<0?c-1:a},a.I)} function kg(a,b,c){for(var c=c<0?rd(a,a.z):c,d=pd(a),c=b.call(a,c,d),h=0;h<=d;){var g=T(a,c);if(g&&a.Hd(g)){fg(a,c);break}h++;c=b.call(a,c,d)}}s.Hd=function(a){return a.s&&a.isEnabled()&&!!(a.u&2)};function lg(){}A(lg,td);y(lg);lg.prototype.j=r("goog-menuheader");function mg(a,b,c){V.call(this,a,c||lg.p(),b);Ld(this,1,!1);Ld(this,2,!1);Ld(this,4,!1);Ld(this,32,!1);this.n=1}A(mg,V);wd("goog-menuheader",function(){return new mg(m)});function ng(a,b){Z.call(this,cg,b||Wf.p(),a);this.gb(!1)}A(ng,Z);s=ng.prototype;s.Sc=!0;s.re=!1;s.j=function(){return this.f.j()};s.Ra=function(a){if(this.f.Ra(this,a))return!0;for(var b=0,c=pd(this);b "+(o-1));return}o=b[g].max;if(o!=k&&n>o){a.Dd("Invalid Value",b[g].description+" must be < "+(o+1));return}h+=j+"="+l+"&"}else if(b[g].type=="string")l=d.elements[j].value,h+=j+"="+l+"&"; else if(b[g].type=="bool")h+=j+"="+(b[g].object.vb()?"1":"0")+"&";else if(b[g].type=="select")l=b[g].object.qb(),l=b[g].value[l].value,h+=j+"="+l+"&"}Df(a.J,a.Aa,a.Ib,a.za.id(),a.za.hint(),h,function(b){b=gf(b.target);b.error?alert(b.error):Rg(a)})};function Ug(){var a=sf.p();K(a,"server_info_change",this.gf,!1,this);xf(a)}Ug.prototype.title=r("Home");Ug.prototype.blur=aa();Ug.prototype.update=function(){xf(sf.p())}; Ug.prototype.gf=function(a){P("server_hostname").innerHTML=a.Ma.hostname;P("server_ip").innerHTML=a.Ma.ip;P("server_broadcast").innerHTML=a.Ma.broadcast;P("server_mac").innerHTML=a.Ma.hw_address;P("server_instance_name").innerHTML=a.Ma.instance_name;P("server_version").innerHTML=a.Ma.version;P("server_uptime").innerHTML=a.Ma.up_since;if(!a.Ma.quit_enabled&&(a=P("stop_button")))a.style.display="none"};function Vg(a){this.ia=a;this.Bd=[];this.enabled=this.ke=!1;this.ec=k}Vg.prototype.O=function(a,b){this.enabled=a;this.ec=b;if(this.enabled){if(!this.ke){for(var c=0;c<512;++c){var d=Q("div");d.title="Channel "+(c+1);var h=Q("div");h.innerHTML=c+1;var g=Q("span");g.innerHTML=" ";d.appendChild(h);d.appendChild(g);this.ia.appendChild(d);this.Bd.push(g)}this.ke=!0}Wg(this)}};function Wg(a){a.enabled&&Ff(sf.p(),a.ec,function(b){Xg(a,b.dmx)})} function Xg(a,b){for(var c=Math.min(512,b.length),d=0;d90?"#ffffff":"#000000"}function Zg(a,b){var c=a.Bd[b];if(c!=k)c.innerHTML=" ",c.style.background="#ffffff"};function $g(){this.Zd=new ae("monitor_frame");this.K=new ae("monitor_universe_frame");this.H();this.Zb();this.J=sf.p();K(this.J,"universe_list_change",this.fc,!1,this);this.Yd=new Vg(P("monitor_frame"))}s=$g.prototype;s.title=r("DMX Monitor");s.blur=function(){this.Yd.O(!1,k)};s.Zb=function(){this.aa=k};s.H=function(){ce(this.Zd);ce(this.K)};s.update=function(){this.H();this.Zb();ee(this.K);be(this.K);zf(this.J)}; s.fc=function(a){if(this.aa==k){fe(this.K);var b=new Z;S(b,this.K.element);var c=this;this.aa=new Pd(b,new Mg(function(a){c.Db(a.id(),a.name())}))}for(var b=[],d=0;d512)return!1}d=c[2];if(d!=k&&d!=""&&(d=eh(c[2]),d==k||d==0||d>512))return!1;d=c[3];return d!=k&&d!=""&&(c=eh(c[3]),c==k||c>255)?!1:!0}function eh(a){if(!(a==m||a==k))return a=parseInt(a),isNaN(a)?k:a}function dh(a){a=a.replace(">","THRU");a=a.replace("*","1 THRU 512");a=a.replace("ALL","1 THRU 512");a=a.replace("@ +","@ 255");return a=a.replace("@ FULL","@ 255")};function fh(a,b){this.ec=b;this.ee=new bh;this.Bb=Q("table");var c=Q("caption");c.innerHTML=a;this.Bb.appendChild(c);gh(this);c="7,8,9, THRU ,4,5,6, @ ,1,2,3,FULL,0,ENTER".split(",");for(i=0;i<3;++i){var d=Q("tr");for(x=0;x<4;++x){var h=Q("td"),g=hh(this,c[i*4+x]);S(g,h);d.appendChild(h)}this.Bb.appendChild(d)}Q("tr");d=Q("td");g=hh(this,c[12]);S(g,d);this.Bb.appendChild(d);d=Q("td");g=hh(this,c[13]);S(g,d);d.colSpan="3";this.Bb.appendChild(d)} function hh(a,b){var c=new Y(ed.nf);c.N(b);K(c,"action",function(){ih(this,b)},!1,a);return c} function ih(a,b){if(b=="<"){var c=a.P.value.length-1;if(isNaN(parseInt(a.P.value.substr(c,1)))){var d=0;switch(a.P.value.substr(c-1,1)){case "L":d=3;break;case "@":d=2;break;case "U":d=5;break;default:d=0}c-=d}a.P.value=a.P.value.substr(0,c);ih(a,"")}else if(b=="ENTER"){a:{c=a.P.value;if(c.length!=0&&(c=a.ee.we.exec(dh(c)),c!=m)){var d=eh(c[1]),h=eh(c[2]),g=eh(c[3]);if(!(d==k||g==k)){if(c[2]!=k&&h==k){c=!1;break a}c=new ah(d,h,g);c=c.start>=1&&c.start<=512&&c.value>=0&&c.value<=255&&(c.end==k||c.end>= 1&&c.end<=512&&c.end>=c.start)?c:k;break a}}c=k}if(c!=k)a.execute(c),a.P.value=""}else if(c=a.P.value+b,ch(a.ee,c)==!0)a.P.value=c} function gh(a){var b=Q("tr"),c=Q("td");c.colSpan="4";a.P=Q("input");a.P.type="text";c.appendChild(a.P);var d=new Ad(a.P);K(d,"key",function(a){a:{var a=a.keyCode,b=this.P.value,c=m;switch(a){case 32:break;case 13:ih(this,"ENTER");break a;default:break a}a=b.substr(b.length-1,1);switch(a){case "F":c="ULL";break;case "T":c="HRU";break;case "A":c="LL @";break;default:c=m}if(c!=m)this.P.value=b+c}},!0,a);d=hh(a,"<");Jd(d,"backspace-button");S(d,c);b.appendChild(c);a.Bb.appendChild(b)} fh.prototype.execute=function(a){var b=this;Ff(sf.p(),this.ec,function(c){jh(b,c,a)})};function jh(a,b,c){b=b.dmx;if(c.start==c.end)b[c.start-1]=c.value;else for(i=c.start;i<=c.end;++i)b[i-1]=c.value;Gf(sf.p(),a.ec,b,aa())};function kh(){this.lc=new ae("controller_frame");this.K=new ae("controller_universe_frame");this.H();this.Zb();this.J=sf.p();K(this.J,"universe_list_change",this.fc,!1,this)}s=kh.prototype;s.title=r("DMX Keypad");s.blur=aa();s.Zb=function(){this.Aa=this.aa=k};s.H=function(){ce(this.lc);ce(this.K)};s.update=function(){this.H();this.Zb();ee(this.K);be(this.K);zf(this.J)}; s.fc=function(a){if(this.aa==k){fe(this.K);var b=new Z;S(b,this.K.element);var c=this;this.aa=new Pd(b,new Mg(function(a){c.Db(a.id(),a.name())}))}for(var b=[],d=0;da.name())return 1;else if(this.name()");this.Wb.element.innerHTML=a};function ph(a,b,c,d){this.ca=c||N();this.G=a;this.X=[];this.af=b?b:qh;this.me=!!d;this.G.className="goog-tabpane";a=[];for(b=this.G.firstElementChild!=k?this.G.firstElementChild:wc(this.G.firstChild);b;)a.push(b),b=b.nextElementSibling!=k?b.nextElementSibling:wc(b.nextSibling);this.Q=this.ca.d("ul",{className:"goog-tabpane-tabs",tabIndex:"0"});this.R=this.ca.d("div","goog-tabpane-cont");this.G.appendChild(this.R);switch(this.af){case qh:this.G.insertBefore(this.Q,this.R);this.G.insertBefore(rh(this), this.R);lc(this.G,"goog-tabpane-top");break;case 1:this.G.appendChild(this.Q);this.G.appendChild(rh(this));lc(this.G,"goog-tabpane-bottom");break;case 2:this.G.insertBefore(this.Q,this.R);lc(this.G,"goog-tabpane-left");break;case 3:this.G.insertBefore(this.Q,this.R);lc(this.G,"goog-tabpane-right");break;default:e(Error("Invalid tab location"))}this.Q.tabIndex=0;K(this.Q,this.me?"mousedown":"click",this.ae,!1,this);K(this.Q,"keydown",this.be,!1,this);for(c=0;b=a[c];c++)sh(this,new th(b))}A(ph,gd); var qh=0;function rh(a){var b=N(k),c=m;if(C)c=b.o.createStyleSheet(),Wc(c);else{var d=Gc(b,"head")[0];d||(c=Gc(b,"body")[0],d=b.d("head"),c.parentNode.insertBefore(d,c));c=b.d("style");Wc(c);b.appendChild(d,c)}return a.ca.d("div","goog-tabpane-clear")}s=ph.prototype;s.e=function(){ph.a.e.call(this);Zb(this.Q,this.me?"mousedown":"click",this.ae,!1,this);Zb(this.Q,"keydown",this.be,!1,this);delete this.G;this.R=this.Q=m}; function sh(a,b){if(b.q&&b.q!=a&&b.q instanceof ph){var c=b.q,d=b;ia(d)&&(d=c.X[d]);c.X.splice(d.sb,1);d.cc(m);vc(d.Mb);vc(d.R);for(var h=0;d=c.X[h];h++)d.cc(c,h)}c=a.X.length;fa(k)&&k!=c?(c=k,a.X.splice(c,0,b),a.Q.insertBefore(b.Mb,a.Q.childNodes[c])):(a.X.push(b),a.Q.appendChild(b.Mb));b.cc(a,c);if(!a.Y)a.Y=b,a.dispatchEvent(new uh("change",a,a.Y));a.R.appendChild(b.R);vh(b,b==a.Y);for(d=c+1;c=a.X[d];d++)c.sb=d} s.Na=function(a){if(a>=0&&a=this.X.length?0:a);break;case 36:this.Na(0);break;case 35:this.Na(this.X.length-1)}}; function th(a,b,c){var d,h;if(z(a)&&!fa(b))d=a;else if(b)d=b,h=a;else if(a){if(b=a.firstElementChild!=k?a.firstElementChild:wc(a.firstChild))d=Cc(b),b.parentNode.removeChild(b);h=a}this.ca=c||N();this.R=h||this.ca.d("div");this.Mb=this.ca.d("li",m,d);this.sb=this.q=m;this.da=!0}th.prototype.w=p("R");th.prototype.getParent=p("q");th.prototype.isEnabled=p("da");function vh(a,b){if(a.isEnabled())a.R.style.display=b?"":"none",a.Mb.className=b?"goog-tabpane-tab-selected":"goog-tabpane-tab"} th.prototype.cc=function(a,b){this.q=a;this.sb=fa(b)?b:m};function uh(a,b,c){H.call(this,a,b);this.page=c}A(uh,H);function wh(){this.na=[];this.na.push(new Ug);this.na.push(new Ng);this.na.push(new $g);this.na.push(new kh);this.na.push(new oh);this.Ad=new ph(P("tab_pane"));for(var a=0;a'¶•¤eõ$ˆ™"ˆ\‡#E1Cn€ÄŽƒÉ~×ÕJ,Ü,Aa•ªUw^4I%PÝÞu Q33{0i1T…Ggwy}%ˆ%'Rœ  ¡  Ž…Œ=¡ª ¦§« £¥§3ž¶G–%¹”pº½0¦ ™³JRo…5Ȇ0IĦmykˆÃxÍTˆ_}È(…×^ââyKŽsµìœé>i_¨%ŽÕînú=ÙâÚÊqØ4eÍ-M¤D!ù , îÈI)*¨êÍ')E¥d]•¦ÃPR A”:!­ûzr’‚“œbw“ %6€"G¤(d$["‡’øJ±ÀFh­aQP`p%†/BFP\cU â ?TÐtW/pG&OtDa_sylD'M˜™ œq Štc˜¥ ¡¢™¦ b ¢2š±D“M :‘µ¹¹ d¡ˆ%À ¢4%s) À»‘uƒƒE3¸ £YU€‹tÚ–ææ‘ÆDŠ$æJiMí<àYà;ŠØ°€˜d<“ O‚tXò^%o/rvl9'L’“–—;†‡9—Ÿ›œ“ ™…£”ª9€% ‹i9³³¨ C¹ "†B B¹µDs Î^Xf}$P × {LÞ?PÊ ”›O4 ×ÐÀEÓóå’›Vë$¸æÊdJÐ#)…pVÂÀ$!ù , ëÈIiR©êͧ"J…d]• ¡RÂZN‰*P*«á;Õ$P{*”N‚Àí\EÐò!1UO2ÝD ™_r6Iöb ¡¤åÔÄH—š8 B—; ²¬"'ªœZÛÚt½’b€K#C'Kˆ‰Œw}?ˆ”‘’K•iz6Š :x‚KAC¨¨Ÿ&}9®tz\ \¶¨ªD5;x ¹¨±Qd( Ö Ë ±KWÖ Ê ŠMBàˈI´éÚˆM=ñˤsøâ¸½8Daƒ¡J`@LG!ù , ïÈIiR©êͧ"J…d]• ¡RÂZN‰*P*«á;Õ$P{*”N‚Àí\EÐò!1UO2ÝD ™_r6Iöb ¡¤åÔÄH—š8 B—; ²¬"'ªœZÛÚt½’b€K#C'Kˆ‰Gziz6ˆ8}z‰’”~Š›%X„K9ƒ:¢¨0}¤% ¨tz\B±¤lc L¢bQ Ç Ñ ÅˆÎ Ñ Ålj ÎÂÝųKÎÞè¸Åˆä ìçÒéÅxÎ(È›PàšX ,ÈéÖ‚|/"!ù , ðÈIiR©êͧ"J…d]• ¡RÂZN‰*P*«á;Õ$P{*”N‚Àí\EÐò!1UO2ÝD ™_r6Iöb ¡¤åÔÄH—š8 B—; ²¬"'ªœZÛÚt½’b€K#C'Kˆ‰Gziz6ˆ8}z‰’”~Š›%…:„A/ C} ¦¦†u\¯ ³h}b¥¦ DÂÃ]=¦¨ ¨Ö ÈV)Ó Ö ÚŠÓÐâÈ9CÓãëDæKè õí¼K¦…¢u ·Ç*00SÊtD!ù , ëÈIiR©êͧ"J…d]• ¡RÂZN‰*P*«á;Õ$P{*”N‚Àí\EÐò!1UO2ÝD ™_r6Iöb ¡¤åÔÄH—š8 B—; ²¬"'ªœZÛÚt½’b€K#C'Kˆ‰Gz ‘‰z5 ‘— “”˜ŠŸC…: „A/ C}ªª†u\³ ·Eh}b©ª6Å[=ª¥¸¥×Wx&)Ô×ÒI9ˆÔ¬á@oCÔêT?KÞÆéØdÛïò]øÁB7¡À‚ 6ЫD!ù , èÈIiR©êͧ"J…d]• ¡RÂZN‰*P*«á;Õ$P{*”N‚Àí\EÐò!1UO2ÝD ™_r6Iö Æ€ÔÄH—š03ª³”hÕ¸ƒ›aÀ—j U {CIkmbK#‡cK‘’€8 „{a’•8™n›•˜™“¥‡‚V:ˆ/q:M ¯¯Cu€~·¸‰Eh³k®¯6 ½[_¯±ƒ6P.]ú6©ð!‡)Vˆ!ù , ðÈIiR©êͧ"J…d]U ¡RÂZN ÔJÀjøN2sK6 ±› d‹I€È)  LØH°W¡G 6 ÊKX¦ƒì ±’.6¢d°¨~z“hÙÂuur/6 X5ƒI;_†t O#E {O››ˆ9V¢£œž9£¨4ž¡©œ±›—;V–C/ €¹6»Ã˜~*½'ÊMo¸º»€nÎÇbXÂ:~]+V*ÍmåK_àOÑrKñ³N@.ê›Ñdù~ÎqЦäD¢BÖ‹ 5D;ola-0.10.5.nojsmin/olad/www/warning.png0000644000175000017500000000115413023355232017375 0ustar wouterwouter‰PNG  IHDRóÿa3IDATxœ¥“_HSqÇ¿¿{ÛkÍ6°åæÌ•«‘‘D®?BRD–¡!$a½ôÐKÛ‡ÝhöDµ‡!¢ ð!‡”B…Z­‰^z ƒˆ¢t›³mw»÷ô˜“œ§óå×/ßÈ+¾Ô! Û9×&“‰¬$IÍ}Wú¾, `³ÙnoÜ¿µ@‚v÷Áëڊ ‰hÑvwñx¼0yÿ ÍM5S,Ë:ÞbZ¡Ôá°ÕÖl¶PU;jk «eð¿ôöô¶¿›zS˜>Eg%¹6VSêÃ½Š¿Ìù}þ“ÿtàv»£îJ‹¨)3àœƒ4 ºÜ#lÛ²Nïñx¢ë"ç/\j:rÐüýyæÓiÌ¥ŒzH¿ÐÚzÌÜ!wD‹¡°ÝåZßYªK€³4ÊʦҰ¡ªLSa5ÿ<ÏiY–‹œó{-ûJfâ°Y'`¾Âb)EE…(™Œß jgq¢íÐ*6° Äî®àÞñ§£Jöý Ê=Ñ‘6 ¢· Ô'NsŸ9Ñ,ˆ² R%ÊçoÑÈÈãŒì—÷ü Ñ`0ÜÞ½k»N¾Ѩ‚ €Â€Ãí;!Gš#ý@pƒó144Ô$I1›É…ލk)W_,9ÝêDpg¸õÞðÖV `;a-$©Jßß-`°çµ’IÓr'ŸÏ‘ïœï–Š\¼<_´eÀØ4™L [é;ÿò°5}‰ŠsIEND®B`‚ola-0.10.5.nojsmin/olad/www/custombutton.css0000644000175000017500000001051713023355232020505 0ustar wouterwouter/* * Copyright 2009 The Closure Library Authors. All Rights Reserved. * * Use of this source code is governed by an Apache 2.0 License. * See the COPYING file for details. */ /* * Styling for custom buttons rendered by goog.ui.CustomButtonRenderer. * * @author attila@google.com (Attila Bodis) */ .goog-custom-button { margin: 2px; border: 0; padding: 0; font-family: Arial, sans-serif; color: #000; /* Client apps may override the URL at which they serve the image. */ background: #ddd url(/button-bg.png) repeat-x top left; text-decoration: none; list-style: none; vertical-align: middle; cursor: default; outline: none; } /* Pseudo-rounded corners. */ .goog-custom-button-outer-box, .goog-custom-button-inner-box { border-style: solid; border-color: #aaa; vertical-align: top; } .goog-custom-button-outer-box { margin: 0; border-width: 1px 0; padding: 0; } .goog-custom-button-inner-box { /* By default in FF2, block elements inside a moz-inline-box are stacked * horizontally next to each other. This stops that weird behavior. */ -moz-box-orient: vertical; margin: 0 -1px; border-width: 0 1px; padding: 3px 4px; white-space: nowrap; /* Prevents buttons from line breaking on android. */ } /* Pre-IE7 IE hack; ignored by IE7 and all non-IE browsers. */ * html .goog-custom-button-inner-box { /* IE6 needs to have the box shifted to make the borders line up. */ left: -1px; } /* Pre-IE7 BiDi fixes. */ * html .goog-custom-button-rtl .goog-custom-button-outer-box { /* @noflip */ left: -1px; } * html .goog-custom-button-rtl .goog-custom-button-inner-box { /* @noflip */ right: auto; } /* IE7-only hack; ignored by all other browsers. */ *:first-child+html .goog-custom-button-inner-box { /* IE7 needs to have the box shifted to make the borders line up. */ left: -1px; } /* IE7 BiDi fix. */ *:first-child+html .goog-custom-button-rtl .goog-custom-button-inner-box { /* @noflip */ left: 1px; } /* Safari-only hacks. */ ::root .goog-custom-button, ::root .goog-custom-button-outer-box { /* Required to make pseudo-rounded corners work on Safari. */ line-height: 0; } ::root .goog-custom-button-inner-box { /* Required to make pseudo-rounded corners work on Safari. */ line-height: normal; } /* State: disabled. */ .goog-custom-button-disabled { background-image: none !important; opacity: 0.3; -moz-opacity: 0.3; filter: alpha(opacity=30); } .goog-custom-button-disabled .goog-custom-button-outer-box, .goog-custom-button-disabled .goog-custom-button-inner-box { color: #333 !important; border-color: #999 !important; } /* Pre-IE7 IE hack; ignored by IE7 and all non-IE browsers. */ * html .goog-custom-button-disabled { margin: 2px 1px !important; padding: 0 1px !important; } /* IE7-only hack; ignored by all other browsers. */ *:first-child+html .goog-custom-button-disabled { margin: 2px 1px !important; padding: 0 1px !important; } /* State: hover. */ .goog-custom-button-hover .goog-custom-button-outer-box, .goog-custom-button-hover .goog-custom-button-inner-box { border-color: #9cf #69e #69e #7af !important; /* Hover border wins. */ } /* State: active, checked. */ .goog-custom-button-active, .goog-custom-button-checked { background-color: #bbb; background-position: bottom left; } /* State: focused. */ .goog-custom-button-focused .goog-custom-button-outer-box, .goog-custom-button-focused .goog-custom-button-inner-box { border-color: orange; } /* Pill (collapsed border) styles. */ .goog-custom-button-collapse-right, .goog-custom-button-collapse-right .goog-custom-button-outer-box, .goog-custom-button-collapse-right .goog-custom-button-inner-box { margin-right: 0; } .goog-custom-button-collapse-left, .goog-custom-button-collapse-left .goog-custom-button-outer-box, .goog-custom-button-collapse-left .goog-custom-button-inner-box { margin-left: 0; } .goog-custom-button-collapse-left .goog-custom-button-inner-box { border-left: 1px solid #fff; } .goog-custom-button-collapse-left.goog-custom-button-checked .goog-custom-button-inner-box { border-left: 1px solid #ddd; } /* Pre-IE7 IE hack; ignored by IE7 and all non-IE browsers. */ * html .goog-custom-button-collapse-left .goog-custom-button-inner-box { left: 0; } /* IE7-only hack; ignored by all other browsers. */ *:first-child+html .goog-custom-button-collapse-left .goog-custom-button-inner-box { left: 0; } ola-0.10.5.nojsmin/olad/www/back.png0000644000175000017500000000066313023355232016634 0ustar wouterwouter‰PNG  IHDRóÿasBIT|dˆtEXtSoftwarewww.inkscape.org›î<EIDAT8¥’?KBaÆçú·ÒT²@úmµ˜´AAn- -5574»Í~†¢–ŠD1 ‡ Ñ!ê+ˆÆMoïiL’Ì[ÏôrÎyçððˆªòYƒš²|•tyïOY-ÎHœ‰,¸ÈÚÝ“S„‹¿]Ù×”õjšøä££³žAé5Q6vˆãóE»Åz½Àk3b@ ŠAµó¶ßJ]€l> áñ´ôK/ÏY¯¤*ñà áÀ>NKp†û €1–Ÿ5qæi™!×öÞ-QUd©ÁßÊãoeqƒi8Û_¤î…±vŽàûþîP[k­Š*ðiº*¶“—ïQ–•Ê.#äð2€mNõ2µõÓ}9Ыdž&YÚÔ:D—AЛdlЍ¸èmò‰:l) ôyàVòYwkâK81IEND®B`‚ola-0.10.5.nojsmin/olad/www/console_values.html0000644000175000017500000007227013023355232021140 0ustar wouterwouter DMX Console
1
9
17
25
33
41
49
57
65
73
81
89
97
105
113
121
129
137
145
153
161
169
177
185
193
201
209
217
225
233
241
249
257
265
273
281
289
297
305
313
321
329
337
345
353
361
369
377
385
393
401
409
417
425
433
441
449
457
465
473
481
489
497
505
ola-0.10.5.nojsmin/olad/www/logo.png0000644000175000017500000000305313023355232016670 0ustar wouterwouter‰PNG  IHDRo0$BòIDATxÚíÜylTUÆagÚŽ-[ T‘h""J\ˆaQ0j(ˆAÀ­)£‰…Ó ¨,j `ÀE²7\E[D@YLYìýü…@Ò|ùêÜ™¹[Ißäù‹éÜKß™;çž3§‰ÈY ©?9ßYCy åM6ò1ëQ†Ã¨FÊñ#Ö q .ä4BfXË‹bV ’ Ó؈‘ˆ!Ùˆ†D°ëÂV^ùØ qÉŒEúR^_È9ÃR^[¬‡xd'º\å•@ÎY†òîÇß:œÄ ¢7:"÷œŽ¸ ã±ÿ@êP…Âz\ÞMê|ªÑ.ÈòžG ÄðB8Mˆsé]€´zXÞ{eNPåM‡Ž`4ÒSü`„½Ã2¤Õ£ò:à D9Ž~—÷$İ­àVšáuˆan})Oý´gý,¯NC”©ˆÀ‹ŒBD)¨嵎sËtY~”× ¿A”gàu/š \òòfBâxÔò^2?týËãå+DCZ^ŽªóøÛŒÁ]ÔËòòŒK×7È€Ÿy¢Œ iyOA”.QzYÞkÆ}Ê ð;¹8¤Î¥ Ñ•ÃêJjM!–ªûÒ«òZá”:Ø|•q¥_ÈÊ{¢ôÁù< QzxQ^¡9;\²ð§:§wCT^eêøÛŒwæ}«åEyŸ©ƒ|„ ó‚:§SÈ Iyùet&ªÇÔ “›åeCôÑ:7B”ž!)ïkuìRD¡Óåê±o¹Y^ˆr‚Nĸt>‚òzAx±OU­Dk·Ê+2ÖØ¬DÐQ— j„º²J¿jCPÞZuÜ}q•sÁà,·Ê›ïàó®%¶BðKïÌö(Å,GtŠÕ¹m¸¼ÎÆ*K!âeŽú™£Èv£¼÷Õ¿éàƒwRÍbõœC 3A/Ú\ÞR½ÂâpI¬ªÕϹQÞZoéIê1Ó=øE s0]öK€å]n0N³Hýì~ÄR-o£ƒòšáS¾E.RÍÕµf(Jé ¼Ÿ,ïUc­®%œ¦“qÉ‘jy&°Ž–7‹3òšŠË¦=è(F¢Ñ¿ë]ˆ¤RÞBõ„Ë–ÌVç¶) ò¦Ãý6H4·@”»S)oб’–¬Òƒ)?ËÓ7ÚÙœJyCyÍÆø¿4…׉« “(¯â±.É–—Qî„•ŒZ×íÝIN^wÄTâÅx_¥Sºú\^ {![–ÊÄôž¸÷zö»t.¾¯ì+3ÔãNàbŸË{âƒ3¸"ÙòfÃàèŒP[ˆD³A=ÇÐÉ4:—ø¼$Á.uŒµ.nF9¢ž{^²å] qpš‰-À•°ÒMa¥'ŽÕšŠKsø]–¾>—×¢Ü ·2ÅXòÊu\žJ‰ñîk +yˆÁJªñ/†ÃJ:!lcó{D|.ïsõü[=¸w<®§“-¯»1°8MSµ6øÍkÞÓÇòºA”ûàv^6æJ;-Og D™ §ÉQóåH$ùÆ èD|.o¥ñÕ½4¸{Âz\²åµÂAcé~œ¦•8¡pš®8iì@ºÊ×/ÝÚsð*zueÒ–§s;NCÙ'à4Y nDéSu}_Óçò—²,x•kŒËT6š@ \ÞoçêØ13€&íPe|lxÕê˜Û/ÏžŒÕv£—Kƒ‚ÃBD(o¶11 ¯Ó¢ôNusej † ¸+ÁòîÁ&H^QÅùU^ pŸÆzBÀm̓q,ΦŃžhKÑÐaqœÙù Œ…Óˆ öךr›lLÐçÁ¯Ük ¯O± vpAg\Æ­Ã…IDAT8Ë’_HSQÇÏÙîv·y7Ût“å6J¯#µÝÑ(ˆÁ˜Mô5‰ŒÈ7_‚ÿ<…ôøô"ùæCe…RAì1‰Yþypiw©\ºvïvî=çÜ{{ˆ"i…ô}>Ÿ?>þ±T*eçyþ¦Çãà8®•RZ"„<™]úùþ  y½ÞeI’Yg“óPˆe‡¿ÙmƒK¥Réúââbi ‚À°,û²°[á}©ÑœKÈ|»‡=åw9·V²Íž=úý·¬±XìZU5G™äí\K¸5qàt±fÛ îŠjÁ3½òföMº‹çŸZ !ý²ï¼l1 † Ö B C× p²³µÇ.TX–½ÒP€jÕíß¡c °FªQp¨`Š5 T•€@g·‚ò5l ª*†èÀ©!¢ ºê5;°Ù¬@b-¤‰v!8ØÛ³K’¤7¸\®¯Ÿ³—|ç*²ŒÃüHeê °ÐÔ)¶nd_µˆ¢¸Õ0b:Þ«|™@ò¡­%Ô[STRª ëÀabǧçOç?¾WÊåò?þÁÔÔÔD8î§”öÍÏÏ[¸@‡j œ-›ʊӋŶb~ÓØßß¿±³³óâˆ`rrrFÅéB¡‰Ä}anmm힪ª1†a,cªëzŽa˜»ëëëoàWƒñññ™b±8Ïç!„°bšæòÜÜÜÊðððkŽã"µZ- (ŠT*•ÄÕÕU|äì±±±™¡¡!#›‚ TFFFúÀ1gM&“£ãÛÛÛÐ0Œj4½º°°ðî¸àv»“¡P¨ÚÓÓSÍd2™cƒ¿/‰\ŒÇã—ÿ‡ýï/A„<<%tEXtdate:create2010-02-10T04:10:48-06:00ÌËÛw%tEXtdate:modify2008-10-20T14:33:22-05:00ƒÓ¿IEND®B`‚ola-0.10.5.nojsmin/olad/www/tick.gif0000644000175000017500000000011313023355232016635 0ustar wouterwouterGIF89a¡™™™™™™™™™!ù ,”§ ¹X€âÁf‚~•ç¦5–÷…y˜ µ`F;ola-0.10.5.nojsmin/olad/www/light_bulb.png0000644000175000017500000000124113023355232020040 0ustar wouterwouter‰PNG  IHDRóÿatEXtSoftwareAdobe ImageReadyqÉe<CIDATxÚ„“ÏoAÇßì, tÁ’%BÒJª‰ÕC iô¬Iõ¢‰'O&zR¯þê?`¢žzähµ Iè¡“Ƥü£uZÒb›„ »ÌÎú °ZêËNfÞÌû~Þ¾·;Ä0 èYü!Bð¹€îE<9‰Çç*Îi¦CZGçÖK½¯Ál¨…ko(¸zF÷¹ÕVÙØß(TЉ×Áýíâž/áègÕ˜å’Ã;57ûháÎhà\··´ŸíÄ–úÞãÛïäeÃÌ ÆÀ×› ^Õù¡À¹Ö&DJmÀXýª­ÂÙù»3XÆ•A©ÆÁ=:>9ÆØA Ùcu®ª»Ày› Pwù&Á露.?–­U«ï1&7p À ‹ŸÒ¥ÒZþ‡$¶ˆ¢CTV?nrk%A¬Ù6ÿ8&@«ÝLÓaùs2QFq`ɯ$vpï-6°ÓDÚĦÖ_æ ùŒJ:9 ù¬…8ÂL€]î-ëÉuŸNÙo(ŠO–Ôͨߨý°'†¼¯‡@Ó¤®—RøQzsþ¶J¥õúÞq!ÿÜÆ¾qÎßD"Ñ›¸ôà•ÚÛw…æLqÔIÄlF–IEND®B`‚ola-0.10.5.nojsmin/olad/www/ola.html0000644000175000017500000007055413134123277016702 0ustar wouterwouter OLA Admin
ola-0.10.5.nojsmin/olad/www/wand.png0000644000175000017500000000107213023355232016660 0ustar wouterwouter‰PNG  IHDRóÿagAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<ÌIDAT8Ë•’ÁK"aÆ¿SÔ!bteY¥ÃË!!º°¨)ê‚:ÖMìžE—]ö´†èÑ[Hç žZ©eˆÝA¦è TÆÊ¶,¸þ 5}Œ3‡ðÙo&Ú‹Žåá/óñ{Þ—‡!ÈS(gÎ1åln¥ßÛiÞÎX˜g£ÊéÛ†1KÓÓTzµòdÀƒ8÷“‰‚"Í©—‹P$Ç'ZµÝR‘K=/àôMV½JAû½­õ‹(¨8Ù¡ß'ÆMع/ØVQ‘^C½ä¡ýÍãdG£²ŒVuúä£ÉÎà$G¶ÓXÂÉ~š¦¡Ûíââk êõdüb8L¨ô’£U«‹ÅP¯×¡ª*šÍ&ª»Qh>BþF(ÃÓ7€•d§âT%‘H N£X,¢\.ãhgÉŸuùžq.’-Ó xž7dǃ@ €x<å<Š;ц;ar…ØMK|”Ýn7ü~?,‹¾u›m¼g¼crC> ™¾Éd…BÁ}>8Žƒþ‰ï™(èóÍa|è ˆD"Èçó=ò#L ™þÊÁ`¹\.— ^¯·GÉd2h·Ûp:…BCÉÿjµJ¥’QØ0²‡7õ³­VëвÎ?P ³µ¯vIEND®B`‚ola-0.10.5.nojsmin/olad/www/ola.js0000644000175000017500000047106113023355232016343 0ustar wouterwouterfunction e(a){throw a;}var j=void 0,l=null;function aa(){return function(){}}function ba(a){return function(b){this[a]=b}}function n(a){return function(){return this[a]}}function o(a){return function(){return a}}var p,ca=ca||{},r=this;function da(a){for(var a=a.split("."),b=r,c;c=a.shift();)if(b[c]!=l)b=b[c];else return l;return b}function s(){}function u(a){a.c=function(){return a.Pj||(a.Pj=new a)}} function ea(a){var b=typeof a;if(b=="object")if(a){if(a instanceof Array)return"array";else if(a instanceof Object)return b;var c=Object.prototype.toString.call(a);if(c=="[object Window]")return"object";if(c=="[object Array]"||typeof a.length=="number"&&typeof a.splice!="undefined"&&typeof a.propertyIsEnumerable!="undefined"&&!a.propertyIsEnumerable("splice"))return"array";if(c=="[object Function]"||typeof a.call!="undefined"&&typeof a.propertyIsEnumerable!="undefined"&&!a.propertyIsEnumerable("call"))return"function"}else return"null"; else if(b=="function"&&typeof a.call=="undefined")return"object";return b}function ga(a){return a!==j}function ha(a){return ea(a)=="array"}function ia(a){var b=ea(a);return b=="array"||b=="object"&&typeof a.length=="number"}function v(a){return typeof a=="string"}function ja(a){return typeof a=="number"}function ka(a){return ea(a)=="function"}function la(a){a=ea(a);return a=="object"||a=="array"||a=="function"}function ma(a){return a[na]||(a[na]=++oa)} var na="closure_uid_"+Math.floor(Math.random()*2147483648).toString(36),oa=0;function pa(a,b,c){return a.call.apply(a.bind,arguments)}function qa(a,b,c){a||e(Error());if(arguments.length>2){var d=Array.prototype.slice.call(arguments,2);return function(){var c=Array.prototype.slice.call(arguments);Array.prototype.unshift.apply(c,d);return a.apply(b,c)}}else return function(){return a.apply(b,arguments)}} function ra(a,b,c){ra=Function.prototype.bind&&Function.prototype.bind.toString().indexOf("native code")!=-1?pa:qa;return ra.apply(l,arguments)}function sa(a,b){var c=Array.prototype.slice.call(arguments,1);return function(){var b=Array.prototype.slice.call(arguments);b.unshift.apply(b,c);return a.apply(this,b)}}var ta=Date.now||function(){return+new Date};function ua(a){var b={},c;for(c in b)var d=(""+b[c]).replace(/\$/g,"$$$$"),a=a.replace(RegExp("\\{\\$"+c+"\\}","gi"),d);return a} function w(a,b){function c(){}c.prototype=b.prototype;a.b=b.prototype;a.prototype=new c;a.prototype.constructor=a};function va(a,b){for(var c=1;c":"
")} function za(a){if(!Aa.test(a))return a;a.indexOf("&")!=-1&&(a=a.replace(Ba,"&"));a.indexOf("<")!=-1&&(a=a.replace(Ca,"<"));a.indexOf(">")!=-1&&(a=a.replace(Da,">"));a.indexOf('"')!=-1&&(a=a.replace(Ea,"""));return a}var Ba=/&/g,Ca=//g,Ea=/\"/g,Aa=/[&<>\"]/;function Fa(a){return ya(a.replace(/ /g,"  "),j)} function Ga(a,b){for(var c=0,d=xa(String(a)).split("."),g=xa(String(b)).split("."),h=Math.max(d.length,g.length),i=0;c==0&&ib)return 1;return 0};var Ia,Ja,Ka,La,Ma,Na,Oa;function Pa(){return r.navigator?r.navigator.userAgent:l}function Qa(){return r.navigator}Ma=La=Ka=Ja=Ia=!1;var Ra;if(Ra=Pa()){var Sa=Qa();Ia=Ra.indexOf("Opera")==0;Ja=!Ia&&Ra.indexOf("MSIE")!=-1;La=(Ka=!Ia&&Ra.indexOf("WebKit")!=-1)&&Ra.indexOf("Mobile")!=-1;Ma=!Ia&&!Ka&&Sa.product=="Gecko"}var Ta=Ia,x=Ja,z=Ma,A=Ka,Ua=La,Va,Wa=Qa();Va=Wa&&Wa.platform||"";Na=Va.indexOf("Mac")!=-1;Oa=Va.indexOf("Win")!=-1;var Xa=!!Qa()&&(Qa().appVersion||"").indexOf("X11")!=-1,Ya; a:{var Za="",$a;if(Ta&&r.opera)var ab=r.opera.version,Za=typeof ab=="function"?ab():ab;else if(z?$a=/rv\:([^\);]+)(\)|;)/:x?$a=/MSIE\s+([^\);]+)(\)|;)/:A&&($a=/WebKit\/(\S+)/),$a)var bb=$a.exec(Pa()),Za=bb?bb[1]:"";if(x){var cb,db=r.document;cb=db?db.documentMode:j;if(cb>parseFloat(Za)){Ya=String(cb);break a}}Ya=Za}var eb={};function B(a){return eb[a]||(eb[a]=Ga(Ya,a)>=0)}var fb={};function gb(){return fb[9]||(fb[9]=x&&document.documentMode&&document.documentMode>=9)};function hb(a,b,c){for(var d in a)b.call(c,a[d],d,a)}function ib(a){var b=[],c=0,d;for(d in a)b[c++]=a[d];return b}function jb(a){var b=[],c=0,d;for(d in a)b[c++]=d;return b}function kb(){var a=lb,b;for(b in a)return!1;return!0}function mb(a,b,c){b in a&&e(Error('The object already contains the key "'+b+'"'));a[b]=c}var nb="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(","); function ob(a,b){for(var c,d,g=1;g=0} function yb(a){if(!ha(a))for(var b=a.length-1;b>=0;b--)delete a[b];a.length=0}function zb(a,b){var c=sb(a,b),d;(d=c>=0)&&C.splice.call(a,c,1);return d}function Ab(a){return C.concat.apply(C,arguments)}function Bb(a){if(ha(a))return Ab(a);else{for(var b=[],c=0,d=a.length;c=112&&a.keyCode<=123)a.keyCode=-1}catch(b){}};p.sj=n("na");p.g=function(){Pb.b.g.call(this);this.relatedTarget=this.currentTarget=this.target=this.na=l};function Sb(){}var Tb=0;p=Sb.prototype;p.key=0;p.Ic=!1;p.Pf=!1;p.Zb=function(a,b,c,d,g,h){ka(a)?this.Yh=!0:a&&a.handleEvent&&ka(a.handleEvent)?this.Yh=!1:e(Error("Invalid listener argument"));this.nd=a;this.vi=b;this.src=c;this.type=d;this.capture=!!g;this.Ue=h;this.Pf=!1;this.key=++Tb;this.Ic=!1};p.handleEvent=function(a){return this.Yh?this.nd.call(this.Ue||this.src,a):this.nd.handleEvent.call(this.nd,a)};var Ub,Vb=(Ub="ScriptEngine"in r&&r.ScriptEngine()=="JScript")?r.ScriptEngineMajorVersion()+"."+r.ScriptEngineMinorVersion()+"."+r.ScriptEngineBuildVersion():"0";function Wb(a,b){this.Ac=b;this.aa=[];a>this.Ac&&e(Error("[goog.structs.SimplePool] Initial cannot be greater than max"));for(var c=0;c=0),i;bc=function(a){i=a};if(h){Xb=function(){return k.getObject()};Yb=function(a){k.Hc(a)};Zb=function(){return m.getObject()};$b=function(a){m.Hc(a)};ac=function(){return q.getObject()};cc=function(){q.Hc(c())};dc=function(){return t.getObject()};ec=function(a){t.Hc(a)};fc=function(){return y.getObject()}; gc=function(a){y.Hc(a)};var k=new Wb(0,600);k.rc=a;var m=new Wb(0,600);m.rc=b;var q=new Wb(0,600);q.rc=c;var t=new Wb(0,600);t.rc=d;var y=new Wb(0,600);y.rc=g}else Xb=a,Yb=s,Zb=b,$b=s,ac=c,cc=s,dc=d,ec=s,fc=g,gc=s})();var hc={},ic={},jc={},kc={}; function F(a,b,c,d,g){if(b)if(ha(b)){for(var h=0;h=0;g--){var h=a[g];if(d||b==h.capture)oc(h.key),c++}});else if(a=ma(a),jc[a])for(var a=jc[a],g=a.length-1;g>=0;g--){var h=a[g];if(d||b==h.capture)oc(h.key),c++}}function nc(a,b,c){var d=ic;return b in d&&(d=d[b],c in d&&(d=d[c],a=ma(a),d[a]))?d[a]:l} function rc(a,b,c,d,g){var h=1,b=ma(b);if(a[b]){a.ib--;a=a[b];a.cf?a.cf++:a.cf=1;try{for(var i=a.length,k=0;k=0&&i.ib;fa--)q.currentTarget= y[fa],h&=rc(i,y[fa],d,!0,q);if(m){i=g[!1];i.ib=i.U;for(fa=0;!q.Fc&&fa=this.left&&a.right<=this.right&&a.top>=this.top&&a.bottom<=this.bottom:a.x>=this.left&&a.x<=this.right&&a.y>=this.top&&a.y<=this.bottom};function zc(a,b,c,d){this.left=a;this.top=b;this.width=c;this.height=d}p=zc.prototype;p.Ba=function(){return new zc(this.left,this.top,this.width,this.height)};p.toString=function(){return"("+this.left+", "+this.top+" - "+this.width+"w x "+this.height+"h)"}; p.Wh=function(a){var b=Math.max(this.left,a.left),c=Math.min(this.left+this.width,a.left+a.width);if(b<=c){var d=Math.max(this.top,a.top),a=Math.min(this.top+this.height,a.top+a.height);if(d<=a)return this.left=b,this.top=d,this.width=c-b,this.height=a-d,!0}return!1};p.contains=function(a){return a instanceof zc?this.left<=a.left&&this.left+this.width>=a.left+a.width&&this.top<=a.top&&this.top+this.height>=a.top+a.height:a.x>=this.left&&a.x<=this.left+this.width&&a.y>=this.top&&a.y<=this.top+this.height}; p.Mh=function(){return new G(this.width,this.height)};var Ac;function Bc(a){return(a=a.className)&&typeof a.split=="function"?a.split(/\s+/):[]}function I(a,b){var c=Bc(a),d=Eb(arguments,1),g;g=c;for(var h=0,i=0;i");c=c.join("")}c=a.createElement(c);if(d)v(d)?c.className=d:ha(d)?I.apply(l,[c].concat(d)):Kc(c,d);b.length>2&&Pc(a,c,b,2);return c} function Pc(a,b,c,d){function g(c){c&&b.appendChild(v(c)?a.createTextNode(c):c)}for(;d0)){var i;a:{if(h&&typeof h.length=="number")if(la(h)){i=typeof h.item=="function"||typeof h.item=="string";break a}else if(ka(h)){i=typeof h.item=="function";break a}i=!1}tb(i?Bb(h):h,g)}else g(h)}}function P(a){return document.createElement(a)}function Jc(a){return a.compatMode=="CSS1Compat"}function Qc(a,b){a.appendChild(b)} function Rc(a,b){Pc(K(a),a,arguments,1)}function Sc(a){for(var b;b=a.firstChild;)a.removeChild(b)}function Tc(a){return a&&a.parentNode?a.parentNode.removeChild(a):l}function Uc(a){return a.firstElementChild!=j?a.firstElementChild:Vc(a.firstChild)}function Wc(a){return a.nextElementSibling!=j?a.nextElementSibling:Vc(a.nextSibling)}function Vc(a){for(;a&&a.nodeType!=1;)a=a.nextSibling;return a} function Xc(a,b){if(a.contains&&b.nodeType==1)return a==b||a.contains(b);if(typeof a.compareDocumentPosition!="undefined")return a==b||Boolean(a.compareDocumentPosition(b)&16);for(;b&&a!=b;)b=b.parentNode;return b==a}function K(a){return a.nodeType==9?a:a.ownerDocument||a.document} function Yc(a,b){if("textContent"in a)a.textContent=b;else if(a.firstChild&&a.firstChild.nodeType==3){for(;a.lastChild!=a.firstChild;)a.removeChild(a.lastChild);a.firstChild.data=b}else Sc(a),a.appendChild(K(a).createTextNode(b))}var Zc={SCRIPT:1,STYLE:1,HEAD:1,IFRAME:1,OBJECT:1},$c={IMG:" ",BR:"\n"};function ad(a){var b=a.getAttributeNode("tabindex");return b&&b.specified?(a=a.tabIndex,ja(a)&&a>=0&&a<32768):!1}function bd(a,b){b?a.tabIndex=0:(a.tabIndex=-1,a.removeAttribute("tabIndex"))} function cd(a){if(Gc&&"innerText"in a)a=a.innerText.replace(/(\r\n|\r|\n)/g,"\n");else{var b=[];dd(a,b,!0);a=b.join("")}a=a.replace(/ \xAD /g," ").replace(/\xAD/g,"");a=a.replace(/\u200B/g,"");Gc||(a=a.replace(/ +/g," "));a!=" "&&(a=a.replace(/^\s*/,""));return a}function ed(a){var b=[];dd(a,b,!1);return b.join("")} function dd(a,b,c){if(!(a.nodeName in Zc))if(a.nodeType==3)c?b.push(String(a.nodeValue).replace(/(\r\n|\r|\n)/g,"")):b.push(a.nodeValue);else if(a.nodeName in $c)b.push($c[a.nodeName]);else for(a=a.firstChild;a;)dd(a,b,c),a=a.nextSibling}function Hc(a){this.v=a||r.document||document}p=Hc.prototype;p.k=J;function fd(a){return a.v}p.a=function(a){return v(a)?this.v.getElementById(a):a};p.d=function(a,b,c){return Oc(this.v,arguments)};p.createElement=function(a){return this.v.createElement(a)}; p.createTextNode=function(a){return this.v.createTextNode(a)};function gd(a){return Jc(a.v)}function hd(a){return a.v.parentWindow||a.v.defaultView}function id(a){var b=a.v,a=!A&&Jc(b)?b.documentElement:b.body,b=b.parentWindow||b.defaultView;return new H(b.pageXOffset||a.scrollLeft,b.pageYOffset||a.scrollTop)}p.appendChild=Qc;p.removeNode=Tc;p.Kh=Uc;p.contains=Xc;function Q(){}w(Q,Kb);p=Q.prototype;p.Ah=!0;p.mf=l;p.Vg=ba("mf");p.addEventListener=function(a,b,c,d){F(this,a,b,c,d)};p.removeEventListener=function(a,b,c,d){mc(this,a,b,c,d)}; p.dispatchEvent=function(a){var b=a.type||a,c=ic;if(b in c){if(v(a))a=new E(a,this);else if(a instanceof E)a.target=a.target||this;else{var d=a,a=new E(b,this);ob(a,d)}var d=1,g,c=c[b],b=!0 in c,h;if(b){g=[];for(h=this;h;h=h.mf)g.push(h);h=c[!0];h.ib=h.U;for(var i=g.length-1;!a.Fc&&i>=0&&h.ib;i--)a.currentTarget=g[i],d&=rc(h,g[i],a.type,!0,a)&&a.je!=!1}if(!1 in c)if(h=c[!1],h.ib=h.U,b)for(i=0;!a.Fc&&ithis.lg&&(this.pg(a),!this.Cb)){this.Ke(a);return}}c=this.Of(b,c);b=c.x;c=c.y;this.Cb&&this.dispatchEvent(new md("beforedrag",this,a.clientX,a.clientY,a,b,c))!==!1&&(pd(this,a,b,c),a.preventDefault())}}; p.Of=function(a,b){var c=id(J(this.v));a+=c.x-this.qd.x;b+=c.y-this.qd.y;this.qd=c;this.cb+=a;this.eb+=b;var c=nd(this,this.cb),d=od(this,this.eb);return new H(c,d)};p.fk=function(a){var b=this.Of(0,0);a.clientX=this.clientX;a.clientY=this.clientY;pd(this,a,b.x,b.y)};function pd(a,b,c,d){a.Vf(c,d);a.dispatchEvent(new md("drag",a,b.clientX,b.clientY,b,c,d))} function nd(a,b){var c=a.be,d=!isNaN(c.left)?c.left:l,c=!isNaN(c.width)?c.width:0;return Math.min(d!=l?d+c:Infinity,Math.max(d!=l?d:-Infinity,b))}function od(a,b){var c=a.be,d=!isNaN(c.top)?c.top:l,c=!isNaN(c.height)?c.height:0;return Math.min(d!=l?d+c:Infinity,Math.max(d!=l?d:-Infinity,b))}p.Vf=function(a,b){this.target.style.left=a+"px";this.target.style.top=b+"px"}; function md(a,b,c,d,g,h,i,k){E.call(this,a);this.clientX=c;this.clientY=d;this.Yk=g;this.left=ga(h)?h:b.cb;this.top=ga(i)?i:b.eb;this.Nd=b;this.$k=!!k}w(md,E);function qd(a,b){var c=K(a);return c.defaultView&&c.defaultView.getComputedStyle&&(c=c.defaultView.getComputedStyle(a,l))?c[b]||c.getPropertyValue(b):""}function rd(a,b){return qd(a,b)||(a.currentStyle?a.currentStyle[b]:l)||a.style[b]}function sd(a){return rd(a,"position")}function td(a,b,c){var d,g=z&&(Na||Xa)&&B("1.9");b instanceof H?(d=b.x,b=b.y):(d=b,b=c);a.style.left=ud(d,g);a.style.top=ud(b,g)}function vd(a){return new H(a.offsetLeft,a.offsetTop)} function wd(a){var b=a.getBoundingClientRect();if(x)a=a.ownerDocument,b.left-=a.documentElement.clientLeft+a.body.clientLeft,b.top-=a.documentElement.clientTop+a.body.clientTop;return b} function xd(a){if(x)return a.offsetParent;for(var b=K(a),c=rd(a,"position"),d=c=="fixed"||c=="absolute",a=a.parentNode;a&&a!=b;a=a.parentNode)if(c=rd(a,"position"),d=d&&c=="static"&&a!=b.documentElement&&a!=b.body,!d&&(a.scrollWidth>a.clientWidth||a.scrollHeight>a.clientHeight||c=="fixed"||c=="absolute"||c=="relative"))return a;return l} function yd(a){for(var b=new xc(0,Infinity,Infinity,0),c=J(a),d=c.v.body,g=c.v.documentElement,h=!A&&Jc(c.v)?c.v.documentElement:c.v.body;a=xd(a);)if((!x||a.clientWidth!=0)&&(!A||a.clientHeight!=0||a!=d)&&a!=d&&a!=g&&rd(a,"overflow")!="visible"){var i=zd(a),k;k=a;if(z&&!B("1.9")){var m=parseFloat(qd(k,"borderLeftWidth"));if(Ad(k)){var q=k.offsetWidth-k.clientWidth-m-parseFloat(qd(k,"borderRightWidth"));m+=q}k=new H(m,parseFloat(qd(k,"borderTopWidth")))}else k=new H(k.clientLeft,k.clientTop);i.x+= k.x;i.y+=k.y;b.top=Math.max(b.top,i.y);b.right=Math.min(b.right,i.x+a.clientWidth);b.bottom=Math.min(b.bottom,i.y+a.clientHeight);b.left=Math.max(b.left,i.x)}d=h.scrollLeft;h=h.scrollTop;b.left=Math.max(b.left,d);b.top=Math.max(b.top,h);c=Mc(hd(c));b.right=Math.min(b.right,d+c.width);b.bottom=Math.min(b.bottom,h+c.height);return b.top>=0&&b.left>=0&&b.bottom>b.top&&b.right>b.left?b:l} function zd(a){var b,c=K(a),d=rd(a,"position"),g=z&&c.getBoxObjectFor&&!a.getBoundingClientRect&&d=="absolute"&&(b=c.getBoxObjectFor(a))&&(b.screenX<0||b.screenY<0),h=new H(0,0),i;b=c?c.nodeType==9?c:K(c):document;i=x&&!gb()&&!gd(J(b))?b.body:b.documentElement;if(a==i)return h;if(a.getBoundingClientRect)b=wd(a),a=id(J(c)),h.x=b.left+a.x,h.y=b.top+a.y;else if(c.getBoxObjectFor&&!g)b=c.getBoxObjectFor(a),a=c.getBoxObjectFor(i),h.x=b.screenX-a.screenX,h.y=b.screenY-a.screenY;else{b=a;do{h.x+=b.offsetLeft; h.y+=b.offsetTop;b!=a&&(h.x+=b.clientLeft||0,h.y+=b.clientTop||0);if(A&&sd(b)=="fixed"){h.x+=c.body.scrollLeft;h.y+=c.body.scrollTop;break}b=b.offsetParent}while(b&&b!=a);if(Ta||A&&d=="absolute")h.y-=c.body.offsetTop;for(b=a;(b=xd(b))&&b!=c.body&&b!=i;)if(h.x-=b.scrollLeft,!Ta||b.tagName!="TR")h.y-=b.scrollTop}return h}function Bd(a,b){var c=Cd(a),d=Cd(b);return new H(c.x-d.x,c.y-d.y)} function Cd(a){var b=new H;if(a.nodeType==1)if(a.getBoundingClientRect)a=wd(a),b.x=a.left,b.y=a.top;else{var c=id(J(a)),a=zd(a);b.x=a.x-c.x;b.y=a.y-c.y}else{var c=ka(a.sj),d=a;a.targetTouches?d=a.targetTouches[0]:c&&a.na.targetTouches&&(d=a.na.targetTouches[0]);b.x=d.clientX;b.y=d.clientY}return b}function Dd(a,b,c){b instanceof G?(c=b.height,b=b.width):c==j&&e(Error("missing height argument"));a.style.width=ud(b,!0);a.style.height=ud(c,!0)} function ud(a,b){typeof a=="number"&&(a=(b?Math.round(a):a)+"px");return a}function Ed(a){if(rd(a,"display")!="none")return Fd(a);var b=a.style,c=b.display,d=b.visibility,g=b.position;b.visibility="hidden";b.position="absolute";b.display="inline";a=Fd(a);b.display=c;b.position=g;b.visibility=d;return a}function Fd(a){var b=a.offsetWidth,c=a.offsetHeight,d=A&&!b&&!c;return(!ga(b)||d)&&a.getBoundingClientRect?(a=wd(a),new G(a.right-a.left,a.bottom-a.top)):new G(b,c)} function Gd(a){var b=zd(a),a=Ed(a);return new zc(b.x,b.y,a.width,a.height)}function Hd(a,b){var c=a.style;if("opacity"in c)c.opacity=b;else if("MozOpacity"in c)c.MozOpacity=b;else if("filter"in c)c.filter=b===""?"":"alpha(opacity="+b*100+")"}function R(a,b){a.style.display=b?"":"none"} function Id(a,b){var c=J(b),d=l;if(x)d=c.v.createStyleSheet(),Jd(d,a);else{var g=Ic(c.v,"head",j,j)[0];g||(d=Ic(c.v,"body",j,j)[0],g=c.d("head"),d.parentNode.insertBefore(g,d));d=c.d("style");Jd(d,a);c.appendChild(g,d)}}function Jd(a,b){x?a.cssText=b:a[A?"innerText":"innerHTML"]=b}function Ad(a){return"rtl"==rd(a,"direction")}var Kd=z?"MozUserSelect":A?"WebkitUserSelect":l; function Ld(a,b,c){c=!c?a.getElementsByTagName("*"):l;if(Kd){if(b=b?"none":"",a.style[Kd]=b,c)for(var a=0,d;d=c[a];a++)d.style[Kd]=b}else if(x||Ta)if(b=b?"on":"",a.setAttribute("unselectable",b),c)for(a=0;d=c[a];a++)d.setAttribute("unselectable",b)}function Md(a){return new G(a.offsetWidth,a.offsetHeight)} function Nd(a,b){var c=gd(J(K(a)));if(x&&(!c||!B("8"))){var d=a.style;if(c){var c=Od(a),g=Pd(a);d.pixelWidth=b.width-g.left-c.left-c.right-g.right;d.pixelHeight=b.height-g.top-c.top-c.bottom-g.bottom}else d.pixelWidth=b.width,d.pixelHeight=b.height}else d=a.style,z?d.MozBoxSizing="border-box":A?d.WebkitBoxSizing="border-box":d.boxSizing="border-box",d.width=b.width+"px",d.height=b.height+"px"} function Qd(a){var b=K(a),c=x&&a.currentStyle;return c&&gd(J(b))&&c.width!="auto"&&c.height!="auto"&&!c.boxSizing?(b=Rd(a,c.width,"width","pixelWidth"),a=Rd(a,c.height,"height","pixelHeight"),new G(b,a)):(c=Md(a),b=Od(a),a=Pd(a),new G(c.width-a.left-b.left-b.right-a.right,c.height-a.top-b.top-b.bottom-a.bottom))} function Rd(a,b,c,d){if(/^\d+px?$/.test(b))return parseInt(b,10);else{var g=a.style[c],h=a.runtimeStyle[c];a.runtimeStyle[c]=a.currentStyle[c];a.style[c]=b;b=a.style[d];a.style[c]=g;a.runtimeStyle[c]=h;return b}}function Sd(a,b){return Rd(a,a.currentStyle?a.currentStyle[b]:l,"left","pixelLeft")} function Od(a){if(x){var b=Sd(a,"paddingLeft"),c=Sd(a,"paddingRight"),d=Sd(a,"paddingTop"),a=Sd(a,"paddingBottom");return new xc(d,c,a,b)}else return b=qd(a,"paddingLeft"),c=qd(a,"paddingRight"),d=qd(a,"paddingTop"),a=qd(a,"paddingBottom"),new xc(parseFloat(d),parseFloat(c),parseFloat(a),parseFloat(b))}var Td={thin:2,medium:4,thick:6}; function Ud(a,b){if((a.currentStyle?a.currentStyle[b+"Style"]:l)=="none")return 0;var c=a.currentStyle?a.currentStyle[b+"Width"]:l;return c in Td?Td[c]:Rd(a,c,"left","pixelLeft")}function Pd(a){if(x){var b=Ud(a,"borderLeft"),c=Ud(a,"borderRight"),d=Ud(a,"borderTop"),a=Ud(a,"borderBottom");return new xc(d,c,a,b)}else return b=qd(a,"borderLeftWidth"),c=qd(a,"borderRightWidth"),d=qd(a,"borderTopWidth"),a=qd(a,"borderBottomWidth"),new xc(parseFloat(d),parseFloat(c),parseFloat(a),parseFloat(b))};function Vd(){}u(Vd);Vd.prototype.Zj=0;Vd.c();function S(a){this.p=a||J();this.ke=Wd}w(S,Q);S.prototype.Mj=Vd.c();var Wd=l;function Xd(a,b){switch(a){case 1:return b?"disable":"enable";case 2:return b?"highlight":"unhighlight";case 4:return b?"activate":"deactivate";case 8:return b?"select":"unselect";case 16:return b?"check":"uncheck";case 32:return b?"focus":"blur";case 64:return b?"open":"close"}e(Error("Invalid component state"))}p=S.prototype;p.gd=l;p.w=!1;p.e=l;p.ke=l;p.zg=l;p.D=l;p.Z=l;p.Qa=l;p.Pi=!1; function Yd(a){return a.gd||(a.gd=":"+(a.Mj.Zj++).toString(36))}function Zd(a,b){if(a.D&&a.D.Qa){var c=a.D.Qa,d=a.gd;d in c&&delete c[d];mb(a.D.Qa,b,a)}a.gd=b}p.a=n("e");p.G=function(){return this.dd||(this.dd=new tc(this))};function $d(a,b){a==b&&e(Error("Unable to set parent component"));b&&a.D&&a.gd&&ae(a.D,a.gd)&&a.D!=b&&e(Error("Unable to set parent component"));a.D=b;S.b.Vg.call(a,b)}p.getParent=n("D");p.Vg=function(a){this.D&&this.D!=a&&e(Error("Method not supported"));S.b.Vg.call(this,a)}; p.k=n("p");p.d=function(){this.e=this.p.createElement("div")};p.L=function(a){this.Jc(a)};p.Jc=function(a,b){this.w&&e(Error("Component already rendered"));this.e||this.d();a?a.insertBefore(this.e,b||l):this.p.v.body.appendChild(this.e);(!this.D||this.D.w)&&this.o()};p.n=function(a){if(this.w)e(Error("Component already rendered"));else if(a&&this.R(a)){this.Pi=!0;if(!this.p||this.p.v!=K(a))this.p=J(a);this.F(a);this.o()}else e(Error("Invalid element to decorate"))};p.R=o(!0);p.F=ba("e"); p.o=function(){this.w=!0;be(this,function(a){!a.w&&a.a()&&a.o()})};p.K=function(){be(this,function(a){a.w&&a.K()});this.dd&&this.dd.ie();this.w=!1};p.g=function(){S.b.g.call(this);this.w&&this.K();this.dd&&(this.dd.j(),delete this.dd);be(this,function(a){a.j()});!this.Pi&&this.e&&Tc(this.e);this.D=this.zg=this.e=this.Qa=this.Z=l};p.ra=function(a,b){this.Tc(a,ce(this),b)}; p.Tc=function(a,b,c){a.w&&(c||!this.w)&&e(Error("Component already rendered"));(b<0||b>ce(this))&&e(Error("Child component index out of bounds"));if(!this.Qa||!this.Z)this.Qa={},this.Z=[];a.getParent()==this?(this.Qa[Yd(a)]=a,zb(this.Z,a)):mb(this.Qa,Yd(a),a);$d(a,this);Db(this.Z,b,0,a);a.w&&this.w&&a.getParent()==this?(c=this.B(),c.insertBefore(a.a(),c.childNodes[b]||l)):c?(this.e||this.d(),b=T(this,b+1),a.Jc(this.B(),b?b.e:l)):this.w&&!a.w&&a.e&&a.o()};p.B=n("e"); function de(a){if(a.ke==l)a.ke=Ad(a.w?a.e:a.p.v.body);return a.ke}p.wd=function(a){this.w&&e(Error("Component already rendered"));this.ke=a};function ce(a){return a.Z?a.Z.length:0}function ae(a,b){return a.Qa&&b?(b in a.Qa?a.Qa[b]:j)||l:l}function T(a,b){return a.Z?a.Z[b]||l:l}function be(a,b,c){a.Z&&tb(a.Z,b,c)}function ee(a,b){return a.Z&&b?sb(a.Z,b):-1} p.removeChild=function(a,b){if(a){var c=v(a)?a:Yd(a),a=ae(this,c);if(c&&a){var d=this.Qa;c in d&&delete d[c];zb(this.Z,a);b&&(a.K(),a.e&&Tc(a.e));$d(a,l)}}a||e(Error("Child is not in parent component"));return a};function fe(a,b){return a.removeChild(T(a,b),!0)};function ge(a,b,c,d){S.call(this,d);this.C=c;this.Sd=a;this.ra(a);this.oe=b;this.ra(b)}w(ge,S);p=ge.prototype;p.Lc=l;p.fa=l;p.ud=l;p.ed=5;p.og=l;p.Ai=l;p.Rd=l;p.zh=!0;p.qb=l;p.d=function(){var a=this.k(),b=a.d("div","goog-splitpane-first-container"),c=a.d("div","goog-splitpane-second-container"),d=a.d("div","goog-splitpane-handle");this.e=a.d("div","goog-splitpane",b,c,d);this.fa=b;this.ud=c;this.Na=d;he(this);ie(this)}; p.R=function(a){var b=Ic(document,l,"goog-splitpane-first-container",a)[0];if(!b)return!1;this.fa=b;b=Ic(document,l,"goog-splitpane-second-container",a)[0];if(!b)return!1;this.ud=b;a=Ic(document,l,"goog-splitpane-handle",a)[0];if(!a)return!1;this.Na=a;return!0};p.F=function(a){ge.b.F.call(this,a);he(this);a=Md(a);je(this,new G(a.width,a.height));ie(this)}; function ie(a){var b=a.k();a.Sd.a()||a.Sd.d();b.appendChild(a.fa,a.Sd.a());a.oe.a()||a.oe.d();b.appendChild(a.ud,a.oe.a());a.Lc=new jd(a.Na,a.Na);a.fa.style.position="absolute";a.ud.style.position="absolute";a=a.Na.style;a.position="absolute";a.overflow="hidden";a.zIndex=2}p.o=function(){ge.b.o.call(this);var a=this.a();if(sd(a)=="static")a.style.position="relative";this.G().f(this.Na,"dblclick",this.yj).f(this.Lc,"start",this.Aj).f(this.Lc,"drag",this.Bj).f(this.Lc,"end",this.zj);ke(this,this.og)}; function le(a){return a.C=="vertical"}function he(a){le(a)?(a.Na.style.height=a.ed+"px",I(a.Na,"goog-splitpane-handle-vertical")):(a.Na.style.width=a.ed+"px",I(a.Na,"goog-splitpane-handle-horizontal"))} p.te=function(a){if(this.C!=a&&(this.C=a,a=le(this),this.w))if(le(this)?Dc(this.Na,"goog-splitpane-handle-horizontal","goog-splitpane-handle-vertical"):Dc(this.Na,"goog-splitpane-handle-vertical","goog-splitpane-handle-horizontal"),ja(this.Rd)){var b=Md(this.a());ke(this,this.Rd*(a?b.height/b.width:b.width/b.height))}else ke(this)};function me(a,b){td(a,b.left,b.top);Nd(a,new G(Math.max(b.width,0),Math.max(b.height,0)))} function ke(a,b){var c=Md(a.a()),d=le(a),g=ja(b)?b:ja(a.Rd)?a.Rd:Math.floor((d?c.height:c.width)/2);a.Rd=g;var h,i,k,m,q,t,y;d?(k=d=c.width,m=a.ed,i=c.height-g-m,h=c.width,y=0+g,t=0,q=y+m,c=0):(d=g,g=c.height,k=a.ed,m=c.height,h=c.width-d-k,i=c.height,t=0+d,y=0,c=t+k,q=0);me(a.fa,new zc(0,0,d,g));typeof a.Sd.Og=="function"&&a.Sd.Og(new G(d,g));me(a.Na,new zc(t,y,k,m));me(a.ud,new zc(c,q,h,i));typeof a.oe.Og=="function"&&a.oe.Og(new G(h,i));a.dispatchEvent("change")} function je(a,b){Nd(a.a(),b);a.qb&&Nd(a.qb,b);ke(a)} p.Aj=function(){if(!this.qb){var a="position: relative";x&&(a+=";background-color: #000;filter: Alpha(Opacity=0)");this.qb=this.k().d("div",{style:a});this.k().appendChild(this.a(),this.qb)}this.qb.style.zIndex=1;Nd(this.qb,Md(this.a()));var b=vd(this.fa),c=a=0,d=b.x,b=b.y,g=Md(this.fa),h=Qd(this.fa),i=Qd(this.ud);le(this)?(c=h.height+i.height,b+=g.height-h.height):(a=h.width+i.width,d+=g.width-h.width);this.Lc.be=new zc(d,b,a,c)||new zc(NaN,NaN,NaN,NaN)}; p.Bj=function(a){this.zh&&(le(this)?ke(this,a.top-vd(this.fa).y):ke(this,a.left-vd(this.fa).x))};p.zj=function(a){this.qb.style.zIndex=-1;this.zh||(le(this)?ke(this,a.top-vd(this.fa).y):ke(this,a.left-vd(this.fa).x));this.dispatchEvent("handle_drag_end")};p.yj=function(){var a=Bd(this.Na,this.fa),b=Md(this.fa),c=Qd(this.fa),d=le(this);d?(b=b.height-c.height,a=a.y):(b=b.width-c.width,a=a.x);b==a?ke(this,this.Ai):(this.Ai=d?Md(this.fa).height:Md(this.fa).width,ke(this,b))}; p.g=function(){ge.b.g.call(this);this.Lc.j();this.Lc=l;Tc(this.qb);this.qb=l};function ne(a,b){a.setAttribute("role",b);a.el=b}function U(a,b,c){a.setAttribute("aria-"+b,c)};function oe(){}var pe;u(oe);p=oe.prototype;p.Ka=aa();p.d=function(a){var b=a.k().d("div",this.uc(a).join(" "),a.ka);this.sf(a,b);return b};p.B=function(a){return a};p.Pd=function(a,b,c){if(a=a.a?a.a():a)if(x&&!B("7")){var d=qe(Bc(a),b);d.push(b);sa(c?I:Cc,a).apply(l,d)}else Ec(a,b,c)};p.R=o(!0); p.n=function(a,b){b.id&&Zd(a,b.id);var c=this.B(b);a.ka=c&&c.firstChild?c.firstChild.nextSibling?Bb(c.childNodes):c.firstChild:l;var d=0,g=this.i(),h=this.i(),i=!1,k=!1,c=!1,m=Bc(b);tb(m,function(a){!i&&a==g?(i=!0,h==g&&(k=!0)):!k&&a==h?k=!0:d|=this.dg(a)},this);a.q=d;i||(m.push(g),h==g&&(k=!0));k||m.push(h);var q=a.fb;q&&m.push.apply(m,q);if(x&&!B("7")){var t=qe(m);t.length>0&&(m.push.apply(m,t),c=!0)}if(!i||!k||q||c)b.className=m.join(" ");this.sf(a,b);return b}; p.kd=function(a){de(a)&&this.wd(a.a(),!0);a.isEnabled()&&this.ic(a,a.H())};p.sf=function(a,b){a.isEnabled()||this.Ga(b,1,!0);a.yc()&&this.Ga(b,8,!0);a.Q&16&&this.Ga(b,16,a.sb());a.Q&64&&this.Ga(b,64,!!(a.q&64))};p.pe=function(a,b){Ld(a,!b,!x&&!Ta)};p.wd=function(a,b){this.Pd(a,this.i()+"-rtl",b)};p.$b=function(a){var b;return a.Q&32&&(b=a.V())?ad(b):!1};p.ic=function(a,b){var c;if(a.Q&32&&(c=a.V())){if(!b&&a.q&32){try{c.blur()}catch(d){}a.q&32&&a.vc(l)}ad(c)!=b&&bd(c,b)}};p.h=function(a,b){R(a,b)}; p.ya=function(a,b,c){var d=a.a();if(d){var g=this.Td(b);g&&this.Pd(a,g,c);this.Ga(d,b,c)}};p.Ga=function(a,b,c){pe||(pe={1:"disabled",8:"selected",16:"checked",64:"expanded"});(b=pe[b])&&U(a,b,c)};p.t=function(a,b){var c=this.B(a);if(c&&(Sc(c),b))if(v(b))Yc(c,b);else{var d=function(a){if(a){var b=K(c);c.appendChild(v(a)?b.createTextNode(a):a)}};ha(b)?tb(b,d):ia(b)&&!("nodeType"in b)?tb(Bb(b),d):d(b)}};p.V=function(a){return a.a()};p.i=o("goog-control"); p.uc=function(a){var b=this.i(),c=[b],d=this.i();d!=b&&c.push(d);b=a.q;for(d=[];b;){var g=b&-b;d.push(this.Td(g));b&=~g}c.push.apply(c,d);(a=a.fb)&&c.push.apply(c,a);x&&!B("7")&&c.push.apply(c,qe(c));return c};function qe(a,b){var c=[];b&&(a=a.concat([b]));tb([],function(d){wb(d,sa(xb,a))&&(!b||xb(d,b))&&c.push(d.join("_"))});return c}p.Td=function(a){this.Ce||re(this);return this.Ce[a]}; p.dg=function(a){if(!this.Ii){this.Ce||re(this);var b=this.Ce,c={},d;for(d in b)c[b[d]]=d;this.Ii=c}a=parseInt(this.Ii[a],10);return isNaN(a)?0:a};function re(a){var b=a.i();a.Ce={1:b+"-disabled",2:b+"-hover",4:b+"-active",8:b+"-selected",16:b+"-checked",32:b+"-focused",64:b+"-open"}};function se(a,b){a||e(Error("Invalid class name "+a));ka(b)||e(Error("Invalid decorator function "+b));te[a]=b}function ue(a){for(var b=Bc(a),c=0,d=b.length;c=48&&a<=57)return!0;if(a>=96&&a<=106)return!0;if(a>=65&&a<=90)return!0;if(A&&a==0)return!0;switch(a){case 32:case 63:case 107:case 109:case 110:case 111:case 186:case 189:case 187:case 188:case 190:case 191:case 192:case 222:case 219:case 220:case 221:return!0;default:return!1}};function ze(a,b){a&&Ae(this,a,b)}w(ze,Q);p=ze.prototype;p.e=l;p.Ze=l;p.qg=l;p.$e=l;p.dc=-1;p.bc=-1; var Be={3:13,12:144,63232:38,63233:40,63234:37,63235:39,63236:112,63237:113,63238:114,63239:115,63240:116,63241:117,63242:118,63243:119,63244:120,63245:121,63246:122,63247:123,63248:44,63272:46,63273:36,63275:35,63276:33,63277:34,63289:144,63302:45},Ce={Up:38,Down:40,Left:37,Right:39,Enter:13,F1:112,F2:113,F3:114,F4:115,F5:116,F6:117,F7:118,F8:119,F9:120,F10:121,F11:122,F12:123,"U+007F":46,Home:36,End:35,PageUp:33,PageDown:34,Insert:45},De={61:187,59:186},Ee=x||A&&B("525");p=ze.prototype; p.hg=function(a){if(A&&(this.dc==17&&!a.ctrlKey||this.dc==18&&!a.altKey))this.bc=this.dc=-1;Ee&&!xe(a.keyCode,this.dc,a.shiftKey,a.ctrlKey,a.altKey)?this.handleEvent(a):this.bc=z&&a.keyCode in De?De[a.keyCode]:a.keyCode};p.Cj=function(){this.bc=this.dc=-1}; p.handleEvent=function(a){var b=a.na,c,d;x&&a.type=="keypress"?(c=this.bc,d=c!=13&&c!=27?b.keyCode:0):A&&a.type=="keypress"?(c=this.bc,d=b.charCode>=0&&b.charCode<63232&&ye(c)?b.charCode:0):Ta?(c=this.bc,d=ye(c)?b.keyCode:0):(c=b.keyCode||this.bc,d=b.charCode||0,Na&&d==63&&!c&&(c=191));var g=c,h=b.keyIdentifier;c?c>=63232&&c in Be?g=Be[c]:c==25&&a.shiftKey&&(g=9):h&&h in Ce&&(g=Ce[h]);a=g==this.dc;this.dc=g;b=new Fe(g,d,a,b);try{this.dispatchEvent(b)}finally{b.j()}};p.a=n("e"); function Ae(a,b,c){a.$e&&a.detach();a.e=b;a.Ze=F(a.e,"keypress",a,c);a.qg=F(a.e,Hb,a.hg,c,a);a.$e=F(a.e,"keyup",a.Cj,c,a)}p.detach=function(){if(this.Ze)oc(this.Ze),oc(this.qg),oc(this.$e),this.$e=this.qg=this.Ze=l;this.e=l;this.bc=this.dc=-1};p.g=function(){ze.b.g.call(this);this.detach()};function Fe(a,b,c,d){d&&this.Zb(d,j);this.type="key";this.keyCode=a;this.charCode=b;this.repeat=c}w(Fe,Pb);function V(a,b,c){S.call(this,c);if(!b){for(var b=this.constructor,d;b;){d=ma(b);if(d=ve[d])break;b=b.b?b.b.constructor:l}b=d?ka(d.c)?d.c():new d:l}this.m=b;this.ka=a}w(V,S);p=V.prototype;p.ka=l;p.q=0;p.Q=39;p.Lf=255;p.$g=0;p.Y=!0;p.fb=l;p.Qe=!0;p.ze=!1;p.nf=l;function Ge(a,b){a.w&&b!=a.Qe&&He(a,b);a.Qe=b}p.V=function(){return this.m.V(this)};p.Oe=function(){return this.ba||(this.ba=new ze)}; p.Pd=function(a,b){if(b){if(a)this.fb?xb(this.fb,a)||this.fb.push(a):this.fb=[a],this.m.Pd(this,a,!0)}else if(a&&this.fb){zb(this.fb,a);if(this.fb.length==0)this.fb=l;this.m.Pd(this,a,!1)}};p.d=function(){var a=this.m.d(this);this.e=a;var b=this.nf||this.m.Ka();b&&ne(a,b);this.ze||this.m.pe(a,!1);this.H()||this.m.h(a,!1)};p.B=function(){return this.m.B(this.a())};p.R=function(a){return this.m.R(a)}; p.F=function(a){this.e=a=this.m.n(this,a);var b=this.nf||this.m.Ka();b&&ne(a,b);this.ze||this.m.pe(a,!1);this.Y=a.style.display!="none"};p.o=function(){V.b.o.call(this);this.m.kd(this);if(this.Q&-2&&(this.Qe&&He(this,!0),this.Q&32)){var a=this.V();if(a){var b=this.Oe();Ae(b,a);this.G().f(b,"key",this.Gb).f(a,"focus",this.Pe).f(a,"blur",this.vc)}}}; function He(a,b){var c=a.G(),d=a.a();b?(c.f(d,"mouseover",a.Se).f(d,"mousedown",a.Vb).f(d,"mouseup",a.Wb).f(d,"mouseout",a.Re),x&&c.f(d,"dblclick",a.Oh)):(c.X(d,"mouseover",a.Se).X(d,"mousedown",a.Vb).X(d,"mouseup",a.Wb).X(d,"mouseout",a.Re),x&&c.X(d,"dblclick",a.Oh))}p.K=function(){V.b.K.call(this);this.ba&&this.ba.detach();this.H()&&this.isEnabled()&&this.m.ic(this,!1)};p.g=function(){V.b.g.call(this);this.ba&&(this.ba.j(),delete this.ba);delete this.m;this.fb=this.ka=l}; p.t=function(a){this.m.t(this.a(),a);this.ka=a};p.Eb=function(){var a=this.ka;if(!a)return"";a=v(a)?a:ha(a)?ub(a,ed).join(""):cd(a);return wa(a)};p.wd=function(a){V.b.wd.call(this,a);var b=this.a();b&&this.m.wd(b,a)};p.pe=function(a){this.ze=a;var b=this.a();b&&this.m.pe(b,a)};p.H=n("Y");p.h=function(a,b){if(b||this.Y!=a&&this.dispatchEvent(a?"show":"hide")){var c=this.a();c&&this.m.h(c,a);this.isEnabled()&&this.m.ic(this,a);this.Y=a;return!0}return!1};p.isEnabled=function(){return!(this.q&1)}; p.u=function(a){var b=this.getParent();if((!b||typeof b.isEnabled!="function"||b.isEnabled())&&Ie(this,1,!a))a||(this.setActive(!1),this.vb(!1)),this.H()&&this.m.ic(this,a),this.ya(1,!a)};p.vb=function(a){Ie(this,2,a)&&this.ya(2,a)};p.ha=function(){return!!(this.q&4)};p.setActive=function(a){Ie(this,4,a)&&this.ya(4,a)};p.yc=function(){return!!(this.q&8)};p.Yg=function(a){Ie(this,8,a)&&this.ya(8,a)};p.sb=function(){return!!(this.q&16)};p.Kc=function(a){Ie(this,16,a)&&this.ya(16,a)}; p.P=function(a){Ie(this,64,a)&&this.ya(64,a)};p.ya=function(a,b){if(this.Q&a&&b!=!!(this.q&a))this.m.ya(this,a,b),this.q=b?this.q|a:this.q&~a};function Je(a,b,c){a.w&&a.q&b&&!c&&e(Error("Component already rendered"));!c&&a.q&b&&a.ya(b,!1);a.Q=c?a.Q|b:a.Q&~b}function Ke(a,b){return!!(a.Lf&b)&&!!(a.Q&b)}function Ie(a,b,c){return!!(a.Q&b)&&!!(a.q&b)!=c&&(!(a.$g&b)||a.dispatchEvent(Xd(b,c)))&&!a.Zc} p.Se=function(a){(!a.relatedTarget||!Xc(this.a(),a.relatedTarget))&&this.dispatchEvent("enter")&&this.isEnabled()&&Ke(this,2)&&this.vb(!0)};p.Re=function(a){if((!a.relatedTarget||!Xc(this.a(),a.relatedTarget))&&this.dispatchEvent("leave"))Ke(this,4)&&this.setActive(!1),Ke(this,2)&&this.vb(!1)};p.Vb=function(a){this.isEnabled()&&(Ke(this,2)&&this.vb(!0),Rb(a)&&(Ke(this,4)&&this.setActive(!0),this.m.$b(this)&&this.V().focus()));!this.ze&&Rb(a)&&a.preventDefault()}; p.Wb=function(a){this.isEnabled()&&(Ke(this,2)&&this.vb(!0),this.ha()&&this.Ec(a)&&Ke(this,4)&&this.setActive(!1))};p.Oh=function(a){this.isEnabled()&&this.Ec(a)};p.Ec=function(a){Ke(this,16)&&this.Kc(!this.sb());Ke(this,8)&&this.Yg(!0);Ke(this,64)&&this.P(!(this.q&64));var b=new E("action",this);if(a)for(var c=["altKey","ctrlKey","metaKey","shiftKey","platformModifierKey"],d,g=0;d=c[g];g++)b[d]=a[d];return this.dispatchEvent(b)};p.Pe=function(){Ke(this,32)&&Ie(this,32,!0)&&this.ya(32,!0)}; p.vc=function(){Ke(this,4)&&this.setActive(!1);Ke(this,32)&&Ie(this,32,!1)&&this.ya(32,!1)};p.Gb=function(a){return this.H()&&this.isEnabled()&&this.wc(a)?(a.preventDefault(),a.stopPropagation(),!0):!1};p.wc=function(a){return a.keyCode==13&&this.Ec(a)};ka(V)||e(Error("Invalid component class "+V));ka(oe)||e(Error("Invalid renderer class "+oe));var Le=ma(V);ve[Le]=oe;se("goog-control",function(){return new V(l)});function Me(){}w(Me,oe);u(Me);Me.prototype.d=function(a){return a.k().d("div",this.i())};Me.prototype.n=function(a,b){if(b.tagName=="HR"){var c=b,b=this.d(a);c.parentNode&&c.parentNode.insertBefore(b,c);Tc(c)}else I(b,this.i());return b};Me.prototype.t=aa();Me.prototype.i=o("goog-menuseparator");function Ne(a,b){V.call(this,l,a||Me.c(),b);Je(this,1,!1);Je(this,2,!1);Je(this,4,!1);Je(this,32,!1);this.q=1}w(Ne,V);Ne.prototype.o=function(){Ne.b.o.call(this);ne(this.a(),"separator")};se("goog-menuseparator",function(){return new Ne});function Oe(){}u(Oe);p=Oe.prototype;p.Ka=aa();function Pe(a,b){if(a)a.tabIndex=b?0:-1}p.d=function(a){return a.k().d("div",this.uc(a).join(" "))};p.B=function(a){return a};p.R=function(a){return a.tagName=="DIV"};p.n=function(a,b){b.id&&Zd(a,b.id);var c=this.i(),d=!1,g=Bc(b);g&&tb(g,function(b){b==c?d=!0:b&&(b==c+"-disabled"?a.u(!1):b==c+"-horizontal"?a.te(Qe):b==c+"-vertical"&&a.te(Re))},this);d||I(b,c);Se(this,a,this.B(b));return b}; function Se(a,b,c){if(c)for(var d=c.firstChild,g;d&&d.parentNode==c;){g=d.nextSibling;if(d.nodeType==1){var h=a.Ud(d);if(h)h.e=d,b.isEnabled()||h.u(!1),b.ra(h),h.n(d)}else(!d.nodeValue||xa(d.nodeValue)=="")&&c.removeChild(d);d=g}}p.Ud=function(a){return ue(a)};p.kd=function(a){a=a.a();Ld(a,!0,z);if(x)a.hideFocus=!0;var b=this.Ka();b&&ne(a,b)};p.V=function(a){return a.a()};p.i=o("goog-container"); p.uc=function(a){var b=this.i(),c=[b,a.C==Qe?b+"-horizontal":b+"-vertical"];a.isEnabled()||c.push(b+"-disabled");return c};p.Ih=function(){return Re};function Te(a,b,c){S.call(this,c);this.m=b||Oe.c();this.C=a||this.m.Ih()}w(Te,S);var Qe="horizontal",Re="vertical";p=Te.prototype;p.rg=l;p.ba=l;p.m=l;p.C=l;p.Y=!0;p.S=!0;p.cg=!0;p.ga=-1;p.W=l;p.Kb=!1;p.Zi=!1;p.hk=!0;p.yb=l;p.V=function(){return this.rg||this.m.V(this)};p.Oe=function(){return this.ba||(this.ba=new ze(this.V()))};p.d=function(){this.e=this.m.d(this)};p.B=function(){return this.m.B(this.a())};p.R=function(a){return this.m.R(a)}; p.F=function(a){this.e=this.m.n(this,a);if(a.style.display=="none")this.Y=!1};p.o=function(){Te.b.o.call(this);be(this,function(a){a.w&&Ue(this,a)},this);var a=this.a();this.m.kd(this);this.h(this.Y,!0);this.G().f(this,"enter",this.fg).f(this,"highlight",this.gg).f(this,"unhighlight",this.jg).f(this,"open",this.Hj).f(this,"close",this.vj).f(a,"mousedown",this.Vb).f(K(a),"mouseup",this.xj).f(a,["mousedown","mouseup","mouseover","mouseout"],this.uj);this.$b()&&Ve(this,!0)}; function Ve(a,b){var c=a.G(),d=a.V();b?c.f(d,"focus",a.Pe).f(d,"blur",a.vc).f(a.Oe(),"key",a.Gb):c.X(d,"focus",a.Pe).X(d,"blur",a.vc).X(a.Oe(),"key",a.Gb)}p.K=function(){We(this,-1);this.W&&this.W.P(!1);this.Kb=!1;Te.b.K.call(this)};p.g=function(){Te.b.g.call(this);if(this.ba)this.ba.j(),this.ba=l;this.m=this.W=this.yb=this.rg=l};p.fg=o(!0); p.gg=function(a){var b=ee(this,a.target);if(b>-1&&b!=this.ga){var c=T(this,this.ga);c&&c.vb(!1);this.ga=b;c=T(this,this.ga);this.Kb&&c.setActive(!0);this.hk&&this.W&&c!=this.W&&(c.Q&64?c.P(!0):this.W.P(!1))}U(this.a(),"activedescendant",a.target.a().id)};p.jg=function(a){if(a.target==T(this,this.ga))this.ga=-1;U(this.a(),"activedescendant","")};p.Hj=function(a){if((a=a.target)&&a!=this.W&&a.getParent()==this)this.W&&this.W.P(!1),this.W=a};p.vj=function(a){if(a.target==this.W)this.W=l}; p.Vb=function(a){if(this.S)this.Kb=!0;var b=this.V();b&&ad(b)?b.focus():a.preventDefault()};p.xj=function(){this.Kb=!1};p.uj=function(a){var b;a:{b=a.target;if(this.yb)for(var c=this.a();b&&b!==c;){var d=b.id;if(d in this.yb){b=this.yb[d];break a}b=b.parentNode}b=l}if(b)switch(a.type){case "mousedown":b.Vb(a);break;case "mouseup":b.Wb(a);break;case "mouseover":b.Se(a);break;case "mouseout":b.Re(a)}};p.Pe=aa();p.vc=function(){We(this,-1);this.Kb=!1;this.W&&this.W.P(!1)}; p.Gb=function(a){return this.isEnabled()&&this.H()&&(ce(this)!=0||this.rg)&&this.wc(a)?(a.preventDefault(),a.stopPropagation(),!0):!1}; p.wc=function(a){var b=T(this,this.ga);if(b&&typeof b.Gb=="function"&&b.Gb(a))return!0;if(this.W&&this.W!=b&&typeof this.W.Gb=="function"&&this.W.Gb(a))return!0;if(a.shiftKey||a.ctrlKey||a.metaKey||a.altKey)return!1;switch(a.keyCode){case 27:if(this.$b())this.V().blur();else return!1;break;case 36:Xe(this);break;case 35:Ye(this);break;case 38:if(this.C==Re)Ze(this);else return!1;break;case 37:if(this.C==Qe)de(this)?$e(this):Ze(this);else return!1;break;case 40:if(this.C==Re)$e(this);else return!1; break;case 39:if(this.C==Qe)de(this)?Ze(this):$e(this);else return!1;break;default:return!1}return!0};function Ue(a,b){var c=b.a(),c=c.id||(c.id=Yd(b));if(!a.yb)a.yb={};a.yb[c]=b}p.ra=function(a,b){Te.b.ra.call(this,a,b)};p.Tc=function(a,b,c){a.$g|=2;a.$g|=64;(this.$b()||!this.Zi)&&Je(a,32,!1);Ge(a,!1);Te.b.Tc.call(this,a,b,c);c&&this.w&&Ue(this,a);b<=this.ga&&this.ga++}; p.removeChild=function(a,b){if(a=v(a)?ae(this,a):a){var c=ee(this,a);c!=-1&&(c==this.ga?a.vb(!1):c-1&&T(a,a.ga).vb(!1)}p.vb=function(a){We(this,ee(this,a))};function Xe(a){af(a,function(a,c){return(a+1)%c},ce(a)-1)}function Ye(a){af(a,function(a,c){a--;return a<0?c-1:a},0)}function $e(a){af(a,function(a,c){return(a+1)%c},a.ga)}function Ze(a){af(a,function(a,c){a--;return a<0?c-1:a},a.ga)} function af(a,b,c){for(var c=c<0?ee(a,a.W):c,d=ce(a),c=b.call(a,c,d),g=0;g<=d;){var h=T(a,c);if(h&&a.th(h)){We(a,c);break}g++;c=b.call(a,c,d)}}p.th=function(a){return a.H()&&a.isEnabled()&&!!(a.Q&2)};function bf(){}bf.prototype.id=s;bf.prototype.De=function(a){if(this.id()>a.id())return 1;else if(this.id()a.name())return 1;else if(this.name()0&&a2147483647||qf.setTimeout(a,b||0)};function tf(a,b){this.da={};this.N=[];var c=arguments.length;if(c>1){c%2&&e(Error("Uneven number of arguments"));for(var d=0;d2*this.U&&uf(this),!0):!1};function uf(a){if(a.U!=a.N.length){for(var b=0,c=0;b0&&c.push(", ");var h;h=d[g];switch(typeof h){case "object":h=h?"object":"null";break;case "string":break;case "number":h=String(h);break;case "boolean":h=h?"true":"false";break;case "function":h=(h=Af(h))?h:"[fn]";break;default:h=typeof h}h.length>40&&(h=h.substr(0,40)+"...");c.push(h)}b.push(a);c.push(")\n");try{c.push(zf(a.caller,b))}catch(i){c.push("[exception trying to get caller]\n")}}else a? c.push("[...long stack...]"):c.push("[end]");return c.join("")}function Af(a){if(Bf[a])return Bf[a];a=String(a);if(!Bf[a]){var b=/function ([^\(]+)/.exec(a);Bf[a]=b?b[1]:"[Anonymous]"}return Bf[a]}var Bf={};function Cf(a,b,c,d,g){this.reset(a,b,c,d,g)}Cf.prototype.xk=0;Cf.prototype.ag=l;Cf.prototype.$f=l;var Df=0;Cf.prototype.reset=function(a,b,c,d,g){this.xk=typeof g=="number"?g:Df++;this.Ki=d||ta();this.md=a;this.fi=b;this.Tj=c;delete this.ag;delete this.$f};Cf.prototype.Ug=ba("md");function Ef(a){this.Xj=a}Ef.prototype.D=l;Ef.prototype.md=l;Ef.prototype.Z=l;Ef.prototype.Yd=l;function Ff(a,b){this.name=a;this.value=b}Ff.prototype.toString=n("name");var Gf=new Ff("SHOUT",1200),Hf=new Ff("SEVERE",1E3),If=new Ff("WARNING",900),Jf=new Ff("INFO",800),Kf=new Ff("CONFIG",700),Lf=new Ff("FINE",500),Mf=new Ff("FINEST",300),Nf=new Ff("ALL",0);p=Ef.prototype;p.getParent=n("D");p.Ug=ba("md"); function Of(a){if(a.md)return a.md;if(a.D)return Of(a.D);rb("Root logger has no level set.");return l}p.log=function(a,b,c){if(a.value>=Of(this).value){a=this.tj(a,b,c);b="log:"+a.fi;r.console&&(r.console.timeStamp?r.console.timeStamp(b):r.console.markTimeline&&r.console.markTimeline(b));r.msWriteProfilerMark&&r.msWriteProfilerMark(b);for(b=this;b;){var c=b,d=a;if(c.Yd)for(var g=0,h=j;h=c.Yd[g];g++)h(d);b=b.getParent()}}}; p.tj=function(a,b,c){var d=new Cf(a,String(b),this.Xj);if(c){d.ag=c;var g;var h=arguments.callee.caller;try{var i;var k=da("window.location.href");if(v(c))i={message:c,name:"Unknown error",lineNumber:"Not available",fileName:k,stack:"Not available"};else{var m,q,t=!1;try{m=c.lineNumber||c.cl||"Not available"}catch(y){m="Not available",t=!0}try{q=c.fileName||c.filename||c.sourceURL||k}catch(M){q="Not available",t=!0}i=t||!c.lineNumber||!c.fileName||!c.stack?{message:c.message,name:c.name,lineNumber:m, fileName:q,stack:c.stack||"Not available"}:c}g="Message: "+za(i.message)+'\nUrl: '+i.fileName+"\nLine: "+i.lineNumber+"\n\nBrowser stack:\n"+za(i.stack+"-> ")+"[end]\n\nJS stack traversal:\n"+za(yf(h)+"-> ")}catch(fa){g="Exception trying to expose exception! You win, we lose. "+fa}d.$f=g}return d};p.info=function(a,b){this.log(Jf,a,b)};function Pf(a,b){a.log(Lf,b,j)}p.ue=ba("D");var Qf={},Rf=l; function Sf(){Rf||(Rf=new Ef(""),Qf[""]=Rf,Rf.Ug(Kf))}function Tf(){Sf();return Rf}function Uf(a){Sf();var b;if(!(b=Qf[a])){b=new Ef(a);var c=a.lastIndexOf("."),d=a.substr(c+1),c=Uf(a.substr(0,c));if(!c.Z)c.Z={};c.Z[d]=b;b.ue(c);Qf[a]=b}return b};function Vf(){if(z)this.qc={},this.Ef={},this.yf=[]}Vf.prototype.ca=Uf("goog.net.xhrMonitor");Vf.prototype.S=z;Vf.prototype.u=function(a){this.S=z&&a};function Wf(a){var b=Xf;if(b.S){var c=v(a)?a:la(a)?ma(a):"";b.ca.log(Mf,"Pushing context: "+a+" ("+c+")",j);b.yf.push(c)}}function Yf(){var a=Xf;if(a.S){var b=a.yf.pop();a.ca.log(Mf,"Popping context: "+b,j);Zf(a,b)}} function $f(a){var b=Xf;if(b.S){a=ma(a);Pf(b.ca,"Opening XHR : "+a);for(var c=0;c0)Pf(this.ca,kg(this,"Will abort after "+this.zf+"ms if incomplete")),this.Nc=qf.setTimeout(ra(this.Ik, this),this.zf);Pf(this.ca,kg(this,"Sending request"));this.Ve=!0;this.A.send(a);this.Ve=!1}catch(i){Pf(this.ca,kg(this,"Send error: "+i.message)),lg(this,i)}};p.dispatchEvent=function(a){if(this.A){Wf(this.A);try{return ig.b.dispatchEvent.call(this,a)}finally{Yf()}}else return ig.b.dispatchEvent.call(this,a)};p.Ik=function(){if(typeof ca!="undefined"&&this.A)this.cc="Timed out after "+this.zf+"ms, aborting",this.ae=8,Pf(this.ca,kg(this,this.cc)),this.dispatchEvent("timeout"),this.abort(8)}; function lg(a,b){a.Pb=!1;if(a.A)a.xc=!0,a.A.abort(),a.xc=!1;a.cc=b;a.ae=5;mg(a);ng(a)}function mg(a){if(!a.Zf)a.Zf=!0,a.dispatchEvent("complete"),a.dispatchEvent("error")}p.abort=function(a){if(this.A&&this.Pb)Pf(this.ca,kg(this,"Aborting")),this.Pb=!1,this.xc=!0,this.A.abort(),this.xc=!1,this.ae=a||7,this.dispatchEvent("complete"),this.dispatchEvent("abort"),ng(this)};p.g=function(){if(this.A){if(this.Pb)this.Pb=!1,this.xc=!0,this.A.abort(),this.xc=!1;ng(this,!0)}ig.b.g.call(this)}; p.mi=function(){!this.ng&&!this.Ve&&!this.xc?this.ek():og(this)};p.ek=function(){og(this)}; function og(a){if(a.Pb&&typeof ca!="undefined")if(a.Df[1]&&pg(a)==4&&rg(a)==2)Pf(a.ca,kg(a,"Local request error detected and ignored"));else if(a.Ve&&pg(a)==4)qf.setTimeout(ra(a.mi,a),0);else if(a.dispatchEvent("readystatechange"),pg(a)==4){Pf(a.ca,kg(a,"Request complete"));a.Pb=!1;var b;a:switch(rg(a)){case 0:b=v(a.va)?a.va.match(of)[1]||l:a.va.bl();b=!(b?jg.test(b):self.location?jg.test(self.location.protocol):1);break a;case 200:case 201:case 202:case 204:case 304:case 1223:b=!0;break a;default:b= !1}if(b)a.dispatchEvent("complete"),a.dispatchEvent("success");else{a.ae=6;var c;try{c=pg(a)>2?a.A.statusText:""}catch(d){Pf(a.ca,"Can not get status: "+d.message),c=""}a.cc=c+" ["+rg(a)+"]";mg(a)}ng(a)}} function ng(a,b){if(a.A){var c=a.A,d=a.Df[0]?s:l;a.A=l;a.Df=l;if(a.Nc)qf.clearTimeout(a.Nc),a.Nc=l;b||(Wf(c),a.dispatchEvent("ready"),Yf());var g=Xf;if(g.S){var h=ma(c);Pf(g.ca,"Closing XHR : "+h);delete g.Ef[h];for(var i in g.qc)zb(g.qc[i],h),g.qc[i].length==0&&delete g.qc[i]}try{c.onreadystatechange=d}catch(k){a.ca.log(Hf,"Problem encountered resetting onreadystatechange: "+k.message,j)}}}p.ha=function(){return!!this.A};function pg(a){return a.A?a.A.readyState:0} function rg(a){try{return pg(a)>2?a.A.status:-1}catch(b){return a.ca.log(If,"Can not get status: "+b.message,j),-1}}function sg(a){if(a.A)return bg(a.A.responseText)}function tg(a){return v(a.cc)?a.cc:String(a.cc)}function kg(a,b){return b+" ["+a.$h+" "+a.va+" "+rg(a)+"]"};function ug(){this.Sb=[]}p=ug.prototype;p.Hb=0;p.Mc=0;p.Le=function(a){this.Sb[this.Mc++]=a};p.Yc=function(){if(this.Hb!=this.Mc){var a=this.Sb[this.Hb];delete this.Sb[this.Hb];this.Hb++;return a}};p.oa=function(){return this.Mc-this.Hb};p.Ib=function(){return this.Mc-this.Hb==0};p.clear=function(){this.Mc=this.Hb=this.Sb.length=0};p.contains=function(a){return xb(this.Sb,a)};p.remove=function(a){a=sb(this.Sb,a);if(a<0)return!1;a==this.Hb?this.Yc():(C.splice.call(this.Sb,a,1),this.Mc--);return!0}; p.Fb=function(){return this.Sb.slice(this.Hb,this.Mc)};function vg(a,b){this.di=a||0;this.Ac=b||10;this.di>this.Ac&&e(Error(wg));this.aa=new ug;this.Xb=new wf;this.Wf=0;this.sg=l;this.ye()}w(vg,Kb);var wg="[goog.structs.Pool] Min can not be greater than max";p=vg.prototype;p.getObject=function(){var a=ta();if(!(this.sg!=l&&a-this.sg0;)if(b=this.aa.Yc(),this.Ag(b))break;else this.ye();!b&&this.oa()this.Ac&&this.aa.oa()>0;)this.sc(a.Yc())};p.Xc=function(){return{}};p.sc=function(a){if(typeof a.j=="function")a.j();else for(var b in a)a[b]=l};p.Ag=function(a){return typeof a.ej=="function"?a.ej():!0};p.contains=function(a){return this.aa.contains(a)||this.Xb.contains(a)}; p.oa=function(){return this.aa.oa()+this.Xb.oa()};p.Ib=function(){return this.aa.Ib()&&this.Xb.Ib()};p.g=function(){vg.b.g.call(this);this.Xb.oa()>0&&e(Error("[goog.structs.Pool] Objects not released"));delete this.Xb;for(var a=this.aa;!a.Ib();)this.sc(a.Yc());delete this.aa};function xg(a,b){this.Jb=a;this.Ha=b}xg.prototype.s=n("Ha");xg.prototype.Ba=function(){return new xg(this.Jb,this.Ha)};function yg(a){this.hb=[];if(a)a:{var b,c;if(a instanceof yg){if(b=a.Vd(),c=a.Fb(),a.oa()<=0){for(var a=this.hb,d=0;d0;)if(d=b-1>>1,a[d].Jb>c.Jb)a[b]=a[d],b=d;else break;a[b]=c}p=yg.prototype; p.remove=function(){var a=this.hb,b=a.length,c=a[0];if(!(b<=0)){if(b==1)yb(a);else{a[0]=a.pop();for(var a=0,b=this.hb,d=b.length,g=b[a];a>1;){var h=a*2+1,i=a*2+2,h=ig.Jb)break;b[a]=b[h];a=h}b[a]=g}return c.s()}};p.Fb=function(){for(var a=this.hb,b=[],c=a.length,d=0;d0;){var b=this.getObject();if(b)a.Yc().apply(this,[b]);else break}};p.Jf=function(a){Bg.b.Jf.call(this,a);this.Te()};p.ye=function(){Bg.b.ye.call(this);this.Te()}; p.g=function(){Bg.b.g.call(this);r.clearTimeout(this.hj);this.pf.clear();this.pf=l};function Cg(a,b,c){Bg.call(this,b,c);this.Lj=a}w(Cg,Bg);Cg.prototype.Xc=function(){var a=new ig,b=this.Lj;b&&nf(b,function(b,d){a.headers.set(d,b)});return a};Cg.prototype.sc=function(a){a.j()};Cg.prototype.Ag=function(a){return!a.Zc&&!a.ha()};function Dg(a,b,c,d){this.url=a;this.ob=b;this.jk=c;this.ik=d}function W(){this.si=new Cg({},1);this.lb={};this.qf=[]}w(W,Q);u(W);function Eg(a){E.call(this,"server_info_change");this.hc=a}w(Eg,E);function Fg(a){E.call(this,"plugin_list_change");this.plugins=a}w(Fg,E);function Gg(a){E.call(this,"universe_list_change");this.lb=a}w(Fg,E);function Hg(a){E.call(this,"plugin_change");this.ec=a}w(Hg,E);function Ig(a){E.call(this,"universe_change");this.Oc=a}w(Ig,E); function Jg(a){X(a,"json/server_stats",function(a){a=sg(a.target);this.dispatchEvent(new Eg(a))})}function Kg(a){var b=W.c();X(b,"reload",a)}function Lg(a){var b=W.c();X(b,"quit",a)} function Mg(a){X(a,"json/universe_plugin_list",function(a){if(rg(a.target)!=200)Ng.info("Request failed: "+String(a.target.va)+" : "+tg(a.target));else{a=sg(a.target);this.lb={};for(var c=0;c=30?(b=Y.c(),Z(b,eh),b.M("Failed to Communicate with Server"),b.t("The request pool was empty, the server is probably down."),b.h(!0)):(a.qf.push(new Dg(b,c,d,g)),a.si.getObject(function(b){if(a.qf.length){var c=a.qf.shift();c.ob&&F(b,"complete",c.ob,!1,a);F(b,"ready",a.fj,!1,a);b.send(c.url,c.jk,c.ik)}},1))}W.prototype.fj=function(a){a=a.target;qc(a);this.si.Hc(a)};function fh(){this.xi=ta()}var gh=new fh;fh.prototype.set=ba("xi");fh.prototype.reset=function(){this.set(ta())};fh.prototype.get=n("xi");function hh(a){this.nk=a||"";this.Dk=gh}hh.prototype.Ci=!0;hh.prototype.Ck=!0;hh.prototype.Bk=!0;hh.prototype.Di=!1;function ih(a){return a<10?"0"+a:String(a)}function jh(a,b){var c=(a.Ki-b)/1E3,d=c.toFixed(3),g=0;if(c<1)g=2;else for(;c<100;)g++,c*=10;for(;g-- >0;)d=" "+d;return d}function kh(a){hh.call(this,a)}w(kh,hh);kh.prototype.Di=!0;function lh(a){this.qk=ra(this.Wi,this);this.Gh=new kh;this.Xh=this.Gh.Ci=!1;this.e=a;this.lj=this.e.ownerDocument||this.e.document;Id(".dbg-sev{color:#F00}.dbg-w{color:#C40}.dbg-sh{font-weight:bold;color:#000}.dbg-i{color:#444}.dbg-f{color:#999}.dbg-ev{color:#0A0}.dbg-m{color:#990}.logmsg{border-bottom:1px solid #CCC;padding:2px}.logsep{background-color: #8C8;}.logdiv{border:1px solid #CCC;background-color:#FCFCFC;font:medium monospace}",this.e);this.e.className+=" logdiv"} lh.prototype.Wi=function(a){var b=this.e.scrollHeight-this.e.scrollTop-this.e.clientHeight<=100,c=this.lj.createElement("div");c.className="logmsg";var d=this.Gh,g;switch(a.md.value){case Gf.value:g="dbg-sh";break;case Hf.value:g="dbg-sev";break;case If.value:g="dbg-w";break;case Jf.value:g="dbg-i";break;default:g="dbg-f"}var h=[];h.push(d.nk," ");if(d.Ci){var i=new Date(a.Ki);h.push("[",ih(i.getFullYear()-2E3)+ih(i.getMonth()+1)+ih(i.getDate())+" "+ih(i.getHours())+":"+ih(i.getMinutes())+":"+ih(i.getSeconds())+ "."+ih(Math.floor(i.getMilliseconds()/10)),"] ")}d.Ck&&h.push("[",Fa(jh(a,d.Dk.get())),"s] ");d.Bk&&h.push("[",za(a.Tj),"] ");h.push('',ya(Fa(za(a.fi))));d.Di&&a.ag&&h.push("
",ya(Fa(a.$f||"")));h.push("

");c.innerHTML=h.join("");this.e.appendChild(c);if(b)this.e.scrollTop=this.e.scrollHeight};lh.prototype.clear=function(){this.e.innerHTML=""};function mh(a,b,c,d,g,h,i,k){var m,q=c.offsetParent;if(q){var t=q.tagName=="HTML"||q.tagName=="BODY";if(!t||sd(q)!="static")m=zd(q),t||(m=wc(m,new H(q.scrollLeft,q.scrollTop)))}q=Gd(a);(t=yd(a))&&q.Wh(new zc(t.left,t.top,t.right-t.left,t.bottom-t.top));var t=J(a),y=J(c);if(t.v!=y.v){var M=t.v.body,y=hd(y),fa=new H(0,0),yc=Nc(K(M)),qg=M;do{var zi=yc==y?zd(qg):Cd(qg);fa.x+=zi.x;fa.y+=zi.y}while(yc&&yc!=y&&(qg=yc.frameElement)&&(yc=yc.parent));M=wc(fa,zd(M));x&&!gd(t)&&(M=wc(M,id(t)));q.left+=M.x;q.top+= M.y}a=(b&4&&Ad(a)?b^2:b)&-5;b=new H(a&2?q.left+q.width:q.left,a&1?q.top+q.height:q.top);m&&(b=wc(b,m));g&&(b.x+=(a&2?-1:1)*g.x,b.y+=(a&1?-1:1)*g.y);var L;if(i&&(L=yd(c))&&m)L.top-=m.y,L.right-=m.x,L.bottom-=m.y,L.left-=m.x;a:{m=L;g=b.Ba();L=0;a=(d&4&&Ad(c)?d^2:d)&-5;d=Ed(c);k=k?k.Ba():d.Ba();if(h||a!=0)a&2?g.x-=k.width+(h?h.right:0):h&&(g.x+=h.left),a&1?g.y-=k.height+(h?h.bottom:0):h&&(g.y+=h.top);if(i){if(m){h=g;L=0;if((i&65)==65&&(h.x=m.right))i&=-2;if((i&132)==132&&(h.y= m.bottom))i&=-5;if(h.xm.right&&i&16&&(k.width-=h.x+k.width-m.right,L|=4);if(h.x+k.width>m.right&&i&1)h.x=Math.max(m.right-k.width,m.left),L|=1;i&2&&(L|=(h.xm.right?32:0));if(h.y=m.top&&h.y+k.height>m.bottom&&i&32&&(k.height-=h.y+k.height-m.bottom,L|=8);if(h.y+k.height>m.bottom&&i&4)h.y=Math.max(m.bottom-k.height,m.top),L|=2;i&8&&(L|=(h.ym.bottom?128:0));i=L}else i= 256;L=i;if(L&496){c=L;break a}}td(c,g);vc(d,k)||Nd(c,k);c=L}return c};function nh(){}nh.prototype.Ma=aa();function oh(a,b){this.element=a;this.Uf=b}w(oh,nh);oh.prototype.Ma=function(a,b,c){mh(this.element,this.Uf,a,b,j,c)};function ph(a,b){this.Ta=new tc(this);var c=a||l;qh(this);this.e=c;if(b)this.Cd=b}w(ph,Q);p=ph.prototype;p.e=l;p.rh=!0;p.qh=l;p.ld=!1;p.Ak=!1;p.ug=-1;p.Zh=-1;p.Sh=!1;p.mj=!0;p.Cd="toggle_display";p.a=n("e");function qh(a){a.ld&&e(Error("Can not change this state of the popup while showing."))}p.H=n("ld");p.h=function(a){this.ve&&this.ve.stop();this.Zd&&this.Zd.stop();a?this.Zg():this.fd()};p.Ma=s; p.Zg=function(){if(!this.ld&&this.dispatchEvent("beforeshow")){this.e||e(Error("Caller must call setElement before trying to show the popup"));this.Ma();var a=K(this.e);this.Sh&&this.Ta.f(a,Hb,this.ck,!0);if(this.rh)if(this.Ta.f(a,"mousedown",this.li,!0),x){var b;try{b=a.activeElement}catch(c){}for(;b&&b.nodeName=="IFRAME";){try{var d=A?b.document||b.contentWindow.document:b.contentDocument||b.contentWindow.document}catch(g){break}a=d;b=a.activeElement}this.Ta.f(a,"mousedown",this.li,!0);this.Ta.f(a, "deactivate",this.ki)}else this.Ta.f(a,"blur",this.ki);this.Cd=="toggle_display"?(this.e.style.visibility="visible",R(this.e,!0)):this.Cd=="move_offscreen"&&this.Ma();this.ld=!0;this.ve?(lc(this.ve,"end",this.ni,!1,this),this.ve.play()):this.ni()}};p.fd=function(a){if(!this.ld||!this.dispatchEvent({type:"beforehide",target:a}))return!1;this.Ta&&this.Ta.ie();this.Zd?(lc(this.Zd,"end",sa(this.yh,a),!1,this),this.Zd.play()):this.yh(a);return!0}; p.yh=function(a){if(this.Cd=="toggle_display")this.Ak?sf(this.Th,0,this):this.Th();else if(this.Cd=="move_offscreen")this.e.style.left="-200px",this.e.style.top="-200px";this.ld=!1;this.Zh=ta();this.dispatchEvent({type:"hide",target:a})};p.Th=function(){this.e.style.visibility="hidden";R(this.e,!1)};p.ni=function(){this.ug=ta();this.Zh=-1;this.dispatchEvent("show")};p.li=function(a){a=a.target;!Xc(this.e,a)&&(!this.qh||Xc(this.qh,a))&&!(ta()-this.ug<150)&&this.fd(a)}; p.ck=function(a){a.keyCode==27&&this.fd(a.target)&&(a.preventDefault(),a.stopPropagation())};p.ki=function(a){if(this.mj){var b=K(this.e);if(x||Ta){if(a=b.activeElement,!a||Xc(this.e,a)||a.tagName=="BODY")return}else if(a.target!=b)return;ta()-this.ug<150||this.fd()}};p.g=function(){ph.b.g.call(this);this.Ta.j();Mb(this.ve);Mb(this.Zd);delete this.e;delete this.Ta};function rh(a,b,c){oh.call(this,a,b);this.Yi=c}w(rh,oh);rh.prototype.Lh=o(5);rh.prototype.Ma=function(a,b,c,d){var g=mh(this.element,this.Uf,a,b,l,c,10,d);if(g&496){var h=sh(g,this.Uf),b=sh(g,b),g=mh(this.element,h,a,b,l,c,10,d);g&496&&(h=sh(g,h),b=sh(g,b),this.Yi?mh(this.element,h,a,b,l,c,this.Lh(),d):mh(this.element,h,a,b,l,c,0,d))}};function sh(a,b){a&48&&(b^=2);a&192&&(b^=1);return b};function th(a,b){this.ti=4;this.Lg=b||j;ph.call(this,a)}w(th,ph);th.prototype.Wg=function(a){this.Lg=a||j;this.H()&&this.Ma()};th.prototype.Ma=function(){if(this.Lg){var a=!this.H()&&this.Cd!="move_offscreen",b=this.a();if(a)b.style.visibility="hidden",R(b,!0);this.Lg.Ma(b,this.ti,this.xg);a&&R(b,!1)}};function uh(a,b,c){return Math.min(Math.max(a,b),c)};var Ng=Uf("ola");function vh(){Tf().Ug(Nf);var a=new lh(N("log"));if(!0!=a.Xh){var b=Tf(),c=a.qk;if(!b.Yd)b.Yd=[];b.Yd.push(c);a.Xh=!0}this.df=N("log_control");(new V).n(this.df);F(this.df,D,this.Pa,!1,this);a=this.fc=new th(document.getElementById("log_popup"));qh(a);a.Sh=!0;a=this.fc;qh(a);a.rh=!0}vh.prototype.Pa=function(){this.fc.h(!1);var a=this.fc;a.ti=2;a.H()&&a.Ma();var a=this.fc,b=new xc(2,2,2,2);a.xg=b==l||b instanceof xc?b:new xc(b,j,j,j);a.H()&&a.Ma();this.fc.Wg(new rh(this.df,3));this.fc.h(!0)};function wh(a){this.e=a;a=x?"focusout":"blur";this.Rj=F(this.e,x?"focusin":"focus",this,!x);this.Sj=F(this.e,a,this,!x)}w(wh,Q);wh.prototype.handleEvent=function(a){var b=new Pb(a.na);b.type=a.type=="focusin"||a.type=="focus"?"focusin":"focusout";try{this.dispatchEvent(b)}finally{b.j()}};wh.prototype.g=function(){wh.b.g.call(this);oc(this.Rj);oc(this.Sj);delete this.e};function xh(a,b){S.call(this,b);this.Qk=!!a}w(xh,S);p=xh.prototype;p.bg=l;p.Y=!1;p.Ia=l;p.ja=l;p.wb=l;p.i=o("goog-modalpopup");p.Me=n("Ia");p.d=function(){xh.b.d.call(this);var a=this.a();I(a,this.i());bd(a,!0);R(a,!1);yh(this);zh(this)};function yh(a){if(a.Qk&&!a.ja){var b;b=a.k().d("iframe",{frameborder:0,style:"border:0;vertical-align:bottom;",src:'javascript:""'});a.ja=b;a.ja.className=a.i()+"-bg";R(a.ja,!1);Hd(a.ja,0)}if(!a.Ia)a.Ia=a.k().d("div",a.i()+"-bg"),R(a.Ia,!1)} function zh(a){if(!a.wb)a.wb=a.k().createElement("span"),R(a.wb,!1),bd(a.wb,!0),a.wb.style.position="absolute"}p.R=function(a){return!!a&&a.tagName=="DIV"};p.F=function(a){xh.b.F.call(this,a);I(this.a(),this.i());yh(this);zh(this);R(this.a(),!1)}; p.o=function(){if(this.ja){var a=this.a();a.parentNode&&a.parentNode.insertBefore(this.ja,a)}a=this.a();a.parentNode&&a.parentNode.insertBefore(this.Ia,a);xh.b.o.call(this);a=this.a();a.parentNode&&a.parentNode.insertBefore(this.wb,a.nextSibling);this.bg=new wh(fd(this.k()));this.G().f(this.bg,"focusin",this.dk)};p.K=function(){this.H()&&this.h(!1);Mb(this.bg);xh.b.K.call(this);Tc(this.ja);Tc(this.Ia);Tc(this.wb)};p.h=function(a){a!=this.Y&&(a?this.Zg():this.fd())}; p.Zg=function(){if(this.dispatchEvent("beforeshow"))this.Pg(),this.Ma(),this.G().f(hd(this.k()),"resize",this.Pg),Ah(this,!0),this.focus(),this.Y=!0,this.dispatchEvent("show")};p.fd=function(){if(this.dispatchEvent("beforehide"))this.G().X(hd(this.k()),"resize",this.Pg),Ah(this,!1),this.Y=!1,this.dispatchEvent("hide")};function Ah(a,b){a.ja&&R(a.ja,b);a.Ia&&R(a.Ia,b);R(a.a(),b);R(a.wb,b)}p.H=n("Y");p.focus=function(){this.Fh()}; p.Pg=function(){this.ja&&R(this.ja,!1);this.Ia&&R(this.Ia,!1);var a=fd(this.k()),b=Mc(Nc(a)||window),c=Math.max(a.body.scrollWidth,b.width),a=Math.max(a.body.scrollHeight,b.height);this.ja&&(R(this.ja,!0),Dd(this.ja,c,a));this.Ia&&(R(this.Ia,!0),Dd(this.Ia,c,a))}; p.Ma=function(){var a=fd(this.k()),b=Nc(a)||window;if(sd(this.a())=="fixed")var c=a=0;else c=id(this.k()),a=c.x,c=c.y;var d=Ed(this.a()),b=Mc(b),a=Math.max(a+b.width/2-d.width/2,0),c=Math.max(c+b.height/2-d.height/2,0);td(this.a(),a,c);td(this.wb,a,c)};p.dk=function(a){a.target==this.wb&&sf(this.Fh,0,this)};p.Fh=function(){try{x&&fd(this.k()).body.focus(),this.a().focus()}catch(a){}};function Bh(a,b,c){xh.call(this,b,c);this.sa=a||"modal-dialog";this.ea=Ch(Ch(new Dh,Eh,!0),Fh,!1,!0)}w(Bh,xh);p=Bh.prototype;p.pj=!0;p.kg=!0;p.ei=!0;p.Dh=!0;p.Ae=0.5;p.Af="";p.ka="";p.ad=l;p.jj=!1;p.Oa=l;p.xb=l;p.dh=l;p.Nb=l;p.Ra=l;p.T=l;p.i=n("sa");p.M=function(a){this.Af=a;this.xb&&Yc(this.xb,a)};p.t=function(a){this.ka=a;if(this.Ra)this.Ra.innerHTML=a};p.B=function(){this.a()||this.L();return this.Ra};p.Me=function(){this.a()||this.L();return Bh.b.Me.call(this)}; function Gh(a,b){a.Ae=b;if(a.a()){var c=a.Me();c&&Hd(c,a.Ae)}} p.d=function(){Bh.b.d.call(this);var a=this.a(),b=this.k();this.Oa=b.d("div",{className:this.sa+"-title",id:Yd(this)},this.xb=b.d("span",this.sa+"-title-text",this.Af),this.Nb=b.d("span",this.sa+"-title-close"));Rc(a,this.Oa,this.Ra=b.d("div",this.sa+"-content"),this.T=b.d("div",this.sa+"-buttons"));this.dh=this.Oa.id;ne(a,"dialog");U(a,"labelledby",this.dh||"");if(this.ka)this.Ra.innerHTML=this.ka;R(this.Nb,this.kg);if(this.ea)a=this.ea,a.e=this.T,a.L();R(this.T,!!this.ea);Gh(this,this.Ae)}; p.F=function(a){Bh.b.F.call(this,a);a=this.sa+"-content";if(this.Ra=Ic(document,l,a,this.a())[0])this.ka=this.Ra.innerHTML;else{this.Ra=this.k().d("div",a);if(this.ka)this.Ra.innerHTML=this.ka;this.a().appendChild(this.Ra)}var a=this.sa+"-title",b=this.sa+"-title-text",c=this.sa+"-title-close";(this.Oa=Ic(document,l,a,this.a())[0])?(this.xb=Ic(document,l,b,this.Oa)[0],this.Nb=Ic(document,l,c,this.Oa)[0]):(this.Oa=this.k().d("div",a),this.a().insertBefore(this.Oa,this.Ra));this.xb?this.Af=cd(this.xb): (this.xb=this.k().d("span",b,this.Af),this.Oa.appendChild(this.xb));U(this.a(),"labelledby",this.dh||"");if(!this.Nb)this.Nb=this.k().d("span",c),this.Oa.appendChild(this.Nb);R(this.Nb,this.kg);a=this.sa+"-buttons";if(this.T=Ic(document,l,a,this.a())[0])this.ea=new Dh(this.k()),this.ea.n(this.T);else{this.T=this.k().d("div",a);this.a().appendChild(this.T);if(this.ea)a=this.ea,a.e=this.T,a.L();R(this.T,!!this.ea)}Gh(this,this.Ae)}; p.o=function(){Bh.b.o.call(this);this.G().f(this,["show","hide"],this.zk);if(this.Dh&&!this.ad)I(this.Oa,this.sa+"-title-draggable"),this.ad=new jd(this.a(),this.Oa);this.G().f(this.Nb,D,this.gk);ne(this.a(),"dialog");this.xb.id!==""&&U(this.a(),"labelledby",this.xb.id);if(!this.ei&&(this.ei=!1,this.w)){var a=this.k(),b=this.Me();a.removeNode(this.ja);a.removeNode(b)}};p.K=function(){this.H()&&this.h(!1);if(this.ad)this.ad.j(),this.ad=l;Bh.b.K.call(this)}; p.h=function(a){a!=this.H()&&(this.w||this.L(),Bh.b.h.call(this,a))};p.zk=function(a){a.target==this&&(this.H()?(this.G().f(this.a(),Hb,this.jf).f(this.a(),"keypress",this.jf),this.dispatchEvent(Hh),this.Tg(),this.G().f(this.T,D,this.ji).f(hd(this.k()),"resize",this.Tg)):(this.G().X(this.a(),Hb,this.jf).X(this.a(),"keypress",this.jf).X(this.T,D,this.ji).X(hd(this.k()),"resize",this.Tg),this.dispatchEvent(Ih),this.jj&&this.j()))}; p.focus=function(){Bh.b.focus.call(this);if(this.ea){var a=this.ea.Ge;if(a)for(var b=fd(this.k()),c=this.T.getElementsByTagName("button"),d=0,g;g=c[d];d++)if(g.name==a){try{if(A||Ta){var h=b.createElement("input");h.style.cssText="position:fixed;width:0;height:0;left:0;top:0;";this.a().appendChild(h);h.focus();this.a().removeChild(h)}g.focus()}catch(i){}break}}}; p.Tg=function(){if(this.Dh){var a=fd(this.k()),b=Mc(Nc(a)||window),c=Math.max(a.body.scrollWidth,b.width),a=Math.max(a.body.scrollHeight,b.height),d=Ed(this.a());this.ad.be=sd(this.a())=="fixed"?new zc(0,0,Math.max(0,b.width-d.width),Math.max(0,b.height-d.height)):new zc(0,0,c-d.width,a-d.height)}};p.gk=function(){if(this.kg){var a=this.ea,b=a&&a.Qf;b?(a=a.get(b),this.dispatchEvent(new Jh(b,a))&&this.h(!1)):this.h(!1)}};p.g=function(){this.T=this.Nb=l;Bh.b.g.call(this)}; function Z(a,b){a.ea=b;if(a.T){if(a.ea){var c=a.ea;c.e=a.T;c.L()}else a.T.innerHTML="";R(a.T,!!a.ea)}}p.ji=function(a){a:{for(a=a.target;a!=l&&a!=this.T;){if(a.tagName=="BUTTON")break a;a=a.parentNode}a=l}if(a&&!a.disabled){var a=a.name,b=this.ea.get(a);this.dispatchEvent(new Jh(a,b))&&this.h(!1)}}; p.jf=function(a){var b=!1,c=!1,d=this.ea,g=a.target;if(a.type==Hb)if(this.pj&&a.keyCode==27){var h=d&&d.Qf,g=g.tagName=="SELECT"&&!g.disabled;h&&!g?(c=!0,b=d.get(h),b=this.dispatchEvent(new Jh(h,b))):g||(b=!0)}else a.keyCode==9&&a.shiftKey&&g==this.a()&&(c=!0);else if(a.keyCode==13){if(g.tagName=="BUTTON")h=g.name;else if(d){var i=d.Ge,k;if(k=i)a:{k=d.e.getElementsByTagName("BUTTON");for(var m=0,q;q=k[m];m++)if(q.name==i||q.id==i){k=q;break a}k=l}g=(g.tagName=="TEXTAREA"||g.tagName=="SELECT")&&!g.disabled; k&&!k.disabled&&!g&&(h=i)}h&&d&&(c=!0,b=this.dispatchEvent(new Jh(h,String(d.get(h)))))}if(b||c)a.stopPropagation(),a.preventDefault();b&&this.h(!1)};function Jh(a,b){this.type=Kh;this.key=a;this.caption=b}w(Jh,E);var Kh="dialogselect",Ih="afterhide",Hh="aftershow";function Dh(a){this.p=a||J();tf.call(this)}var eh,Lh,Mh;w(Dh,tf);p=Dh.prototype;p.sa="goog-buttonset";p.Ge=l;p.e=l;p.Qf=l;p.set=function(a,b,c,d){tf.prototype.set.call(this,a,b);if(c)this.Ge=a;if(d)this.Qf=a;return this}; function Ch(a,b,c,d){return a.set(b.key,b.caption,c,d)}p.L=function(){if(this.e){this.e.innerHTML="";var a=J(this.e);nf(this,function(b,c){var d=a.d("button",{name:c},b);if(c==this.Ge)d.className=this.sa+"-default";this.e.appendChild(d)},this)}};p.n=function(a){if(a&&a.nodeType==1){this.e=a;for(var a=this.e.getElementsByTagName("button"),b=0,c,d,g;c=a[b];b++)if(d=c.name||c.id,g=cd(c)||c.value,d){var h=b==0;this.set(d,g,h,c.name==Nh);h&&I(c,this.sa+"-default")}}};p.a=n("e");p.k=n("p"); var Nh="cancel",Oh=ua("OK"),Ph=ua("Cancel"),Qh=ua("Yes"),Rh=ua("No"),Sh=ua("Save"),Th=ua("Continue"),Eh={key:"ok",caption:Oh},Fh={key:Nh,caption:Ph},Uh={key:"yes",caption:Qh},Vh={key:"no",caption:Rh},Wh={key:"save",caption:Sh},Xh={key:"continue",caption:Th};typeof document!="undefined"&&(eh=Ch(new Dh,Eh,!0,!0),Lh=Ch(Ch(new Dh,Eh,!0),Fh,!1,!0),Mh=Ch(Ch(new Dh,Uh,!0),Vh,!1,!0),Ch(Ch(Ch(new Dh,Uh),Vh,!0),Fh,!1,!0),Ch(Ch(Ch(new Dh,Xh),Wh),Fh,!0,!0));function Y(){Bh.call(this,l,!0)}w(Y,Bh);u(Y);Y.prototype.Lb=function(){this.M("Waiting for server response....");Z(this,l);this.t('
')};function Yh(){}w(Yh,Me);u(Yh);Yh.prototype.d=function(a){return a.k().d("div",this.i()+" goog-inline-block","\u00a0")};Yh.prototype.n=function(a,b){b=Yh.b.n.call(this,a,b);I(b,"goog-inline-block");return b};Yh.prototype.i=o("goog-toolbar-separator");function Zh(a,b){Ne.call(this,a||Yh.c(),b)}w(Zh,Ne);se("goog-toolbar-separator",function(){return new Zh});function $h(a){this.element=N(a);this.oh=!1;this.J=j}$h.prototype.jb=ba("J");$h.prototype.lc=function(a){Nd(this.element,new G(a.width-7,a.height-34))};$h.prototype.setActive=ba("oh");$h.prototype.ha=n("oh");function ai(){}w(ai,oe);u(ai);p=ai.prototype;p.Ka=o("button");p.Ga=function(a,b,c){b==16?U(a,"pressed",c):ai.b.Ga.call(this,a,b,c)};p.d=function(a){var b=ai.b.d.call(this,a),c=a.Xd();c&&this.za(b,c);(c=a.s())&&this.ia(b,c);a.Q&16&&this.Ga(b,16,a.sb());return b};p.n=function(a,b){var b=ai.b.n.call(this,a,b),c=this.s(b);a.Ha=c;a.eh=this.Xd(b);a.Q&16&&this.Ga(b,16,a.sb());return b};p.s=s;p.ia=s;p.Xd=function(a){return a.title};p.za=function(a,b){if(a)a.title=b||""};p.i=o("goog-button");function bi(){}w(bi,ai);u(bi);p=bi.prototype;p.Ka=aa();p.d=function(a){Ge(a,!1);a.Lf&=-256;Je(a,32,!1);return a.k().d("button",{"class":this.uc(a).join(" "),disabled:!a.isEnabled(),title:a.Xd()||"",value:a.s()||""},a.Eb()||"")};p.R=function(a){return a.tagName=="BUTTON"||a.tagName=="INPUT"&&(a.type=="button"||a.type=="submit"||a.type=="reset")};p.n=function(a,b){Ge(a,!1);a.Lf&=-256;Je(a,32,!1);b.disabled&&I(b,this.Td(1));return bi.b.n.call(this,a,b)};p.kd=function(a){a.G().f(a.a(),D,a.Ec)};p.pe=s; p.wd=s;p.$b=function(a){return a.isEnabled()};p.ic=s;p.ya=function(a,b,c){bi.b.ya.call(this,a,b,c);if((a=a.a())&&b==1)a.disabled=c};p.s=function(a){return a.value};p.ia=function(a,b){if(a)a.value=b};p.Ga=s;function ci(a,b,c){V.call(this,a,b||bi.c(),c)}w(ci,V);p=ci.prototype;p.s=n("Ha");p.ia=function(a){this.Ha=a;this.m.ia(this.a(),a)};p.Xd=n("eh");p.za=function(a){this.eh=a;this.m.za(this.a(),a)};p.g=function(){ci.b.g.call(this);delete this.Ha;delete this.eh};p.o=function(){ci.b.o.call(this);if(this.Q&32){var a=this.V();a&&this.G().f(a,"keyup",this.wc)}};p.wc=function(a){return a.keyCode==13&&a.type=="key"||a.keyCode==32&&a.type=="keyup"?this.Ec(a):a.keyCode==32};se("goog-button",function(){return new ci(l)});function di(){}w(di,ai);u(di);p=di.prototype;p.d=function(a){var b={"class":"goog-inline-block "+this.uc(a).join(" "),title:a.Xd()||""},b=a.k().d("div",b,this.Ee(a.ka,a.k()));this.sf(a,b);return b};p.Ka=o("button");p.sf=function(a,b){a.isEnabled()||this.Ga(b,1,!0);a.yc()&&this.Ga(b,8,!0);a.Q&16&&this.Ga(b,16,!0);a.q&64&&this.Ga(b,64,!0)};p.B=function(a){return a&&a.firstChild.firstChild}; p.Ee=function(a,b){return b.d("div","goog-inline-block "+(this.i()+"-outer-box"),b.d("div","goog-inline-block "+(this.i()+"-inner-box"),a))};p.R=function(a){return a.tagName=="DIV"};p.n=function(a,b){ei(b,!0);ei(b,!1);var c;a:{if((c=a.k().Kh(b))&&c.className.indexOf(this.i()+"-outer-box")!=-1)if((c=a.k().Kh(c))&&c.className.indexOf(this.i()+"-inner-box")!=-1){c=!0;break a}c=!1}c||b.appendChild(this.Ee(b.childNodes,a.k()));I(b,"goog-inline-block",this.i());return di.b.n.call(this,a,b)};p.i=o("goog-custom-button"); function ei(a,b){if(a)for(var c=b?a.firstChild:a.lastChild,d;c&&c.parentNode==a;){d=b?c.nextSibling:c.previousSibling;if(c.nodeType==3){var g=c.nodeValue;if(xa(g)=="")a.removeChild(c);else{c.nodeValue=b?g.replace(/^[\s\xa0]+/,""):g.replace(/[\s\xa0]+$/,"");break}}else break;c=d}};function fi(){}w(fi,di);u(fi);fi.prototype.i=o("goog-toolbar-button");function gi(a,b,c){ci.call(this,a,b||fi.c(),c)}w(gi,ci);se("goog-toolbar-button",function(){return new gi(l)});function hi(){}w(hi,Oe);u(hi);hi.prototype.Ka=o("toolbar");hi.prototype.Ud=function(a){return a.tagName=="HR"?new Ne(Yh.c()):hi.b.Ud.call(this,a)};hi.prototype.i=o("goog-toolbar");hi.prototype.Ih=function(){return Qe};function ii(a,b,c){Te.call(this,b,a||hi.c(),c)}w(ii,Te);function ji(a){this.Ff=a.device_id;this.Kd=a.manufacturer_id;this.Sc=a.device;this.Jd=a.manufacturer}w(ji,bf);ji.prototype.id=function(){return ki(this)};function li(a,b){a<0&&(a=4294967295+a+1);for(var c=a.toString(16);c.lengtha.Kd)return 1;else if(this.Kd=b&&c.top<=a&&c.top+c.height>=a);b?this.ne.stop():this.ne.enabled||this.ne.start()};function yi(a,b,c){var d=0;ab+c&&(d=8);return d}vi.prototype.g=function(){vi.b.g.call(this);this.ma.j();this.ne.j()};function Ai(a,b){vi.call(this,a,b,!0)}w(Ai,vi);Ai.prototype.u=function(a){a?this.ma.f(K(this.Wc),"mousemove",this.Eg):this.ma.X(K(this.Wc),"mousemove",this.Eg)};function Bi(a,b,c,d){rh.call(this,a,b,c||d);this.vk=d}w(Bi,rh);Bi.prototype.Lh=function(){return 65|(this.vk?32:132)};var Ci,Di;Di=Ci=!1;var Ei=Pa();Ei&&(Ei.indexOf("Firefox")!=-1||Ei.indexOf("Camino")!=-1||(Ei.indexOf("iPhone")!=-1||Ei.indexOf("iPod")!=-1?Ci=!0:Ei.indexOf("iPad")!=-1&&(Di=!0)));var Fi=Ci,Gi=Di;function Hi(){}w(Hi,Oe);u(Hi);p=Hi.prototype;p.Ka=o("menu");p.R=function(a){return a.tagName=="UL"||Hi.b.R.call(this,a)};p.Ud=function(a){return a.tagName=="HR"?new Ne:Hi.b.Ud.call(this,a)};p.pc=function(a,b){return Xc(a.a(),b)};p.i=o("goog-menu");p.kd=function(a){Hi.b.kd.call(this,a);U(a.a(),"haspopup","true")};se("goog-menuseparator",function(){return new Ne});function Ii(){}w(Ii,oe);u(Ii);Ii.prototype.i=o("goog-menuheader");function Ji(a,b,c){V.call(this,a,c||Ii.c(),b);Je(this,1,!1);Je(this,2,!1);Je(this,4,!1);Je(this,32,!1);this.q=1}w(Ji,V);se("goog-menuheader",function(){return new Ji(l)});function Ki(a,b){Te.call(this,Re,b||Hi.c(),a);this.ic(!1)}w(Ki,Te);p=Ki.prototype;p.Kf=!0;p.$i=!1;p.i=function(){return this.m.i()};p.pc=function(a){if(this.m.pc(this,a))return!0;for(var b=0,c=ce(this);bc.end){d=!0;break}}d||a.push(Fb());for(h=c.start;h<=c.end;++h)a[g][h]=c;g=c;for(h=0;hc&&(c=h)); m&&!i&&k>d&&(d=k,k=0);i=m}k>d&&(d=k);b==512?g="No slots free":(b++,c++,g="Free slots: first: "+b+", last: "+c+", max contiguous: "+d);this.Ek.innerHTML=g;g=(1+Math.max(1,a.length))*14;for(h=0;h512?(k.className="patcher_overflow_device",k.title="Device overflows the 512 slot limit"):k.className="patcher_device";i.Id.push(k);d.appendChild(k);F(k,D,function(a){return function(b){mj(this,a,b)}}(i),!1,a);var m=new ui(k);m.me=a.element; m.lg=Math.pow(8,2);F(m,"start",function(a,b){return function(c){for(var d=b.Id,g=0;g=0;--c)a.rd.td(c);a.Jg=[];personalities=b.personalities;for(c=0;c0){var h=new ti(personalities[c].name+" ("+personalities[c].footprint+")");a.rd.bb(h);b.selected==c+1&&a.rd.jc(h);a.Jg.push(personalities[c])}a.ri.style.display="table-row"}pj(a)})} function pj(a){Y.c().h(!1);a.Ad.value=a.ab.start+1;a.Bb.M(a.ab.label);a.Bb.h(!0);a.Ad.focus()}p.wk=function(a){a.key==Nh||this.Ad==j||this.ab==j||(a=parseInt(this.Ad.value),isNaN(a)||a<1||a>512?alert("Must be between 1 and 512"):nj(this,this.ab,a))};function nj(a,b,c){Vg(W.c(),a.J,b.Dd,"dmx_address","","address="+c,function(d){ch(W.c(),d)!=j&&(Y.c().h(!1),b.setStart(c));a.Jc()});var d=Y.c();d.Lb();d.h(!0)} p.yk=function(a){var b=W.c();this.sd.style.display="inline";var a=this.Jg[a.target.Ub()],c=this,d=a.footprint;Vg(b,this.J,this.ab.Dd,"personality","","int="+a.index,function(a){c.sd.style.display="none";ch(W.c(),a)==j?c.Bb.h(!1):(a=c.ab,a.pb=d,gj(a),c.Jc())})};p.Jk=function(a){var b=W.c();this.hd.style.display="inline";var c=this;Vg(b,this.J,this.ab.Dd,"identify_device","","bool="+(a.target.sb()?"1":"0"),function(a){c.hd.style.display="none";ch(W.c(),a)==j&&c.Bb.h(!1)})}; function qj(a){var b=a.mc[0];Vg(W.c(),a.J,b.Bh.Dd,"dmx_address","","address="+b.hi,function(b){var b=dh(W.c(),b),d=a.mc.shift();b==j?a.Ig=!0:d.Bh.setStart(d.hi);a.mc.length?qj(a):(b=Y.c(),a.Ig?(b.M("Failed to Set Start Address"),Z(b,eh),b.t("Some devices failed to change their DMX start address, click refresh to fetch the current state."),b.h(!0)):b.h(!1),a.Jc())})};function rj(){}w(rj,Li);u(rj);rj.prototype.i=o("goog-toolbar-menu-button");function sj(a,b,c,d){Mi.call(this,a,b,c||rj.c(),d)}w(sj,Mi);se("goog-toolbar-menu-button",function(){return new sj(l)});function tj(a){$h.call(this,a);a=new ii;a.n(N("patcher_toolbar"));var b=ae(a,"autoPatchButton");b.za("Automatically Patch Devices");F(b,"action",function(){this.sh()},!1,this);a=ae(a,"patcherRefreshButton");a.za("Refresh Devices");F(a,"action",function(){uj(this)},!1,this);this.Dc=new jj("patcher_div","patcher_status");this.ge=[];this.la=[];this.zc=P("div");this.zc.style.width="100%";this.zc.style.textAlign="center";this.zc.innerHTML='
Loading...';this.zc.style.marginTop= "10px";Qc(N("patcher_div"),this.zc)}w(tj,$h);p=tj.prototype;p.jb=function(a){tj.b.jb.call(this,a);this.Dc.jb(a);this.ge=[];this.Dc.la=[]};p.lc=function(a){tj.b.lc.call(this,a);this.Dc.lc(a.height-34-27-16-5)};p.setActive=function(a){tj.b.setActive.call(this,a);this.ha()&&uj(this)};p.xe=function(a){if(dh(W.c(),a)!=j){this.ge=[];this.la=[];for(var a=sg(a.target).uids,b=0;b0&&a.la.push(new fj(ki(c),g,b.address,b.footprint,b.personality,b.personality_count))}vj(a)}})}else a.Dc.la=a.la,a.zc.style.display="none",a.Dc.update()}function uj(a){kj(a.Dc);a.zc.style.display="block";Wg(W.c(),a.J,function(b){a.xe(b)})} p.sh=function(){var a=Y.c();a.M("Confirm Auto Patch");Z(a,Mh);a.t("This will change the start addresses of all devices. Are you sure you want to continue?");F(a,Kh,this.cj,!1,this);a.h(!0)}; p.cj=function(a){var b=Y.c();mc(b,Kh,this.sh,!1,this);if(a.key=="yes"){a=this.Dc;a.mc=[];for(var c=b=0;c512)for(c=a.la.slice(0);c.length;){var d=[],b=0,g;for(Ng.info("new round");c.length&&b<512;){g=c.pop();var h=512-b;Ng.info(g.label+" : "+g.pb);g.pb>h?(d.unshift(g),Ng.info("deferring "+g.label)):(a.mc.push(new ej(g,b+1)),Ng.info("set "+g.label+" to "+b),b+=g.pb)}c=c.concat(d)}else for(c=b=0;c90?"#ffffff":"#000000"}};function zj(a,b){var c=a.Fd[b];if(c!=j)c.innerHTML=" ",c.style.background="#ffffff"};function Aj(a){$h.call(this,a);this.kj=new wj(N("monitor_values"));this.kc=!1}w(Aj,$h);Aj.prototype.setActive=function(a){Aj.b.setActive.call(this,a);if(this.ha()&&!this.kc){var b=new ii;b.n(N("monitor_toolbar"));b=ae(b,"monitor_view_button");b.za("Change the DMX Monitor layout");F(b,"action",this.Rk,!1,this);this.kc=!0}this.kj.ya(a,this.J)};Aj.prototype.Rk=function(a){a.target.Eb()=="Full"?N("monitor_values").className="monitor_full":N("monitor_values").className="monitor_compact"};function Bj(a,b,c,d,g){function h(a){if(a)a.tabIndex=0,F(a,D,i.gf,!1,i),F(a,Hb,i.hf,!1,i)}this.p=g||J();this.Db=this.p.a(a)||l;this.Od=this.p.a(d||l);this.$=(this.wg=ka(b)?b:l)||!b?l:this.p.a(b);this.Sa=c==!0;var i=this;h(this.Db);h(this.Od);this.vd(this.Sa)}w(Bj,Q);p=Bj.prototype;p.g=function(){this.Db&&qc(this.Db);this.Od&&qc(this.Od);Bj.b.g.call(this)};p.B=n("$");p.toggle=function(){this.vd(!this.Sa)}; p.vd=function(a){if(this.$)R(this.$,a);else if(a&&this.wg)this.$=this.wg();this.Od?(R(this.Db,!a),R(this.Od,a)):(Cj(this,a),this.Db&&U(this.Db,"expanded",a));this.Sa=a;this.dispatchEvent(new Dj("toggle",this,this.Sa))};function Cj(a,b){a.Db&&(Ec(a.Db,"goog-zippy-expanded",b),Ec(a.Db,"goog-zippy-collapsed",!b))}p.hf=function(a){if(a.keyCode==13||a.keyCode==32)this.toggle(),a.preventDefault(),a.stopPropagation()};p.gf=function(){this.toggle()};function Dj(a,b,c){E.call(this,a,b);this.qj=c}w(Dj,E);function Ej(a,b,c,d){(!ha(a)||!ha(b))&&e(Error("Start and end parameters must be arrays"));a.length!=b.length&&e(Error("Start and end points must be the same length"));this.zd=a;this.oj=b;this.duration=c;this.nh=d;this.coords=[]}w(Ej,Q);var lb={},Fj=l;function Gj(){Hj();var a=ta(),b;for(b in lb)Ij(lb[b],a);Fj=kb()?l:qf.setTimeout(Gj,20)}function Hj(){Fj&&(qf.clearTimeout(Fj),Fj=l)}function Jj(a){a=ma(a);delete lb[a];kb()&&Hj()}p=Ej.prototype;p.q=0;p.Hh=0;p.La=0;p.startTime=l;p.Eh=l;p.tg=l; p.play=function(a){if(a||this.q==0)this.La=0,this.coords=this.zd;else if(this.q==1)return!1;Jj(this);this.startTime=a=ta();this.q==-1&&(this.startTime-=this.duration*this.La);this.Eh=this.startTime+this.duration;this.tg=this.startTime;this.La||this.Cc();Kj(this,"play");this.q==-1&&this.Fg();this.q=1;var b=ma(this);b in lb||(lb[b]=this);Fj||(Fj=qf.setTimeout(Gj,20));Ij(this,a);return!0};p.stop=function(a){Jj(this);this.q=0;if(a)this.La=1;Lj(this,this.La);this.Gg();this.ff()}; p.g=function(){this.q!=0&&this.stop(!1);this.Dg();Ej.b.g.call(this)};function Ij(a,b){a.La=(b-a.startTime)/(a.Eh-a.startTime);if(a.La>=1)a.La=1;a.Hh=1E3/(b-a.tg);a.tg=b;Lj(a,a.La);a.La==1?(a.q=0,Jj(a),Kj(a,"finish"),a.ff()):a.q==1&&a.Cg()}function Lj(a,b){ka(a.nh)&&(b=a.nh(b));a.coords=Array(a.zd.length);for(var c=0;c'};function Yj(a,b,c,d){this.p=c||J();this.ta=a;this.Va=[];this.Gk=b?b:Zj;this.Ni=!!d;this.ta.className="goog-tabpane";a=[];for(b=Uc(this.ta);b;)a.push(b),b=Wc(b);this.Ca=this.p.d("ul",{className:"goog-tabpane-tabs",tabIndex:"0"});this.$=this.p.d("div","goog-tabpane-cont");this.ta.appendChild(this.$);switch(this.Gk){case Zj:this.ta.insertBefore(this.Ca,this.$);this.ta.insertBefore($j(this),this.$);I(this.ta,"goog-tabpane-top");break;case 1:this.ta.appendChild(this.Ca);this.ta.appendChild($j(this));I(this.ta, "goog-tabpane-bottom");break;case 2:this.ta.insertBefore(this.Ca,this.$);I(this.ta,"goog-tabpane-left");break;case 3:this.ta.insertBefore(this.Ca,this.$);I(this.ta,"goog-tabpane-right");break;default:e(Error("Invalid tab location"))}this.Ca.tabIndex=0;F(this.Ca,this.Ni?"mousedown":D,this.gf,!1,this);F(this.Ca,Hb,this.hf,!1,this);for(c=0;b=a[c];c++)ak(this,new bk(b))}w(Yj,Q);var Zj=0; function $j(a){Id(".goog-tabpane-clear { clear: both; height: 0px; overflow: hidden }");return a.p.d("div","goog-tabpane-clear")}p=Yj.prototype;p.g=function(){Yj.b.g.call(this);mc(this.Ca,this.Ni?"mousedown":D,this.gf,!1,this);mc(this.Ca,Hb,this.hf,!1,this);delete this.ta;this.$=this.Ca=l}; function ak(a,b){if(b.D&&b.D!=a&&b.D instanceof Yj){var c=b.D,d=b;ja(d)&&(d=c.Va[d]);c.Va.splice(d.jd,1);d.ue(l);Tc(d.bd);Tc(d.$);for(var g=0;d=c.Va[g];g++)d.ue(c,g)}c=a.Va.length;ga(j)&&j!=c?(c=j,a.Va.splice(c,0,b),a.Ca.insertBefore(b.bd,a.Ca.childNodes[c])):(a.Va.push(b),a.Ca.appendChild(b.bd));b.ue(a,c);if(!a.Xa)a.Xa=b,a.dispatchEvent(new ck("change",a,a.Xa));a.$.appendChild(b.$);dk(b,b==a.Xa);for(d=c+1;c=a.Va[d];d++)c.jd=d} p.xa=function(a){if(a>=0&&a=this.Va.length?0:a);break;case 36:this.xa(0);break;case 35:this.xa(this.Va.length-1)}};function bk(a,b,c){var d,g;if(v(a)&&!ga(b))d=a;else if(b)d=b,g=a;else if(a){if(b=Uc(a))d=cd(b),b.parentNode.removeChild(b);g=a}this.p=c||J();this.$=g||this.p.d("div");this.bd=this.p.d("li",l,d);this.jd=this.D=l;this.S=!0}p=bk.prototype; p.M=function(a){Yc(this.bd,a)};p.B=n("$");p.getParent=n("D");p.u=function(a){this.S=a;this.bd.className=a?"goog-tabpane-tab":"goog-tabpane-tab-disabled"};p.isEnabled=n("S");function dk(a,b){if(a.isEnabled())a.$.style.display=b?"":"none",a.bd.className=b?"goog-tabpane-tab-selected":"goog-tabpane-tab"}p.ue=function(a,b){this.D=a;this.jd=ga(b)?b:l};function ck(a,b,c){E.call(this,a,b);this.page=c}w(ck,E);function ek(a,b,c){ti.call(this,a,b,c);this.Xg(!0)}w(ek,ti);ek.prototype.Ec=function(){return this.dispatchEvent("action")};se("goog-option",function(){return new ek(l)});function fk(a,b){var c=b.type,d=b.value,g=b.id;if(c=="hidden"){var h=P("input");h.id=g;h.type="hidden";h.value=d;a.appendChild(h)}else{h=P("tr");a.appendChild(h);var i=P("td");i.innerHTML=b.description;h.appendChild(i);i=P("td");h.appendChild(i);if(g)if(c=="string"||c=="uint"||c=="hidden"){h=P("input");h.value=d;h.name=g;if(c=="hidden")h.type="hidden";i.appendChild(h);b.button&&(new gk(b.button)).L(i)}else{if(c=="bool")c=new dj,c.Kc(d==1);else{c=new $;g=d.length;for(h=0;h "+(t-1));return}t=c[i].max;if(t!=j&&q>t){a.Mb("Invalid Value",c[i].description+" must be < "+(t+1));return}h+=k+"="+m+"&"}else if(c[i].type=="string")m=g.elements[k].value, h+=k+"="+m+"&";else if(c[i].type=="bool")h+=k+"="+(c[i].object.sb()?"1":"0")+"&";else if(c[i].type=="select")m=c[i].object.Ub(),m=c[i].value[m].value,h+=k+"="+m+"&"}Vg(W.c(),a.Ab,a.Md,a.wa[b].id,a.wa[b].hint,h,function(c){c=sg(c.target);c.error?a.Mb("Set "+a.wa[b].name+" Failed",c.error):ik(a,b)})}hk.prototype.Mb=function(a,b){var c=Y.c();c.M(a);c.t(b);Z(c,eh);c.h(!0)};function pk(a){$h.call(this,a);a=new ii;a.n(N("rdm_toolbar"));var b=ae(a,"discoveryButton");b.za("Run full RDM discovery for this universe");F(b,"action",function(){qk(this,!0)},!1,this);b=ae(a,"incrementalDiscoveryButton");b.za("Run incremental RDM discovery for this universe");F(b,"action",function(){qk(this,!1)},!1,this);this.wf=new ge(new S,new S,"horizontal");this.wf.og=250;this.wf.ed=2;this.wf.n(N("rdm_split_pane"));var c=new hk("rdm_attributes",a);this.wi=c;a=new Te;a.n(N("uid_container")); this.Kk=new df(a,new ni(function(a){kk(c,a)}));this.fh=new pf(rk);F(this.fh,rf,this.xe,!1,this)}w(pk,$h);var rk=5E3;pk.prototype.jb=function(a){pk.b.jb.call(this,a);var b=this.wi;b.Ab=a;b.Md=j;this.wi.clear()};pk.prototype.lc=function(a){je(this.wf,new G(a.width-7,a.height-67))};pk.prototype.setActive=function(a){pk.b.setActive.call(this,a);this.xe();this.ha()?this.xe():this.fh.stop()}; pk.prototype.xe=function(){var a=this;Wg(W.c(),this.J,function(b){rg(b.target)!=200?Ng.info("Request failed: "+String(b.target.va)+" : "+tg(b.target)):sk(a,b)});this.fh.start()};function qk(a,b){Sg(W.c(),a.J,b,function(b){var c=Y.c();Z(c,eh);rg(b.target)==200?(c.h(!1),sk(a,b)):(c.M("Failed to Start Discovery Process"),c.t(String(b.target.va)+" : "+tg(b.target)),c.h(!0))});var c=Y.c();c.Lb();c.M("RDM Discovery Running...");c.h(!0)} function sk(a,b){for(var c=sg(b.target).uids,d=[],g=0;g100?d=3:d<-100&&(d=-3),ga(a.axis)&&a.axis===a.HORIZONTAL_AXIS?b=d:c=d;ja(this.bi)&&(b=uh(b,-this.bi,this.bi));ja(this.ci)&&(c=uh(c,-this.ci,this.ci));b=new uk(d, a,b,c);try{this.dispatchEvent(b)}finally{b.j()}};tk.prototype.g=function(){tk.b.g.call(this);oc(this.ai);delete this.ai};function uk(a,b,c,d){b&&this.Zb(b,j);this.type="mousewheel";this.detail=a;this.cb=c;this.eb=d}w(uk,Pb);function vk(){Ej.call(this,[0],[0],0);this.Gc=[]}w(vk,Ej);vk.prototype.Fg=function(){wk(this,function(a){a.play(a.La==0)});vk.b.Fg.call(this)};vk.prototype.Gg=function(){wk(this,function(a){a.stop()});vk.b.Gg.call(this)};vk.prototype.Dg=function(){xk(this);vk.b.Dg.call(this)};function xk(a){tb(a.Gc,function(a){a.j()})}function yk(){vk.call(this)}w(yk,vk);yk.prototype.Cc=function(){for(var a=0;athis.Ua?this.Ua-this.Ea:athis.Ua?this.Ua-this.Ha:a,!this.rb&&!this.od&&this.dispatchEvent("change")}; p.Tb=function(){return this.Bd==l?this.Ea:Math.round(this.Ea/this.Bd)*this.Bd};p.vf=function(a){if(this.gb!=a){var b=this.rb;this.rb=!0;this.gb=a;if(a+this.Ea>this.Ua)this.Ea=this.Ua-this.gb;a>this.Ha&&this.ia(a);if(a>this.Ua)this.Ea=0,this.uf(a),this.ia(a);this.rb=b;!this.rb&&!this.od&&this.dispatchEvent("change")}};p.pa=function(){return Fk(this,this.gb)}; p.uf=function(a){a=Fk(this,a);if(this.Ua!=a){var b=this.rb;this.rb=!0;this.Ua=a;athis.Za.offsetLeft+this.Za.offsetWidth;a=K(this.a());this.G().f(a,"mouseup",this.Ph,!0).f(this.a(),"mousemove",this.ah);if(!this.Yb)this.Yb=new pf(200),this.G().f(this.Yb,rf,this.Rh);this.Rh();this.Yb.start()}};p.Fj=function(a){Mk(this,(a.detail>0?-1:1)*this.gh);a.preventDefault()}; p.Rh=function(){var a;if(this.C=="vertical"){var b=this.af,c=this.Za.offsetTop;this.Vh?bc+this.Za.offsetHeight&&(a=Pk(this,this.Za)-this.Qb)}else b=this.af,c=this.Za.offsetLeft,this.Vh?b>c+this.Za.offsetWidth&&(a=Pk(this,this.Za)+this.Qb):b=a.r.s()+a.ce&&(d=c-a.r.s());var g=d||a.r.Tb();b==a.I&&c>=a.pa()&&c<=a.r.s()+g-a.ce&&(b=g-(c-a.r.s()),Fk(a.r,c)+Fk(a.r,b)==Fk(a.r,c+b)&&(Rk(a,c,b),d=l));d!=l&&a.r.re(d)} function Rk(a,b,c){if(a.pa()<=b&&b<=a.ua()-c&&a.ce<=c&&c<=a.ua()-b&&!(b==a.s()&&c==a.Tb()))a.r.od=!0,a.r.re(0),a.r.ia(b),a.r.re(c),a.r.od=!1,Jk(a),a.dispatchEvent("change")}p.pa=function(){return this.r.pa()};p.vf=function(a){this.r.vf(a)};p.ua=function(){return this.r.ua()};p.uf=function(a){this.r.uf(a)};function Ok(a,b){return b<=a.r.s()+a.r.Tb()/2?a.I:a.Da}p.Ij=function(){Jk(this);Ik(this);this.dispatchEvent("change")}; function Jk(a){if(a.I&&!a.Xe){var b=Sk(a,Pk(a,a.I)),c=Sk(a,Pk(a,a.Da));if(a.C=="vertical"){if(a.I.style.top=b.y+"px",a.Da.style.top=c.y+"px",a.O)b=Tk(c.y,b.y,a.I.offsetHeight),a.O.style.top=b.ef+"px",a.O.style.height=b.size+"px"}else if(a.I.style.left=b.x+"px",a.Da.style.left=c.x+"px",a.O)b=Tk(b.x,c.x,a.I.offsetWidth),a.O.style.left=b.ef+"px",a.O.style.width=b.size+"px"}}function Tk(a,b,c){var d=Math.ceil(c/2);return{ef:a+d,size:Math.max(b-a+c-2*d,0)}} function Sk(a,b){var c=new H;if(a.I){var d=a.pa(),g=a.ua(),g=b==d&&d==g?0:(b-d)/(g-d);a.C=="vertical"?(d=a.a().clientHeight-a.I.offsetHeight,g=Math.round(g*d),c.y=d-g):(d=Math.round(g*(a.a().clientWidth-a.I.offsetWidth)),c.x=d)}return c} function Lk(a,b){b=Math.min(a.ua(),Math.max(b,a.pa()));a.Xe&&a.Fe.stop(!0);var c=new yk,d=Ok(a,b),g=Sk(a,b);c.add(new Bk(d,a.C=="vertical"?[d.offsetLeft,g.y]:[g.x,d.offsetTop],100));if(a.O){var h=Sk(a,a.r.s()),i=Sk(a,a.r.s()+a.r.Tb());d==a.I?h=g:i=g;a.C=="vertical"?(g=Tk(i.y,h.y,a.I.offsetHeight),c.add(new Bk(a.O,[a.O.offsetLeft,g.ef],100)),c.add(new Dk(a.O,a.O.offsetHeight,g.size,100))):(g=Tk(h.x,i.x,a.I.offsetWidth),c.add(new Bk(a.O,[g.ef,a.O.offsetTop],100)),c.add(new Ck(a.O,a.O.offsetWidth,g.size, 100)))}a.Fe=c;a.G().f(c,"end",a.nj);a.Xe=!0;Kk(a,d,b);c.play(!1)}p.nj=function(){this.Xe=!1};p.te=function(a){if(this.C!=a){var b=this.i(this.C),c=this.i(a);this.C=a;if(this.a()){Dc(this.a(),b,c);this.I.style.left=this.I.style.top="";this.Da.style.left=this.Da.style.top="";if(this.O)this.O.style.left=this.O.style.top="",this.O.style.width=this.O.style.height="";Jk(this)}}}; p.g=function(){Gk.b.g.call(this);this.Yb&&this.Yb.j();delete this.Yb;this.Fe&&this.Fe.j();delete this.Fe;delete this.I;delete this.Da;this.O&&delete this.O;this.r.j();delete this.r;this.ba&&(this.ba.j(),delete this.ba);this.de&&(this.de.j(),delete this.de);this.Ob&&(this.Ob.j(),delete this.Ob);this.tc&&(this.tc.j(),delete this.tc)};p.gh=1;p.s=function(){return this.r.s()};p.ia=function(a){Kk(this,this.I,a)};p.Tb=function(){return this.r.Tb()};p.re=function(a){Kk(this,this.Da,this.r.s()+a)}; p.h=function(a){R(this.a(),a);a&&Jk(this)};function Ik(a){var b=a.a();b&&(U(b,"valuemin",a.pa()),U(b,"valuemax",a.ua()),U(b,"valuenow",a.s()))};function Uk(a){Gk.call(this,a);this.r.re(0)}w(Uk,Gk);Uk.prototype.i=function(a){return a=="vertical"?"goog-slider-vertical":"goog-slider-horizontal"};function Vk(){this.kc=!1;this.yd=[];this.Ei=[];this.data=Array(512);this.Fd=[];this.Ya=0}w(Vk,Q);function Wk(){E.call(this,"console-change-event")}w(Wk,E);p=Vk.prototype;p.getData=n("data");p.setData=function(a){for(var b=Math.min(512,a.length),c=0;c=496)this.Ya=496,this.Bc.u(!1);Xk(this)};p.pk=function(){this.Ya-=16;this.Bc.u(!0);if(this.Ya<=0)this.Ya=0,this.gc.u(!1);Xk(this)}; function Xk(a){for(var b=N("console_channel_row"),b=Uc(b),c=a.Ya;c90?"#ffffff":"#000000"}};function $k(a){$h.call(this,a);this.$c=new Vk;this.bh=new pf(1E3);this.ee=!0;F(this.bh,rf,this.xh,!1,this);F(this.$c,"console-change-event",this.xh,!1,this)}w($k,$h);$k.prototype.jb=function(a){$k.b.jb.call(this,a);for(var a=this.$c,b=a.data.length,c=0;c4294967295)a.M("Invalid Universe Number"),Z(a,eh),a.t("The universe number must be between 0 and 4294967295");else{var c=W.c();if(c.lb[b]!=j)a.M("Universe already exists"),Z(a,eh),a.t("Universe "+b+" already exists");else{var d=N("new_universe_name").value,g=Qj(this.nc);if(g.length==0)a.M("No ports selected"),Z(a,eh),a.t("At least one port must be bound to the universe");else{var h=this;Rg(c,b,d, g,function(a){var b=Y.c();rg(a.target)!=200?(b.M("New Universe Failed"),b.t(String(a.target.va)+" : "+tg(a.target)),Z(b,eh),b.h(!0)):(a=sg(a.target),a.ok?(b.h(!1),b=h.Bg,a=a.universe,jl(b),b.Bf.Pa(a,!0),Mg(W.c())):(b.M("New Universe Failed"),Z(b,eh),b.t(a.message),b.h(!0)))});a.Lb()}}}a.h(!0)};function kl(a,b){this.element=N(a);this.Vi=b;F(W.c(),"plugin_change",this.Ti,!1,this);this.controls=[]}w(kl,Xj); kl.prototype.Ti=function(a){N("plugin_name").innerHTML=a.ec.name;N("plugin_preference_source").innerHTML=a.ec.preferences_source;var b=N("plugin_enabled");a.ec.enabled?(b.innerHTML="Yes",b.className="plugin_enabled"):(b.innerHTML="No",b.className="plugin_disabled");b=N("plugin_active");a.ec.active?(b.innerHTML="Yes",b.className="plugin_enabled"):(b.innerHTML="No",b.className="plugin_disabled");var b=a.ec.enabled&&!a.ec.active,c=N("plugin_conflict_row"),d=a.ec.conflicts_with;if(d.length){c.style.display= "table-row";for(c=0;c");N("plugin_description").innerHTML=a}; function ll(a,b,c){F(b,"action",function(){this.Vi(c)},!1,a)};function ml(a){this.Qc=a||window;this.bf=F(this.Qc,"resize",this.Jj,!1,this);this.xd=Mc(this.Qc);if(A&&Oa||Ta&&this.Qc.self!=this.Qc.top)this.Cf=window.setInterval(ra(this.uh,this),nl)}w(ml,Q);var nl=500;p=ml.prototype;p.bf=l;p.Qc=l;p.xd=l;p.Cf=l;p.Mh=function(){return this.xd?this.xd.Ba():l};p.g=function(){ml.b.g.call(this);if(this.bf)oc(this.bf),this.bf=l;if(this.Cf)window.clearInterval(this.Cf),this.Cf=l;this.xd=this.Qc=l};p.Jj=function(){this.uh()}; p.uh=function(){var a=Mc(this.Qc);if(!vc(a,this.xd))this.xd=a,this.dispatchEvent("resize")};function ol(){this.Uj=new vh;this.pd=W.c();this.Uh=new hl("home_frame");this.Bf=new bl("universe_frame",this);var a=this;this.Kg=new kl("plugin_frame",function(b){Og(a.pd,b);jl(a);a.Kg.Pa()});this.ii=new il("new_universe_frame",this);F(N("new_universe_button"),D,this.Si,!1,this);var b=new S,c=new S;this.xf=new ge(b,c,"horizontal");this.xf.og=130;this.xf.ed=2;this.xf.n(N("split_pane"));this.Oi=new ml;this.jh();F(this.Oi,"resize",this.jh,!1,this);pl(this);this.Hd();N("split_pane").style.visibility= "visible"} function pl(a){var b=N("home_control");we(b);F(b,D,a.Hd,!1,a);new Nj("plugin_list_control","plugin_container");new Nj("universe_list_control","universe_container");b=new Te;b.n(N("plugin_container"));a.lk=new df(b,new lf(function(b){b=b.id();Og(a.pd,b);jl(a);a.Kg.Pa()}));F(a.pd,"plugin_list_change",a.Nk,!1,a);b=new Te;b.n(N("universe_container"));a.hh=new df(b,new hf(function(b){b=b.id();jl(a);a.Bf.Pa(b,!0)}));F(a.pd,"universe_list_change",a.Pk,!1,a);a.Li=new pf(5E3);F(a.Li,rf,function(){Mg(this)},!1, a.pd);Mg(a.pd);a.Li.start()}p=ol.prototype;p.Pk=function(a){var b=[];Ng.info("Got "+a.lb.length+" universes");for(var c=0;c@¡ó@p>„@0>3„@P>ˆËâ„æ2ƒø„ÐÏ V@èúI?˜@HúÁ|€óaÆù„® €Ðõºû@è|€Bç: €Ðù„Î t>@ã˜Xˆ-~ ¸¥Ñó|5IEND®B`‚ ola-0.10.5.nojsmin/olad/www/toolbar_sprites.png0000644000175000017500000001060213023355232021141 0ustar wouterwouter‰PNG  IHDR ‘tXIIDAThµ: x”E–ï?ú¢Ó 9ÈÙ„®@HÂpAÃM„È1:*°FĆC×UˆºŽº~ÂŽ,"£qg‚ „S4$BBŽrt§»ÓÇí«¿ÓNÓ9pœúRý¿ªzïU½úßUõ‡‚aIHHPŽ3f±¿¿ºN§ á8®ëÎ 6äü §…œ?Á( Y% $ šA€¢¹[ ¨ÛyÝ!Á®…,âÝâõ~PùÔSO-H×jµ!<Ï×Ùíöüq·ò§¬ùß8`™8 %EJ©V‡(U”mX^Ùû©;0ƒÓÏÌÃÖÓM'Ìïèí=T÷½&("ðß´“J¶vGõÖ)éæ›©îp¼ÇºGNú¾/„? ?>ø‰7aOíôôt}PPÐþúúúD“¨°j´þ<Í™ÔýtÊðððœêêê'rrrÚºå3#ÿ¸Óô-Ï7t‹×1Hå,‡t~ØøøôçÆjÄ„9l·$cMucuîîB㪳} ûuÓGq* {OæL{Ö7žéþÜ¿¹ñ=ºÈŠ·ÿÎ;‰&å÷ÓñoQ‡¡üaaa9gΜy¢  À[~jô+ŸŽÚ?8yéÔßM‹ 7´9ì·îÔ}²ðtÅÆ¢’+Îá<=®‹¬%dÎÉ4( ž¦(*$jþœq{ÈXO¥ùTB´Tè&n²ä›-IÔ;~]J60QÓuSntRÆÄÏIÍ VÌïM–÷ä ×–úîæ"Öî»L9:Böƒ U#Âý* «V«÷^½Õ4ñ¹ÂÄÄdS|¤¿*¦ŸVS~>/àçÝÛÒ#""¶ ß§|OÞÞ˜ AA !èèb86õz·¸8øý ¢ë?üñ«>_(ˆf‰çÍWÏ9üëb“–­/Üú!ûí²«õOn…ŸzâåÏ9ÒiŸ]Ýî'EýÍ {¬B¡Ø[YoŒ š„ò'$›>{bpÚ·åÆâŠó'Pþìô”””-¨€äõÒ¦øÁú Ñ›ŸÍXeµKœ¬-f¾M4ï>‘žùú·XûŠ[®nzåŠÇ\ÀY'Ó$†]GST…aŸ@Ѩòµ­ï¼ãy†=“{4è ‰eµæS#—™ó‡Ï–N`†'™óZÿ, ¶×EAxÑsÒiŸJ¹/¤Pzô€²ò½”+ÁGÓpbоý/}/Ña1qÑg²I’€Ð(Úí IæœÉ t¤7ì©Ô•û»ç†½q{Óv8²ü’²'`6)àBKÄväÀ¡ÖÈc ~~~å—¨ÀøˆA¸Wèõ@²ñ‚£µ³ãöáê%G|D¿(‰‚|­x>š¥·Ñ UCQôF‘‚ùèþÖ0,UÌ á“Ê*P¨˜y1OÅøâAúÌÇÂÍ'†µäÅI´ÿ,J7 ~úå:\.­‚[Æþ€ ©QªM†¢¢(ósŠI¢*/·Ûçï¢vÁ™°оn„ܳ‹@”pP{$+ÂÂ6ÃIÈËhtã¶mmm!6Þ¨Fwc·óàÀjÃÚbæx´N%‡!!4v˜¹ò\^¤å„€ºï$äKc²‚UÄŠ00™ÛUTªþÐ/ô[È(X9£³]ÝžOôyŒÝÖ(˜Û*xÌydå³X®± £¤Y¶/…sð“"¯’™™)Aë.(‡é÷#¶—,Y™§³awŸ!Ö‹Cç¦Íf ±©"ŒÅYSÒ¢|~ EX€Úÿ\yUÄ‹MÏKkM¨éèqBŒ‚I¢()Ë! k²“{Ìý•é@x?ì©Oþ'ëÖ­C#AYYF ˜HˆÆÛ…D½NðqÏ´äõÖ3dÿd˜´cWè-ËŸ_.{?ô ÀÊ¢'T0,(0=`ñ‰ ¸ž†9sÿ ~ªç(¬„¶wEô'i4šRsõ‰ÉA“ æV+Gò¹ð¦¢04:˜²ƒkkkË!yؼƒÝN¯Âµ¾s "aÎJ\¿Óý#‰‡£¿ûfÈ´×þ;–ãšØ%±l ¥ÑDÐ*&Ú~zÇÕZâÝr÷D-€¹I®v‰§[ÝSw¢R©T¥¦êS“ƒcS f³ åwÚùíúV¾fG"Ê)ÿ`pMMM¹'!z·¢Í‡NE¾üñÁ&»B…á›×i¶¯V©Ô2ªvçXûÏž4.Øp(µÆ{>+¶%ôl÷7 Œ–€ûxñÆfEE…É' ªª ´Í[`úÔ±`¿ú€‡‹rV„™È‹œÈ;J{ ØÑ6ŠÁrCéû V(@­R@ô¤• ú¨”2LÓ£@äFg¥dE ÊÐÛÚ…FGGÌ%ß ôg$µÙ`…æ¦V¨¿c”ên6©¯7 ¸^q¹¥¡¡á®Ð©€½“à‘µŠühyíÒ>û5\6[óO±å§ÐÐ N7”Öjchn¸êàÇï^h¹Û|ìÏ»á¢IÏ Iâ¨pvT8R‰âqè»P>Â0&&åo 0_ün ŽµÙ$G(¸}Ç$ÝDùOƒòW^i¹{÷îÏ\Ûür]C³±øí¿:˜< °¿>D­íç¯Öèƒú„½òÙžÃu-õÙëkà¨û = ŽÛ`AÀ\Èòæá #{Iúkç8h³ÛÁbµI®VhmkƒV«=`þCu0úÈ, ?%†T_\:óìhñÜ=”—± ÎLMMЇ™ÏÝ  CG4ZÕþ6Ž3h.Ÿ© «­(Ñg"#ðV,øB{[ˆ•9Ø]`”–BÁt9ßð$½]'|o±&Õ–^‹Õ?†\™UüôKMõ…ÂZ¾UÜá‰ë‚1o‘m7Û,ç0vüwÌ®r¡õê¹fÍš— 0süøñ—_~Ù.ÿÈÆ–¼_Î|{Ù^VWyYljjÊD†&o¦U-gí¥üÀ3W*ËSÅè1Ô‰ÇKʯä—VT58®ä{ã{·Qéb”ŒbBIͳX÷x¿ ë«“ÐoέXãMKÚ^‘Aqq1`$ƒÒÒR¸úÅÝMüMx³Ix¸ÞŒúlDu_ÍáþÉv•Ç^ù˜nÙú è 4å‚1ì ‚ äŒ Îù˜šÿhÄÕ@ƒÒ‰Ž¿œx¿  ÛG]&êì.¸54}ÃÝDu/ ÃêÇŽ£’““߯¯ …%%%ëÍ U#ñ^ŒÆÓ!W 1$½~ëÖ­\™–ðàé¯FÕ÷ȯIÖÌÀPЃÝsˆà+½Ž=¸û<ãFYŸü»Š‡.<7`ôÊx‚V’¤Þ&Š{ßÁ17¢€†B ^™#ÙÙæ€_Cd3lÄ‹èžîÉ-¯«ù¯_¿þF^^5jÔ(Yþ‹/Êòc/ˇã 1§zó_§ü.b×sçNAX”P°ÿ|IÜø¡ƒ“]ßîâ/œs¡y?cžO¢ÊU˜keâu z*ºØ;ç›ôÎÕ¸«OŸx]ŸìMOÚ?þ¸4bÄÀ€÷¸rÞ‡y*%q0ãT\ð8[öÎÂOzWÞ§ÏêœþqÑZ Þz¢Þ;ÐÙ-ÁÑÿ¦œ­-žpX–»B)ü8qñ=”^hùòæWTT7bÀ«˜ý_}õÕy¼ë:ˆ7ÿÑx2ÅÓaõk×jQ)1¦µ—üÙĪI½·Ì:¹ENä¥&h£Ö±ÔÏîEìÜc4ÀÅkeÅjŠbq-T—^Ô˜ÍPÜ«£•¹éœ”½b<®+׳¥GˆÈ9Ý•••²ühlûwìØ!˲‡Z,–†Ã‡×"³ù}p®o½UsªŒrà-‰’tº´ÊÑÒâ¨öêî’(Åqš¦ûÒ˜äÓ(6ËR}Ç®½¶žU’»@&€Q°óðƒ)Ï|7‘0cÆ ?º•ïÒ¥Kxw×([WÐ8Õô|DÐþ ¯ý)i¬èXet¯¡î›ž èÄ$/8íd%hÙOÑ–¯Fºç«V­’=Ù|´ncbbâ|¢|„ìàÁƒÄ×V´WÒÕûB®cHq ¶ˆÏAÞ¤<¹ÝÃÏû¹`92î‡äSšGÐ àí½¶ëxiÔå PV>Ožíг«;˜ÈO<—[~Ì›~½ü9[ÛüG޼{ñÜèdý7¾yë ~v&’],õ.‹¦© xè¼sS01¨ŒëhrÒÄâ1b-9²&t7‹)S¦H&L€}ûöÉa×Sù\¸èýޏ`ïç´-…Bîó)²±Ëc®/!Þˆ>Ú÷* A"/zâÉtÐ1ÛÐ8•À1éÂ…/Ãïºoà  ðö¾5..î÷¸ùy] ß_7™Û&æƒI\§&UÝ1À°aCñü ¼_²NøÓ—uj{7Æ· O‰o`êA¡×oÿÍ俟õW}¼qÈÒ’¹¨„i${qzBç4zÆ=-ýOîšÐ<ïõ?ÿüóÒ«¯¾ ,€9÷sy>oÜ®ÚDùFá·à&üì÷ÚqÉü—ÉÄ*Pwn<³ø5}Wt¤ß·’òÂGç ¿Hš]•¢¢¢Rü§3þÇ èõúÇöìÙs´+Üûî·Q'ÁÔ´ 2îëžÆ5n$Þ]Ýu5ïûÙÕ?x2ÂD}†XYþÈÈÈßTþû]?ÅòK(JQ„Q+ïç÷b}†Zϵ»`<ÃÒ¥K!++Ëv]c½}^xe<¥ÏÂoÁNå#dÜ;ÞÒ[ú /**j<†Ý©ÿ“ߘxРA¡Èò0Ö¬ý{Åžä~¿¢`Žû›Ëÿ«ÖkOüÓ•ÕI/]YÝ[1¦OŸ¾jÒ¤IRhh诒½·ót…÷ÿ”¨Ò58 —rIEND®B`‚ola-0.10.5.nojsmin/olad/www/new/0000755000175000017500000000000013155164170016017 5ustar wouterwouterola-0.10.5.nojsmin/olad/www/new/libs/0000755000175000017500000000000013155164170016750 5ustar wouterwouterola-0.10.5.nojsmin/olad/www/new/libs/angular-route/0000755000175000017500000000000013155164170021535 5ustar wouterwouterola-0.10.5.nojsmin/olad/www/new/libs/angular-route/js/0000755000175000017500000000000013155164234022152 5ustar wouterwouterola-0.10.5.nojsmin/olad/www/new/libs/angular/0000755000175000017500000000000013155164170020401 5ustar wouterwouterola-0.10.5.nojsmin/olad/www/new/libs/angular/js/0000755000175000017500000000000013155164234021016 5ustar wouterwouterola-0.10.5.nojsmin/olad/www/new/libs/bootstrap/0000755000175000017500000000000013155164170020765 5ustar wouterwouterola-0.10.5.nojsmin/olad/www/new/libs/bootstrap/css/0000755000175000017500000000000013155164170021555 5ustar wouterwouterola-0.10.5.nojsmin/olad/www/new/libs/bootstrap/css/bootstrap.min.css0000644000175000017500000034463613023355232025101 0ustar wouterwouter/*! * Bootstrap v3.3.2 (http://getbootstrap.com) * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) *//*! normalize.css v3.0.2 | MIT License | git.io/normalize */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff!important}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee;opacity:1}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date],input[type=time],input[type=datetime-local],input[type=month]{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px \9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.form-group-sm .form-control{height:30px;line-height:30px}select[multiple].form-group-sm .form-control,textarea.form-group-sm .form-control{height:auto}.form-group-sm .form-control-static{height:30px;padding:5px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.form-group-lg .form-control{height:46px;line-height:46px}select[multiple].form-group-lg .form-control,textarea.form-group-lg .form-control{height:auto}.form-group-lg .form-control-static{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:14.33px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{pointer-events:none;cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.active,.btn-default.focus,.btn-default:active,.btn-default:focus,.btn-default:hover,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.active,.btn-primary.focus,.btn-primary:active,.btn-primary:focus,.btn-primary:hover,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.active,.btn-success.focus,.btn-success:active,.btn-success:focus,.btn-success:hover,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.active,.btn-info.focus,.btn-info:active,.btn-info:focus,.btn-info:hover,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.active,.btn-warning.focus,.btn-warning:active,.btn-warning:focus,.btn-warning:hover,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.active,.btn-danger.focus,.btn-danger:active,.btn-danger:focus,.btn-danger:hover,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none;visibility:hidden}.collapse.in{display:block;visibility:visible}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px solid}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none;visibility:hidden}.tab-content>.active{display:block;visibility:visible}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important;visibility:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:2;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px 15px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding:48px 0}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:absolute;top:0;right:0;left:0;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{min-height:16.43px;padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-weight:400;line-height:1.4;visibility:visible;filter:alpha(opacity=0);opacity:0}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-weight:400;line-height:1.42857143;text-align:left;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2)}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000;perspective:1000}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;margin-top:-10px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-15px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-15px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-15px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important;visibility:hidden!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}}ola-0.10.5.nojsmin/olad/www/new/libs/bootstrap/fonts/0000755000175000017500000000000013155164170022116 5ustar wouterwouterola-0.10.5.nojsmin/olad/www/new/libs/bootstrap/fonts/glyphicons-halflings-regular.svg0000644000175000017500000032430213023355232030421 0ustar wouterwouter ola-0.10.5.nojsmin/olad/www/new/libs/bootstrap/fonts/glyphicons-halflings-regular.eot0000644000175000017500000004723713023355232030422 0ustar wouterwouterŸNAMLP',(GLYPHICONS HalflingsRegularxVersion 1.009;PS 001.009;hotconv 1.0.70;makeotf.lib2.5.583298GLYPHICONS Halflings RegularBSGP©ÜMMFîÍéŒÏÒÙ£(uÊŒ<0DãB/X ïNï ˆCCê^Ç rmR2skÉËPJ"5+–gléW*iÕW–/EÓ4#¬Ô£U¦~²f‰‘UDÜĹ÷ˆ«±àJ·1á/!þþ/žºÊsª7’“kŠ•”(ºˆ¡hNøé8oíd$yq޹1³âÖ9ƒ@-‰‚HG’ôµS"øFjôØ 6C3”¤&ž‡ÁøªW51ÁÓÜ×BŸ¯aËêQaR†U/õ¶{*¿‚Ëï‚=–@dôøh$¡1ÉTÛ—nc+c’ÞA¡§¼ •ZÉ€¤@QÑc­a‡ÕÞl÷2>ÊK°Èmó' “ËC‡HMĬfB‰X,¾YòÂp¨e¢ î¸UøØ*Ò”zÿ m‚ËËiO1nEÆ.›„ä hx!aC XTÚV¢Å©Â‹– —éR¥š%¥|Iä HðÅÕPƒ5"Åb’N²µ=âøƒrÙ/_åRŒ›”™_ à%Ò„uzÉéÒ˜Ö5’2Ä¡ÒãPÚ)žÔþžÆÃFƒ7S‹q„FÀ{náia·¸@DÐsˆ;š}9⬥?ź‘§Â R{¦Tkí;޵ǜ×U\NžZø›Q-»^Ôs7òf 0˜ÊÆS3A Ü _n`W7Pp˜»ôài«í³!ðgØ/à_p»ÁÒZ€-=Ã×¥~WZ#/á4 KF`´ »ŒzßÒ0Û| D‚ѵì‚&däI‰´ŽüÃÁ;·Mì”{'¶om†”m¢ I !wi9|H:§Û§À»ç÷Êþ¾{û~ö¹ýqº¸©Oøåôî© ú›,˜ ‚L]&„J0ñ•Ù9/í9&ÌYø è“°{;÷ú'À3`’e@vH„yDZ$º„3ˈDx28 ƒW€ Cx5xw‚B`£$C$'ãÊEl…y Õh¿ëÔ€ DJ $(p½îQA”A܉A–@'Ç$ hpÊ0ÎV0 `ºs¾ªeÒ$É4$"t2=f´˜4„A„{Tk–0|rH¤öÄУï`L&±´sÔh¦]”§A<£¡‹²`R´'£•!ƒ‹1N¦;£_Št3Û#  âòëúØêVãê *veÑF`E O$Ž{)ÙW=p:®ÞÖF`о2ÆÄ2Ú“CëÁŒÒ^×.Êć˜¡ø–øGþ<û.pçNe2ê‹ïÖ´ºÞ+YìsÛl:ÂÃË¼ïµ Ü«u5©¦ÞîÐtÀu•^8¾Ì6èóÈ„TmyðQÉ%þu~ôòš%~1rÒ˜aýwßš^ù_©Z£Za¢ƒ²0!Ùè¡·úNö`¥.Ž uqÀ±çêYB¥\™¨ó…„ÊᨀÔê…[eð‹îîþ:@ êJ'EÛ,¯3ubj@p¨ÁÆäð´f¨Éßóîµ·eW9( óºå ´Þ…‰³æ=‹l”G¦à7gj âSƒM6ư ô0ƒÿ9ò§–OË‘¨üíl§®B¼aªÝò¯  ƒ<¦çžÇBÕ™(VRAp¡fù^°ú¯+g9 qÓݹŠMÆt]»ØªpëE•r@]‡@ó©VŸkV¥ uêädé^ÑX å–—R@?EÕöY2ô¨˜Éï]#àǼš4ÀJÞåKöÁäÖ'ÃÁ¾d²âPC|mãmånä#¾‚$+48u'…çe&û¿€[n[LáÈù’ž±%{BCDÚL:^! ‹‚ÓbÆ™:&Éÿˆî‚g3“-3Ðøu´è­ÇæÐð¹ƒb iLZéÚ‚W‚FSÉäIdÍñ¡6.‘k5Pî„l7ž7üUz’T:NýN¡‘—.ý"€ªåü)‰Å—ì’['ß|U"Aƒ€³—‚I•Ûv©wÐÛØpë™í­t¹dk‚ˆž9Ø›Šå««Í9n¨D‹mq¹—7I|6›Kbcƒ]¶Mô“©²ÄÎ÷—è¶BA€BøÈª_ôJºT Ùüq Ð 6@—§„¸F—‡ƒžhd`G®Tëñ·:MÅ7'à…L,éIh—ÆFP »Ê~j½ŠŒíÄ ¬$¡„ Ä3™hAÝä’-SŒ^ûÚ†…Ðä-%qeÏìë~ÀÆQq«§¬ln"i¾ž&‘æÑQe?FlKï¨"úAsÀ(Ý3Y;"¡LžÚÔe€tå'ÄRzMœª1 0¨{=æ÷)ž€ ³K %$C Âø‘9ŠMðö¼ë¼4c ê€EotjÍÂV§GDŽ)lñ8“¯,˜\wÀ¥à !%$¿×3tÉ TBz’žÒ´ iUJÒÝ[¢Çxgd„Brï$Å!eqˆ’"J>࣠)\~¡‚Љ3(^ â R€8#>Öb›äH€âG'7_ fÓ«cκtDoAA߃†(q™B<ý`Ç­`VˆüøéΫ”©Ö˜Â*úbÞÏu‹P­4v@—+•Ê.’îQåÔ¥$V‚¡•í@C0 íR¢ÓÜP[‘z:X¦H#eäÁ òs >?úEÈWO>@IØ$|s¬žiâ ES¥²)0AŒ?£9•ab,¶@KšñÌ©o&îþüˆ¬Q´%¬ ÏžLu+› Â+H|ÌÆ?´NKÌ4ŒÆ’ÓCnPtè³ 'OTòœÒ.j5àÄ´8ÈÜv¶wÖœ«I¥&•+ß`¼ŠyScaO[#¡g°§Q§œ€¸Údª[îK½I矗`ôÄŒLPýÓ¸ #°Áœ½ ©)2Ò7aTƒäëi@c\Þ‘î ÂâÈ0nêC»pòß–é‹4͵Žxö*ñËÐR”zÕYâ„b‡ÀúÛT[\úkU™vìHʈÜq’p঄IÂíIëÅ—) ‹bB X”PºN´…štzí 2 Iæ==¤ ¦³ˆý¨Ã;}†bŠœàqþÓjiÞ†§a²#" ¬Ÿ>1¼‚°1äA›£p1ÖíÝP‚§OÇèO—ux÷Qôù°¹Î Fϲ(úhÝ„©O'MDxÊLíK$ȵœhæ& ù‹¦Ð1ŒïÄ4››Si ÜãrHJ’P°tDMË;rMã‚+”ö— *–àŸíØ—5u2$ªf3’K ß<ùP²LçrÑc‹I)˜Öå^ëda> %Åàѳb (Ÿú–@,‘2f,~"¦7ÛR;®EÑŽ;¬­”HXå(ú¹Ÿ4Š2ZäÝ'TªÛ¿ö‹„”½2J+ÿ^!#oŽ„›”Y~4Ø-׃òGW*ð!ßÃA•0&8€fä{`¼½øàWö=’DP8’'ÿ= ÖR¦ g©}ôiP>“Ê#¹Ëå¹4ÃÒEÐBRY®Æ^4eóý‚§N8¸V,[B‹†ĨîD#X†ø]²,Öèâ«LBsNC> +¢íoÍê^x¨ì§  ÷•újCì.4ÀYa‰_{e¦A2=rŽðØ+‰­´Öî§¡9PO»A!! ×}´YÊPJe„—çGnš±%xü1¬/}RgHØša Ž^3-Š© ‹5 ¶|‹qS§ÐðaWK{ 1al`IÀ1Ó ™ÆQé¾ëf_yyCZ)ÄL3X±] W6@DM™Tø<.„«uëGÎKŒì8ÙDsôÚбWæ‘r…Ý\ß7Z\ÕËÿòVÓ"I¦¢ŒõS¡§®dµ‰>CަÈUjßÉežÉÈÓD ®3MÇtWcP﯆–òÓ‰6#3Qךnቩ…°J\º¡Ã7ž#磱`Ø€Këë¤ ©×lV6 &ÓTŽ’ Þ~îÚl.’¾¡ <˜˜BP £*´!zRZÄäeÑ™»¾¾Ù·T±#£CéLH±¬ÈªWÅ)ÚD›†÷“p®YU#ÉÊ51{WJ€Ž¤4^Äf³Ì¼Z°öÌÑy6–Ó‘T2™dÎ4H=êB„Ҋɬ}œ&݃êÂ,aPçv+:2æ~òÁ*0¼°¢ˆd¦É“ÂõÖƒd ‚øáË!"A+‰rHn ¡ÇàsAäÁÈÚ—U €ýø¤b H“ÛN6þ$.ÐlÀ};½@£¡âiKà \¬Ò‚:v‰QEÇ:,|ýªQ  Y0|Ç%Ö@í° ÜäqcçÓÑdqh¯«è«¹vÜCÍGV†°©¸¯-(шm…’1»®âq89KF–Öä "2±ò}RrzóŽ,j^¥ÀqË\…Ý–#pƒ»+õ`flš³½â:k ´t–5E„OaIÃJ¬P @ps­E™j1ä4;6öô/aHÎ.¼ÏÓ°TX¤p“L‹¸ÄL8¤½Fç„Üši¨lí1–²YØŠ8É %!/Áù{­¨ÒÅñ éœ‹ÙåÆXœ€ºbˆ•½…NÉÂxp»ºäPWê½ÛíèÄcI9g²*þº¿îƒ¹œ%:Ö»LËÞuŠ‚CAOÂŒ­™%¬/Å“´(Y¢³^ï? Þã&I'ˆÈuh[x‹´–Qô$ÇzҵŽø‚ ß³ž‚(=V×€Ÿê ¾mð­ÅU) »ílΠΒ¾Ìiœ•d㦈™¨½~f¦ùjGíµÖR{D€%>®¥@”…”6‚¥¤1‚œ`Æ!Î ` ņ¶wYó§‰Õàk/a0A†«Â¹ŸÔ´ÊYh²¯—µòˆdìæxš‘k:fšƒÿ漣<ÕØÙWL4`8IYMBÁSlcäÖßÈà™-»EÒ‚'ÎÚŒÅ:,ÿD¬°çÑÙøÆ©84Ó)~÷ÿ2·j€Ÿ–Ç i¶·B(Lãµ| "a©š¦¯4,¦b8§”¥Ô“i 94¦åÔŒÒjWщ° ©6*ÐTð£†c4gŠÌ“¢×UMÉb³RÇE²þª‹ò…C5‘Æ)jäÈ´ ‘­16pbÃëÛÆŽH÷§ªFxòˆñ¹¿—¯«Ä£%4âòQÙÄC‰Êˆ§Å $9Ò:ÅM>òEÖÝaÜÆo«ÌŸ^ÂØ<IwÞYgq7s[†ð’ð -yÐ1ع5†äaÄãMKš×æRBÇY€†óFq}¹âç±ô8ïÀ²*ÈNtå'.Yb„”›¤ÍðZÍûvÅK (Ê]&ÉœŠ( Õ™¥ý2¯:0Õ €äo¤ÎÑ…PKiBH4Uð¹X,Ž¢[ˆð$ 0­mX±å»Ø´‚ ò¥fë5ð0± VR ©8ê%ÙÑñÊÞ§§Dt°ÃUŒ‘s`ô·-BPÈzôP”së°Á¦vIë¶8z-¥t1DiB ÒÝ"˶ÜÈYTJ ƒÄ.š?Ô0Ç7à€jL¢ÃNžú[2ÿtÈÂĮ̎†æ ù#þ6?E×»†”Œ×¡®ˆ:ÉžÎY;ƒç¬A&q…êSØIRÈ)Éss 9*xÒß0Bj)mìáH§A¾öhyÐhòMm¤&4ÅŠ…4€ €‡ÜÚg¸ŸVæ&tYóÚ¦ÏOCS0³Y²ô‚d7MvNïj)wë÷AÉ(¬âo "Í¢É[¦Ö E`›”þŠë7ez¸Ä†»Þ-·QÀ]¦6Û+BcaÍ@^IÂ:²Ò»´Þþ¾=ƒ—š­ˆsSŸäÏncÇùÓ 6 ‚ÍçOã¡B„4½ˆŸç L¥¨ÀGpãB‰q/<•zAãÓCÁ¥» €ÔA~¹ÉxÐ0 6rih£Íh¤IìØ·O‚N,:oÇÁkìçÚöÅ/ó¸{H°,ÛzЂgÚfÈ»z—¯Ó΀5ýFõ²TrÀn/ät``l†Á™*H6jT¡tG/xøË@P@(„ÄIèp Òeº!ùê`wv,:A쑜¹N£ 4}09zÇqCìä$rìüM`Y†Q”’ øMää•«³÷Ä(|éB!í>¢ÁØ>«O pwj A*@›ªŸJäC[h&3üëB QbýÏ©8 …:ñ“%f~v/‹lâSäÐèÒ0ÝèþÐð0a“·¶"ŽBæ8(f úuGoÇšÈgyñÅ×t£_Ãy~ÀÍ”Ž Ã%ä…°ûm†L èà!I$äXt0ƒÏ€~ÀeŒPˆzËÍ]¢Uìg Ð=_±?ñºµº.j#+`li‘¡ BŠñâM5›Ò º¿Å‘GÒpŒž7«a †Ö’%Y[UG9æ™òÆÓ@\bDêÐY…’{‰{¤ðED0®— Ö$ Qø+FvCð`ݨì3°ýQ¥ “î±E\àÐuC9ÍáÃ![€$êlïßõ šúêù6ßD¨oÙDgÀGˆ*+X!¸%#‚C€q‘ ?é­8ZUB)U@o¢ÏpgÞ©¶ZØq…¡¡É8ŽÊ9øžÇ|ucácAÑœ¶­é°•W;©@á" €Ø>P‚Óïåh_™Ç9}.6€„V/ÇO:à3´}Ž¡ZS ±µœ{:ØÚ~’óþœÅyŠk¦cO6;OÎBá=—bVñ. R¿k‹ oñ ¤ÿ^±GV=áØ }ïoI"+ ô ]w‡×FªÁzÏ·ä®ö`<“Éõ²30ûh÷ŒÅ3]êRfú—¿859s¼`K…M€¤8ñË X»Uqˆ<‰˜¥\˜“ÆZOàssè¿M’·&j&Ï ÄÖ÷ .§%Ÿ ÒPÊBL~^äßÿùGˆËˆ‘3páD‡¬•:í¸×£Z¿£Á¹¨©<\ñ«Ç i¯¨ÛW̆¨ÈÂ"(”ƒ:áÅâz‹©–X–~êÎ0PG]8ª¬ƒŒˆRQMNT¦qfÝW~!Ý0”R%Õ‘0ðxvGFy/Fø-›Ïwúu‚/ôî*ë+’Æ \õÂ8@ˆ6¢«Âþ©´‹»c<´àLƒ;c[šû÷ŠÛÙº nr ŸQS'o£QuòT®{qÒ_œÍ¿ƒƒSdª»A*ð:mò8Yuz2ÿPB« ìHh`l´k’pèÿLLh cEb6eÛÒ‹ ?!„™>| *=Vü­»Kî@žë“rx‘0ÓG`%ryr[6êŠY3Œ7ŒÅ ‡f*—*n•à%9™ÚdfÃè1ó1Þ¢Ú^'Ìý]‰š– RÍßèqÜÔ.Øê÷,œö•‰Ó^%„¯lÂÚâ ã½eØØ#wWÂÑsó56!Ù=âå!q[ö°ÄØ Ã%ÈÔ®]ó‹5^:€½m¨5©)?V b|šuÀ7f“ºìw°œæÄð,:çYe æ†R%” ò[À›î Éo gæF«AzµFP¥›òŸÀÔx›¶î{Ïíöd‚xíÖwÃ8Ž˜–Ù”{{L> ®‚d¬2CäL‘º¨äLÞ,œLÜè,„ò(àmSìø›ÃØåå$=Ñ|%Öluè& Ä…”83ãÚ N ¢XåŠx ë \VnõÍïžJ[)I›êwŒÄ/Ñé¹»²Ú ²| GÅºÙØY×Áð÷DHµ˜½*›Sýªîè¤æ’p6®0ÓcJ2ã@ÅW´%Ѧcï¼_^Ó$Ñç#*:G§®æ6Ž¡ïn>ÍD;úù¥~¤`9ëhXB ñUŽ«JB_вˆ˜ùˈî%ªý’´w'¹$³èv|#T<68çªKM¶Ï‘-Ù5U+¾¶¡'íB ËĪN…‘øŽbJìÃOv'Èì|‹„+*MŒ¼k(dˆ }›CÚ˱@ ³Áq°³¹&ùaR%}´ Ë!ÖVЃ‘s3w2¦ŽÑa²2²ÿŽawHæz¡/Q0ðF¦ Ù]~;ž¥Ã¤ËÖ NDùP mü˜K3xÞŠke_™£  ñóþS¯!¡V&=²²ª²ºvç_PÀL9؃Y£¡i¿ §NU­Ó_¶¬¯)–ƒJ6Ý9‘f*ÊðS ± 17ÚF|¸BR$É·y,Ʊ.¿ÀÕ&=uqsáó¡ODÅòB›ÈôR„=çÙɳ—eøØ½É‡àB®¬ä¬ÖH­¡®ˆ ª2lu'h7^#ÿS…)£Xi2..Pe¡/@FÕKÉ‘$é](Ø%à|–2ÉðY1pC±8tÁùIøã11N//+\»“p¥jÔÄïôd€”ÎáWÊmé›ÃI=ß½·ÓY“Zx¡ÔMЉPý8²“1/ JG«õÄ^U ,PÈd1O®ó^¬yßpq”l¿£2hÝÑ$øjvñø‹þª­ÌõžIšö%‡Š¨§áèÔ]VæÎÖ .'[+WU8Á­[Žå†Dê’³è,ß»¾-=[ÀåÙ O wÿƒ ¿Eê)å3±ø¬äó¿J&¥dïقݶR¡¬—S–\.° •5J$I&ó‘Ýoª·Hȳ~› l‡½Îz>€ Ux/õHñÐu;š?Gt®{?à³;óT¡ŒªH äLþ|Fú8á†ð²}ˆ¡{ú˜p:ß2tì͆a·Ëѧp6ÑÏíÔû·¶øè5Y"LÚD“Œù.Šr¼ØV“ß‘²ßS_ ºÚÊkþÏ]»n&úH¸z§~¦9‘æ ¦p $§4Ù‚”'¢{º& ¸«ÿËM\ŸÎ°éч¨®!ìq®ià ÏÄ(.hš'Ë B± T­²Ÿ|ž{I„6cLò¡.¹ž£ë¹iI¾ê«¿\!à;§àg`1â ᾕ˜j%C ¹o3*60÷·EŒ˜ØŽž]tä‰.×-%0 Y‰KÇ_nft] ·*VFCÆtJ’°ÄTÔ+¤\WZ8áòÄâ×gFвàÙ^ Þžf¶ 5šI=¶×ù#6ö.@õ2zÒÃ;Wš`ÿB/Ä™QøŠgí°ühŠjyJÓ°€N²AX¤3ªÝ,õ¤› Kä6è’ë6Ú²ØM0®T@ Ž…O{¡£˜4kj£|"¬ftÑŸ”Û„Uü‚<-üÞa†®Õæ5bú)í^R±°8™„ÎÁž:†§il¾­ÀKaÇ6@µæ”Ã!ÀÍÃ] buvÎ$ ‡oUÇœ~:.…Lût–èêe—ü Ç€¢JξP l$S[z–~Rq39é’ºô¶9ëQïË/m"•%ʤ‰¯†¼7Ÿš Ãî5MKLŸé‘§"IßG„ èXTÞŽXL¿FðݧV j‘p^¡/MÃgÁÛ»{¶¹»wô ì*øº€ž9ÿð—ÊO¾Êˆ<Ë"aôÁþ÷Aáîïˆq¿»¢†.M—2@möë‡p¿^Ú'“wß•möÇkxO8 ü$[ó«&Áü|Y‚Zyý`2_|%r—“/åJ?¡QùÃṈl‰3ÞÎßK¡E$–wÿvCËh£û a@÷U€1©Mø¾%0?1*¥ –$GÓZÓ{!|ÇÊ¿À$ÃßÛ•Â-òÙªEv;‹Í“:佋Ÿ`BlÏ˸ ìŒ§Çɬ›oQÝ0&‹•ûþñ,†F?¡ýÆä„^s,‡c“™ÁhË•ÿ$ÃEücl0åºw`ý⺹ň©@/€r^l˜8cT·3™Ük@›ÜúJÂÝ”´uPÐ&ʪNÉódùJjTK¸ªi ·é*u§»éX–{t“j~½É¡}ùñi\BÈKenâ‹Èµ|NëÖê šu’ï#Ã]@lõCZ$iPæa½ã¸©t04y20ü sØÖªâ,AuÆ!QÒØBäÏ–ö–^ìˆ@VsÉ‘€‚\ÞZßaã7©ì¾‰©¸âш³»6-Tïr±ÀäU˜ àu“Œ~ë°1HÂJ¨(<Î±Ž‚ò½Ó³bRÔ–¸qi Ï鿢¬J?íeÿGÁ §*jVħ "áØã†:Y);-Fådô!ðH£»ÙG~´•u¦x cb6m•¼ø)&;ñ0‡ÏdU?‡8ÅX~ïŸ1Ñ2šÛ¼¨t€ˆIØxè5ÄÀ{(ëz„ê Ü'¿ûÿ[ ÅƒkŽèZÐ…ØìéÍi,ðÅb™1̇‹¢Íá`º±(ôªmHáNðìüe‰K¤°ßÔ/ [à´(õö#Qô—GdÊuÎT©½^øm³¢¿%ù†ŒÅ!(˜7Kgé…P=èhøÏ•ákÉU+ŒÂÆ.[Òe¯‹Ïм³CÁžÿå"GDÿΨ£›<*<ÖÏþéh «)¤` A˜U @O]hýlÅf2”…!HžçÏF#QBÂé=uȾ9f´h€ó;"R„¥Ú’KÜ3-‚(G )¼P±áø¡¨ž¦²T],7ÁecÞ ë F4hH Ós³73á–Ÿ ¡² âÛ`àºR–¡Tíwfͳ;6Bó>Ř 9&ÈâÛÑÚÜ‚Î?’—÷ø)À\¨Œ€<&Ŏ™ð5 LÃJu¥@YžÝÝ,냲ھÛ_wÂ0˜^é17ñððöìpÞ»‡*>D”8㟘ü°_)$UźóÊR´!jOFôÖ>{ˆÐ’‘ »t,¯-…bPµ,m`D"/ŸzðAâ ͔إêßQZGÕ&U]xejxæåLwvõ~²œ=)@ØB¯Ö6Ê?!;53/ps@tƒOZS7©”§Ø™®’nŸØlxèûîÿZ?áƒZù—j a²–{ýû6—¥ÿL4›Š«1Ÿ 2¹´ù¯‹Q‡iÜý&Ö¥lƒˆá½Åì]o= 7Äļ ofüЖür MEV@ƒâHõ¦èòû/èýaD¥Ù¦ëH•ƒ®®lK5)ÂŒZ OE´œ˜„3Á¦IG©'г;îD'¶zl(‘ ÷EŸÏÑ$Š.Ùœð-W R'\w+)Âw3æêº¾ù¸ @Û%RÔ)ÿ.ò~Š9;]ô.šg+)Ø%ÈökÕÎÀÒ‰³¨^ÒöN€W·>b1z:s†¨oD Kö²ºÂ2w[|>9â®vWMFâ¯uÞ`¹ëÍax‡chÕ«õU·`*ʆeû]O V'6ý‡ÀƒxÔd?¼H]_rõA»£+zÀd­F›¯H ÄÊ‹<¤…Ç´£ÕÆkUsFzÀºòÏaHÖÇ9-³œ˜ƒgv‚b‹=ÓëL/žE»)°Ä.˜½x9j%Bã) $—ŒéAËB¢æì ƒÛŸt b.bÒAE¨žZRböH(‘£õJÿyaãˆÒ9Wj0f¤ßF'›°Xàz¾Ã ï$DQ­6´ëžqƒØ` oÊÐ i=áÁ{#4¤©FYHù@ØJÐ3 3i~‘tYТÙhkH‡PÏñ×÷ý17ÓàॆYÜD—"Üp—Ħ;'³16€Æf—pu‹ ô¾>þF›oDÅQi¨náÌ’-Ïç @P#äš«‡ ¦h“j Þ‚ˆÅ€f´¶C– –ƒ7°”T5HVXÉpíöÉklÄ­Œ³®]™ÚyXrÆ)?ͺÓBNJš Bƒ÷øä½#Ë›9e”&&»_0•Ó=®špZÉ6§ªh¤Ù)ð Ì—ƒa bÀŒí=(p)‡âÙåí¬;Š.N•,“ÃWí^ *hÔºŠC—îm}E™7iõà‡6Á‚Ã÷aËIívͲxpƒ*Ac#4‚ÿýûŒ³Ç Nö&ð`)®Ä‰ˆ£H£We›ƒy7jl¡ï°oÝEh_n3 ­ ‹jp?ª4èp2WÀE'kT_ã &£°!È–jVl˜HíÓ»_kÉšáÈâöʳùaYùŒ ¡ sÎ@ä[…G"ÊÓbYÕLÛÜ«X¦ªi ÕC˜q8ñ&úzVaY{èÆ#I@µ§­2˜Žmó!ôdŒ[1 …AàÆ¢šÿnKèðòÕÆeײå/>ßdƒm†uX:xÊ·\„âpòN‘ûý©l+ƒH+cÇtSǶ‚æCÀ±[íà~3ŒÍeÀ}6° \³,ÎñÉ„˜×|¤YòÝ§çø˜§v]¬'û|¿žŸë&í–ìMô2° dõ¬dsàx-((76”©aX›½m=ÕîÓŠ¿ãQˆ—<$ªª€üóQ†˜„º\“ Ô ªqiéH阇¬‹‰i'i¤”$"£{S*VwF‹“/°t<ìÊÁáQ`Ê’Z¸š+ðpr)›(¹.jµé¸«Iük5õ <ä´ʆ±Ë®ÉÖ, kO‘‡œDTˆÊJ&^7º£‡ÄªQþ¤ËÏvße &žZØ’ ^4úÆ^s°ñD+`WHµ™®bì6ÙÄ©˜ ¸®ÈL˜W{ZZ ¦@°ämqáûv¦É·(DÁ\+Ôlåéû0*¥V¥ß‡°VmÕЧæhÆæØ/S`|³^\<-™„©Ã6ë¸2©N3‚" ToŸóŒlräÅe ‚!õÅH2 ‹pƒA Ö›¨ ‡ÞÃÏ{›È¼þ/£òŸÑçœudU2*2ò"c«Ì"p…${©€y, 饋ö&\àm¾&º`Ð|x ¦p…ˆCªÒw#ÂÉûW9D­IiñÑ–Cˆ›Ksï–ç‡S¶“ã3ï ,¶‘–þM›’;j¨þBë§4š›P›2ÙÙiµîïf¶®É¿íÁbA­]a¢idíÂðŠ­¨†"Äò×i!aQhÔCNO½±žŠï‚õYí “xF$Äøg—9ž¥‘Z`W«°…VBâg¸± ìÚ#j\Ë‚—¨€eùGñû [³.à¾]‹ª0º~X{2›D©„? Šø"óŠ3ÄBáj,ÀK~Æb#„0¬É’L˜kcÍ(6 ¸  ±aüE7λ/ÕŽ¯%­ ü±œ·ï àÉÄ¡Rë^JûëÅCÏZ+71XÛ´ÐUO,Á„öá}#-”eÙ¤ 4ö3Å‚ðítÃ8§™Z7†Îià¬Ê<:iÑ?Ft‹Fk–C W'˜êf0i<âXdj—ùŒ”0ÛW#i‹‹š–eCÏ zI7ˆÎB°s·¬˜.Kƒ  *ëÝV‘°«dÿ‡ŸDljö@ì«ï% ©Üˆå ÎZˆÄsÝï®sh̸%‡^ß ýèøÍ÷@8†ò§¤øÎ?  Nº8gÔGøgr¨X°€Sƒ» üä• Ap ‘³º4‡z*ö¹4áÝà§,í¹Ät4GÙnÔè÷‘¼õdSå>fî”Q–CòÏWUZ{SÙ;Nxå½Ê}°ÇH&º¼* ­9׸¯q‹šU1 Êó a `(M-aÈG}Õn¶Ì½è¢Ú0 –¼pÊÔÇmcnñŽ òð‚ɘÀ_ú\±ül¼ÞÛàþ»}Î È Þ9÷FávžHþkƒJZüNO å´mZáÁQžíÒ¤ aSûëfú )QC+2 d’˜¡[¯ý» ÌïÁõH"t*Þ Ác*bÏÆÚ¢÷¯q°¨,µ™óã#S˜Ÿ#¢äu›'Ò¬õ:4©as¥©¾CDMF§|ɸm©_Ã1L]öáY˜Ê\À§ý*¤XœŠ>tú–¯¸Ìg‹§ØD‰Ÿ£Šøèd@&[°)8ÃÎ;<œ{óÊ8<–È+VG\°H˜®¦^¯a—‹aeÝ-4”úsÚJÔA \à hM[‚\`ð“¼#¿pD5Z97g;²÷BWâmÎä‰qTXX‘%0¹vºžã†ù&ù·]E ¹Û4]ûFŸIJä¤ù–œ„&ÝSŽ_¦îƒ4ÈR‰0 ¯¥Dü+Ëme¹Ô¨Y ƒg÷ÐOøñ+M{”03Ïv'Í…f…ÁÅt¯áè :;ôØ±Ê Nô¦nà\Ç”^Ü,)1Þlãá’aBïZZÚ„[•à ¸ ûZSÒÒä¼UYhÜ߆ÏÊw€õ‹šS¸\®/¤*?zQЋÿ`X4ïg¹ríÛ[§ŠCWæÛGû.§Y„ì0Q|ûRÔƒ‚E[w¾¦î„yƒ)¸áï‘,шï$ËNK@c/b -#Z¯I ¹G$Æ—¯™‹tmçÊH#êð)X£wPZAD|¢S oýfŠõT¤€ÝHÚë)¸ÎäÓçÇ>ªM1 b 7á°…ɆS‹uÐÃq× ö·öjK4[sð„‡ •—×xL ›Ö¼Ç¢©ë]5 ú!M!A¾dƧN Ë><«:Ç»Z(°8†ø)e… „ß »¥™†/™WØÈÀ| ý°bªØéˆú<é÷œƒ®T?%à ²:@±äÔ,-àø€ecMPð8u¤m°VÐgŒ9Héö6®Ëç‹}¾=³5ƒ—AbÒÄŽæýÏ찬ΙÀV:’…_ leÉ¹ß ÏÊî–•v ý`Í0Žä!$`GÁéA"I;$ß^?ú®Ší‰Ke O¢ Í÷³N(Õ½çö“YyÊ5Bç¡w¸ÐV¹%ˆju;)lFµoaåìË›7óxéÿ’Ú¸Ø4-‰É%ë †ð$ÏÖ¹/zskǘ(sh>»ÁDD©ÅƒÉt¥TÄ7örurÀœ¸0ÉÒ¢ `Ü´h5 5Œ¦Éä¶“Sá}¸ÑÝÈÿÒ4hrva¼éléc!ZjB]¹Ž¦©ÎxâD¯¶ÿb–TxzYS‚ß6_ö)ƒÊo°Ôp>˜#@P¢SÓ*ýbÜS\q Æ‹xñYfQ><"ó·²ã¢ Y6‘ÅòIEr_7ñˆÒ° VÔHÃ!³ÅIçrŒELçŽ6ž!N»öq"'’d “aþqMvºÅ‹A‚%íõºº¾ ñv³í½Ž nð.;šëA/Ïç°ô2ʲ‰œa8D$ÿGWv…#Ìû 9®kÅÅ'ü‰ËoØŸœo€@âýÌ (]gkí+}/ (nq‡ºìK(f¢ÍÖ ÝÆŸÐ¸žpüøÌ2ÔÈ3Y°ãÝéw²pDþdG´q2$ÌÉ}‘KÓ¯A­"öE&N‚tg'NeýsÕó!Юð4qìœo}ì¿¥Sµµë,oÕjr/s œTþMT—&öÐðQf\12¡h'&ctN¦ú'TÅx7¼]2û ;GÍ Ê…ë¢ã|Tª++:%/ †è¦ûгÿ1T ‘ÅúÏ“ óË€Ÿ<ÔñÌ4ÂÓÔùŠÀÍ”×ÿ“Ë— É,0~áò!¡W‹O©à'‰ áÍ:sñuÈÆÊÒ¦Ù†ù(´^ﮎ µ¥œÂ)˜ø7èØfÁ€Ñml¥òÒ¹î1Å«tÜÒZƒèhÀ ÊL0 §£·–6ÒX"JÒ‚í Œˆ4§9ØÑ Ö©Bé}ƒÞÔ­`è`‘¥®ð„Ó’ç #¦JÞïnéäôÑ_‘F­ H|š¡$OÈKÎú=¡Å“i1÷¡¦7Œ”o-HËq¡ªûp[É«%%:ˆä€Éˆi3Û ú„G C—LL‰4ŠSÐ:ždBòj|‰ˆpYÓöSþDP>¶pÓvÞ²5KLeè{t0®ò‘yÇEND$à*;z»5šŠN’áBIóÙgnŒ€.NÉ|×¶àÑnДRÈaS¤Z×ÂJcH² mÍÑXøÜÊßek;_ 6È,yÊÂb”0#¦Z„¸A e|w‚ÔÌG U½1l¸ËLDØ7ÄV£q’Ýt[­xuÝE”QULˆïðPBlZSh–’.áé1Q0UìÙ±8R„iúp;¦ñ{óôH#–GON!?ë£èt>©Q |pÊk¤Ûó¨q!çgT,öÕjÇÐ2ÃÈsÇ4툊t”jä·nÆ›/IÉO˜E!Ë‹nFõ›4¨†·ˆM&Ô1„’—¾…xÓ$§ew+v™SðË  bm]e%8 ²äPÌ !úﳌsÂó_06£ò)ÂQ´2JB†êØý „[t9®–ƒ'”§³Ôœ,§¢Ìô[½fÆג¶]˜ÂBŠBÃ@š¦îr&B„s|•Qš °§™×g¨íOCˆž1‡ÜJ Dç<ÌÏâUÿ‡²Î¼Ó(o©!³h¦ÜK½Hüê 0q›ˆ’§AÑVˆ¼'p´fÌy"Q O…Û 2ÇZ»¾ŸqÂà½#d"›@bQ»,®“ w)îPÍ\b`xŠßOþ)Þ¢ d¼MC€$[Ho¤WÞ¦Ñva4{äDZ`52íýº‡³5;‚…X°ÿaoK†;˜6“%ÁR(À‚ŒÓÆÑ…x9Š8 À2rãDc÷¥@ÙˆŒæ¾É¤îF×<†d(ÈAN#FI·ž›zmEþ‰»F=©±…Æš­å•S‚€f 4Ê8§<'´„íjêŽô-ª˜Ú'ǘ<ÒTbñ2Ýv€EÀt¸¿q¡Ò3qODd_íÐ{`/œhhê‚öÌ`Â’9_ü1hAY|/ùë «Þ·Uê-Í•ºÐÄAÞ”Õo(ñËê"“$r؆TÌ×PR;§.¸-w>&LJøiC`A£^±—Ó#‰€ÄX8—t—öâH?€dÁ¿aÃÄ–TSTÚa¨HŸ0@ÒîŠðóU)ˆ£æï^e}Jb7%×Ü”%:›ÓÆ¿@—¯MŽ+ñ»y”sqŽª¡ëLÌÒýø¿á ÊYª00Ô÷GüD¡ >Ä©êAW ˆ¶ð2IÛ:ÄÙF žÈÇš3ãŸ2Ê íq€÷À”:6S•—ŽÑ]KÎÏ" ¥®g[¦ åÏ‘H“˜âB¬5ÈVEqÛLJŒ•X{C¼ˆ¹§B½ÅÙÒ!¥P«Iáq9»øLlx–®Êª7Ò>Ö¤–Û]@Õ!@9H”!ªíäÈpÀÉ™Õ$ â?ÞÕ)›«Üލl°/"±”ÀÌ–¯+“@`}}:\÷•¯Ð 8•zQgS£¿+ò’¤¿Á’C„£}€R:ŸõHþUF\¡Xþ’göÀ/âë€AZ%c1ÕwlET–wX  ZNh¥ …Äyf2DÆ €Ã¸‰&v®L“qî4Æ7•ñ§ûÊzúð\iJyÀèJ-k¯NÄ3½ ë £-¼s‘ÑJ5‰—)ÙV0™N0ÝdÚ\Ó›d0d-©ãEÚ[mf£\£UmÁx²ÒÒC«R<(`ªÑ•æƒp4^!hÔQè `¢ù!l“ ~Æ™ì:J‡É ñlüW±þ€9˸ÌZXB=ëÈl)`jžªeVJ³àU€³†G!®sØç1Ô?Ƽ3„¨ÃŠ.³}bIaÙê6àÊ• œt?èÀ€ÞSxZJ'Ãp ië,¦.ˆñ¬ØR2T`5˜-R BxræWHö JP°e#Bb‰|“¯”-±þ¡ì‹[²„ ÆäPÂâý…¤¨Eh‹±³Â‹(5Sœ¢•fÕräÃ/]˰ÑIÆŠ ÌÖd”ÞE#ú¢O®Sú3—9Ó»]¸º³€e‚¿Û®Õɹ.9_Œbêe§æ¾MŒ´9b#e©(’¦-ˆ 0§Ò×Ra±àÆ„9ùº–ˆ"þ‰±þýýU,áÂ%ú~¾XèÜ€ö—”ëz€Û½{'6[@„t[W%ýÑ* .d'vR {”ÒðhЦ!ÞAed’CªE}»x=E[|ïB$7J¡* B-á ,=k7”[_¶ê-ÐIô– ¢«€’‡J5eÖ̶Ä´{ Èí( ´†;WMw§`«°€Ë~pÜA °z 8‡îfæ))âŒâÂ(Þü@ ©ĪÙ……Ù<áî…ä.a%N òìné@bz­Ã‡ÈÑÀµ¿>Àëô%…‡€T*?lgb¿döÈ<‚ĵãúÀw9Na¬Å¼8;<^*%›yÒ:tD¥Ò•Z<@ü‰0ª¨«ä‚q4±äÐíl\ –†1†îÉŸÓ`/ž$IJ Ò“sN)¼;:A;’)$ו °Ww¢y%KrÞIv\b¶V™£\n­d{ÀÞôÈ6t»ví×/~¢ü*OÖí 7U>£8ûr‚AC<ºjéŠEâ¢-jçØç‰·¨üxsî)ÌD¢›–1¼ÃŒ/ÏÊq“p**̸À$Ù‘, Ûá ƒ³BõȼpÄúk MhpˆKê7ÆUè¤Ã]ðøáh&„-ž$ˆéŽ»¯”“Yê£;àqËé6w•zÝ÷ÖWûî˄֭A¦h²ìDœ‘^RöÞÉ"­Æs5fýüîw ˆ¿ä+çQ&’/9È‚–œ¸wNbÇëéü­ãü°Øz{娕ÓþYÅ> ]NEÚÁ±c,ßž# BFý:0ÍØ/-EȾÆÂŒÇ׃ëF\êŒôäI§{tìäA»Z‰C™ORÃuk¥ iú”ô)…ytkdN¸&›v§A±™ˆ P{ÍÖîôËP'šó’>ÈêàxàÆ†`.Üä%,;:Ô¿Ù:Ž©«­¿íaFñ§oTQ«}v#ôìš×£‘öÚQkèÆ'ÝsÄÔÓÖØ÷~…µÞÍz5hMÄQÊ’áY>C…èÊ™„è¾i·ÌU± ÓNF#J0uŒÎCðäð8k“! f«éì§v ¹{Eñ/ÏëæIKIEË> ºp·yd†Ìe ʾ”=zô†:@7ÖJà÷ijÌ|ÆÆ5g8Àîx Å3çO±Œªþ€ÄÜÜ þ3€H1‹ó±Ø„F. y´fz´ìWIM ñÙƒÆj[.wæ%„i?Ò†UÂè©f|}@+[8•k7Cx¤˜S…íEOÞ¯p $ä—üáç¾Qæ»+™Ê:¸<á]¶¸Kâ3‹T-y²ÂÍ[NÑÖz´µ„;y³Š¤-HZþªY^¡Ô.¥M*Ô'h8ÒíA….°Nï2r‰œLBœ 7:Or’©}‘C‰SËšS9äJq#ì£WI}*8ËD!ˆ¸# g#Y>8`• ìÐ’Âñ ?a…2H,^ñãÄ'ƒï?¸ÿ^¸ˆæ§nƒhãOÆ’­¿i<ѪæÝYa2É+™üÌ6a°F±âa<Ì!„Û0¬‰2½]c:ïe¼K¤¬X˜X˜[UgéO¯u5iÔyPcVÙTºž5RIúŸA6òOÔ¸i ¤ýCŽ\‡ñ…—ãQZM„DÄÆƒÓÚÏB!X–Ä:ôÐã\!Ç^Á…"{¡E Vax$P \$ ³DBBTÞÓFtèŸ~™Ã{O‡¼ wïøž5a#ø`«=g€Ð°Yý2>‡±MG¯-G­kèªÛ1T¾b¦ü…L ¹`*Ù€«V¬X ­Þ*¥xªe§֊Z*c`ªVÁSÕb¥ºÅJUŠ’ªÐ*6 TK@¨zqPÄâ¶ÉÅh“ŠÇg†Ì*ß”U§(ªöQU4‚§9L’ ­cMÆ*ŒT»©R!R,B£È…E°Šˆ ¾*C|TzøôpðôFèô@èô4èô*àôà÷õ±î±í…°–†Ø¬á±Xób°€L€.™T2y`®ÀUpbàåÀë ªT, %@`äÀ è€# ?@t€¤øGLˆëÅžSÀ)öžÃ¿ z“ÿtϲFy׎ 14LhŒÐဃf™°ÈeÀ(.)pK€@\âà —X¸e@Tb v•h˜DÀÅ&ù0-IbD‰ d@ZD1¤@ ‘DàyÀ¸ó€Ñ§CN| 9Ü4æØÓš#Nc lÂÀ°;¸, `c‹XâÀ³@(„2$0 "@- ˜$èB@‰<$ÐÁÀø8p7C¦ €àbè(@¥ PA@…F ¸0Àõt‰üœÞ‹äG­éÔOR—‰éIJâIïTñySÍMW52\TÆoRå¥KV•0ÈŽ¬à»‚Œ( - $²€’š€” ¤!6¦„¢wˆêH¢©†£ùúGù­ O r~àe~/à]þ·àV~/àP~7 Szï Kú— Fv`;ö¯`9vÑ# J¤Ü§BÍN‚,ä×ÎÅÓ­²'°`¡'â‚`\LTþðÙApBs)r…!Õ â( Òi‚`ola-0.10.5.nojsmin/olad/www/new/libs/bootstrap/fonts/glyphicons-halflings-regular.ttf0000644000175000017500000013053413023355232030421 0ustar wouterwouter€pFFTMm*—ÜüGDEFD OS/2g¹k‰8`cmapÚ­ã˜rcvt (ø gaspÿÿglyf}]Âo”¤headM/Øœ¼6hhea Dœô$hmtxÒÇ `tlocaoû•ΠŒ0maxpjØ¢¼ name³, ›¢Ü¢postº£å5¦€ ÑwebfÃTP±TÌ=¢ÏÐvuÐvs—‹ ÐZ Ф2¸UKWN@ ÿÿÀÿ{ , Üh, ܰh@( + ¥ / _ ¬ ½"#%ü&&ú' 'àà àà)à9àIàYà`àiàyà‰à—á áá)á9áFáIáYáiáyá‰á•á™ââ âââ!â'â9âIâYâ`øÿÿÿ * ¥ / _ ¬ ½"#%ü&&ú' 'àààà à0à@àPà`àbàpà€àááá á0á@áHáPá`ápá€áá—ââ âââ!â#â0â@âPâ`øÿÿÿÿãÿÚÿfÿbàßäßµßißYÞÜýÚÚÙ!ÙÙ     þø÷ñëå|vpjdc]WQKEDÞÜÖÕÎÍÅ¿¹³ Œ5 *+  ¥¥  / / _ _ ¬ ¬ ½ ½""##%ü%ü&&&ú&ú' ' ''àààà !àà&à à)0à0à9:à@àIDàPàYNà`à`XàbàiYàpàyaà€à‰kàà—uáá }áá†á á)á0á9šá@áF¤áHáI«áPáY­á`ái·ápáyÁá€á‰Ëáá•Õá—á™ÛââÞâ â åââæââíâ!â!ïâ#â'ðâ0â9õâ@âIÿâPâY â`â`øÿøÿõõöªöª (øÿÿ(h .±/<²í2±Ü<²í2±/<²í2²ü<²í23!%3#(@þèðð üà(ÐddLL[27>32+&/#"&/.=/&6?#"&'&546?>;'.?654676X& žjžà  àžjž )"& žjžà  àžjž )L àžjž )"& žjžà  àžjž )"& žjžà LL#32!2#!+"&5!"&=463!46ÂÈ^þ¢Èþ¢^Lþ¢Èþ¢^È^p@LE32!2+!2++"&=!"&?>;5!"&?>;&'&6;22?69ú þ” x } x } ” þí x }þí x vþ” ú¤¤L þ”   d   ®  ®   d   l ¤¤dŒ®;2#4.#"!!!!32>53#"'.'#7367#73>76èòp<µ#4@9+820{dþÔ–dþÔ 09B49@4#®bk§Îv$B ÙdpÚd†>u®½hi-K0! .O2d22dJtB+"0J+«kuž0ªwd/5dW…%{L°>G!2+!2++"&=!"&?>;5!"&?>;4632654&#¬^CjB0  0BjC² x Š • þõ x uþõ x u¶Ë@--@°$?2O*$ $*P2@%d   ¯  ¯   d   Û ÈþÔBVT@ÈL¼!2#!"&=46ú üà¼ÈÈÈè°%A+32!546;5467.=#"&=!54&'.467>=è2cQQc2üà2cQQc2ÈA7 7AA7 7A°–d[•##•[––––[•##•[d–Èd76!'ö ˆÓûPÔ‡ $ op zy¶Ã³#»ý%**%ê·$ ”–üpd°L #7!2"'&6&546 6'&4#!"&7622?62~ ýÌýÌþø Œ þø\l û‚ l¤¤L ýÉ7 Úþøþø & þð ýÚ €þ” l¤¤ÿðÿ𺺠2'7' à&™ cÖ_"ý™Öfþþ³nº ™&\Ö`þtýšÖfüjpO°°32!546;!¼úüàúþ °ŠýÚ22&&Lœ%6.676.67646p…'0SFOˆ$WOHBý¨XAOˆ$WOHBù£"üÁ7Q)mr ›ý¢*`)nq&* ÿø»§)2"'#'".4>"2>4&ȶƒNN;)þíwŽd¶ƒNNƒr°”VV”°”VV§Nƒ¶dyþî%:MNƒ¶È¶ƒ[V”°”VV”°”dX¯D>.54>‰0{xuX6Cy„¨>>§…xC8ZvxyµDH-Sv@9y€²UU²€y9@vS-HÿÓ^{”62!2'%&7%&63—ƒ¥þª‚þ©þª‚þ¥ aþŸ ùþo ö÷ û ÿÓ^{”"62!2'%&7%&63#7'7#'—ƒ¥þª‚þ©þª‚þ¥óðÅJÁÃJÀêN aþŸ ùþo ö÷ û dŽâ‹ŒåŒÓ°°&2##!"&=467%>="&=46X|°>& f  û‚  f &>°°°|ú.hK æ ]  ] æ Kh.ú|° °L#'+/37GKOSW!2#!"&54635)"3!2654&33535!3535!35!"3!2654&35!3535!35~  û‚ Ud£ýÚ  & sdüd düd dáýÚ  & üïd düd dL ûæ   ddd þ¢  ^ ddÈddddÈddddd þ¢  ^ dddddÈddddLL/?!2#!"&546)2#!"&546!2#!"&546)2#!"&5462þpmþpý½þpmþpLþpþpý¨þpþp LL/?O_o32+"&=46!32+"&=46!32+"&=4632+"&=46!32+"&=46!32+"&=4632+"&=46!32+"&=46!32+"&=462ÈÈ¥ÈÈ¥ÈÈüõÈÈ¥ÈÈ¥ÈÈüõÈÈ¥ÈÈ¥ÈÈLÈÈÈÈÈÈþpÈÈÈÈÈÈþpÈÈÈÈÈȰL/?O_32+"&=46)2#!"&=4632+"&=46)2#!"&=4632+"&=46)2#!"&=462ÈÈ¥¼ýDþ…ÈÈ¥¼ýDþ…ÈÈ¥¼ýDLÈÈÈÈþpÈÈÈÈþpÈÈÈÈ&,è  62"'&4?622Ñ;±üñþ€±«Ý;±üð€±«nnBB# "' "/&47 &4?62 62ˆ²þõ ²þôþô² þõ²  ;³þôþô² þõ²  ²þõ ÿëÅ™%I2"'#".4>"2>4&3232++"&=#"&=46;546™Ä³‚MN,mþÔwŽb´MMo³˜XX˜³™XXþ¼– K  K – K  K™M‚³byþÕl+MM´Ä³‚MX™³˜XX˜³™# K – K  K – K ÿëÅ™%52"'#".4>"2>4&!2#!"&=46™Ä³‚MN,mþÔwŽb´MMo³˜XX˜³™XXþX^  þ¢ ™M‚³byþÕl+MM´Ä³‚MX™³˜XX˜³™‡ –  – ™°-32+"&5465".5472>54&&dd§Ò[›ÖêÖ›[Ò§g|rÅèÅr|°þpá¦>þÙ¸uÖ›[[›Öu¸'>¦7ÈxtÅrrÅtxÈd°°/?32+"&54632+"&54632+"&54632+"&=46–  – þÞ–  – þÞ–  – þÞ–  – ° û‚  ~ þp ý  î þÔ þ>   È ú  ú ––GO27'#"/&/&'7'&/&54?6?'6776?6"264X!)&1-†=+P˜˜P08†,2&+!)&1-†<,P —— P/:…-1&+x²~~²~–˜P09†,1&+"(&1,†=,Q——Q09†-0&* !(&0-†=,P˜þ™~±~~±d°!%)-1!2!2!5463!546!5#!"&53333333ô,); û´ ;),,;)ýD);dddddddd;)d KK d);dddþÔüà);;) dýD¼ýD¼ýD¼ýD¼ Ñ62++"&5!+"&5#"&l` ¯ ú þÔ ú ¯ j`ý  ýÁ  wþ‰  ? dè°3!#!"&5463#"&=X;),üàRú°þp);ývLþpú™™02".4>"2>4&3232+"&546ãêÖ›[[›ÖêÖ›[[›¿èÅrrÅèÅrrþ|2 ¯  ú ™[›ÖêÖ›[[›ÖêÖ›;rÅèÅrrÅèÅ  þí 2  ^ ÿœ° )#!3333ýæ)ò)ýæ¯Ñ¢Ðþžàþp°þÔ,þpþÔ,d°°/3232"'&6;4632#!"&546;2!546&È¿ þ¹ & þ¹ ¿T2  ûæ  2 „°þ>þpÂüà þ¢  ^  ¯¯ ™™12".4>"2>4&3232"'&6;46ãêÖ›[[›ÖêÖ›[[›¿èÅrrÅèÅrrþ|– ‰ ß & ß ‰™[›ÖêÖ›[[›ÖêÖ›;rÅèÅrrÅèÅ  þíþí ™™12".4>"2>4&%++"&5#"&762ãêÖ›[[›ÖêÖ›[[›¿èÅrrÅèÅrrþçß ‰ – ‰ ß &™[›ÖêÖ›[[›ÖêÖ›;rÅèÅrrÅèÅþíþí  °°9!2#!"&'&547>!";2;26?>;26'.áî º û´ ¹—ýÔ W – & ú & – W° ýtþW  ©Œ È þ>  ˜  ˜   ™™'2".4>"2>4&&546ãêÖ›[[›ÖêÖ›[[›¿èÅrrÅèÅrrþ‹ýý™[›ÖêÖ›[[›ÖêÖ›;rÅèÅrrÅèÅ]¾ $ ¾  ™°(76#!"&?&#"2>53".4>32³‡  þ– …mtÅrrÅèÅr–[›ÖêÖ›[[›ÖuÀ$‡ þ–  …LrÅèÅrrÅtuÖ›[[›ÖêÖ›[™°576#!"&?&#"#4>323#"'&5463!232>³‡  þ— †ntÅr–[›ÖuÀë–[›ÖuÀœ†  h …n‚tÅr$‡ þ—  †KrÅtuÖ›[ý¿uÖ›[v† h  …LrÅ d°°/?O_oŸ!2#!"&546!"3!2654&32+"&=463!2#!"&=4632+"&=463!2#!"&=4632+"&=463!2#!"&=4632+"&=463!2#!"&=46}  ûæ Àü®  R ý2  2 Ò  þ> ¾2  2 Ò  þ> ¾2  2 Ò  þ> ¾2  2 Ò  þ> ° û‚  ~ È ü®  R d 2  2  2  2 È 2  2  2  2 È 2  2  2  2 È 2  2  2  2 L°#54&#!"#"3!2654&#!546;2„uSþÔRvd);;)„);;)ý¨È ÈSuvRÈ;)ý¨);;)X);––dLL 732#462#".'.#"#"'&5>763276}2 dÀ!C@1?*'),GUKx;(.9)-EgPL ûÍ3 0þ[;P$ 9¶7W W°—!1A2+"&54. +"&54>32+"&546!32+"&546äèÞ£c 2 äþúä 2 c£*    `    —c£ÞtþÔ  ,ÑrrÑþÔ  ,tÞ£ýÀ þ4 Ì þ4 Ì ÓGÝ9%6'%&+"&546;2762"/"/&4?'&4?62A þþú  úXx"xx"xx"ww".¬ ý ¬ ^ „x"xx"ww"xx"ÓrÝ/%6'%&+"&546;2%3"/.7654'&6?6A þþú  úÒ `Z  HN.¬ ý ¬ ^ d ¡š g~„jÄbì1K3#"/.7654&'&6?6%6'%&+"&546;2%3"/.7654'&6?6Ç ‡D@  *o;7 *ý‚ þþú  úÒ `Z  HNì ³ÙiËT "–²Z¬G !¾¬ ý ¬ ^ d ¡š g~„j °° !%-;?CGKO3#!#!#3!##5!!!!#53#533!3533##5#535#5!!#53#53#53!5!ôddþpdô¼ÈÈþÔÈdXû´,,üàdd¼ddýDÈþ ÈdôÈdÈddÈ,ýD,ddd„ddþ ddôþÔ,„dddXþ dÈ,,ÈdþÔ,þÔ,Èdddþ þ ôdþÔddddÈdÈþÔ,ÈdddþÔddd °° #7#3#3#3#3#3!5!#53#53#53dddÈddÈÈÈdd,ÈÈüàþÔ,ÈddÈdd,ÈÈÈèüèüèüèüèûPdd[[[[[ ¦°  "'463&"26ôªþ0ýV C;S;;S;°ýVþ0ªÛ Í;;T;; Ò° ! "'463!"/ &"26ôªþ0ýV ªþ08¨ýDþÓ;S;;S;°ýVþ0ªÛ ýVþ08ª¼Í;;T;;d°°&!2&54&#!"3!2#!"&54?6,9K@  ýD@ ¼  ü® ‹°Kü|@ ¶ @  üJ  Ï‹ÈÿÿL° !2 46ú þ>þ>°û‚¼þC°°EU!"3!26?6'.#"#!"&/.+";26=463!2;2654&!"3!26/.6þD N9  >SV– N ýÚ N –  –  î  – þ±þ & X &° þÓl l- þp œ œ  ýv  –  –  Š ý¨ ˜  ˜ d°L!)13232#!"&546;>35"264$2"&4ôÈ8]4$–);;)ü);;)– '3]ÈdþϾ‡‡¾‡þïV<?!©(% þ_5,Rþy:" *2þ“8 ¬T¢¯ü2*BBW-Þ‘Y". BB % îýZÉdð°'2;#!5>54.'52%32654.+32654&+ñ50;*7Xml0þ ); !×9uc>--þ‹Ni*S>vØPR}^Ÿ3:R.CuN7Y3(;  G)IsC3[:+ 1aJ);4ü®ePZÈo°!56764.'&'5mSB„ ,Jþ º­  °95(ü¹1(aaR@ 9ÿµ°%/#4.+!52>5#"#!#3'3#72 &È2þp"È& 2èû›KK}}KK}„ ü®dd R ,Èüà§§ §!ÿµ°%/#4.+!52>5#"#!5!'7!5L2 &È2þp"È& 2èC§üà§§ „ ývdd Š ,û‚}KK}}KK°L/?!2#!"&=46!2#!"&=46!2#!"&=46!2#!"&=462Xý¨èü üàLû´LddþÔddþÔddþÔdd°L/?!2#!"&=46!2#!"&=46!2#!"&=46!2#!"&=46ú¼ýD³Lû´Ý¼ýD³Lû´LddþÔddþÔddþÔdd°L/?5463!2#!"&5463!2#!"&5463!2#!"&5463!2#!"&ôXý¨þpèüÈ üàþÔLû´¶ddþéddþéddþédd°L/?!2#!"&=46!2#!"&=46!2#!"&=46!2#!"&=462Lû´Lû´Lû´Lû´LddþÔddþÔddþÔdd°L/?O_o32+"&=46)2#!"&=4632+"&=46)2#!"&=4632+"&=46)2#!"&=4632+"&=46)2#!"&=462ddA üàþéddA üàþéddA üàþéddA üàLddddþÔddddþÔddddþÔddddÿœ°L#*:J!#;2+"&=46!2#!"&=465#535!2#!"&=46!2#!"&=46dd–ddôþ þú§ÈÈÂ,þÔXý¨LddþÔddú}KdK¯ddþÔddL#*:J32+"&=46#3!2#!"&=463#'7!2#!"&=46!2#!"&=462ddgddü®ôþ /Èȧ§ûæ,þÔXý¨Lddû´LþÔddÈdK}}¯ddþÔddȰè!2#!"&546 Kî,,ý,,„þÔ,è,ýv,,Š,ýD,,°L!2#!"&5467'2"&4,Xû¨J÷*J%ìüÒpNNpNLü ôdý¶ƒœ>þàôtNoOOoÛ6‘2.'&54>"264ˆuÆsFE²66 !^Xm)!fh˜H„uX£yH¸¸™™2".4>"ãêÖ›[[›ÖêÖ›[[›KtÅrrÅ™[›ÖêÖ›[[›ÖêÖ›üoVrÅèÅruß5.54>6?6&'.'&76#&*IOWN>%3Vp}?T›|J$?LWPI¼)(!1 )  Huwsu‡EG€^F&:c—YE‡vsxvýþ!K‚:%A'# " A)Y¶ Ël */7>%!2!"3!26=7#!"&546 7èl lý27»þ);;)ô);È»£þp¥¹¹8þ–¡7cõs* sÈ »;)þ );;)¶Èþ´¥¹¹¥¥¹þ×þ–2ªc“L6!#"3!2657#!"&546&'5&>75>^i¤4Ã);;)ô);ȹ¥þp¥¹¹Sþ¬ 9dTX .9I@F* L’6;)þ );;)™g¥¹¹¥¥¹þÓþÎ Ë 0!;bA4Ò L5!2!"3!26=7#!"&546 62"/&4?622^^ ªÈ þø Ȫ þüþø ¯È þø ȯ –þø È­ þüþ÷ ­È þø È­   ­È È„L326'+"&546údÐþ0dLþJÅüÅþJè°L#3266''+"&5462dÐÐþ0þ0dLþJÅþJÅüÅþJÅþJè°3''&4766°þ0þìÐüÅþJà*àþJÅÈ36 &546ó.üÒ2þ  þ èÈd„è32+"&546!32+"&546úÈÈ¥ÈÈèüà üà ÈdLè#!"&5463!2Lüà ¶üà 346&5&546ôìþþ0d¶þ *þ ¶þ;èÿþ³O#72#"&5&5&5464646ddþ1þ2ÒÒNüµþ: µþ9 è þ>¶ þ=¶,èL32+"&5&54646Rddþ0ÐLü¶þ;èþ;¶dȰH  #!"&762!2#!"&=46®õ ûî õ*ý÷èü9ýäýHddˆÿüuJ  uþ `ÅýØ(„þŸþŸÆ(&;ÿü(J ' 7(ýÙÆaþŸÆ#ýÙÆaaÆ™™32".4>#"#";;26=326=4&+54&ãêÖ›[[›ÖêÖ›[[›}d––d––™[›ÖêÖ›[[›ÖêÖ›º–d––d–™™2".4>!"3!26=4&ãêÖ›[[›ÖêÖ›[[›Eþ ô™[›ÖêÖ›[[›ÖêÖ›þ~dd™™32".4>"'&"2?2?64/764/ãêÖ›[[›ÖêÖ›[[›å xx  xx  xx  xx ™[›ÖêÖ›[[›ÖêÖ›­ xx  xx  xx  xx  ™™$2".4>'&"2764/&"ãêÖ›[[›ÖêÖ›[[›T‹òw‹™[›ÖêÖ›[[›ÖêÖ›þ1U‹ñw‹™™;K2".4>";7>32";2>54.#";26=4&ãêÖ›[[›ÖêÖ›[[›?2".4>#";26=4&#";#"3!26=4&+4&ãêÖ›[[›ÖêÖ›[[›––  –  ú  KK  ^  K™[›ÖêÖ›[[›ÖêÖ›V –  – þÔ 2 È 2  2  °°/_3232++"&=.'#"&=46;>7546+"&=32+546;2>7#"&=46;. – g—  —g – g—  —g¹ – Df¨  ¨fD – Df¨  ¨f° —g – g—  —g – g— þͨ  ¨fD – Df¨  ¨fD – Df™™?2".4>"2>4&"/"/&4?'&4?62762ãêÖ›[[›ÖêÖ›[[›¿èÅrrÅèÅrrš@||@||@||@||™[›ÖêÖ›[[›ÖêÖ›;rÅèÅrrÅèÅZ@||@||@||@||™™02".4>"2>4&"/&4?62762ãêÖ›[[›ÖêÖ›[[›¿èÅrrÅèÅrrƒjþÀÊjOÅ™[›ÖêÖ›[[›ÖêÖ›;rÅèÅrrÅèÅ}jþ¿ËjOÅ™™!2".4>"&32>54ãêÖ›[[›ÖêÖ›[[›KtÅrAKiõý¸hstÅr™[›ÖêÖ›[[›ÖêÖ›;rÅtxiKAÐý¸>rÅtsS°ù6!2#!'&4' &ýÚýöF« þÝÈþÝ « &S™ù &5!"&=463!46 ýöýÚ&ñþU & þU #È# ·]™ #!+"&5!"&762ª« þÝÈþÝ « &‰ýöýÚ& ·]°32!2"'&63!46&È# þU & þU #°ýÚýö &·™] &5>746 ýö^°¥$,[‡Ç~UþU & þU #$DuMi±qF °°+!2/"/&4?'&6!"&546762R,^ùjù^þ!þÔ^ùjù^°þÔ^ùjù^ûP,^ùjù^IIgg+#!"&546762!2/"/&4?'&6öjù^þÔ^ùý ,^ùjù^`jù^,^ùýñþÔ^ùjù^™™/2".4>#";2676&#";26=4&ãêÖ›[[›ÖêÖ›[[›³Ð:#6#:1–  – ™[›ÖêÖ›[[›ÖêÖ›ºþÒ.þ  –  – °°IUaho276?67632;2+"!#!54&+"&=46;2654?67>;26/.'&;26!"&5)#! Ä &Ä0  =  2 þpÈþp 2  =  ¦ Û 3þ5±3 ç þ‰ X þ‰° v  v !{,  2  ¯,þÔ¯  2 0€y¢  • ª  ür wþ‰  ¯¦+I6.'&&&547>7>'.>7>&67>7>7>-Bla‹bŽD8=3™*U  :1'Ra\‡{À%&¢=>8\tYR-!Šq[Fak[)¦²þÝÈ•X1 ™"@&J<7_…?3J5%#/D &/q!!6ROg58<'([@1%@_U2]rÏO.>7'&767>.'&'.'&>77>.'&>' '8GB    `ŠH  >JS>H7 '+" NA 5M[`/Pg!;('2"&"IbYÏC€e\D9$ 886#1%)*ƒ‘§—J7gG:    8G\au9hªoK$œ]54<&"&5476&2>76&'&6?6&'&'.¤{nO9:On{¢{nO:9On{°ø°FZ  2Z_ƒˆƒ_Z2  Zýÿ# %8-#,- "F-I\b\I*I\b\I--I\b\I*I\b\IÜ9>|°°|;7Es1$F^D10E^E$1u$/D0 "%,IÿÜÔ°';L!#7.54>327377>76&'&%7.5476&6?'&'.P”[©vY,9On{R=A ”&/l‰'Pj˜R.Mv&  6ýQFZ  *HLh5)k|# %8- ,- "xatzbI\b\I-yþRµUÖ4Zrnc­1ˆ?1FrEs1þ­þ»1) ùþù]@ €€ @]ù )1ES>L°'+/37;?CGKOSW[_c3232!546;546;2!546#!"&5353353353353353533533533533535335335335335Rd2û´2dôüddddddddddü|dddddddddü|ddddddddd°2––222þpýîÈddddddddddÈddddddddddÈddddddddddw—%7&=#!"&=46;3546'#"&=463!&=#'73546oùùŸý¨þÝÑXñý©zÑ#ùùñµzŸæ*æ–ý¨dX–þ˜zdþMæ*æ–µz–°L!2#!#"&546dè);;)ý¬þÐd);;L;)ý¨);þÔ,;)X);dL° ?32!546!32!546".5!2>&54=–ÈþÔÑÈþÔ(LfœÀœfL(, '6B6'°úúúúþpþÔ)IjV\>((>\VjI),ú +'%! !%'*úÿÿÔL 'LÆþŸþŸÅ'›ÇaþŸÇ'îMÜ 7 MýÚýÙÆaaýÙ'ÇþŸaÿQd_è)!232"/&6;!%+!!"&5#"&?62”ê–æ*æ–þƒþæ–×ý–æ*èýÙùù‘¸ùþpÈ&ùž°032!2#!!2+"&=!"&=#"&/#"&468^&€d,!ý‡02*þÔ*É6°¢%þ%+È*2222 Á*°L !53463!2!!°ûPÈ;),);ýD°ûPèdd);;)ÈüàÜL 3463!2!!ÈÈÈ;),*:ô,þÔûP, þpX);;)ÈdýD¼Ek¯+32"/&6;#"&?62{æ––æ*æ––æ* ùý§ùùYùD¯k&=!/&4?6!546¨ùùý¨ùùX`å)å —— å)å •• °° !.#!"!"3!26=4&53353‘¬$ý`$¬-ü);;)è);;þ«dddÜ-(ýd;)d);;)d);Èddddÿœd°L #12"&54%##"+"&'=454>;%".=4>7i**dý]&/T7 È£ü" Lü®Rü™ÈþìQú úþÔú )2( Jf°,53232#"./.46;7>7'&6327"&)^Sz?vdjŸO9t\U>/ v?zS$2451 7F8°%Mþ¹­)(  ()­GM~ û¾1==œœ7'''7'7'7'77 àNê´´êNà-››-àNê´´êNà-››²Nà-››-àNê´´êNà-››-àNê´´d°°!-=32!2+"&/#"&54?>335!7532+"&546Š2(<H(<î,úF=-7‘` 1d–dˆÖúþ>2ývdd°Q,–}Q,d-þ¨!2$'$ÄÆ(dÔÕþ‰dw}á¯þÔþ ô°L 0<32#!+"&/&546;632+"&546!#35'!5Xú,î<(þ¸<(21 `‘7-=|ýédd_ˆd–d22ÂúL!þ¨-d,Qv–,Q(ÆÄ$'$ddþ ôdþ‰ÕÔ¯á}wdO7G%6!2+#!"&5467!>;26&#!*.'&?'32+"&546dkn  T.TlnTjƒþª¦:d%ƒËþ8   ’VýOddiæp &yLNþ­(¢  % Hþ YS(22·Säþ ôÿœd°O6F#!"&'#"&463!'&6?6*#!32!7%32+"&546Ûn ¬þªƒjUmlT.U  nJ’   þ%Ý‚&jþªPddOæ ýó ¢(SNLy& p®·d(þ­Y÷ìäþ ôaL7G2#!"&/&?>454&/!7%.!2#!"&=46ÞNS(¢ ýó% æp &yÆ22·Sì÷Yþ­(–ôþ nTjƒþª¦kn  T.TÖËþ8   ’Vþ­d%ƒý ddÿýè-I!26=4&#!""&5&/&7>3!2766=467%'^ôþ NLy& pæ  ¢(ý‰ìS·22(SYLddüæjTnlT.T  nk ¦þªÏþ­V’   þ8˃%dšš%2".4>%&!"3!7%64âìÖ›[[›ÖìÖ›[[›†þíþí  š[›ÖìÖ›[[›ÖìÖ›þ9ß ‰ – ‰ ß &šš%2".4> 6=!26=4&#!54&âìÖ›[[›ÖìÖ›[[›%þí  þíš[›ÖìÖ›[[›ÖìÖ›èß & ß ‰ – ‰ šš%2".4>&";;265326âìÖ›[[›ÖìÖ›[[›Kß & ß ‰ – ‰ š[›ÖìÖ›[[›ÖìÖ›þ@þíþí  šš%2".4>#"#"276&+4&âìÖ›[[›ÖìÖ›[[›—– ‰ ß & ß ‰š[›ÖìÖ›[[›ÖìÖ›» þíþí ˜˜–¦2".4>%&277>7.'.'"'&65.'6.'&767>'&>7>7&72267.'4>&'?6.'.'>72>äèÕ›\\›ÕèÕ›\\›d+: =?1 " "/ ?9 #hu!$ 0 E.(,3)  (     *!A 7 ,8 !?*  ˜\›ÕèÕ›\\›ÕèÕ›  ' "r"v G  .&* r$>   #1    %  *  '"  $  g2( % ¯…67'"/&47&6ô¤Žþý‘ûPM<†;ý¬+oX"O…\eŠè~Y‡+" ý¬n+WeÉ`°¬#'7;!2#!"&=46#3!2#!"&=46!!!2#!"&=46!!dè);;)ü);;ÈÈüè);;)ü);;þ ôüè);;)ü);;þÔ,¬;)d);;)d);ddÈ;)d);;)d);ddÈ;)d);;)d);dddL° !2#!"&46!–„ü|;Èþ¢„°**ýDþÔÈôôd°°%32!2!5#!463!54635#!"&=ôÈ);,);þ Èþ ;),;)Èô;)ü);°;)d;)þpdd);d);dddýDÈ);;)Ȱ°+AW!2"/&546)2/"/&4?'&6#!"&54676276#!"&?'&4?622,^ÇjÇ^5,^ÇjÇ^þ/jÇ^þÔ^ÇË^þÔ^Çj°^ÇjÇ^,þÔ^ÇjÇ^ý&jÇ^,^ÇÎ^þÔ^Çj¨¨#;CK2".4>"2>4&$2"&4$2#"'"&546?&542"&4$2"&4ÛòÝŸ__ŸÝòÝ ^^ Æà¿oo¿à¿ooþ-- - L- 73H3)z þ‡- - - - ¨_ŸÝòÝ ^^ ÝòÝŸWo¿à¿oo¿à¿ -!!- -! ‘$33$ 1~¤ - - - -ÿØZ¹¼[%676&'&#"3276'.#"&477>32#"&'&6767632'."Õ[v_"A0?! þˆ-  Y7J3$$ þ«)G"#A.,= # (wn‹kV8@Fv"0DÿG([kPHNg8Bþ*­Ö[eb›2!þ‰5(7>B3$$' þ®)M"#!7)/c# *xn‰fL@9N¾DÿH7!$†W]µBþ$&dX¯DD>.54>"".#"2>767>54&‰0{xuX6Cy„¨>>§…xC8Zvxy#!?2-*!')-?"CoA23:+1! "3)@ +)?jµDH-Sv@9y€²UU²€y9@vS-H-&65&&56&oM8J41<*.0(@  )*D*2Om9ÿòw¾.2&/7'/&477"/&4?«»BB8"._÷þ{ÔiBBi BBþåBºBBB7._÷…¾BB^*k"5._øþ{ÔjBºBþFi BºBþåBBB»B77/_ø…Èè°2#!"&54>!"264ªšd:;)ý¨);XþÿV==V=°.2üG);;)¹3-ªýD¼ý=V==V°° "/''!'&462†*$þéÔþÌþèË3Ò, #*¡þæ*#þõþÔÒþÍË4Ô$*' à2@K#.'#5&'.'3'.54>75>4.¼&ER<,Ÿ 3'@"‹ª MOW(kVMbO/9X6FpH*Mþ6&+ÐþÊ  4C4%df”­J2#4.#"3#>36327#".'>7>'#53&'.>761T™^™'<;%T)ñÅ-6"b Œ"S5268 jt&'V7  0 $ݦ -$a­P‹N(?",9J0* d2‚>2 "“" ‘  7Gd/9+DAL!Xÿÿ—°32"/&6;3+##"&?62–æ*æ–Èæ–È–æ*,úú„ùü|„ùÿÿè°%#5##!32"/&6;3353!57#5!èddd,ý¨–æ*æ–È‘dcÈÈþÔÈÈ,¼ddôü|úú„dÈÈýúd–údÿÿè°!%32"/&6;33!57#5!#5##!35–æ*æ–ÈXÈÈþÔÈÈ,ddd,Çd,úú„–úd–údûPddôdÈÈÿÿL°32"/&6;3##53#5#!35–æ*æ–ÈXddÈddÈ,Çd,úú„þ dûPddÈÈÿÿL°32"/&6;3#5#!35##53–æ*æ–ȼdÈ,ÇdddÈ,úú„þ ddÈÈû´dÿÿ°°32"/&6;3#53!5!!5!!5!–æ*æ–ÈôÈÈdþÔ,dþpdþ ô,úú„ÈÈþ Èþ Èþ Èÿÿ°°32"/&6;3!5!!5!!5!#53–æ*æ–È þ ôdþpdþÔ,dÈÈ,úú„ÈÈþ Èþ Èþ ÈLL!2#!"&546!"3!2654&^¢¼»£þp¥¹¹gþ );;)ô);;L»£þp¥¹¹¥¥¹È;)þ );;)ô);LL+!2#!"&546!"3!2654&&546^¥¹¹¥þp£»¼dþ );;)ô);;þoýýL¹¥þp¥¹¹¥£»È;)þ );;)ô);‚¾ $ ¾  LL+!2#!"&546!"3!2654&!2"/&6^£»¹¥þp¥¹¹gþ );;)ô);;þ ¾ $ ¾ L¼¢þp¥¹¹¥£»È;)þ );;)ô);ÈýýLL+!2#!"&546!"3!2654&#!"&?62^¥¹¹¥þp£»¹gþ );;)ô);;þû¾ þp ¾ $L¹¥þp£»¼¢¥¹È;)þ );;)ô);ÏýýL5!2#!"&=463!2654&#!"&=46&=#"&=46;546&¥¹¹¥þpÂ);;)þ>¿Dþ¼úúL¹¥þp¥¹d;)ô);déþä&þä –È– Ùמ#%2"+'&7>?!"'&766763 ˜,þ÷þó  P''þÒ K » ž  þS#þÊþÅ  ånnV/ÓþL5!2#!"3!2#!"&546&=#"&=46;546^þ>);;)Âþp¥¹¹ñDþ¼úúLd;)þ );d¹¥¥¹éþä&þä –È– °°1!2/"/&47'&6#"3!26=7#!"&5463!îmþÈ)8mþïœ);;)ô);È»£þp¥¹¹¥,°þpmþÈ)8mþÔ;)þ );;)”ÈþÖ¥¹¹¥¥¹¢¢#2".4>"2>4&2"&4áîÙ]]ÙîÙ]]ÃæÂqqÂæÂqqþ{ rr r¢]ÙîÙ]]ÙîÙGqÂæÂqqÂæÂsr rr L°#3232"'&6;46!2!54635ÂÈõ þ' þ… úþ…èû´gd°þ¢þVª^ü|úúd22L¬# ++"&=#"&7>!2!54635Gz ô"Èú 'ýùèû´gdžþM úú!¯üúúd22LK" 62"'&4?62!2!54635Œq‹ýóþÜ‹Ôèû´gdÓq‹ýó#‹ýÒúúd22L› #'762'&476#"&?'7!2!54635‡Ž*MÔMÒý«КÔþ=èû´gdÿŽMÔL*šÒý©ЛÔý:úúd22L°#'/'7'&6"/&4?!2!54635^WЛԛÒÃL*ŽMþúèû´gd°ý«КԚÒýPMŽ*MþXúúd22ÿì°¯% ! °þþÆþq¬ý3«gþq§üùæ¹dL°+!#"&546;!3#53L–ýD–úôdÈddèü®þpèþÔ,ÈÈEݰ/'&"!#"&546;!3#53"/&4?6262LþÕ_  •þÈ–úôdÈdd°jþ\ÊjO)è•þÕ_ “þpèþÔ,ÈÈýÎjþ[ËjO) °>'.!#"&546;!3#53"/"/&4?'&4?62762Lg†%þöþ·–úôdÈddöFƒƒF)ƒƒ)FƒƒF)ƒƒ)èþóg†þöþpèþÔ,ÈÈýŒF)ƒƒ)FƒƒF)ƒƒ)Fƒƒ—°/!"!#"&546;!3#533232"/&6;546Lþ¢þ –úôdÈdd–d–æ*æ–èþÔ–þpèþÔ,ÈÈý¨úææú—°/'&"!#"&546;!3#53++"&=#"&?62L¥*þùþn–úôdÈddëæ–d–æ*èþp¥þ÷þpèþÔ,ÈÈý…åúúåȰL !2!546#!"&5!52LûP“û´dL––þÔýÚ&þÔÈÈ}­—-1;&=!5!546#"&=46;#5376!!/&4#5;2+§øøþpý/22Èddþ‚÷þp÷ddd33æ*æ–È–þ…dÈÈýËæ–È–æ*yÈdd°°Q%6+"&5.546%2+"&5.54>323<>3234>^%È"%þá È"  d d 1tû®5gD‘ þ>?1) þA¿..@  þ¢^  þ¢^ d°L3"!5265!3!52>54&/5!"!4°"2þpKþ Kþp"2KôKL8 üˆ88 %Šþv% 88 x88 %þvŠ% 8LL  $(4!2#5'!7!!2#!"&546!55%!5#!!'!73£wiþÙÈþpdwþ%,);;)þÔ);;),¼þpü,¼þ‰dþ‰dÈiè–bbÈdÈ;)þ );;)ô);dÈÈþ÷…£…ÆÈÈføddÈŸŸ&767>".'.7¢.‹wfüw3À£ .1LOefx;JwF2 ï¢Â1vŽüevˆ/¢ 5Cc;J™|sU@°L#A2/.=& &=>2#!"&=46754>ü¸¦ud?, ÊþÂÊ 1;ftÊpR&mû´m&L!((" È""’’""È '$+ þä 2þÑ2ÔÔ2/2 !°° '!'3353353!2+!7#"&46!2!546LÈý¨ÈÈÈÈÈÈü®¼ ‰üJ‰ ³LûP¼ÈÈôÈÈÈÈüà*dd*þÔ22d°L #"!4&#"!4&!46;2¼d);,;gd);,;ýþÔ;)d);L;)üè);þÔ;)ýD¼);üà);;)ÿœ°L%)!2#!"&546!#3!535#!#33ȼ|°°|ýD|°°„þ ÈÈþÔÈÈ,dÈÈddL°|þ |°°|ô|°ÈýD¼ÈdþÔdd,dþÔdôdþÔ,ÿœ°L%)!2#!"&546!#5##3353#33ȼ|°°|ýD|°°„þ dddddddÈÈddL°|þ |°°|ô|°ÈýD¼ý¨ÈÈôÈÈdþÔdôdþÔ,ÿœ°L#!2#!"&546!#3!!#3!!ȼ|°°|ýD|°°„þ ÈÈþÔ,ÈÈþÔ,L°|þ |°°|ô|°ÈýD¼ÈþÔdôdþÔdôÿœ°L!2#!"&546!- ȼ|°°|ýD|°°„þ þÔ,þÔL°|þ |°°|ô|°ÈýD¼þ ––––,ÿœ°L )!2#!"&546!!!#";32654&#ȼ|°°|ýD|°°„dýD¼d‚&96)‚þ ‚)69&L°|þ |°°|ô|°ÈýD¼ý¨ôdVAAT,þÔTAAVÿœ°L%)!2#!"&546!#3!535#!##53#53ȼ|°°|ýD|°°„þ ÈÈþÔÈÈ,ddÈÈddL°|þ |°°|ô|°ÈýD¼ÈdþÔdd,þ dþ dÿœ°L#'!2#!"&546!3!3##5335#53ȼ|°°|ýD|°°„ýDÈþÔdXddÈý¨d,ddL°|þ |°°|ô|°ÈýD¼Èþpôþ dÈÈÈþÔdÿœ°L"&!2#!"&546!#575#5!##53#53ȼ|°°|ýD|°°„þ ÇdÇÈ,ddÈÇddL°|þ |°°|ô|°ÈýD¼þpÈ2È–dþ dþ d §§%2".4>"2>4&!!!'57!àðÛž^^žÛðÛž^^žÅäÂqqÂäÂqqlþÔ,þÔdd,§^žÛðÛž^^žÛðÛžLqÂäÂqqÂäÂÐÈddÈd §§'+2".4>"2>4&#'##!35àðÛž^^žÛðÛž^^žÅäÂqqÂäÂqql2ddd–d,Èȧ^žÛðÛž^^žÛðÛžLqÂäÂqqÂäÂÐd2d2dddddÿòÿÂA 62632+54&#!"#"&5467&54>3232"/&6;46÷nµ,,.xªªx€þÔÞPpVAbªz– ‰ ß & ß ‰Awa­ñ­úúsOEkdªbý³ þíôô ÿòÿœÃA32632&"#"&5467&54>++"&5#"&76762ön¶,+.yªxZþ† % þƒ OqVAb©æß ‰ – ‰ ÇAwa­xc¤hþ“sOEkd©cý’äþí  ÌdLm%5!33 33!#"!54&#¼þòªþòªþÔþÔªþòªþò2dd,,Mþ³þÔþÔd22y7›/2#"'2!54635#"&547.546324&546X^“Y{;2 iJ7-þÔ-7Ji/9iJ£›qYƒZ=gJiû22ûiJX5Jit£'‰œ*BJb{"&'&7>2"3276767>/&'&"327>7>/&'&&"267"327>76&/&"327>76&/&òoOOoSÙÜÙSoOOoSÙÜÙþ=y±" $GF`   Pu "Q9   ùcŒccŒcVQ:   Pu "GF`   y±" $òoþÕþÕoSWWSo++oSWW"±y  `FG # ‘uP  :Q # úccŒcc:Q # uP  $`FG # "±y  dè° "!#5!!463!#53'353!"&5+¼,´þ¬þ„ ?,Èd¢ÔÔ¢d´þu „ à þ„ÈÈó þÔÈüàÔÔÈþ  ‹Èà dè° !! 463!#5##5#7!"&=)+5¼,þ¢ýÚ ?,È>¢d¢Ôªþ | › ýø^ýÚG þÔÈü|ÈÈÔþd 77 P°ô#3!#732!!34>3!!Š¢ddþÔ¢ÔýÈ!,ý¨Èd!sððüà,ô Èd,ÔÔ+$dþ¢Â$+þpþpôLL293232#!"&=46;54652#!"'74633!265#535Šd2þÔ2s);;)ý¨öþº;)X>,>Xý´ÔÈÈL2dd2ú–;)üà);öFD);–>XXýæÔ¢d¢d¼L6=3232#!"&=46;54652#3#!"&54633!265#535Âd2þÔ2s);ÈÈ!ý¨);;)X>,>XœÔÈÈL2dd2ú–;)þ þÔ$+;) );–>XXýæÔ¢d¢ÿ¢Ô  #!"&762#";2676&35’} ,û, }@DÐ:#6#:àÈ­û°&77&P'þLþÒ.þ dd LL/?O_o32+"&=4632+"&=46!32+"&=4632+"&=46!32+"&=46!32+"&=4632+"&=46!32+"&=46!32+"&=46©ú  ú  ú  ú šú  ú üêú  ú šú  ú šú  ú üêú  ú šú  ú šú  ú L –  – þÔ –  –  –  – þÔ –  –  –  –  –  – þÔ –  –  –  –  –  – °)33#!2!&/&63!5#5353!2+!7#"&46!2!546¼dd^>1B)(üü()B1>^ddÈþ>¼ ‰üJŠ ³LûP°ÈdO7„S33S„7OdÈdü|*dd*þÔ22°+52#4!!2!'&63!&54!2+!%5#"&46!2!5460P9Â<:H)"¯ýZ²" )H¯¼–üJ–³LûP;))%&!‘‘!&þ•*ÈÈÈÈ*ý¨22°$.2"&432!65463!2+!7#"&46!2!546 –jj–j·."+'þ¼'+#þͼ ŠüJ‰ ³LûPj–jj–þë9:LkkL:9þr*dd*þÔ22°,62"&5477'632!65463!2+!7#"&46!2!546X/[3oœo"o£"."+'þ¼'+#þͼ ŠüJ‰ ³LûPk‹6NooN>Qo£þ 9:LkkL:9þr*dd*þÔ22°",!!.54>7!2+!7#"&46!2!546X,þÔ%??Mýî<=BmJþ¢¼ ŠüJ‰ ³LûP°¡‹9fQ?HS½TT¡vKü~*dd*þÔ22Èè)2!546754!2#3#3#3#!"&546/R;.6þp6.d6\¬ÈÈÈÈÈuSþpSuu;)N\6226\N)þG6.dddddSuuSSudÿÿLL/3!2#!"&546!2#!"/!"&4?!"&=46!'–„ü|¶  þåà % XýôW & àþß ªdDdLþ ôýD 2 à % XX % à 2 ddd°L#-7!2#4&+"#4&+"#546!2!46+"&=!+"&=È Sud;)ú);d;)ú);duè);ûP;ñdèdLuSÈ);;));;)ÈSuþ ;)þÔ,);þ 2222©¬  !&4762 !2!546ઃþýû 'Yþ¬V/þ«¢ ü|ýUYƒY(þnþª0Uü22!°/.#!"3!26=326!546;546;33232!½'þp'½q*}¨ý­20È/2‡úþ––ýŒ22,þÔ2°° "!#!5463!#5!#!"&5463!#5„, þ‰þÔ w,Èý¨, ýv  w,È ýÁ O,T þÔÈþ ýÁ  ¶ þÔÈÿœdGFV32676'&7>++"&?+"'+"&?&/.=46;67'&6;6#";26=4&äÃKŽjI C   )V=>8'"d 1*Ã) "dT,Ÿ| -oËtEú  ú GAkŠI ! "% ,=?W7|&êF@Je5&2WO_e_ 2  2 ÿœÿæ~ $4<Rb%6%32!2&'&#!"&=46#";2654&'&"2647>?&/&6%?6'.'.§. ‹ü+jCHf7ý" *:þÔ>XX¹P*† €@--@-þ˜ -?0 !3P/|)‚( )f!% = „÷ &* xÈ"6Ô2&„CX>È>X¬83 DÉ-@--@þÛ‚ # ³=I+E( /—/}X&+ 5!H d9°Q`o322#+"&=#+"&=#"&=46;#"&=46;546;23546!2>574.#!2>574.#q– Oh ..40:*"6-@# – d – ¯  KK  ¯ – d×)  )þùk)  )° m!mJ.M-(2N-;]<* K  KK  K – X – K  KK þÔÈ "þpÈ "°®),!2#!"&'.546"!7.#Ô Vz$RýÄR‚(z Œ}VG+œ0œ )IU!îzVþ`3·BBWwvXZÅ3 Vz™&--% óó,(1#þÂÈ„32#!"&546+"&=Û–g¬T)þ>)T¬H6–6¬gþ )TT)ôg¬üá66áÈ„33#!"&546+"&=Û`³–T)þ>)T¬H6–6–³þB)TT)ôg¬üá66á %'5754&>?' %5%ý‚þ†Nd––d/“‚\þ¢þ¢^^ÿþåª<à–Ç”•È–ú  (Aýb¦¦“¥¥dô° 2"&4$2"&4$2"&4¼|XX|Xè|XX|Xè|XX|X X|XX|XX|XX|XX|XX|¼L2"&42"&42"&4è|XX|XX|XX|XX|XX|XLX|XX|þÈX|XX|þÈX|XX|ddLL/!2#!"&=46!2#!"&=46!2#!"&=46}¶  üJ  ¶  üJ  ¶  üJ L –  – þp –  – þp –  – °°/3!2#!"&546!"3!2654&!2#!"&546!5^ô¢¼»£þ ¥¹¹Ëý¨);;)X);;ý±ôþ G°»£þ ¥¹¹¥ô¥¹È;)ý¨);;)X);dþÔ,dÈÈdd°L;!2+32+32+32#!"&46;5#"&46;5#"&46;5#"&46–è222222ü222222L*È*È*È**È*È*È*,è£ *.62"&%#462"&%#46"&=32ŠW??WW??þù|°|°¼°|°ýÀ|°|°¼°|°°*(£C²²BB²²þÀ°|°||°|°þÔ°|°||°|°þÓŽÿµÈ”B76+2+"47&"+".543#"&'&676/!'.6éE*  '?)’¸ T ¸Ž0I' *L #3¶{¶,# nþÙ  6F82 þà*5#"#!#4.+3#525#"#5!°2 &È2þp"È& 2èýD d È2d ô„ ü®dd R ,ý þW 22© –L® 05"'./#!5"&?!##!"&=463!2èþßEþÔ  1;E%= !'þì†y±üè,2 " ëý# 22+.°¦"A2‡Vþªýãdd°°GJ!2#!"&546#"3!26=4&#"'&?!#"3!26=4&'"'&'#&#2Lû´FF þÕ&  7 ? 9   9 þàÅg°û´LR ý  2 2 £™ 2 2 $ì þ°°#'!5!!2#!"&546)2#!"&546!°ûP°û‚þpmþpG,LdÈü|„þpdþÔ,°°#'!2#!"&546!2#!"&546!!5!2þpmþpG,ÈûP°°ü|„þ þpdþÔ,ý¨dd°è'+!235463!23##!"&=##!"&546!2dddþpdþpŸ,èþ¢––d––þ¢ þÔþÔ,°°'3#3!2#!"&546!!2#!"&546ddd–þpG,þ¢„ü|°dþpdþÔ,þ þpdL°'+32+!2#!"&5463!5#"&546;53!X––Âü|^––dÈ,LþpdþpddÈþÔ,°°'!#3!2#!"&546!!2#!"&546°ddývþpG,ü®„ü|°dþpdþÔ,þ þp,0o€ #"&54632aþî5þèþ*A2„~ 6'&4Oî**þ{î)ü)î*2A~„ !2"'&6dè)þ*þ„*þî*2,~o #!"&762{î)ü)î*aþ**î°( 5-5!5!¼ýLþc¨üà å¶þ½ÝÁÁÝûØÈd°° 1#3!35#5!34>;!5".5323!°ÈÈþÔÈÈ,ûP2 &d2"d& 2üà„dd,ddþ  ýÚdd & ,Lè%1#4.+!52>5#"#!#3!35#5! 2 &d2þp"d& 2 ,ÈÈþÔÈÈ,¼ ýÚdd & ,üàdd,ddÈfrJ32 +"'&476½  þ0Ð   þ)× J þ0þ0  ×× >fèJ32+"&7 &6S  ×þ)   Ðþ0 J þ)þ)  ÐÐ fÈJr"'&=46 4 þ)þ)  ÐÐw   þ)×   þ0Ðf>Jè ' &=4762j×  þ0þ0  ×áþ)   Ðþ0   ×Ùÿù=°:#463267>"&#""'./.>'&6è°|°þVd&O "(P3G*+*3M, :I G79_7&%*>7F1“ °|°|°ÈÂ5KmCKG\JBktl$#?hI7 ÀÈ„°!2+&5#"&546!5úX–ÿ–«,°þpþ ² ŠdddÈL°!2%!#4675úî'=ýDXýDd d°Q,ü[u¶}ü4ý]ddMoÃ__<õ°Ðvs—Ðvs—ÿQÿœÜÿ…ÿQþÔÜ£¸(°°d°°°pŠŠ±EØØ¢HE°d°{°È°Èô°ÿò°°°ÿð°°° °d°ÿÓ°ÿÓ°°°°°°&°n°°°°d°°d° °d°°ÿœ°d°°°°°°°d°°d°°°°°°°°°d°È°°°5°d°È°ÿµ°!°°°°°°ÿœ°°°°Û°°u°°°° °È°°°È°È°È°°ÿþ°,°d°ˆ°;°°°°°°°°°°°°°·°·°°°I°°°°]°ÿܰÿܰÿŸ°d°°°°d°ÿÿ°°ÿQ°°°°E°°°ÿœ°J°°°°°ÿœ°a°ÿý°°°°°°Ä°dÿØd9È'dÙdddÿœÿœÿœÿœÿœÿœÿœÿœ ÿòÿòdy'dddÿ¢ÈdÿœÿœdÈÈddd,ÿµd,A22È>ffÙÈÈ****²èèNNNNNNNNNNNNNN¤"~†¬äFnŒÄ2b¢Ü\ºrô bÊb¾ 6 „ ¶ Þ ( L ” â 0 Š Ê  X * ^ °h´(¦æTª*v¶ 8|ÀtÐ*Ô<¨Ì6`°þR¦.j–°àþ(h”ÄÚî6h¸ö^´2”âDl”¼æ.vÀbÒ F ¾!2!v!¸"@"–"¸##"#8#z#Â#à$$0$^$–$â%4%`%¼&&~&æ'P'¼'ø(4(p(¬) )Ì*&*J*„+ +z,,h,º,ì--ˆ-ô.(.f.¢.Ø//F/~/²/ø0>0„0Ò11`1®1è2$2^2š2Þ3"3>3h3¶44`4¨4Ò5,5ž5è6>6|6Ü77N7’7Ô88B8†8È9 9J9ˆ9Ì::l:š:Þ; ;Ü<:>Œ>Ô?(?n?ª?ú@H@€@ÆAA~BB¨BîCCBCvC CÊDD`D®DöEZE¶FFtF´FöG6GvG¶GöHH2HNHjH†HÌII8I^I„IªJJ.JR§@.Æ j (| ¤ L² 8þ x6 6® ä ú $ $4 $X È| É0’ ÙÂwww.glyphicons.comCopyright © 2014 by Jan Kovarik. All rights reserved.GLYPHICONS HalflingsRegular1.009;UKWN;GLYPHICONSHalflings-RegularGLYPHICONS Halflings RegularVersion 1.009;PS 001.009;hotconv 1.0.70;makeotf.lib2.5.58329GLYPHICONSHalflings-RegularJan KovarikJan Kovarikwww.glyphicons.comwww.glyphicons.comwww.glyphicons.comWebfont 1.0Wed Oct 29 06:36:07 2014Font Squirrelÿµ2 –     ï !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ     glyph1glyph2uni00A0uni2000uni2001uni2002uni2003uni2004uni2005uni2006uni2007uni2008uni2009uni200Auni202Funi205FEurouni20BDuni231Buni25FCuni2601uni26FAuni2709uni270FuniE001uniE002uniE003uniE005uniE006uniE007uniE008uniE009uniE010uniE011uniE012uniE013uniE014uniE015uniE016uniE017uniE018uniE019uniE020uniE021uniE022uniE023uniE024uniE025uniE026uniE027uniE028uniE029uniE030uniE031uniE032uniE033uniE034uniE035uniE036uniE037uniE038uniE039uniE040uniE041uniE042uniE043uniE044uniE045uniE046uniE047uniE048uniE049uniE050uniE051uniE052uniE053uniE054uniE055uniE056uniE057uniE058uniE059uniE060uniE062uniE063uniE064uniE065uniE066uniE067uniE068uniE069uniE070uniE071uniE072uniE073uniE074uniE075uniE076uniE077uniE078uniE079uniE080uniE081uniE082uniE083uniE084uniE085uniE086uniE087uniE088uniE089uniE090uniE091uniE092uniE093uniE094uniE095uniE096uniE097uniE101uniE102uniE103uniE104uniE105uniE106uniE107uniE108uniE109uniE110uniE111uniE112uniE113uniE114uniE115uniE116uniE117uniE118uniE119uniE120uniE121uniE122uniE123uniE124uniE125uniE126uniE127uniE128uniE129uniE130uniE131uniE132uniE133uniE134uniE135uniE136uniE137uniE138uniE139uniE140uniE141uniE142uniE143uniE144uniE145uniE146uniE148uniE149uniE150uniE151uniE152uniE153uniE154uniE155uniE156uniE157uniE158uniE159uniE160uniE161uniE162uniE163uniE164uniE165uniE166uniE167uniE168uniE169uniE170uniE171uniE172uniE173uniE174uniE175uniE176uniE177uniE178uniE179uniE180uniE181uniE182uniE183uniE184uniE185uniE186uniE187uniE188uniE189uniE190uniE191uniE192uniE193uniE194uniE195uniE197uniE198uniE199uniE200uniE201uniE202uniE203uniE204uniE205uniE206uniE209uniE210uniE211uniE212uniE213uniE214uniE215uniE216uniE218uniE219uniE221uniE223uniE224uniE225uniE226uniE227uniE230uniE231uniE232uniE233uniE234uniE235uniE236uniE237uniE238uniE239uniE240uniE241uniE242uniE243uniE244uniE245uniE246uniE247uniE248uniE249uniE250uniE251uniE252uniE253uniE254uniE255uniE256uniE257uniE258uniE259uniE260uniF8FFu1F511u1F6AATPÃola-0.10.5.nojsmin/olad/www/new/libs/bootstrap/fonts/glyphicons-halflings-regular.woff0000644000175000017500000005560013023355232030565 0ustar wouterwouterwOFF[€±\FFTMXm*—ÜGDEFt DOS/2”E`g¹k‰cmapÜÀrÚ­ãcvt œ(øgasp ÿÿglyf¨M”¤}]ÂoheadQÀ46M/ØhheaQô$ DhmtxROtÒÇ `locaS`'0oû•ÎmaxpUˆ jØnameU¨ž¢³, ›postWH- Ѻ£å5webf[xÃTPÌ=¢ÏÐvuÐvs—xÚc`d``àb `b`d`d’,`HJxÚc`féfœÀÀÊÀÂÌÃt! B3.a0bÚ䥀 ‰êîÇàÀ ðÿ?óÿ@u" Õ@aF$% Œ1– xÚí”?hSAÇ—¤iSÄÆþ‰mß½44±­Ð,qÊPKƒ qÒ ÒXE]²(2 ‡.¥Ô©ƒ]´‚ "EœD· ­¥¹ßi]DÔ¡ZJõù½\µº8ùà“Ïï½wïî›w¿„ˆšˆÈV"±F¦pUÔ¯û×â.Χ(ƒg’KÃ4O n«;âN¸‹îR{¼g`'!ÛÉP²MùUHEÕ J«¬Ê«‚*ª²ªªYq”9Ícœå<¹ÌUžá9Ô!ÑQÓIÖY×…-Ïó°¢KCõ•è+ Õ¤ÂÊU)•Q9¬4©Jª¢¦Yp˜]Nq†Ç9Ç.q…§yVV ën¬×)Ñ9»’÷Ê[õÎ{“ª¥öºv¿V¬å×›Ö¾¬ö­FWb++{Ý>·×¸a|ã€ü*·ägùQ¾•òм,Kò‚<'ÏÊÓò¤W@õExÌ¢¾DÄÈÃ&ÃUØd¸#› ËÈÀ&à x õMx˜<·aäa“çŒ,l2<€‘M†Ç02°Éð6óΠ^†‘…çP¿$Ò6{¸‡,´#›ÆžÐ{ MÎwpÌBïá8H¢þ#³6™7adÖ&'~‰95r 3wÁ"Ð[žEt’ØÜW‡:ýÓ­:$"ô™>2Íÿcÿ ò5*ß.ýlŸôÿäN þ/öÿøþhþ‹±Á]GtýéTèßßÑ(øÿÿxÚŽ |Õµ0>wÖm#Y¶e[’%YÞ-YR'rö„ÄYÈj¶°D% ,@ØBØKZjHÙÚ¤@b¥¥¤-…RôÊë+¥nûhK›~¯åË룼–¦¥$Öä;çÎhµèëÿýþ^fîܹsï¹çnçœ{ι Ë´0 ¹Œkb8Fd:Ÿ%L×”Ã"Ïü1þ¬AøÕ”à AæY£Œ>,ÈØ”Ã㎀#œp„ZÈ4õØŸþÄ5maßd“e²ü ?ÈœyÇ=¤øI:C‰Ç “DÜãõ(nI¤xˆL ‘.1¢!„P'™JD‰t‘Hj€@L4’ì…P†ô“h' )ÈbÒ)vHŽX,fù1Ñc\'²âcGÍÖÀ±„u˜>ëŒñ1Ù ~Âtüà?ññ„éø!x¡øÁT_qâ?qB‡ÛÐF‚‘¤#ŒL%½©DÀÑ›"¯ä?Y­øýŠºÇ¯ÀƒºÈj??8>NÑSkem„²¦AY³µ²Db¡4 ÙJ)¤•;•@¹j“ÅP$ ˜ï'qh®8`›ë;aŒêXÍÃ6CùFâ*„dËYýcá±Ú"ÔŒ‚ù„Ïù£Ûø'?hÆL¬Vã—ŒÖ,½>c‘eË3eV¹Òh† =Cû‘Àš†éÇ~äõxC½\((qb@ ¸4ð‰x†K&h×Î ¥©4\2ºÇ±6N1|-Ô;­Ïëj›ï–É YuÔ@†ájêî›Ñ«xú¦õ†ži¸äЧþmKó ëÛÙDøEöw¦q3ÿÌ·.»¼cAw@¶4t.Žgãñìükg´Ér°{~ÛÓWl~¬{ÿÖlW2»êöð} Ã27Ð6a2Ì\€6o”z@³$´ñ¡ÞëHÄSÉÞHˆ «g®›Ñí±bõtÏX7ó0KštÔÞc1Á,«Õ7—Bò oLëè˜ÆÔ6Ä·6[,–æÖ%ñiáZ ¿‡,’l>T†pòK³œSGg¬\> ñ#»øAö#3Œ«ØEµŽy‚kÂî6v®ìÚçè…Áºç†;u3Ó!ZIÎ8ì˜M†k?³8¶C˜£Wq{`ìC*‰Ðh>HÜ1¿_söÙkâŠìh)œ›ž®ojªOO'» !~dXñgÏûB(ô…ó†ýÊ0< kOYxÊe§¬©±Æ§Ä­5k¦ —=d ã²ðÓϧ> íü+ütÆCç-o Ǫ†„/äÃõ_koïܶÿ¶¼sñÕ+f°ÿÎOßz±tpÛu7-™}…dõíþ9Å sàˆ©e Œ³\9.H4’!0¥S\ ʱk2™ï"?ip7œ\2z§ÙÔÔlÞ°Ñt=¹î…Wùç\!ûKyOXimUÂì¾nov›ì ÛÇ6²:½èå 2Æ óLZkAýAÍ^âqCæ™Þ” &PæˆïaFÆê¥Iª0Üã>þ&ïù…Q #F£Qý»Ñlæ> A³·q*˜O‚á­ýãÏÿ‹ÑȦæ_@27¦ÌlÄ,¨‚sþø‰Ñè¾fÈ ¾6âp7üÜ©?úÿMþ›Œ‰±1vˆA˜Ü2‰¦]$j"‚‹;‘vÛlk~va0¿ûgì¥j£úÜzþ›¶ÝRD:ÿg©×濱cë6’ÅÅywú%ôgâ(þƒØ#'´ÎuBµò#ì=ù_@?ƒ>ÆFØýVbŒ0žaá!¬aL4tXv¼¡ü:ÅFööh÷²9‹ïj^µxÞŒü¾¡ézÐÏ}´WnŽ}7}¶×»j“¯ÆÎšÎïi½H©­¿º¶ÆÁÞi¥ýÅtêïüKüSŒŸ‰aÍXEôºEºbbBQ1ØÉöf”t‘x†ôF騆 ·-"dqA÷ׯ\ê·~F`³»è6²iä•+À ÿÔ¢Û^ȲÂ}שï׆k&»ÝĹ¾»íÈà<- \èœ;Äâg1>¨w†0Ü0ßvòÉ^x ìÝÝ7lÛ<”šyÝÎ}™ÌS·o›9éÜ-Û®ã¾6kžÐ±lË´¾ën¹ùðЇo¾åº¾i[–uó—§~¬æoà`jàÁ•Š{i×\C4,"iW8’JoñVò„bp¨ûwˆ²Cýªºß!‹;Ô'7×D.v¹ÔÇÖÔ n‹õoZ-n²ë¤ÕÁ°eùÏP‚òŠio4Š~LYä/zmþw_ÿò¾ØìgþϽŸþý§RÞÏ"tÞ Ó&NoN€¥)4ÆÉM ³CÛG2«‰\j²Ê8d-É@>#ÛOt^¶Àì5¼+x͘e.^á]ƒ×¼à²ÎÛG 8›^æ ômŒ÷(ÓÆt1 ÷s™Ìbf³J›°ßÒ —%‘Œ‘ â<‰¬4ŽÞHâø”ÝÅ@ešê÷8CÈÔòŠ,»5<Â(—åk²c5Y®I¿þ¶ìÍØ—âùAøú]|Åךål6+›Õ=øHVãcb´KÕ‹B´6ßi4• #´‹_Û©|&ó>NvQŠk#®pW•=ä¿uº7”ÛHɰR$ ç÷î ³[5ì‹™ ™ ÌÍÌg¡ ­µé%ð1Ïä9}¼°ÐûÉÇþúÏ&@$&¸¨ÿ¹÷Œ¡l¬”ð=Ó1RIñò}9æØ#ÎÏ‚«zû??1z&®ôı_aÚùc|PŒI[íÝ:uÐ; ¯þäÇl¿Ñ->k4ŽýæGõ£ñYÑm|Zôwà }û“ÑHnÑR=-B¾ë™õü ~åm¼§‰.Ù± .ÀÃõ¦Mz^,—»ë0%£ñ°Ê8®‰Eý«G¬Ä**|ÿsg|oÔò±ŠÀ¹zOýÿ¿Ö¬0s–¾zâÚé.¬ãWN¶^± ‹„yHk<v3t{8-Ù|Ã' ø«eêøa~ÖìÅH94²Èx¼¢×AÅ-³@üy bT4@0ìb#]DŒDÓÑ“½lj€DSio:AgÐàöÄS½ìP z:„;¦¶-á|yH"r ·¤{ÒB{\ˆ´5RLi‡6öAƒáAÖæã–tM¾]èèÛßtÓá›øaøRò±KºûàËC¤­!Ø1ô´CÞígCÞ샂ð +ù¸³1EG·!ÒÚ€ÝXzû––®î¾éÙ›nz–µvÜ@±x™ôíô›Ê-#i^ Ïxñ*$)®ÎÀWü’ã¤=ÖO\fùäó€[WŒ´“öþX~V¬?«ÿîþÐ `Lei¬::v4Öß$?‹=Rþó˜•a#ÿc¤÷]8YåÝFJâ™b&'{%LCìEÀÏ¢­‰Í ·Cf]Ç^$Šù/ÍùïÒfߪÞM;ÀÚ;«óÉœ… ¥°Ê„6ù°CXÕV¸¥À§ð#êÆX~ FðƒÚ<ç :þvC¿¯cºµyBpLvŠ£¬Ó1ðÐF”v#ß9† /êö8VFë©01Óà­_Kôí?Êæx>£}úÔ#€G7ÔÑ‚\WŒp!.@ü¸îü»±bùwÉ¡+{ÜoªÕ­#»ÔPÃQÒ®nÄ«66 cZ­çD‰¡¥â’Â(. °Ÿºuï;n‹M}ÑÁ‹Åý?»œ‚ªžävÊtžÉxíêF»ì²{É+È–²ù`¢ ×=Ÿ×" rPÏ€l˜DîV̶ߤ¿±™•»?ãíZ@ë¢Hÿä°…]º[˜¥3Àö5€Ì%O ¨¼ê)Þ\^„Ñå Z;ú˜>F÷ºtf›-IºzÓ® €çŒyúu1Üu™o<å:Éoa:uqß‚Õwòykk ⋜‹}0?jv²«X+ÀèæÝ}V»›­ïäG$sþÚŸº ?2ò6ùª¯†ý´YÊI5c‘$óCfýb!¯X¤*|FÏÔÖ^º$Üpº7ïpäí55§ÅÝß¶6[¿mµàjg¹¨°®¢l>*öñ KO& ±‰8÷Ü¢:ǰ…o¿êÖkõ¢‡Kåm~™o¾Sä-*4¥E¼}P/ûÚÍ%  k:¡e×"å1AéJˆ–èÂâCAX𴹋Š8= LƒÅ¢>°Ü±a¦åÿ—v{ä|K.3 ÆÛ×:\B¬xǤüwðºå˜bÉeb€Ï>Ö1Û¿v‰HÅ?äf¹›58Ôó †þ%Í6›$ɲÜ'p¢L^H¯âXÎbpI’VqnÖæ¿ÞéAé8¥åK”g'i‚!Uz†áSEšªI×ßûõÞ5Ù÷ýN=ñ»ûhpÍÞVÜ?¡›(ìEÅ ÿàš½¿¾V¥³rûÍ?Þ´éÇ7ž®ýõÞüËV£Ú‹‰É¿âµ.´ãOø¹Ü;°÷•¤ Ñp¤ 4žNéRZm.–OÔø> Mu¾L'¬Éj5©ªâÓ`;´Mt‹AQܶM„›ïôyëVí™ë<`‘’ $m)Þyš¤Ú³ÑX„™ÛDaî:Ìáݪšq»1JöFq³15¤ä-Þl¸è\ƒ…3‰~X¡æ-2pFÿDðe‰éÖ/ñf!¯è2®½iç:à“=Ãhýà{ü%Ü{t…^€¶ *ÄPˆˆ…ðBͽ]îÎYÓD3ÀØjd úÓÖÔ*æw|âê¼GLϽ}ùË‘k7¸Ã‡Ï=0×ä6„o¢z*­ž¶âzo‚ð1~Jçw0ý0SÏÔe“Pw%¤”#@BJB À  %Ùø+„’ ü'¸½œÀ;¤%!&©§ )ðHÈq î7fÉqöH.§Žæ²ìÐÉç!ØEÚÇŽf³ì‘,ü9Õšƒ$9” æH{~iž€Û ŸZ³ð)O|‚!"‡üD.K‰ÒQ a2Õ %©£š2WŒ¥É‚\ëŽ{é*™õB{7â,˜9.ø'ew U^¨ƒW¯&Þ$»r9¼µçrcGõBôçwl¬¦òÿä’lö<üÑú¾™Ê·îSQÂã‚…ˆhì! i¿Ñ¨vãîÎJ :³Y?üñ#ù•¸_Óm4²ûq[ð‡ýýËûû }×,¼EóõA{VåПºˆ‰œ®ÎP|žDöåg©?9M©ÅÇId?{¤)®ûÊ/ÂðÐ /\[ ˆ«JùÒƒ¹ë[àœf4G>ËÁÌÁQ€K ó^  Œm×â¹ †¦›O—Çù -7wê]ËÌê„ô<ÝU3jÆ,ÄÉäˆ:“¿Y“µqÅ~ 0³™/¥m‘¬Åµ@CŠ—CÜF€q<·é’y¤xËhúŒõÄ\ôЦ0=—RgYìd‘(õ¼(_ð2’¸ŒØÉÊa³‡_Ä{p·M …T*¡‹0žU­”T¶˜Ù!³if$ÔŸÔ(Wâ¤q¥RC:P a3=b²Ñ rK1'-»{ Íö•HèʽHý1Êá'`Ùkϯex¢$’¼.¹hŽ{܆`¤Fé¤ z›EÃ0®øc5xfMÑĆä¾}çß¾Sýï•S¦¬œÂÂKÅ]Nëf'ÛpPιS§`BmmHÒv9Ä4ሄ^ìm D $¡˜Š,€'Ü„ „ pìWÉ­îgØdV/L¶;–ª×MZL­ñõó“ê­µ¢H>{€,ßë·ºÂΘ±ªã×÷Ÿ쬷ΘQSo ÛlÜûùsÉ¿hýùÿ?A¿ˆ2qªÓÐ`ÀÝ5 ƒ€œZ€&*ê“X1L5:Ù6¢ë´öÏ‚+ÙÝßêO]ue·jõƒÅ¨%?ïÛ¼&ÓØÑaW?{ï¢Ë­Ë2[þ}ÉÒW?ÎÞJÄbòÒΙ›¥kÏ-\»Þb7‰sIì¬kf&ΛÜfê¹x~¬¿·nì™O-9÷VÚçÎ ”~cˆW"È—y)b\)„2MrW±Ëfˆ;MíóUë7¥ƒ'[¯ÍÀô¹’-c/ö´.¾Ø¾”›æ¨uÙMèþlŸ&øš.Óõ9ÔÛ) GêÑÚ!Ã!W* ¸60CŠÑ„#”Üq£ÅçŠÔørqŸOÝÈKÁZOÎWqù,Æ8Ì/XpãðÏíTšÉÈ‘±g<>¤)˜‰[J8£o` ;úÔS\ÓSЧ¾Æö“Àá“%š†h~ðÌpÌ|J˾F~Kì=E0Nî¸QƒXßÇ©ÞÇ*çþÑç8;D7öQñÑ1ªµQCÃ% *E‚yëy}ƒ¡ UG?>üI`æ>Æê÷'Ê6<ž+ƒíÓÄÿ3IVògÕÏ®yOŽû•ªQ$WBv®ÛH vî…¢è[ýÏ 2ÿ+ý£ Ê'ÿø6N¸ß†<úÿúžÛÇîÉ•¶¦— ‡2”ÿSñ娚9ÿ³X†1 \•┣ûý­Ìdf>ÃBŽ~¶²ÊÕÍ-ˆ”t>¦W]Ùìp©PrœîZ[±²'žÊåÈ+¤ÆŒâµl†9]ï8qã‚ì‚C§é!Œ¶' ë@AA¯OuÿÐ¨äª !?M\…JMÍ­ÍfÇž)«ß•Ë=õÔÉw?A•N>Ï–ƒžË¼}újQ<ÇpÇ ^Îñò(»€}¿±½½1ï„+¿“2Çàq F²÷4R¾„´iHÄ—îITër8ÒÐß^§™Úù!gm­óä>¸Îÿ´Î'á÷ÆÞÚ¸hÑÆEü`­sÌŠo¹ãÎÚl¾ñ…Û!õ(9~í¢ ‹oÐàþ%#ð)þ~ƃúj$Þ@€Õ”ˆLp½GåOa{é®Íß¿fÎìé”)°zèªØ”Y×<þõ¯ïØñõüýÛ~°ùšÏ^õŸcàÒËš·sóÐÞëæ½ºã·Þú²ýÂÝ´N•RUâЛÕRÔT”Y%8ÛÀ­¤òKÌs3Ãq¿d]^©QTb' œÄzx¯)îH´“FÒ©P„mUÎZ¼jQ&œX¹ñÆåoŸß<0¸jÉYG¼±ŽÔzê]ЇþÙ$8cÖÚ&ÖhäyŸÝ¼õšÍwΞ{Ëê9^˜¼æÁsfß¹åšm[våÕÀ‚“ÃÓ£!É(ZíAsÈÛ§ÇÎyÁBмÀü•Œú8RiÔ£B­g6ˆ{ËUm¦’tyW!bšpÇ®d nÅ/yÌ‚áʼ@vÅÓ/©»Ô%Çcý¹—öªŸxñEn’:üå4YÃýõ²¼,yZ-ækr¶—úcH&öÇ^È©ÏCº'È®'^T®Ç÷“5ºœîóÐÇê˜r)(Š(IèÒJ™U׌&#€ÝŒ! +YM.ÿJï«EX^|‚ÂÂÞL–«w@´Ú¾ìò¡ZsgßYÓæ´ºˆ…ü\ªÑîµxêÔŸ ²Á¿xÓ„µyºý—LïõCyo™…’<ñQÊO$)÷W6¥m%݆®r݆Õdõ”™‡Õ½Õð’{¡üO‰bþpÿ»AE܀ʌÞg ÐÎÎý²ˆ¾¤§iò~ºA¤¼¢™òßO"mo*î!ƒÓ[TÀœŠòm¬dHÑT1Ó$… ÉPÔ4^ÌûsfcA3·ß,ˆêXA­òPŽêbâksîYà†‹ šyHˆhýPäÍËâ+b‚W=}¥Óû;¿¾‚µ¨"Z&x<SySVYíÖ&=ªþ4Ÿ¼&‘è1Jä5u~è,Ó¿¤zïeù–g^QB\/¡PÊ„%+p‚re|Pn¥ ¤T’†cZ>?¢çï–eòžV"_[‘çQ©/…5Yãá|бàqI£ö/\§Ó9ö–Óçããªdi°ÀEBh$ªåvÒõ ±€…Ó wOL¤ …êÐúfpa ¦,?HógHùf2¬ˆµRbî…²L v >ÞUÀSo™–°^1/,šˆÄ“¢vc«°Yò GmôÀŨÔ~¸Amêzª Ë?Ç/¦’ÿ4ÔÎ0‰‡yj̸pák²î¶2«öH «ÆeE€RßbéÅÏ/"M 7ò5u²lÂ[ŸdrC‘&YÍÜ&I `!>pû˜;¦õåJ-bàÂ--.à´VäMÚÅ4>©¼Fj¿–/î5ÀºÎσ¶¯£²ƒ¢Þt5}Â>Cþ*›<'ß÷˜dµæ?,cÂø¾üïdGfëåü¼2Ò0wã6óó˜òL¬h"ÜfõKä¢×òÿζp;ÕÇÕǿ϶PÕd¨cÿ©1¾EO‹šÑi¾%ÿö÷ÉŘ(DCäâïW¬·‰ªõVé2š„I)ˆTöiÃM›êµøFTÛz¡0ëÁªµù›U¯õ Sµþ7V¯ÿ mBW6;›nYZU¢zSÏTg>(“h……îF"âÞ½Të½·‹¤ñR]çßûLÛ¶™|¦ûLx‡[Õs,'NU|®€¯¹Eà<ñ4)«R–‹Š pß*ЏvU#¤gÄÃ*ñg˜ò·jÉ™*=~܃¨ìA‰SÜýÄ“ÎÍîA J‚Hwä3@Nur®bw™°È€ÊŒxÀ}[ƒ`ð7º½’‹ø¤Z§ËÊ›tPlh Õ³¦L.)NU‚}¿¥¡kqÜ'ØÝvÅéõˆFQr×·úŒ{ˤóS]óZëLùÿ(×@ã*úSfÂ^‚–+uöPe_k#Žñ•.É8éÎÉ‚%Õ ¯,…ª@•›£TK£¤Ñ…º§Ÿ t`‘ß‘ˆXÔAD;¦‚b†¤|pßAºâ7ð}qÒ¿é2 @Yû`Ý~¥îÁµ¶ŠˆiÔ¬K½û0jŸ÷ÒYÕ( žøÛR„úÃÓ~^ˆ¨Ò§8ƒ>…è=ãF"šËœA[å‹ÓDqûvQœCîŠXõ|Zõ‹sO÷…þ \ä/Íf.ÁÙÕä³F;ÌæÿkáPñ•ìb‡d³z7ÔeͶ-6‹b²y¶ØÌbÀaWjnh7YôLáFû!½4ƒÀwßâssFCºnh–Ì_0óû…’> á±M½Z²« °ò‡€ïnC휌 ¬ÄÃ*#5/OöUÑN\(3oÄ@…[7`‹Mg8xÏßg¬e;f\yñ½—|fÖ¤©Þ‘¨Û]ëi5®¨q5q&Ö>¹'ºôâóï¼áå°ÑßÙ353éükÏYê­‘œß=WŸ7çâ+΋yxþIÎe<¬¾“ûÂPÃh±X aëêv׸‚Ó"ÆùŠcJcú›oHÌO†Cu]³L5‘®«†ÔÒÅk““¦ðÑ–†ó¦õ„§]xóЏæŠ ˜~ÿ#ª;!‘ÞÛ)B58¨/P¬í õõHšÑF#0‰°B(ôÊpì}ÑFstÒÜM|¹ÆlçˆÉ)]tϼ&ƒÝ–™¿,ã™—nt,¶h[ÐäY4ݬ$žwQ×’µ,Ë ž@‹ÑàÆkåš`D”ƒg]rÿ£™·|êüY}ÍVq’wRC*ÔŽ9[o»ÿ©ç§×ÎÜdðX 6Žš&Í=ÿâÍ}—íß°À/*Í\Ë”)³ƒÉ5gOò˜lÓ¦¯¬Ø}ÙÙ1:>OýŠYÇòs(•p6Ÿ‚[‚B/tçˆ*Ì -n:±½ <Цðøè)Èú ¬á+Þ°~q_}ýäÅëoxt>L®¯ïƒV– FßÈßG¼@dÎ9ׯ[<ñs/¼í®Û.<7î±ðÖsó§B²ÉždïB'·wX‚üœŽ³Î¿äü³Zéµ£üáW²ÁÕ—Ù>2²½?í2ȳ¯±÷8›ç¬žÕÓ={õìfgcsC³ÜåœÕmãå –ÛÏrâ¾õe ¾#Œ›‰E>ˆòü45µqo:áJ£Öì¼X«°^ioº“P,x‹µfµ:/y ñ¼¯n9§VóÑ¥S§7=éºòîè’u-í\¸%•KåϦUv¶Î¼,»â³€„íÅêZ=Öv›ûâk¯¿¤NÑ*+_§.ýÚŠŸõÖž»iýšÚƒ=w @¥æl¢m˜röô>ÛO­ÇÊo,VÔ²’×ëÉz &:'ÿ4ðÎ5¨Ó…!êÕ9èpI 0@I[ÍPU""©sÙîInv‡R>ñA¸Ž˜É9tæ$ç¨3/«š³|k£8y´iE û“ßøÝc8óÂE×!Qè\Û‚} %Ašf4ì s*®A8¦‚A³Ø΀Ü>D®=5uw¶Öõúj³ênG z?2”Qª/I=î˜ÛfýHýè÷4Ånºå“]™æ¾€ˆYmðªG"³É2äPEÝH™Íf¹vZnž<š—PiA_Òq/³ŽPÉDÕ¿ð ã¨$$Ž~%NyhrÜOdM\‘-þŒmŸ(ˆä@\³º#½„ÔêÆ¼“ÒNïçJŸOÔåã>a+ÿ µuJ¨*(%¢FP„JÄW””¥Š¦½ø–ßð‘,$)ç÷)åÿ˜ú³’ÿê}×ÿ˜ B\­–àÏ_»ïúÇþ¾w¥Vé] 0†ÑT¥OCÊQ}è¾ë5±ÐÂâ{Ho*ä™;;õ葞ÉrǨâêõMÔcå5­ÜãÑ4S : ´ýMŒ‹îæ›7(kY:멪¸•zÒ`ˆgp ›J†stˉý±v'²¡¦eðÒG^~äÒÁ–içD›»1šš‘Š6ºdA Ø@'N ðŠæ±³Ö­N.Öô?Îf²Â…Ü1˜ób•ŽzJý¡±D ì¥V o@7R@6Š<Àþ%IF©Ø0êmj= [Ž}N‰âÒüÛŠ¤57¹ÿpò©yŒÄv4@<mЭá¿Á9TÅòp?ÚR7úú¥Š0Ò›š´ÚQÏG¸[j„¬ÐÈßÙÍziß÷·b“´ú~ƒð/)wC?â±ï רa¥-/ŠC®n“™û.Ä•ÛH j63¨€’иŠpø‘“KrhëÏÏÂîX–êIçÆŽjß ¿‚o­è1ÁÅ9 ŸfÔ\Ž~Ú:-¦ÔÑ“K 4©±7BYÍö‰Ì†Žy%›DC~e“èmÀÞ@Ñ]Ñúÿ%Àrþ©ÖÙs4T® ™Åâ®ÐóÖG-âUgõ>ÏíûH‚OpVÖBìÂ]ô{9&ÿ^6¹|Ðm’õå _PLLI7Ç’¦iÊ®õé "'T }Æãï? 4»ó¹›…|‡¦[FÇ­útu/Ù_y;Z”¼?Û£H†K®0Wz¤èc#¤ÙÙÐ)€Ž~.rÁŠÄ¥+ÊB‰°Š±&J°“ƒG 0ùË[ýÐäÙü‘.Ρìr·ŸO³kŽÝ;VC•‰ oX¨ úÍöKÛSß³ër¶t‚åí²í„:z‚X\±úxm‹ÛJhÿ™x¸ðÐN÷ÇhÛ5¯ ¥Kè`…;ydp.Ec›4²XžD<-´llµÛip.»^ØâpÕ×: Ùu/î»öü™.«ÅY[ïrl¯_æ4¸šã½ÉkzÎ$~Dq…]7/T_<赈¼¥Þã4K§$ðÆ–˜ÿ ™»ð&w“«öä· †ž©S¡¸7ÿÿµ|K‹^üŠø›Žâ¯7íMsMGýáùçÿ°èhÇÃw”…¹Ã㢴0]?²´˜fjaÍ5aŽi–Цè6C¼2ôno• ¤“Õf ì=ñ–)õd^Ëÿûövï qNcãÔŽ´ûþ‹l=uÙáì]?;¡fâù-EÕ~äìöáÏnÏvøÕ}5¸Ï×%»šë¾÷ýú–ìèOÕ»³dë¿=„Z%v¹Žè ӳРn¯K— u ÐÌ“*J¦„ê#1äh„u1HrìÐ o»ý}ÿ”õõSZâu=¶‹îw§;¦nÏ—UØ ï‚Äãä•ü` FÝçïȶŸ½En?»¥þûß«k&»¢ÍÙl9 Yõúíd«†gAâÃ8NSGáê³ÊDŸ09M‘AK{Þ€K3ÝŠ„­ª[_]’%W4zÖÛˆu9é\~åúåën3ÔÉê~ñÉzir–„ñé Ååô¨“X3kâ`PsÄêøÜÊüâ’nÇåïÚ=mùºÁ]‹ÔƒJËks„ÍóTÓ9d™ÒõeYN`}ž¯/û]U#Æób˜;R̨“ÐÀt,¢ÚlŸh*ö¢×#JB+ (´¡iGx\}~IÖ³F·Ýv@T÷Ëu†ÛÖ­¸êJ¨Ú ±­÷ÌÿœÃ @-Lœ™¨áwäzÃY§îg—”úÓâw‰`wx-ù¿Øö´(dÙ¢]ƒ×ÉÛFÏ3_÷øXcY’mQÔƒçßWæb¤-©ÐF ¡êKõ5Õd-0bƒâ¨çƒ—֨“T+æ‘_ïZ„xÜcËÿÐj*`ûûåˆ}|xâ~¸LÇF*ÚS*oêŸMتêA­Íó–²ýîTž1pÇ7µ1?‹R t>éó»¶R'"ú‹ÀäÆÁEÂyÓ)oƒP7ž”æ‚Å%«ËÀ$rÃvõ¬ QŸ¿û½eE”ÇãØç”+½»nùzlÝåVlÝFrktÉÖ'µ¦'?R®„'ZƒCEÕI§Ky» gaÎö0þ‹ü¡^áê} pE;…õKq{ÒáT/ù?ïi"%íÆÞ1ÎÞ’ÿbñ-ÞÔ¾qÆ›Ì˵ƒÛ+ ¢Š8Æ]ÀÊrI¸Üú”Ú£V•{¬dȪÍœ¹\è•AÍôÓQÐvOÄSÕõ]0.ÛêúN¨ìX9s¹Õv¡b?OE~ÚFPU}ož[YîKårÀéÖðñA¹ÃÌ“U%‡§7D€w ýêöˆqÔ bá/í‘hÈ íáAÙ±‘hPbQØ“JB8ÕI ºä?áI%=ÅX‘tÜO¥;¹(P‘hºLìd£Ñ S •'hÿݱŸ>|þùÿT»‘¬ÜV?Ù,O•Ýç"\`ª7‰ÕãíÁ.‹2ÐçÝ>Îæ¹Dá²Í fÎÖm•g;œ-íö„ÌCŒ'œ¥Öéu¹,»¡¥Î z—A`-ÇÙ¼¼Á$Öx vc“Ãk2·¦[x–p\cÚbüí“l΀ÝihµsµœÙivðaÛÃêM,gĨlñŠÁMžà–zÓܳ›7JvÞÔÙÀË‘V‡RWÏ‹N³•ÝäoÎ4‰(Ú-„µXB^ÒCl&Vnô±nŸ¿¾Án D4[k6ž³†›ìN×&µº}f§“3Y¼QwÐ@$“U$(Ǫo¶:-üZG¼…#&‹Å†/…} –?ÄßN}Æ¥¼‚7íA!M´àühöøW>£æï?iX²pÊýùr›¼A–Ù¡àbþöó?uϱ›Î¹³-hñäØíëå6;»êSÿBõ#/‚µé@Ñ¿J Æéþ !%Q­)”ÀDq:{JI^Þ‘Ë¡õPY7UGçÊ(ÂÀ¼Ÿö¡h³?Hmÿ¬ÈÑŠævREˆíHŽôçÔ=ÜN`P)QœŸ¥Žæ€G9®ÓFM‡ÖSáMG§õ@2¤E‰$Q µ$Çs±~ä’TkNµ"×9®Õ†8ûcêF¤ñ^ê"?+GÙ  ^÷*¦¼gUlFVxªÚU™poC¨°ž.XCƵŠ×µÍ‰×qï‚Kê[¯k[¯ãöK—(lÀ;ö ºÓ¡ínè%^ñRÔj­,$)§ ø·Êì1‹‚n.¿ßG÷:CÐïfŽÓ(ßñ,˜íÐ;š„Ä´©ôR—¿Fëž_~ðÎã^øø;¼ó¥Õ«¿D¾ô;6|/jGGSSG„›G’ӎļD¬ñzbRï¤/X?½ñûŠÃíñUÚÇp14u˜$`¾ß[ßœH47õ7Iò~¥‰~Iÿrêß™sùù#èŸ6ŒÛ+‘h„ºe€Wò6@wK“̸h6, ‡1Cµ"à‡·æ©Ú=­mÎèñe°AòÓóŒâ– =¾àôî@“z—ÜÐÐá² ¦sÒóls³]ô;kklµêÓr¬^"sƒ¡é’Ü>Õ&Õ„¬-[×ß{ÅJiÒ´9[‚ݵ³È©¹-ç]±dÞ¢µ²cÒ µAnµÛ¹ƒägç}ê’‡¼»6hTï–ëüÉ–´?3sÚÝ^k­úŒLêcY ˆ1ëZ²´n[÷¥ƒbÝ´¾E߆ŒçÕ¤Íw¬ºàk3Ôf™•åˆ>† þÿfMäÕD‚è…Õ ¸aåñDðé ~}&ö¬Á@¼£5u gn¨›OÈ¢<¹­'` &bÓ¬¼±-6à÷®;ƒÁX÷"‘d*²a¡wÒüÞY”¦´vÖÔt·L³ð¦Xë¬Ö¸kñUß©ø­ü·aîèÔ=HR_Ã@¦£Ä+j“2—öT*‰Â£è%ìÓ/͸oƤ ¿±Óyá‡ê £—»î›1ƒÔ9/7›  þ~Æ7áýŒ´_“ÛùoÃÓêÖ+‚þ$DüÒ¯sÞIH:çr£ ƒð ¤yiF:Ýå¸ðïäv÷ËýÀ(Œ¿d®O":¦ omØÿÅìdM”8åÒ ;¤žZ9uêÊ©üHCg\›K/*‰ŽýÔ™g*¾-óIèÑö—±¢ˆ_ÁE¢œ‹RqîR'û[¥fõ?GÕU½Ao‘vb A$ÿeõ]¹Õ/‡Ô¿ª£o©?|ƒÔÞQâm–4™G¢Œƒ7ñG™83Ú3+ ¼74‡z*)¡$Ý‹JÀØpDµî“Núj5pÐq¾·“eDf/ÒÎ>ÎÛü‰è´à”%é–Ãg‡Wµø¸{…Uóë:g,ênН¸l²¿µU‘\ŸÏt™'Ö¬ñ%ÒüÑE‚«}àòÍíu¢úC›èꘒÍܻߺp±}UË+^b'‹’¯«o(5gã¼VÃBÕIœ¼äOEüm>·ÑÀ½©þ€5yšzgö†}úÁ¥ÜüA”©P-øP/ú€Þ«ì„ò Õ6Ì)¡x5/t;1šp“1”L º9õAܳ|÷êÝÑ)ýµáåîX]mûókFEéH/ñ4}:¸,oLMªoò®»6]YãMó5¢Ëê0u[›ßyÒ«ˆfVêh¾˜?¸äÞE-A§_iï«ßÝj²ñ Ô. 6|Þå5’`#ÏÕZ-÷svÁfq˜ÓŸ›íês·Íš>¢ãÚwêÿ î7C—å{ A“ú…ŠÒÖ]B¾ëÕîz,i÷H'dù„äávÚ?’`E‡• üx,‡öm±¸z‡`ÍF[ïê2aõv‰hp™%(ÔÌ’öü¾Ê‚ÉýÙ5Ô¦;GÚÑŽh”í¥²³¹\Þy";|"«ÙÊ–©rx‚zËsèP‰HCT×v¨P$…éõly}‡iyhvMŽCù…r)Ý#Ãx®›¿-Ü.(ót%fu»ôÊ€(Û…eÁ•UU–oâ² ¥p´ÔqeÑˡ啗¥sòy¸iº X–æk¥`É>£X¯@2Pø¯. ¨2ÍŒ>«n„|‘Ê,/4—£Ôþ}Âò  ®ð?Aí¸&ÍJŸ†Åær§+­ðÃÉñCV“]{ŽèìZÍ0- úùA=–ä Fø®$ë+”Óöñ%U¸Zy¢­ÂÞ—Ž°Ù²RÕ ·Bƒº)¿÷¥ŠâwT8úÁ(áaÙûRÁΣ*-Àª—ÆÙs€r5v êÿ!^tZ:/ÇK,'±ÂêF  9€»=ãÚæGˆ<§¸CíÑu“"$º-¾î²F÷óS2ç(óÉF 0Q©Ü+XšðwÈ,»]=b÷h[qžB‹QI’ þ§ú;)"ÁÅŒšÓ9ÜÒ2ãšô6Ãr?çÓ}lŠV Ç=b¸[˜µ£j¯¢4€Az”ó™Œ÷KÚkQ?TÿÂ[%“É$°K¢Qõ-¯Ñl_@l/ &;ÿ˜Éì°¨ËDrª?P_d£E1ý~ýz—â^Iº~b°÷§ÔrÜè¼e¡uмf¹­P•/ÍÕº#Ü Eÿ+šS\ìG‡-ØR4¨« ‘S®óÖS®óVä¿‘; ÎÈ*`ßG¸é*5'Çäûd™Lº ˜¯ÿ~¤ÚÆê à…5¯”FšÒÆhb`  ½êœú³Â4€ý[b$~¿Gç£NÏAX$òÛ÷ß~ô‚ }[»‘Wß}åê«_Á‹z×6múÒ&~Oñ%Þæj/árÍ&|_SˆÆÒyã<ç-â*LÏ›ø«Û,©·JQ›z»Í¤œð«·£ÙÂÉçÑ|’V|GVW~öËÍz ·ý ê¨ àH ¯œ†ó³¨EÉ ¤º²Yîn‘¢çH4ûr7P?99­Îæß¡|O-µ·5³Š ²%ã4µ dzêO/4ùL_Pså’TÔ>¿LQ›ÄD(ú ˜ÚôùJ8òÿFµÏ+)jCb ›MuØ2Xc8$ñt°}œ&§@€«Qr¼-ÚÜÖ¤þÎU_o6ÇÕËq7õP1êŽË¤+ÎÛ¾rc6ªI ë\ ê(*v´2¼4Uc(Aü Ì£9ú3öŒæ]Çz÷Øü»­;0'¡=äÛÑ*,e5Õ6ª»VÔa,ÌqhÌ*ôë²P@wȬ°G²¸/ÓOÖj÷|ÌFImÇ #Pzë;J¨wÊŽ}ž < ‘ú ŸÀz TŽút‡ˆ~£`ÂȱGP%;? ®5(Þ(u¨”# ”ÇÈvÕŠIÈñí#9,?Gù¡¬b4K]ýQgÔŸ]ÒE[à phʯ§‡ÛG›¡à+` ÜÄĘp ?Å@á>!Ú}" ÍÒ½¸Êr=ÔCÀD5ï 62¾¦ZYêèå?à× ³ÖiðËA¨‹ T(øE U•Ju³;"}©ØÕº#–ê‹Lˆc¨äÊéÓ—£VäòéÓWþOû›&ÙCIÔ™úÛÇu8*烞QæçaðQ^*z(¨L­|JÓ‡½^Žf©p1¿ûõ„0À4~œCˆ³Ux¨Î*ršV²*N9Ï€„׳¯Pðú„Å«sñÜp¶ˆœ_LŒ‰ŠŠòÍá3ÙZ"}ˆ&ÓrôO¿|lõêÇ~©ÝÈk¿C¾/Wj><ËüSÅxÔÀåMêbS“¯–—úg(]½J(Z#Ÿ†x©\$OC6¿8-àf:{êƒSҳ蚨oý4:œÓËÜ)Ž¥ËWb¼"uÅiu·hŽŽ~½dãÊéì%û¯¯ÕB±ûóAM sÍâÙWH.gvÿ%ùç4ý–ãvø+¸œ§ð=¿ ðÕSêG‡Ï‹jWHWÀæçu>…–[ÿB{[çuûɶsÕ;la›z›iñÕÝWß­Ô\z½ÆåCðäƒÛÖ|¥ž\f·«Ÿ×te¿º&ÿ¹ß•+Býk«è/t¿ Ï CM„ /@SÃ>Tm ±G`vú`?þª£ôþÙGÆ(Ù,zb" Õçðe¶¸üAÞ×AÞiàÿ»´š7ÐÓéQÁ¨R<Æ"i X ¶:¸IÜ‹(a‡V¾öœúã¦Ëç§;4Réù—ó]}—Ïœì^þá«Ï1ÜvîÔµþÚù—7œÔÊ=Ùpù|§[Jοœeíµ{)­eÜüÝü#Œƒief0ó™KðJâq²"*öF#¬(©¸GjJFhŒ¸‡Xè#ш·âµ£ñÝkš¾—5EÔR¤PÍ΋ㆠ^p C©eoÿêíe…€:•ç¯{6ÈÛ¬Íï5ÔÍs‘ÅÆ™8‹XÏ K6×ðV[ç=çÙ}V+ÿhͧ×ÀßJŒ›lÑâŒZZ›5ÈßW‘‰±”;®þTýé†e«V-Û@ÚH†êIðÙë¬ÎD<Í™[Ç)ÖÍÀßÏÖl^bÃXeòÙNN±„¬"K]£@Œƒ×bŠ©šË?.æH÷H gzXaÆðÐÙ’Aîˆ}MO¦eýXÂüH§Nr ÐóÚŸW¨;ñhtñ»gttOöyu3=–Âü*פîÌåØ¿ C ÂFGsh9JîͽZ°-”k‚’]L-Õ~hÎii¡.ê49ÍQr5¦ñ½I,VÝ“ÿ…^jf”»_}Ô,“í¬Q6?Ì5åÿNVçÁÏÕ ÞžËªYÙœN›å%ezËÜqƨï>ÁZè  “NtñŠÓ1š a Õ%þž=è yÏhÞ™«« H¸Á—ËJZöš?ý h½vrœkÊÁ@åmÍY`®^insðêF\”*ö|Lœz!/?·)(“0 Éâ MS4(šÈ—hðØ{²º™’æñ-î'×hŽæ‰ëoê7ûcCÒžÊ?‹6²âñ’²'|ubˆÕ£@´þÌ!³býÙ¡¡ü»Ðf{tzø…1UÒA?=Œ@œáá t%˜ä•‰ÀÌåiuš“[ NòÈiáD ±ˆGÝT@Š:Ïp<ü(õcÓXéÉÆUm2Úϱ7z›ÚOòíM^öFÏ´YUfwGsüÁ“#‘t:Â/‰ªƒ•¶Îå~±OsÞ]µÇF×ÿÏçÝ‘¯ž(úü(^È‹Á±?Lû$ÀSʽ… WzT>mì'_§‚údŒ®ÐÔç:¥Ä5®Lh;¯H7ÜWgzêgÄZÆÆZb3ê{2d5Jj¦Ä9Þc+ãù‘\vqzç²DbÙÎôb ©Æ¶g ù"l@צpæQB½býÛS Qí>€“+d p²¾î%}¯L!“™ƒ‡òçšcdwHo˜¸Ææ×p€x(Tì¾pÄèxî¿ßp#ê:dvQ qŸdAðQFdÜL³¦K¤mÒPRËí ¤pU?òlÃëÖ ¯ûzg°-ª‰¶…ÔjPÙî©b·ùG×aRõ¿ú&^qÅàä>uÓ8¤•p&ÃӮф ¤`íMGSŸ®¡®óÙܵao°ñã¡ÜWÜ›Z´aâÌٟݰ·V5ŸÊR¿s2NX ÛqGB  ¾O “ÊKÒg éôðÀÀBWþý)Sg\õÙùêžÓ¡läË÷ö]zöÀ<ß²o-_þå- ø±›ÆA£ŸKMqÓ­!´Ã¦Si­gyñüý¿ÄÛ°]Kû;SêÆT'ã©ókPqÉæeêÆe›7cZT{~*‡7‹bê\H…?ðjÙµl3•P œïоwïT2²ðjŠY;Ö)ºl DËueytOTøïÚjö¡üñU¶H­í¨úœXögɬ,õW´ÉÏ¢^ŽÚÂu¶¡![]Øv”Fèç”| ã®QGá¬h`(¨# ƒR¼'5X©D§ÌQ ÊqMË6gûc'býúu³:'—ôÿ™®H( „?¸yÕµ¥ú¶Ë6£~.òe¨¬[n ¸ªŠÿ*€±U«yZsÃt 9ï‹›¸R!GÙý·©ù“MM$ÚxŽz€¬$]êÓ{ÐÃL<ü}ùç4ÞÆàJZÕõê~ÒMVŒÕ•hy× >@u»Êí šå…î+³¿Æèôõ]áß2FqO8jü–Ñ¥°WCÿ»Qqíˤërw®‹.Êìä„«¾Þ¥\õš_´úü§ãôöyš¶\O¿nÔ)IÍKGR§êHÅq”¸ÜIÚÑÅ. d+u@Ï´õÓ ê¾k–ÙŤ}9¥êT«v6ö*x¤g¶e7?—™Ã¬Ô}õS§éÕ-ð íAUÛü‚í OMlJ ÕpÛíժݧüîÕŸYw–Õéhœi6û\fAöZc,·rjFœTå‚ÐMj8kOë«51‹þT»¼ýqW½_ÙnéØ`•7®%³K«èÜéWÜs–d0š‚á:»Ñ`´¶OX•ÞùÒs$ã4¼?:ÿSI1¢¢W-¾Pr}ê²£Š §9õ.Ôû& Pš™^f ³8(ºW¡I¢ÃÛ`¬¢`@5a}ˆzµêiþV ¾p„²PÔ½+:–£d\jÃ"=üa€j£Šð­ä)W§Ô$qö{ÇÚÖÍœ×p)—Vüõ®|£7hj¬ŽÍöâ—³õ»¥Éâ$·Lëè˜Ö¡Ê9›\öúŽÚn[ ±¤k{lG‹‰Ä.m „m~ÇT—ÀºE‹Ûù¡ÑbÈ­¶m¹` »—wònyæP&—:P¯LJØí–YŽúéÀŒÕ_îp™NW¨‰ž›zVÛìS׃]7ÖÕEÚd“%i¸ç™¬|ñ ¾úèÙÌEÔWMÁ“™7râ ÀÞHB¨´Ë6þ`UG¹ZˆæÎ ø9 N2l2ÝÛÉ…HY˜½(šÅ—ÒÔÙiwœ½Ý“[ýÞ`ªcZ¨–R;Yz=TrÒvHþ9ëc. ¡Ö²êGäŠÒº6»*pÕüÎ…'»[â‹:ú/˜ÒªXØ¥œ´CYÑ…Mñ˜ÖtÌÐ-'º]£n,{@üð cø˜Ob¸þæþÂIÑN‡.”xÁN ¹F9ëÊë›Nÿ­Kóß[º£ÞXÓr=ÛôéWÎmó °Ý°Æ¦ØY+¾Ê?sýJõ¢Ä×gÌXµuËPý¹¯%È—V^¿Ûéè[­ù‹ ··ô„ÔWˆ ¯;éúWæ ³xv±iÈ/‡×XS3±åȼ”2¬¤÷Ô©Z¾ÁÛ f×2Ôå/yòÉÏ?ñí»ä8ð®M@ÓQÔÎ*Ë„ÂýÈö¡¡íCäXùk¢÷²?MzTy?±àÕZËÃYu׳)ÿãé]Í•ßô1–-ã—þaÿ7jô‚~”ÍÄá .dãÄá » –Ä'Ó·½¸š§º“VÔøz£tXKþÙ2k̹d?¢§z‚§úz¥´ÙKŒ.º>,¡¸BZ¦¿`q„—'ºk–Hèqy¢û°æ¤5¯¾j>aÇÅÅ\CÙÕ#ÊçH;#pÇø½Ð7lº4¿}” ÖIR¸7Œ„°ÞŠ0§ûœð$âì=«VÁ¿úÑö‘í#ì¸ä_.Ñvª…sð{g>ƒÁh!­îÚA·b¹/p7¼Ðî™=Üz—Á©¾mi”%—ÍŸš3)^Ošj¼<_ãU¶NY63dsIr£™´8E—jñ¬ßý®Uð´„*Ï 33Ï|v ¾ãè;ÔÛOÆéB@ñù,—ü,ŸÑ\cwd}6k.žuØkÌF9þ±'Ìä2Ð6D]e±‘xÜG¾J³K.×½}†ñS«†$ƒ@ t"š;2É©ê¹*¤Ž”ŒÛ4§Ü1_ƒäxõ7³ÕQ§bj´Xˆ£§ß9›„§ÚQõ½;®#Ï{9†Ôe¼I š-ìå¥br B<ÞÖ9òdpzœÜIVªûóÿQ:l„+ëséi Õ#=ÑìT¬ð¬+R˜Ñ(ªâMÞDC$â ¹Êaç̱ êONgÄj1ž9˜¶›ÍÄÜgqXkè„}F«Åèðùd¢¤×ÖÒc¶ŠG“,µæå&—Ó.Øâ˜.^É·wwcƒ>ÀE´_]3ûžUˆ±|ãt{JÕfªçª‚u_ù.º\ÿºþ*êö²W•=ÌÅ}ÔlNçÕo+^®ïßVÌ£îé‘ vØP£>~†‚s¢¦T¶jWz~_¶¤o‡gSÐ}-­üDñTd‚ Ý-TÀAaÈêYfµ²˜Ç3,PATcm²Ú Õ¼4gã¸}‚½•màE$BŽ„w¢Åª8Ü>«¬9–ä‘ì¸JWâ©°O¥õ/9ÿPªJCÉXA{,™@c,tEJ¯ËTÈj½¾9ì•8QÊñ•Óõ&¨ äHŸ þPÁl~K%Æžù1€¾Ñ»¹ ü-èeÈD zxN›»Xuz’Ý.9½ä}‰MÂc&œ:¯ê”Z5¿ãÓ™8·ø% ÕµÕ½øm³˜¼ïomõCBö:ÐäÖá‡l´ï˜8™ÎßÄí¤~óËܦ¢E²¿j•T§ßÁí¤YH˜Yá»vønƒV^IN]]ÂŽåCXkg#Ås cÀSûˆB’$‰Ã=’$ªkø}cG¹&ö÷/¨ßzç»ß}çä¿çÊÆµ_îÑv6<7¸½ý´IVGG™úg*lôŸ\RXS²T‹‹®)ÙšEî¤Ê%Y uôóÁ~Q~>X¤¸ˆÏÐ…±Ö`9ÓW‚“k*‡@_ÕŠpM¸]0¦*ƒ%ãaÀ“3XíŒK¹Mü|ô{†£FÔ”»ƒú‘ ì·¾d7[Õnò¦Õlÿ’ͬÆD‘üÜÌÏ÷@¤Úmõ˜ÈÏñ8‹Ÿ›°e ¯cżô#gH›ÐÄdd@~.ŠjÌlÃlÉ›äeRcxîEÌä(( Íí™Kž™Ïm¼êïGëX”A7¾×Sõ·µ@[lÚ×.%ÈëæÕ£nMDsˆ]n€_Qî·• Ú5Ài?zûÔGüTèG3²¦T@e èi´×,ˆƒ°r¸ O2<°Ðè•éÒl+³À°/,Á–%‰¹­m²à ¼ÓÛšXØn›|–Eš›¶÷]˜Žˆ¢lí™ôœžÆÏ[m<’|#¹z×+„5ˆ¢ 7&\5Sô-˜{þüAEß×^Ù¸ì¬t“Kä ÂËέßçMñ©^rq]‚îFmÞC%2þ„vJÒð)W-Î}OM"`Õ9l²+ì=…%"«çë£ó­Tò˜'8ÂzH3QÒßûÑ©ùYìP~V¶‘زèNiì¼ÍÜ 7ŽÕðÄÛ›¿ ëÎþ?w1ê×xÚc`d```dòÍ?ÌÏoó•AžeP„áBYñtý?ðÿÖ;¬"@.Hc èxÚc`d``ùß &ÿ]a½ÃA‹Š_xÚ}S½JAžÕS<‘`ŒÚÙ‹« ‹€ÚùÂb)6â ˆ>@DÈÄ"èX\o“ !‡­Žßìι{Çé,_¾Ùoçgg“˜gÚ ˜¹#J†VYp>uC4Ó&*Ù<=$Œìð¾g9ÓW@.0Ÿ¢qêò‡ú- õñüêñÛ;Æ:pt"HUåeèܾ5äÕçü Vg(÷[Aãx­9ÏÝ!ÖÞ´÷EMŸêß—ï4þN†&Óž×ðwj³tþ™³ÔžeσèLpŒ>†w‘ï†õ>GàÙpfz`Í|´Þâü^ªaÙżø>äŒÇð¶)Ço© o¥²‚MÜg+RŠm¹RqÑí,÷«‹RJ¹à1—ÔÕX‰TªäN7t‹{I–E—\îFÿë8ãU ºÉÌmbÍù:f—N±&’ýj9ÌYxÚc``ЂÂM /^0úáK˜Ø˜”˜ê˜Ú˜Ö0=avcÎcîa>ÂÂÁbĒIJˆåk ë.¶"¶/ì ìIì§8ä8’8öqšq¶pnã¼Ç¥ÁåÃ5…ë·w÷)ž^-Þ8Þ ||||[ø5ø—ñ?˜ °JPK°Lp›—…PÐa)áá "Z"WDmDWˆžc3KÛ öOÏ~•ý/‡‡cŽLŽuNN+œÞ9K8;9—9/p>å"à’à²Îå›k”ë676··-nßÜÍÜËÜ·¹óó0òðóÈòhó8ã)äiáçÙâ¹Ê‹ÉKÏ+Ÿsª9§@.xÚ­’½NAÇÿw ‘h ‘„Âê /‡"‚TÆDñ#J$Š–ròqr|è!'‰Oá3ØØXøFÁÞ§°0þwY …1Þfg;73;3»Âx†ñE0C€ q=ç®Ëæq£XÇ4î°‹GÅA$ñ©x ×ZBñ8Úƒâ DµwÅ!ò‡âIÌéaÅSä¸âùXñ ¢úw¯°ôÛ.¿0«?ù¾o–ÝN³âغgÚÖÑ@\ÂA´`àžsbˆ“ ük`§¨sÝ¡}›,ì«0©YƒËa Dðä®ÈµÈµMyFËMváYd°ÅS÷±‡í2Œå¢Äé0~™>´/ãŠqJŒžG iòô<ýÒ#cýŒ´0ë·C~G²ÿ²ƒ9ee Kv«¯­Ð²[Ú·{&V(Ó¨1j•1…M‰Zqr7±,gKÜ¥þXåè›­õå0éíò–›ÌÛQY{Ô ªý›MžY˜¹Ð¶z=ÉË×a°:[jEÝ¢Ÿ ¬² BZìZÿ=nôüs¸`Í+oÍýÔÌxÚmÕU”SgFá샧BÝ]óýÉ9Iê$uw÷-J;m©»»Pwwwwwwww˜lîšµ²Þ•‹³ó]<3)e¥®×¿7—Ré^ üÎèVêVê_@÷Ò$zГ^ô¦ÓЗ~ôgÄ`†0mé[¦czf`(3233 ³2³3s2s3ó2ó³ ² ³‹²‹³e‚D…*95ê4X’¥XšeX–åXž†1œ4i±+²+³ «²«³k²k³ë²ë³²³ ›²›³[²[³ Û²Û3’QŒfvd ;1–qŒgg&° »ÒÉnìÎLdOöboöa_öcà@â`áPãpŽàHŽâhŽáXŽãxNàDNâdNa§r§sgrgsçrçsrs —r—sWrWs ×r×s7r7s ·r·swrws÷r÷óòóòóOòOó ÏòÏó/ò/ó ¯ò¯óoòoóïòïóòó ŸòŸó_ò_ó ßòßó?ò?ó ¿ò¿óòóÿf¥Œ,˺eݳYϬWÖ;ë“M“õÍúeý³ÙÀlP68Òs䘉ãGE{R¯Î±£ËåŽò”MåòÔ 7¹·êænáÖܺÛp;Ú›ZíÍ[Ý›Ƶ? ѵ•Öµykx×~yÑj?\3V+wEš×ô¸¦Ç5=ªéQMjzTÓ£šå(»vÂN؉ªk/ì…½°ö’½d/ÙKö’½d/ÙKö’½d¯b¯b¯b¯b¯b¯b¯b¯b¯b¯b¯j¯j¯j¯j¯j¯j¯j¯j¯j¯j/·—ÛËíåör{¹½Ü^n/·—Û+ìv ;…ÂNa§°SØ)ìÔìÔ¼«f¯f¯f¯f¯f¯f¯f¯f¯n¯n¯n¯n¯n¯n¯n¯n¯n¯n¯a¯a¯a¯a¯a¯a¯a¯Ñî…îC÷¡ûhÿQNÞÜ-Ü©ÏÕÝö¡ÿÐè?ôúý‡þCÿ¡ÿÐè?ôúý‡þCÿ¡ÿÐè?ôúý‡þCÿ¡ÿÐè?ôúý‡þCÿ¡ÿÐè?ôú݇îC÷¡ûÐ}è>tº݇îC÷¡ûÐ}öôúý‡þCÿ¡ÿÐè?ôúý‡þCÿ¡ÿÐè?ôúý‡þCÿ¡ÿÐè?ôúý‡þCÿ¡ÿÐè?ôú©îvíNjÿHMÞp“[q«nî®Ïë?é?é?é?é?é?é?é>é>é=é<é<é<é<é<é:é:é:é:é:é:é:U¦>ï÷ë:é:é:é:é:é:é:é:ù=é;é;é;é;é;é;é;é;é;é;é;é;µ}·ê­VÏÎhåS¦èèø·ªÙoTPÃola-0.10.5.nojsmin/olad/www/new/libs/bootstrap/fonts/glyphicons-halflings-regular.woff20000644000175000017500000004315413023355232030650 0ustar wouterwouterwOF2Fl±\F M?FFTM `Œr ‚©$åe6$†t „0 ‡"•Q?webfeŒ5였ó@ Â?þ¾ Úöˆ ¬töÿŸ” †ŒÁ“ÇØÜ,3+2q ËF®YOì&>±é±bÒm¤5ZŽæH$±ªYŠœ½{ìH jd† Õ‰ ü²%÷¹Ù§y"§÷ö×+@¹Œ]½«eŸû{úÒûv Nc‹)»nù“É?~?è¤hòÿž_ç&iÆÊÈÑÁ¤‹?º>üå^K ûv´-cÛ1íô€‰2K áy·õ,'nä«à(ð3EwiàB‚ &©ÿ éÎT´lhØ0MÒØÚÒ†dåYØrñﲬ³ntiÞ]Ýyur•´¼®û™îVXsj¡¢žågMnªÓ™HW•©ÃÔ r2ô>iT`V7¸ÍR(±¨ÉÏàÿ+ o6ó'cÅÈB°æë4ç·Öι݇ƒ‹ã¿š®T ]a[Qd<3wq8,Ž…îrTI¡8áŽ0>E¸?ù*E¨ç—¦•#Ïú7'ìÝý†S ocûÊ·í_‹7&#*Ñ+)½³ Ð+4a°A6¶cŒçy±Ù£†f(bFéæäÿé´$;{ YAÃ1vP-tGøÿŒáÀ±Í"û°•ÛCÂf- W‚÷®šÔ™ÎuKÖ°Kã#­íä¬Ö*K†<Ûü (ÑßëÔ÷×ÿZþ`Ù« åµ[—%êYTЬ{%¯ÉŠ$ˆ­ s{oïíœòˆƒÕ»ïvt"pàœ4`Èêß©ŠÏ¤}o `ã³Ýú'neÜ> äG5szó_Nó ’PKÓ¦vmUÞ É¾{z½ÜòîóÿŸøøŒ‡"3`l ’–W#Ô½^@+,c¹Éko©AOpnuµ§Ôzó–zJ)õÜÎ¥÷˜Û1Ç}ááÿO=Þ­¶€x¾RÆÄ`ÁJ‰`§qƒ¥‚Us/¿+økÒvÇ1xlÝßçjl–Elì\nDŒÈÃÆ¶¯V†±æÿÐjg›{Zdå‰z7 5ÿß!xmÂ5oÂ[½¿uïû&·¯1Ú‚HBkAâìqrêÎRÄ £·°(\ghôÈ7‰ìÒŠy=†HµZóUPhéÐ$8RgÓÄ€zÂgÍ­ÉN:‹à1u¬$Ü…¯¤¡ž>Rý]åú—¦¬"Ÿôf7¼— õK¯^'˜ªë½3“+E/¼Ä^‰YU5]¨NB.ÞÊ‹¥Ò8ßÅ+ÎÍ8ù,|‰{M|ŒAŠåua|Ðaˆ’ìŽÕÞË…Õ% lKG¢Pí,NuæÜÔkþcï8mX@ÚÓdÿ̘?ñüÚó¢çYÓ&Ïþ{êö”ø³ÇÏ?ÛPÜ(®GŠ]¶¿ÏÆä¯äOää·ä×ä—är-¹’\LFÉ9—,&§“yä8r¬û´û3÷ÜŸ¸?p¿ï>ê~Ûýºûsèäÿ‹žÐ¢ÓDǤzó1ú¡?\U5q=­ÙtÑzÔ’†&Znj¢%émM´"}¼‰ÖtkÞDºwh¢-=ÿm¢½Bíéõ76ñô®ƒ&:Ò»Éqt" Ö1:“¬ëЕ¬©u;ô"K_¡/JdÖc0–l²õ0²Å'^B¶ù8VC¶Õzg°²½¬[ ;Êúdì ÙYÖbȃu‡¼©u;œ@ž*}y‰| .©¬'C>\g=ò9àVëů·[o†|gð õ^ ž¶>Šüd¼ 9­ÏÇûäîØÅø” *E|A¥ã*M­[ã[*mOÜßQéz?PénÝ?R)YÁoT&[ÏU*‹•5ÀSÙ MB þì¡¥ð[³ ­„ßoYDh­Õ{ìÑ,}1f?›«“NNœ¢ ]ÔO/^;\ÚÂJÊ ÏBÇEsJrª ÄšõÆ'ò…g/ããÑB%Ÿ¡o Cõêºn•7‹Ü:|õyƒKt²&÷$§Øs¯|¹õwPˆùÄ\i]¾$Z@+Í ¶¶Õ€90x]»r¸­%¾ÈÕ+öRU¬Em‡+ܰª£;w u¬À9/I¼Ô7È7Õ¦¹Qþlu\¦yÐW‹N)ë8‰Ü°vYî*u´m”¡±¿éâ©âºm( fÊE½òÿG8² ¢j#I¬½RŽÌùz #q¸ß·ß „)Y ×$‹ áЛ†c_%¿m-{!0-` ;áå…¬ñhyVõäÁ]Hv! Ïta½\KïÅ¥[Ì1{"çj 6@ì–3T0%¥¿éΘ"ÇÔ™ÆZI†Gä›S“÷‚.³ÄΣpÆÓ¬SÆ1eéûÙ“ÄØ›ù YÁÿv»8d±\±B¡l¡SûþR)ÒÓ†çù¯–®€ {IŠÓ†ôÒ%”¯>û0ÐŽÚ¦³\ð'”cg½2%4 QŽD¡ 0Í’3B²"ÉMŽÕŽ&€ÛŠhIÇÂÚ§ÒRg·ME¤¡©¡¶š I½Î(©ÞÕ5U–D] }ò™bí8$—‡ì8¨>óáX ²h•"lµÎ€âj.%ˆÛ€HHÇ- Iš¦Ý¸#1’C4õÞYÞ7„íî®íYÝ–¡V o>PÊ]¡6¿·˜ö™O4ÿ7f ½~AJdYFÕ€Ê.–ÞoõÃþy) Æ8lÆ ¶22ŽeŠœ¦Ò1H¡[t‰°@!È… 2\€@¸5ÄÙ“Ê%Z×îüÛkÞ’aõ®Ü@ú.`n¨3ÊOFŒ¢R(ó…¥¶÷ÿ½ZkLkF íHWjY I¤ê5×ç*ñ6ÚÎeµSbk.¤¼5F,ì.•N0ßÔ™’¹€|”†V¦€||~Nô‡( 4·ìÚ],ìJp|~ùxeÓÉA¨Ô¡¯5ˆˆ/»Ú»S¤ýäô”Ðvò×Üy?›ù²'_v|rê„ËXÜøîHéQʰµÄ“B@= ÝX¬ßú¬B9Ë4³˜«ÃT©ØB‰B©c ­Á«H‘P£Î+‚ò‰_““ÕYHÙ#¬$ªËÊ` ìFø£ñB;ãµÂ+Û”…BPR°4̼ t­:tõ"ZEºJ^!XÂÇ“à¬q4_dTW(5äÜ€§åÿä¸ÚI±”UŇÒAÍzþ@U6ÿn.WGXýÀÁèHìRKÀÛ&'swM±jŠÊŽ˜‹±<Ÿ”±˜3¦)€–`#F@  F Ô¢àþØvoÍb$x ï+²à¼uû&´}‰|ÊX&[Ùª8F‹-¹E&/>Š/ÑGÅ.aêz^ŠÞ/ƒÔþ})œ²’ó'“x©‘$O=<ÇÂz™¤oä§áA9MØ&ò~î¡™¹3rµ3gŸœ¦'¿8Ò£\°-¶MDzÈè˜økºÍ5†ù±´A ÝÂýªG9©ä|1-Ø! Ç87û[œô¤,mRîu|¦57® =Xþ‘¤,˜aJ§Ù›¸^t´N›4ÓØ\fЄ]AzH^7·ªF•èþ•™„&k"LU>}ì>çrBåX(Û‚ªë‚Tš%¿« Jª¿„­dhKÄ”ó¶P“²KÁTFaA‡3HH†C[r;a›À¶d·™‡•54ÈÌ ‰—lL„kjG{¡ì8Ÿh~ä fR@Ðìü9wàB¨¤àÐ0ë zSõô°âÿ'— a7‚@Ý@N›±ŠÝƹl‘bj3hNî²Xö‹F/Éíe¢s£Ù'úŠDsQ«ñ<þk^Óíò×¼²ýˆZASO¨idºSJãxN4D½³ÀKÓ!´¹Ôù !Ù«v‰¬hA`ÛE–·X•¼Ê- ¢P íÄ:Ÿ‚ÛѤCê:ÂÂWÍzS½sÄdO :¶_¿«ÔË`Š:tÁaηБ ¥†²Íسú¢® ¼IYð4Ç # ø*ÒÍ+<êqn°oÔ¸u UÌcwwóx$dµ³ðÆ¿}ÏûÖÁ94Ìýšíü9p¬*T:ú%GQæ…^aŸ‹‡äÝË'¨çeƒôbö¨Šl-ÕÜ*XÝLç%*ź¸.…ÚŠÈ\Š@pR$Tå*KÖͽ¸hp‡ÀˆÈèÁ‚ßã¦múÁ‘â-/“oSÚ3ŽßÂEàÏÎto¸ž}çжV‡oõeJ `<™$öÙtíØ½ßü ª]g*ßZ›„µ6q°Àùl’ø~÷E¯« †Sú¸/Š’ùi£ÄTÆtÍk‚Ç®à²WÝþ Ü=?j¹G¢ÒÌÔUUAJÆõý›`†ÒbÔË‘—ƒGˆõQÍAÏ«©ñÖÎÆÚìcƒûê½WËï©èWSmÝÀ­g³ºÚFËñª‘&©^õúؘԡˆ6;C1:=ÛˆP‰äºÕ`ÊÚœVVÿ“ÔEÆ5"´hO«Xà~«ÞØN3_5Ó]ºz-þ­ä’CWÓÝtÔ¥‚Óˆ´ÐËeÜ]°\¶”©¿V¯–‹ÿcÔ#m[ÆkuÞ—­_ʱ"©ÉösH³ô<}xï±…m0båxHÓqb‘a3tfçMTÛÑÏ*]I» Þ}×(ú¾œ,M”„–=Š Ý@ŒJAÛÆÐd‰ ¬Ë?§6PV±ö[ dVãvôæ4jžÒß›‘lH\â÷ÔŒÅè{˜ØòMôå½È˜\ºåYþÜ€`9MÃ`Db‡<Á;a#zò†‘<Šx"ó,¨d‚gCi¿`‘c’›:ÁÈâI´â>jw·Ì}JÈÉz§^:V.ý:×þÚ‹{¿Í¼(ȲB÷æËɦ’ÉóxŽ<Db#"S£¡{ô’PùHu½N/ë{r6;wU¶æÐòsÖPО“<¤çXÀàYâsÔÄ÷ÞMxu°‡\šb‘Ús¸$Ž˜xŽÊ(¢‰/^|^*0j~mà¬;#·%J„ÞM4Çp˜QM׬ð::b\C2gf°°]½zÒP8T™ Uª“QbÖètºƒC½TŸ> p 8+6g_2–lΡ6§Hò ÚÎdžH:÷ d›<æCÍé6³¯Ø¤ê/«¿6ãE:ÂK‹”"Ë`kJ©<›ÏÆ¢ä=ùvž7„¥âN5·µ`°ò›¶Jt‹Ù\j¹6Í…%Ëž7ô*¥'¥•U•Ù4±:âX+ ä\bü’E äìôÞaf®ŠxŒ“}Á‰1+p™‹B¥Ë0î6òâ”åýž3rõA$Nš~¶ô#³dª}ÇפŸP7h÷H7b£FªžÂ§…‚¬8ð ³P>øBtGNÐŽ¢ðmä‚xô@j …‘¸|{Às9à»=þwRÙ/­«oDJs5z>“;Š'xÝñEÐq^ré^=G?½…9Aê¡æ–ÇAä_—£íK%µDÉ®:uikjkîIeÉæ½¬GúÕ#*¡†)µjm‘á|½t£¹}`Jæ©Z؈éÖ÷H=4î{gߢ¾)¡qXˆMA,šHøŒ7û1‰ëV"¥Ùo,çY#hýü÷ݨSò_ê;‹Ía_Ô—Z^cn4¢­ ‚H¸E«®?‰«°}Ñ È¡»­Üî¼Ù¤=}BžWvÞªUeðåhšƒÚGŠ“F…‰‘æ;@2S¥Øœ€@Ëf þÂËünÍâ2Ð#Žæ¹ñfÝY:]¿JyåH]­•-·˜G׌wgv'¡â|ˆÄ0eñ Ã_7ˆðÒ«n+fßÙ¸âàY<«ç(Í ª?öì’©‘yòù¡%wm¬+jƒ&&!è¢c“^¡u'bü&ñhŸm6¤šÎû¹*2 ?´AÇI«¶Æ²5FW¾Ø™[âÆœ¨BõUzïIÎE”“!’m:‹ÒûœxhÔe—ÝÇ®n¼z|]% mÙrÁU¸FÚ¯”ù®1Æ ‰};!n F¾& gòÚñÿP‰†Ý¯¯;&×ö©œøï$$¸éF«).t›BíQ¨3¦Ž½(žC=ú·Óä¦XÀÎØesÔ;Ýiû«¶­ÙŠ@¼Ñ~üNíÉΡEë ÔSR‹¡ˆh\éè£úÁBeñoº†½œ ´¹ÎbTÑ„nÎ’ju¹¾À g@ä÷'qQ딎nx.u6bVU&Ô ›]¹;Ûïª!C_ „ ž5Æ*Þz¹ɺûm€RQu‘ªq‚’঱PüÚZ0ƒ¶}mñ¼¡ÌÊõn½¦^nÕOrÉT¦âÁ‘µÎ:ŸUã'×hÀæ§0nZ¡p^Ré|DFª_b\ò@–Öm‚èDEë8Æ{oèGM‰á œq¸ÝÏ}ÜîSd ®C,ûiÀÜšEêŠé/°ÞË[d8]Ž×,MCIšÎÐó_u—,]V™cñ"—ä¤p°g@ì`"y)‹,;B³^e­žlÚ¡ª2'€.(ÍÐĘây>à-|Îh­ÜÓÄwšúþê;©jå¥è’íÕÑÒiÔ½±ä¯ê_o|!@ö)ɢݪÄ=ÙÌŒSPz—éˆ*!z})¼|ƧT}½j‘†E£tC¬Zå¡nŒ½ýœ*ÕžõÉ4ۆ׽[¹©± ¾9»Ð®¨Žèˆ‘’Ý“õŒz`Wmeôo‚‹|j8j­ï5á9¼öµ@.úšE¿VÌ/ÌZW@|—f_ç\"${ᜑv¡àòƒóœÀÈ/¸ò¶;a×:Se¦i3TäGË*ëÎýƒ]¸Æ¡/ÌhÀ2C32$¿Óô¿ü1}¿ŒD¤ÍNXÉøþtì?FÏí~n,Pj9.î–>×£ü¨Í{ 9ýÉEN-v|3h†ò‘CÅиE”•‡ XTàâË;P–$Ã=JÖ-ÝÕgÝ•ýùigz~q—(Aé<:h1±9³3áNì̽õQ‰‹ãÇ}CLØWùß§Â׎Ü~ƒá Úb™¥"†‡Í|Ç4u}îð­×Ùc™y€à‹È6°¡2ÿ[ ¥ØÖ\d¸,µÒŽÕ³bkù¤ÌDåä¾%0TÜx­®{=;öÔ·‹†(„i‡ ØLS·øß1½˜øý©Ñ3ÿNÏh/¤6?æ'E^ö~ÿÆÔP®{sZì™ZÓK”ÄžB{’DÌtø&‰½Ôz’Ó÷)µUoaù5Q¦3‘È—ˆr~¿Ž‘¾ ¦ôÙùF] $º<èútm(š} ûÃÏMB@‡ž[œGxìÎFÓh8›#}ˆô,£#À˜u ýLaz(ÞQh±4%Óxm`Uà•Õ¹.E¨ãv1a’ž4_'/[¨d±{Fx¨IÊ59žŒ ƒDõ<êì&8VˆEóFgÉÈ٠芘#õI‘äŸ2S²Íîÿ_ã©]QqAšnˆÑ_ðQç>bÞ˜4g¡¨­±-®0&E#c¦Üi8¿ vR/Õ4ÿržŠëšP7•£KsOWµN3ÕvE\bq†ûQß5Z¹Ú½Vy5]½Ööàh/ i)Åû¦Ž-/´°ã¡kµN¬Ñ޾ÈÄ#eì)"Píñü {ýKSQx‰²¸¦>aã&µí¶Ž,„  _èg¥´ñ-mác<×n]Ч-®5‘2c¨¹¡®ñz ¬7d Pœzóåµàòð²V„ö“û¥OPvf¼Rþ R¤ÓÆà°“9†Z -ŸÁÞd†÷®šˆ¿C›šñóÇ`,öatÁ=‡k?v¢í4#P è¤BÌ¡šØ¥¸/[õs.-bH)ɺzï '}¶×¶Ýîwœ!rÁXÎZе ´.:’Vn×;î-î>Š:á 6àrÿ½‡UÁcsÕ4k¬VW¬{’ú‰ð#­˜5ß‘0ÁBÝãìÇ`Üÿ0ušÑ".QÊÆ¬›dB´˜0£”õ˜CžÐrõ]íïà#íºQ9lqœàN^ôÖ³¯éôh~ NU\´ ¼16š ~éè“á”S‘n‡Tòl¢‘\þTHÒ²Ú›-ÙÉ~ªG~)$…oQ7-ë¯Cï°ÌÈì}q%/a™¦³vO°ª|[q4–‚Š’³~Bc-$NÜ7ž6½ŸwÒ{œV餃.&£ö(†o¹©*õn<§Øn9¡ÁJ– "a‡© ДÍÝ+¡† aÊ/»ýººð;7zDØZη{×tM Mp—£ iØšk¼NPwˆØ‘ͺðH`T ö$23–†fÓöÀÐÚ0šzÆÈ;­¡¦žç"ð]Œòª‚*ŽY²¤é,äQ¡WØàô¸lS鵯ÅOŽrW$5]K¡VÙ»Bâ…Üš…I¸ŠkÚ|ß=²&Á[ÔèêÞÑÞÅ58EÓR¤0Þ‹Gk«sSîñÁnãònnuãúñExKÐrô¢¬Œ}‡~mñÙ`ŽG4u{ÐÑñ=]6f¤÷âר BoÖ&< ™Ã±c;2 ®P$Ãǃ{mW_cžõª'B6Њ?$½^z[C—Y¹Ý­™é¥jÐNó~ þ¦Û®0¾»›út¢¯ú°Ûâ„6/)-‰1:p$Dꥅȗ ® ,'³†üyàõ±øÁv˜Ä …nœ‹F³T×Ñ™['a¦MbÎJ]»%&î¬lc6&ÂèIpFåÄ ¨ÜoðŒiƒªÄÉþã5± ø'r¨äËår‘(q¼ïèú®ëî¾z6Á°öžîÉ(5óÐáEôàÉ¢ÕŸl\…Lñkº7«°1ÅY4^)bٗ¦8ù¼yøÆªäÛ NžØ=ƒ›9zT–^[T$‡dkœ QâiK%áˆ6޵üqµéçõÌîfO|àÚàcÐ8$•ji^vrþ.QQR"âYárÄŠãâõ¸ ¨Ãkø’¥ÞrŸº¼Kˆ¢µû æè N·eíÏRiû4¦¾Õ!3Rù¢º"4¦ˆÈñúšn™bámÉ-y[X¦¦ÿÏñ."Æô!”øÜQK¯åE\Nëµ4gÕ ×ø§¿¦ƒï±aN¦p‚ >k)9ÁÁ0ˆBZêÌBs ö¥yŠrŽšer«)v¯¢®Dóëtèrv\ûvù[­ü>órµJmœ– aœò«µÌ¼›~uÝêêÕº>µrMZœ°˜cíB<øã`)\y×t|Ûïÿr'<†ô˜à>ù×Öþã[æÃŽ—ï­èh7ëú­þZÅŒ8caI!¹ ´p⢟ÍÌ®,¶GÃí »k 5@ÈÙô÷ÿ`ôÉiw ˆÒnО8pŸv¿ çÉé*²Â'O ÝÔüв ÝA[È.¡¤rhóT pR?+;Ëÿó\*H‹sLqÞæëUš¹f–â:ql-㤠ñ*6!…hç+ˬ{h·‰ö- jg±kÉMMÉ×P#ã¶ä:¼}‘±¸{/ÝëîVËßŶC]옙ê·&[³W$Ú«^ß#àû¸¶4fWa\ ‹Á5ìð躺M[6ž½)T§3—•›~üÚέÉÔÀ ã:. Z”¦¼¨`sÞi(ÍRô©Q…¼²Ì|/ú`ù ilÏ^°L# §÷òf¤-ñ×;-C;_ÜÞù*ù{@EMCooÂ_¤œÆÃõ7¾TöãrqzÜFµ%ׯ|™šUEÆ«Us^Ýœv{ ë¤¦fQ<Ä¡‰VPüïÃÊTfͦî?¥õmØpÙP*È&¦÷ÐQ‡G‰ù{cœJïñEPe2)ŽxP½0AÑßÍûMɪZH¶j•"×»"ÙA¬ÐC+zq‰mVzá–žóU%ØCµ:@1æãðW¹Š î[y)ÎJ@÷o±b% ÷j”A>)NÒÇ€Ôiç¼$’AóˆÀìt`>Ì?f0gÿH36pè6áÌD|ûM›ä áö4N¡° œ’ 4J½JÚƒ¯ µj¤ž˜Æ‡´ó\ íp 3ÓøŽ£8À¦ªÑã–Яï”»­6p®ùV?:¬$‚sDùÀNúµƹ‘2ï’n’,¶„HÝO\‚[¸øÕ¸›öKÙ-)«W~¹iém™?ÿ®ƒTÐ:°ÌðÞºUÖeYŒÓãŠ-#dJe)¯±ÚÏZªÕ5”?ø$»æ¡\d©W<·¹¹,Ɇ†š;¯Ø·¸Ã5ÍÍòS¸Õ¸¯¼—T«T–ñšÎÌ„f(PY°v=Q ~DX*¼ßÝ8øè¾©s- Â˨®Î€55 ­ X¢R¥l QCÏá¤Î á“øÑÀl|òý5Î{ûÓ¦T\t꼕+éï£e»nÅÛ¸‹’ÂPsÓèlû3™ùUO©[üÛîÇZ»ÉS3åÀîŸ*èì,˜ª†ß:ÛZþ¾ÆÔL‰›¬†ÕSô'̵æã*õòŒ*@¨øı~xgno2±¹áˆâ- …Œ ³W³Š«½V;äpZå9?~„«$«6Ÿ<”µQr‚bQ8&óse•ÉEb¯ÚQ,·þ^|B²µï碘ïVd¬V-¶(Ü]ã .ïèËŽ8/qhV¡nR®ó®QÈD‰*ùU(*1hç1Ã`ØQL{…Uj `àÒ"šo3Ü»æ™V¨l…µ: ÑíêÂØÀ jaFaàžE­¶ÌžZˆ‹g1±·zü°Ì2Ö Õ:ÍAuÙZIf6–ƒ2Õtw+Љ‰f§D‹ïÉ誩CL-}g»µZ³0>Ò„óxJ¢ýÿÅ>\îÁëQ‰¸AÚ_C¶i‚hßÒbl] ‡6ÞÕÞÜ4*šA˯ɰüqX‰¤7„»YòX.€-¾ŠÚÕ¸•aɇÃVâh¬–iKg•ÔÏqN³RĆN(r'Á]¼à%Ù˜„…­ôˆ@3ÔÍ€ÎÂj§Z¬÷J†.;üãnmÝú¯ÕÎ,SûûØ0x¯³ÃõøØÍ»£OF33­Ò§¶…«<$'Û»¸G—E+´Ú}¥¥Îóúó§…'1ðf3›ÆýÒyÐ5Ý/&¤Zœ\RBô7dmíô]æ¼8§§Â\Íý„3ß‚„Ȫ˜@÷ìo¿ûTé¿3eu^·W@Šªü”–ަe7l–!Bã,Às‚äæ1ÜÍß$šäò¯ÛZ§ã&Ù’ç?¯âdCéá (YЦSm>‚J"&ptÞ܈ªP㇄BF¬ø´Ú±àÙø4ŒGá5œ t^Ć$¯Þòj-aã g^ÁÊC¤–…ƒAsÖT=k¡TS,|€ràåš9I·½BϘЬ†ö'ÂìvGA¶Î@ÍtÀÌhQÕNj†&€åT=Îxt;2]¯P¡|T- LÞƒ’Éç¿ñe1ãݽWÃZÅš*MrH5?„ñ‚=àýÑo°¬"ëÆ9ÑK5Îø=«'kÉ-*•„èA¦E| þ Þ qÒ”‘_?\£7%öŽ|M6°fª+““+’S*}çW_Ü]3ª¨ú¶fmÜ®ØÒ˳ÒÜm w!–—î÷å.ÛR#‰é¬ª;Æíú¦±q qó71ŠÖä$•ݙկ_ÀóiKà&ìJ©Î¬M®Š¬öÞÇemåVÄ5PÏ0>¾¾ Qçµ5ª†W•©H­Ih×åù&ù4ÒIlÓE7}âsÈéÄm[cȾ좄|d^ ¢ì÷%Uvé1¦D“²>“.èT¬Ò7*é=tƒZ¸_§ãŸ¾1Ð¥:=0pZûš6Ò‹ŠN„t(åuíÆ­; ÇBÒ]³‘$€k¡ÚŒ€Â.ó{ªFÄ*/UZ’ÆNüç ¦|oqŠÊK—G;^Ö侞9N§ûeÿíxK‹ ’¡¨\‡whþøñ~¡òòZpHÔb‘‹Í䉸 »ˆÛ[k¶8âÉÍÌk÷â.bX.Q¾Xp¸xYa^µÐ"˜Ñ#럙ãB³wnb¤¿óåuÓð ém5žF²½~>ÇÐ8€­ÁbýúŽäN:Ýp4 µ[gv^ B½ÓFÐUzû)?œ¼60ÐFÉÉ8˜‚Â/2 ŒC8¨Œ®>N8GîÍ%ló%èÝ5ºFH˜{4„6h§Žï¸4Ž%Æ# 7¸è›ñŽÍúËx óoºÜN tª\•'ßȨ ¨ úæE£Žæ½0#ƒïj¸NãVïÓ¹dà?WlcW×ð‹ Äí ž½Öµµuû-“»}2„2¨¶¥EN¿}#‡äµµ2H^a3ðõ»¥r»Áqs§¤°ˆ„-S3&Èïô„f´í‡£ÌëÎfwl.š=Wø8å„,õàÒcHá®jžcTê±W®‘× s9ò0žî”ZàDÎM“ú¾C2’ZM’ÝûdjµŒtŸ"8À:gí{.Ʊ°Ð1Fb6ƒ1Ç8"yÔ¦>˜õ¿ ’­WÀ9£ë ÓVšŠŠö ¯`×j¿ý®š¿Tò””‘‘€²µr,nƒ©iÀ­Á ¥d³… ÿôéqN§ªÝ .g+ ïSÂë¼ Qúù·¾ë áKaB¾ŒÛà?_í‹ÛQE ‡“µr¸†ÿj¤î‚h>ô•E¦Ó›;C×­7…‹·^q¯ Æ`U¯eú#-Ÿ˜·;oJ˜Ä‹ãÒæŽÔ>) Çý‚;Jgí£Ï×­9R;Ogí¢ÅýiI7ú}—â8K¡’œÛq¦j¹ÑeØ“£+Ù—'nñÏ·k3‹Á­»üeFÏûžì…0±šò¯ßV#©íÆp¥MAzb^PŽ÷VÏu¤Û~Þ1uº—Ò“•wnÈ ^›.II—¡Š_ÆÌÚvdW®ÈöóÎ[Q,ÍÞè+L¾b‚í¾É¥å„ÆÄ‡q¼þ 9«V}ï ”ÎVÑw4qUä3&jÛıHYb¼ ü¹ˆ ¿ttTœõˆ7Ïò’«ÙarBwP9?)Ûu•é‹T/Ùa£•ŽA19–±kªM \ÓäPÝßs›<ØTažÐã@‚…õq±Ø+û£=Ù[5ÄÍ”·¶Ö×?²9£WÀÉ+^ýo¯^Eàã8s)åfç —2aôæ­QŸx¤·i‡é& NE>"^NaäaŸ;fŠÙÌ9]NE& t^°ÀCLz'âe…8ZRñs&6Þ²7_üãcyJž‘1 Äþ@TZ°?SD2û ‡|ÔPõÔËOÓŒé\dªRïÞðû7zHÕøƒî±9iÈ‹Q#µ¿¶‚zr³óc.ò4ö†GýR4ÎÈqx¦ð¾<2~X’hµ÷náãੳ¨Å2ˆauB­NCÑ+›¢k—Xó0Ñ aj5n>Þ‰¨õ²e3övÞ§Óôé<¥>°_²Ÿ Û uH: XRÿ%~9á!4öüoÑѼ¦è3…ºâ”8?¶‚ Î1d#ïÔÑü–šA&‹„„{A!i6 ‹ŒíÜ/XaŸ£á㇤=W‰;|ïðä) Ðg¾~£ ?*¾æ‚½Ã }¿ãÚ§ˆKtÌ>5|­E޵ÐîÑÜÕ.§ýôAûš Qñ6üú ²€¾(6 6Ñ”Æ7–Ú÷<9ùù_ð•CÁ f1þëÐŽéi8¾®†å», V»4$ÀŸutÉøœø£ÆiÁ,.`v6r â£òŽP ¯½gFBÉŽÇ tòÃçÚ C3½;˜ ,¼o“æãœx| /KóMp©1S_¾‘X.f÷Vª†#¼U>È’Èõˆ#Böñ]µ A‘IVoÀÌІϵÀ‘¿üGTV1nr+£ÎOXÂS•% ‹›³¶™f§OZ[Û_ý9œû‘P­ß°÷ {Gln‘%ß#ÚÛhÀdw¿H ù=† ¸y©e/íªW¼³´¶>Ò,Óö¬°IP,*MV•ð„~ºK&ãe¢Ä‹»ûMì½£=ò)‹qF¿ S¶ß´"ÉGÑëTšF™*¹LX,hŠ[—´º“§wŽw´íeñWQEÙxÚëº ?áè“{^Ú†EŽxïh»iý»¢×‚„J”³ÃÀH¥|ó^ÙÍ“Š…Ée*^‰Ð¯.ãuÚxE™èëËb#î;›’ôÔ<]z]\íƒ×¨wÚN»ho¼chq¸E˜£=ºçâ4Q1¸7ýÝçWü½Ì“lÕ6á§¿­HE_Ì£ ùqyÿ‰á YRŽ¤Û«ä9~l4sæVyù­™`Š×Uß›,ùŸþñ×Å#_Êu´ù+Deêêí™àéMÙü¢~h³qªë²‡’·#YúÊæñzü$;Û 5ͯ9$µË z²>ÿ ¾*jõOŸøŒñÛ$œÐ$O/¯ÀÃxRí½ƒÂtýf-}*žoïɦøÙÌ|3†M;xÞ¨¯U”•µl/.ñ~XÇŽ¯Yá¼4™x3&æë×x®";¤$KIö’5ÛdÚ­ ½Êáüú‹~w[ÊÔM9OØã%4ÒáQ¨}éS^žìt–è@ÑËæw[›Y;-ÝöÿÀºs;¢b¾ÍwH-* ï––Ãim½¶IÊ-¶1e/•~ø¨TNN®.òp²ßð)H$ûë«Wïß~ÎðµÉƦí¼O ( é9è†,Ù ]gM6rê+„#»%ƒà/süw¯Aœ$õŒqÆ4ËO> d9}÷+ðÑ$Œsôš³ý?0£™a,>y‹¹Úˆs<ðþ=†,ð‹c_*\âƒDí¼Ü}È2Mí°ÍÌT8/í4ægæ'Ú¦žâ8'û}"‹Câ*„\9½#Y>z$ŽæöÔ7c[s“|"$}» ymÌïÕÀ«zQx 5·%å oùå“$j†kÐÎp)ñx½Äû-:º†Ð˜|?˜oãøf§‡gFrÀžß2ŠS‘ÇZ÷Œq}qˆŠµ …o€,wyÅO¡gÊCF1Öl˜çŸ'íL5T3õò3ûÑðyª¦M‰9Ú2"s”˜ò5uD•‹6ÀÔ-Jì‰U†bsºÏ «O)ƒÌw¸R -2æ/5fÜ<ªBQÌ4kŒ˜ê­G¹ )%ß¼ãr’Ï›f@=šâBF™‹ïCB±©‰‰ƒ‡&'‡F}@©&ÓÈÿ„y×ubâÐÁÉÉC?'«êåñçSæ49+—Óä±Cø®³íIîð¤ÙŒ+×ç˜ëf/R«Uê ÌîC °Fu:C*£} †T:º¶}{ÂÜݽâ²·ÔuªÎ×ø•¬e[!®–>ú? ‹ÄåýÚ¸¸"ÇM 8gzƒô0\HkƒÔZ³:Ähå­~™@ª+ô#«Nê Öfj¾çyµîå‹ioÀ!„B÷ þñô·“±R'©5>Ú`Úò[!ÂÄTˆ`mCš I…ÑÃ}¸n >Wßô!M}UËavõ¶4€3)!§kcÈ‚²ómþ?’Ž Ýådïw•ãv«!×”;Xϡۨ}½8ívt•ëÐ"Ó¼# kÂvXŠJ™±[“l¶[ZÝ™MÀ§ñÃXC3lê–[ ÃTa¼Vj‹¡…ÚÊ»¥åŒÑ¬"Å“Ñò t:‚(žêà¦ÈÁ<¾cZóve—ýQ›ÇîT…Ÿ qHá‘i{ Ò銀Q埓'Á“Ö»“i öPØöï¿­èüȯáímKÊAçIŠõ¤BFƒ £=‰‰µâÖTá…½¶à(âœ&TSŸ?/ïØA:Ö·¬»ÐžV§(ø÷@wïFa^ã¦]…Œµäo]*Óñ99¬R¿iáñ_Ôò˜À™þÎË2vM“€Ø`P§“ôf¦´{QYÏ«íH#V7vÅ7ÌÒ° q>@àó«~uɘ׆Ax°Ã/ƒ«xÙ°Bþà3£Ä Ùô‰tƒÊÁy†b0ŒžnG`Á òEÚDìÙäA’Ô: ÆPØwIÓ7ÏìnWÓ÷2ED}.(h•Ü"‚óãU]¢9Iíh_îV¯@‡›GZ0C Üpb ó:ã™L 3¡tN*ªN ½2¿Ó!¼3Œ Ca³—yn.•ÊÝÉ‹Wâ`̳Ü}±QBÌCªÃi Á¡8*Ãï{57‰¹ìO#aT¢ËB½Ÿ‚½Uíoþi§0ç ó_ËðÑù^ ChrU}~rÈL 1òzÿ>..ö=%GÁš›GŒ£ ëüo ™‡ ŒEéu‘P³Psؘ޸èó8­ðüþP¨Ÿu&;æÊ*Œëù|i&¤ÿPbÛÈ›°²˜hÒ;´[—€|y*cƒVšh†Ò¼Ò(ÿ”~Î_A•qU2·½ÿôGIQÇ3`®^Êvþ=î@¬ÜK'¤µÐ‡èËZ#4sJ=º¤:sY©è sÚ¥bÂyj ¯ë·S_E܃"Žª‹Š@ž~‚Ÿç¹>­86ºñ#Îy±Úäå[ïècòSï„¥ÙŬ–”òò#­SJ”GZû®yvvÝßSùÑæ‰p¸waTšžÏõÅ/, 9'Jkv%%.†~oò[ÌóŸ è¡§üœÂR±Bj¢ŸSèÈ€*$'øè…©pçS¥u à+ç9\¬í_f+åòüù8õu\,¶ÊÓtæåðpžÑÐkØ®J0hó(]N„QÈvó³W¬ÇÌ7ó •8«ƒ6:ÜÖÝ£Ïâ ·ñWc“¯Y_i>ú¬ŒÝ"‘ßR¡çõ’â(Óe]Þ6ø¹ªRA%U—6&´F]”½7@̳k3X h?ŒÁKïà®ÞQ¤2™Bk¾[?.ÿ€Ã.K¡ÈKAbŽÌ6ýÞÄ5¿·kò’eŽ+]²FްeöWH©Uò«û0OÝ×§¾5…´øÿ ¤úîäe3H‡®coÇ>l]0¶2±ˆcý¹‡ÝHÊ9š{Z {sOõ–!¥A,þ7†?Å·3w俎A àFjÚÿ¸8¸Bí&8U$G…¡ÂµÙßé$µY5˜‚†FâL…5nÇì²Øò1–”> qóº2££.«6“e—é î ì¼Úõ—œ+˜–@/¬¢ð™µkíb{à÷(Å7Ði=¥É{l݂ͬ­âÎæ¿¦ï 8«…1g(»üè%ÎÓh/ëEf¶M¹ÒÝtŸ5½Ÿ̼vg½oÚ ê~à©›WKi父U«ßأݖ­w¬RS‚EìFíßT¬²%ª `=í‹ø|*=1‚ò*Žù»ý·S§Xö¬€·Ø^êòÓw)l–ÃÖfQHãúŒ(YSþô„SËŒK·æ1ÞØâíW]µf™Ÿ·°7ך³^&ýpô@T'.ìÀ%3³•„à š¯´ßÞò»ù5ÏzaTf6Ñë©A5ÜL•óXÌ¡æ·Á|ñL¸-Ÿå–ηêÄT×g{A)ªî­®FÑ•."hü“ùj¢ A;.ðâ~Âþ …oÞ%°è ýG#Ñ}&]Þ×¾cÜ`C»hH9xnN†·Y Îlð²cÞ¤\+v\EŸ¥«Æ§1¦D9K·Xá)2b.¿ó­“NôÚýW¢§ŽÜQש$¥/£”|6tð™Ã32Ô›£´7¡¡¦–2¸ÑÛиyuü0e×ñ€)’NØuh'dœ¶Ãî„õ~xY‰É ‘´>ÄÚ# bˆ"k3Ó𠼃®Ì: 9¿º¢vˆú$ПCÝ:Ê)H¹Ë> Õ¦šzÇÛ;e“d\jmfŸäOÏa%ò9š‘ˆcK›xÓÐÛ¥Å!k©%HÞDn“ü{YÜ"“{n_Ö} ß)9ƒ= _/û‡ZÎ(éù>lú¶­÷YžŸÖV÷‹gQ#§ß­:QÄ•ÈbwƒÇ÷Õ$¾zw±ðÙ®‹#¿»ãU˜?|ÅðïGÔ΄hÁzü{ùoº$wñ×Ïœ´º)|Vh‰Ú?»Œ ZV7¾%ŸüGûo/£×†‡ôéEÏ"¹KÓ²… ìµl¥p76Î-z !Ál€4n>”¼$\á×zV?szûqejìQçëé]m‹›æ^æ=^µ ä§í­¥! ²ºl…ôHB4sL i9}Þ2¢^×ýKÐ5ÅOBú)èíO ­çv^~ªêµýïÝ€x¦“rm\KÚ&G^Ð5CçÐL¼}&Fºò”ÀËâ¨B]K†¡n3††|ÍsGjyðkþO¯µÚbåsܽæaW?R6ð¡·²¾JÂÇfhãÚ2 ÄÊlBS§\=¢jÕÕV—Ê*”ôY¦“^¢¢Á™„˺^E)Õè*”\½Ÿ  ‚rÔr(a¢@ø„6nÔŒ£?¥}ÚdL°©¦šg¢IvqØNcÐÇa‘Æ®kŒÍ÷mLŒöcÁA!¤±hd¸£±Vëðµ¹Îòwc=¢¦æ†–áæ–Õs_Ò:ŠÿÒ—•¢sLËí£g>‘œ—1Ü*4-%ð&Ëõ0Ubƒ)Eܬ†*b¸ÔÖ51—Äï„ç ä+è+;˜Ž<…«†’`!q°fÍÎMù*Æ,[/GK+{×®,>CâLŒóR%%cŒ³ÂÆÃ~‘’'EG†A‰®GºÂ=‡hÂäŸ”Ž°8:IDìN)ÅWÌ»áAF)ucw'qhÍXè²L@a„¾~Œ6ÌPc2Lã"¥A…2bìÈU ™À&Œ€‹ÿ ¯9öA#ÓQLO¬:E€9k§©’‘ÆfÞKF•b93tºL$c‰Ë¬pÿLzÿ ¿5ÔdÚp¢þðùÛ°>$`œ.÷ï«~Xó=¶¡ã?„ NͰ/ŠÄ©L®PªÔ­No0šÌ«ÍîpºÜ¯Ï ‚b8AR4Ãr¼ J²¢j¿}øŸÐ Ó²×óƒ0Š“4Ë‹²ª›¶ë‡qš—uÛóºŸ÷ûAFP 'HŠfXŽDIVTM7LËv\ÏÂ(NÒ,/ʪnÚ®Æi^Öm?Îë~Þï÷‡à ’¢–ãQ’UÓ Ó²×óƒ0Š“4Ë‹²ª›¶ë‡qš—uÛóºŸ÷÷ÿb$œ«tV&g®Ï–íÁr>¿<Ùyóå?’“˜ûfþ{ç´·£‰µ›ž%îµïÇÌ~ßZûþaÅzW¾¿¼÷ÜõÝ2ŸµsvïÀÌò™ÙeW«‰µ‘à@DDDD$""""bffffÖ}X ÓO„0ÆcDDDDD¬µÖZ›6Wò08BÖçI¥ƒ.H¬W ¢ßˆÇÐ9 ‰u„*¥”R*J^}€Ä:M”´$I’$IÒF‚‹™™™™yÑŸžûÞóÀ_WÍÆý

 Plugins:

Name Enabled Active
{{plugin.name}} 
 
ola-0.10.5.nojsmin/olad/www/new/views/universe-overview.html0000644000175000017500000000043113023355232023537 0ustar wouterwouter
{{$index + 1}}
{{c}}
ola-0.10.5.nojsmin/olad/www/new/views/universes.html0000644000175000017500000000121313023355232022055 0ustar wouterwouter

 Universes:

Id Name
{{u.id}} {{u.name}}
ola-0.10.5.nojsmin/olad/www/new/views/universe-add.html0000644000175000017500000000317213023355232022426 0ustar wouterwouter
Input Ports:
Enable Device Description
{{plugin.device}} {{plugin.description}}
Output Ports:
Enable Device Description
{{plugin.device}} {{plugin.description}}
ola-0.10.5.nojsmin/olad/www/new/views/universe-rdm.html0000644000175000017500000000010713023355232022453 0ustar wouterwouter
ola-0.10.5.nojsmin/olad/www/new/views/overview.html0000644000175000017500000000463513023355232021713 0ustar wouterwouter

{{Info.instance_name}}

Instance Name: {{Info.instance_name}}
Hostname: {{Info.hostname}}
IP Address: {{Info.ip}}
Broadcast Address: {{Info.broadcast}}
Subnet Mask: {{Info.subnet}}
MAC Address: {{Info.hw_address}}
Up Since: {{Info.up_since}}
Version: {{Info.version}}
Configuration Directory: {{Info.config_dir}}

Id Name
{{u.id}} {{u.name}}
ola-0.10.5.nojsmin/olad/www/new/views/universe-keypad.html0000644000175000017500000000310313023355232023145 0ustar wouterwouter
{{field}}
ola-0.10.5.nojsmin/olad/www/new/views/universe-settings.html0000644000175000017500000001212213023355232023531 0ustar wouterwouter
Id:
Mode:
Name:

Input Ports:
Enabled Device Description Mode Priority
{{port.device}} {{port.description}}
static
{{port.device}} {{port.description}}
static
Output Ports:
Enabled Device Description Mode Priority
{{port.device}} {{port.description}}
static
{{port.device}} {{port.description}}
static
ola-0.10.5.nojsmin/olad/www/new/views/plugin-info.html0000644000175000017500000000037713023355232022273 0ustar wouterwouter

{{name}}

Enabled:
 
Active:
 
ola-0.10.5.nojsmin/olad/www/new/views/universe-patch.html0000644000175000017500000000010713023355232022770 0ustar wouterwouter
ola-0.10.5.nojsmin/olad/www/new/views/universe-faders.html0000644000175000017500000000270513023355232023143 0ustar wouterwouter
{{c + 1}}
{{get[c]}}
{{c}}
ola-0.10.5.nojsmin/olad/www/new/views/universe-header.html0000644000175000017500000000234113023355232023123 0ustar wouterwouter

{{header.name}}

(id: {{header.id}})
ola-0.10.5.nojsmin/olad/www/new/index.html0000644000175000017500000000677213023355232020023 0ustar wouterwouter OLA
ola-0.10.5.nojsmin/olad/www/new/css/0000755000175000017500000000000013155164170016607 5ustar wouterwouterola-0.10.5.nojsmin/olad/www/new/css/style.min.css0000644000175000017500000001054013023355232021236 0ustar wouterwouter.fader-group,.faders,.keypad{text-align:center}.keypad{width:300px;right:0;left:0;margin-left:auto;margin-right:auto;margin-top:5px}.backspace.btn{width:50px;margin:2px}.keypad-keys{margin-right:7%;margin-left:7%;margin-bottom:7%;width:86%}.keypad-field.static-fake{display:inline-block;vertical-align:middle;padding-top:5%;width:190px;height:50px;margin:2px}.fader-group,.value-span{margin:1px;display:inline-block}.keypad-keys .btn{width:100%}.btn-keypad{color:#333;background-color:#fff;border-color:#ccc;height:50px}.fader-fader{writing-mode:vertical-rl;-webkit-appearance:slider-vertical}.fader-group{border:1px solid #67a7e3;border-radius:4px}.off,.on,button.col-xs-3,button.col-xs-3:active,button.col-xs-3:focus{color:#fff;background-color:#67a7e3;border-color:transparent}.left-col,.value-span{border-bottom-left-radius:4px}.right-col,.value-span{border-bottom-right-radius:4px;border-top-right-radius:4px}.faders{padding:1px}.col-xs-2.ng-binding{text-align:center;color:#fff;background-color:#67a7e3;height:26px;line-height:2;font-weight:700}.left-col{border-top-left-radius:4px}.navigate{padding-left:0;padding-right:0;padding-bottom:15px;height:41px}.row,.status{padding:5px;text-align:center}.navigate>.col-xs-2,.navigate>.col-xs-3{height:100%;outline:0!important}.value-div{display:inline-block}.value-span{font-size:11px;border-bottom:1px solid #67a7e3;border-right:1px solid #67a7e3;width:20px;text-align:center}.index,.value{text-align:center;width:100%;height:50%}.channel{width:30px;font-size:10px;text-align:center;display:inline-block;border:1px solid #337ab7;border-radius:4px}.status{border:1px solid #000}.status-light{width:20px}.status,.status-light{display:inline-block;border-radius:20px}th.top-table,tr.special-mouse>td{text-align:center;padding:8px}.plugin-table{text-align:center;width:100%;margin-bottom:10px}.round-corners{border:1px solid #000;border-radius:10px}.top-table{border-bottom:solid #000 1px}tr.striped-table:nth-of-type(even){background-color:#F8F8F8;border-top:solid #d3d3d3 1px;border-bottom:solid #d3d3d3 1px}.special-mouse{cursor:pointer}.navbar-info{margin-top:8px;margin-bottom:8px;font-size:12px;text-align:center}.navbar-desktop{float:right!important}@media (min-width:768px){.navbar-mobile{display:none}.number{width:50px!important}}@media (max-width:768px){.navbar-desktop{display:none}.save-settings{width:100%}}div.checkbox-tr{text-align:center;vertical-align:middle}table.info>tbody>tr>td{border-bottom:solid grey 1px;padding-left:5px;padding-right:5px}.settings-table,table.table>tbody>tr>td.left-table{text-align:left}.settings-table>table{width:100%}input.priority{width:70px}select.priority{width:90px;display:inline}.caption-overview{width:49%;display:inline-block}.button-caption{text-align:right}.btn-grey{background-color:#d3d3d3;color:#333;border-color:#BABABA}td.align{text-align:left}.plugin-icon{color:#898989}div#header-universe{padding-bottom:10px}div#header-universe>h4{display:inline;padding-right:10px}div#header-universe>div{color:#d3d3d3;display:inline}.static-fake{height:34px;padding:6px 12px;background-color:#eee;border:1px solid #ccc;border-radius:4px;box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:3px}.number{cursor:text!important}.input-group,.save-settings,.settings{margin-top:5px}input.form-control[type=checkbox]{display:none}input.form-control[type=checkbox]+label span.glyphicon:before{width:20px;height:20px;border-radius:4px;border:1px solid #ccc;content:"\e014";color:#d9534f;background-color:#fff;cursor:pointer}input.form-control[type=checkbox]:checked+label span.glyphicon:before{content:"\e013";color:#5cb85c}input.form-control[type=checkbox][disabled]+label span.glyphicon:before{color:#a9a9a9}label.fake-check{margin-top:5px;margin-bottom:0}.nav-tabs{overflow-x:auto;overflow-y:hidden;display:-webkit-box;display:-moz-box}.nav-tabs>li{float:none}.nav-tabs::-webkit-scrollbar{-webkit-appearance:none}.nav-tabs::-webkit-scrollbar:vertical{width:12px}.nav-tabs::-webkit-scrollbar:horizontal{height:12px}.nav-tabs::-webkit-scrollbar-thumb{background-color:rgba(0,0,0,.5);border-radius:10px;border:2px solid #fff}.nav-tabs::-webkit-scrollbar-track{border-radius:10px;background-color:#fff}ola-0.10.5.nojsmin/olad/www/new/img/0000755000175000017500000000000013155164170016573 5ustar wouterwouterola-0.10.5.nojsmin/olad/www/new/img/light_bulb_off.png0000644000175000017500000000122413023355232022240 0ustar wouterwouter‰PNG  IHDRóÿatEXtSoftwareAdobe ImageReadyqÉe<6IDATxÚ”SKkQ¾3“É$ÉÃÒ$Š‚©&Ð…Z•d)J®\¹sÓ…  â(]¸q©¸qÕ ¡‹‚u!HLì#D%uJÚIMÀÒ´vÚæa2Ï;×3jJÒv8Ü3s¾ï»çžs/EA]}òQe…ñî…¼õ£ «hšfŸ=8ä8P¿Yà›‰è™«“c×Çâ‘ÐP£­«bíçöLæsN¬I!È/‚îJòèóÉÛ’±pc´uXÜé»÷.E‚7 ’˽„>(/ñp"5®é¦i`S¥á<†bÚŠ¡”w~íßOßÌÈ @<¼¨èfÇ$ˆÈ:ÖZ²®b“Í Úp$ßîå8ŽPm+µºÒ´ÎÙ’ u»®ªš¦xŽ,>¦U°ÿqµ"€³¾ÕjlîudhñŸbÙ°Ïå]Z¯TA`ÏV’_^ÌgóÑëôyXÎçq:Â~Žò¹<~žáž¾y_LÞVìÇÎAóëÔëù·W.Î ºø—sÇ‚îðãW³ï¶¤z¦PµPU†±6* ¥òTÁ» ÷¡¸Vʬˆßa÷Œ®ëÈVÀJ‚[*Ì-[åXÆÎÏ-­” ?Ëø¯!Û)ÀîݰšÊÜzHr†Ä :ÁúÎc©vä|v·¸xmDE´93õÉ™H·ÿG•À“ÉÒ4çŸoYÈžÄ?6…>“$ 5»ƒ Ç^c讀M¥Òw ŒÂè¦íp¿v.1Ýœx™IEND®B`‚ola-0.10.5.nojsmin/olad/www/new/img/logo-mini.png0000644000175000017500000000134413023355232021170 0ustar wouterwouter‰PNG  IHDR3mÀ¤¯«IDATxÚå–MHTQÇ{%:cQ––9H„R´ú\´pU³‰> #Œ ŒvÑ¢Má"ERFaQ%-ÄÚØ¢Dƒ ú± …ù5&“óú/þ‹?¹½ûîLô‡Ì=ïœóÞysî»gÖÿ¢Ù nƒ/ r`Ü ˜ä“B”dŽÀY;À[à ?ÁtÀöìü‹ÅÜaŽ>—`œ9IÒªÄgm¯äϯÈŬYÉÓ"é §Àaà…žŒ¹PäbÎ_èŠÚZ90 ¶[m?xÃ}E*fgü¨äÚ`<¼c@3ˆª½Œý âE(æcs|±ß¸¾i¼›Îýl=gŽtÅ”‚aÆÞ§í×Y°2,ÁC:®ÚÏ ,æ ãfÀZÚb`ˆö¶°£c|±R LÛA‚¿+¤Õ\‹ñÀãnÕÚǹ§òªJn£­“ëz`ÒBöôS±eç9Ó í´:Oû}äõ“¦µrãÚÖãü׌b[n“õ(ó”9ÓŘk†ëM¼>lš>brã àªri—6[/‡µ iS¢OyNÙèøÃüÕ e½…9z‹¹N[Þ˜¾¼mt¸*¶à¨A•qt‹í"sœr(f˜¶[–˘³+ŸC=˜ÑǶ©ŸËà¬kÀ"þ®Æ'Š9Kß÷À‹0€ö˜Úé0ÀB‚z ^¹Ï"3ŒÐ·Øh³äOš6p?ž¥–3ÔƼåÅ´Î[õ1î®Éa xI§NÑ›¸GTÕ|ˆ!ƒ*¦æð™~í ŠɤPkrŠƒ:ù˜T}:Ù*Aù!$Á(ë@ÅÁwÛ±\’϶2®ðp¥¬‹ÑÏw/×ÝÀE­ŒÏ€Å¶AsA‚Ìÿ¤~° =™IIEND®B`‚ola-0.10.5.nojsmin/olad/www/new/img/logo.png0000644000175000017500000000305313023355232020235 0ustar wouterwouter‰PNG  IHDRo0$BòIDATxÚíÜylTUÆagÚŽ-[ T‘h""J\ˆaQ0j(ˆAÀ­)£‰…Ó ¨,j `ÀE²7\E[D@YLYìýü…@Ò|ùêÜ™¹[Ißäù‹éÜKß™;çž3§‰ÈY ©?9ßYCy åM6ò1ëQ†Ã¨FÊñ#Ö q .ä4BfXË‹bV ’ Ó؈‘ˆ!Ùˆ†D°ëÂV^ùØ qÉŒEúR^_È9ÃR^[¬‡xd'º\å•@ÎY†òîÇß:œÄ ¢7:"÷œŽ¸ ã±ÿ@êP…Âz\ÞMê|ªÑ.ÈòžG ÄðB8Mˆsé]€´zXÞ{eNPåM‡Ž`4ÒSü`„½Ã2¤Õ£ò:à D9Ž~—÷$İ­àVšáuˆan})Oý´gý,¯NC”©ˆÀ‹ŒBD)¨嵎sËtY~”× ¿A”gàu/š \òòfBâxÔò^2?týËãå+DCZ^ŽªóøÛŒÁ]ÔËòòŒK×7È€Ÿy¢Œ iyOA”.QzYÞkÆ}Ê ð;¹8¤Î¥ Ñ•ÃêJjM!–ªûÒ«òZá”:Ø|•q¥_ÈÊ{¢ôÁù< QzxQ^¡9;\²ð§:§wCT^eêøÛŒwæ}«åEyŸ©ƒ|„ ó‚:§SÈ Iyùet&ªÇÔ “›åeCôÑ:7B”ž!)ïkuìRD¡Óåê±o¹Y^ˆr‚Nĸt>‚òzAx±OU­Dk·Ê+2ÖØ¬DÐQ— j„º²J¿jCPÞZuÜ}q•sÁà,·Ê›ïàó®%¶BðKïÌö(Å,GtŠÕ¹m¸¼ÎÆ*K!âeŽú™£Èv£¼÷Õ¿éàƒwRÍbõœC 3A/Ú\ÞR½ÂâpI¬ªÕϹQÞZoéIê1Ó=øE s0]öK€å]n0N³Hýì~ÄR-o£ƒòšáS¾E.RÍÕµf(Jé ¼Ÿ,ïUc­®%œ¦“qÉ‘jy&°Ž–7‹3òšŠË¦=è(F¢Ñ¿ë]ˆ¤RÞBõ„Ë–ÌVç¶) ò¦Ãý6H4·@”»S)oб’–¬Òƒ)?ËÓ7ÚÙœJyCyÍÆø¿4…׉« “(¯â±.É–—Qî„•ŒZ×íÝIN^wÄTâÅx_¥Sºú\^ {![–ÊÄôž¸÷zö»t.¾¯ì+3ÔãNàbŸË{âƒ3¸"ÙòfÃàèŒP[ˆD³A=ÇÐÉ4:—ø¼$Á.uŒµ.nF9¢ž{^²å] qpš‰-À•°ÒMa¥'ŽÕšŠKsø]–¾>—×¢Ü ·2ÅXòÊu\žJ‰ñîk +yˆÁJªñ/†ÃJ:!lcó{D|.ïsõü[=¸w<®§“-¯»1°8MSµ6øÍkÞÓÇòºA”ûàv^6æJ;-Og D™ §ÉQóåH$ùÆ èD|.o¥ñÕ½4¸{Âz\²åµÂAcé~œ¦•8¡pš®8iì@ºÊ×/ÝÚsð*zueÒ–§s;NCÙ'à4Y nDéSu}_Óçò—²,x•kŒËT6š@ \ÞoçêØ13€&íPe|lxÕê˜Û/ÏžŒÕv£—Kƒ‚ÃBD(o¶11 ¯Ó¢ôNusej † ¸+ÁòîÁ&H^QÅùU^ pŸÆzBÀm̓q,ΦŃžhKÑÐaqœÙù Œ…Óˆ öךr›lLÐçÁ¯Ük ¯O±9ÆØA Ùcu®ª»Ày› Pwù&Á露.?–­U«ï1&7p À ‹ŸÒ¥ÒZþ‡$¶ˆ¢CTV?nrk%A¬Ù6ÿ8&@«ÝLÓaùs2QFq`ɯ$vpï-6°ÓDÚĦÖ_æ ùŒJ:9 ù¬…8ÂL€]î-ëÉuŸNÙo(ŠO–Ôͨߨý°'†¼¯‡@Ó¤®—RøQzsþ¶J¥õúÞq!ÿÜÆ¾qÎßD"Ñ›¸ôà•ÚÛw…æLqÔIÄlF–IEND®B`‚ola-0.10.5.nojsmin/olad/www/new/js/0000755000175000017500000000000013155164317016436 5ustar wouterwouterola-0.10.5.nojsmin/olad/www/new/js/app.min.js.map0000644000175000017500000003663013023355232021112 0ustar wouterwouter{"version":3,"sources":["../../../../javascript/new-src/src/app.js","../../../../javascript/new-src/src/controllers/menu.js","../../../../javascript/new-src/src/controllers/patch_universe.js","../../../../javascript/new-src/src/controllers/rdm_universe.js","../../../../javascript/new-src/src/controllers/universe.js","../../../../javascript/new-src/src/controllers/fader_universe.js","../../../../javascript/new-src/src/controllers/keypad_universe.js","../../../../javascript/new-src/src/controllers/plugins.js","../../../../javascript/new-src/src/controllers/add_universe.js","../../../../javascript/new-src/src/controllers/plugin_info.js","../../../../javascript/new-src/src/controllers/setting_universe.js","../../../../javascript/new-src/src/controllers/header.js","../../../../javascript/new-src/src/controllers/overview.js","../../../../javascript/new-src/src/constants.js","../../../../javascript/new-src/src/factories/ola.js","../../../../javascript/new-src/src/filters/start_form.js"],"names":["ola","angular","module","config","$routeProvider","when","templateUrl","controller","otherwise","redirectTo","$scope","$ola","$interval","$location","Items","Info","goTo","url","path","getData","get","ItemList","then","data","ServerInfo","document","title","instance_name","ip","$routeParams","Universe","id","OLA","dmx","interval","Dmx","i","MAX_CHANNEL_NUMBER","MIN_CHANNEL_VALUE","$on","cancel","getColor","$window","list","last","offset","send","light","j","change","dmxGet","length","ceil","Math","post","page","d","offsetLimit","limit","getWidth","width","floor","innerWidth","amount","getLimit","$","resize","$apply","regexkeypad","check","channelValue","value","MAX_CHANNEL_VALUE","channelNumber","MIN_CHANNEL_NUMBER","regexGroups","result","undefined","check1","this","parseInt","check2","check3","field","input","tmpField","substr","fields","exec","submit","begin","end","active","enabled","getInfo","Reload","action","go","changeStatus","current","PluginState","getStyle","style","background-color","Ports","addPorts","Universes","Class","Data","name","add_ports","u","universes","hasOwnProperty","push","Submit","indexOf","AddUniverse","error","modal","getDirection","direction","updateId","TogglePort","grep","Boolean","join","InfoPlugin","description","getElementById","textContent","innerHTML","replace","stateColor","val","loadData","old","model","Remove","Add","PortsId","DeactivePorts","UniverseInfo","merge_mode","ActivePorts","output_ports","concat","input_ports","Save","a","remove_ports","modified","forEach","element","index","port","port_old","priority","current_mode","modify_ports","ModifyUniverse","header","tab","hash","location","Shutdown","goUniverse","constant","factory","$http","postEncode","PostData","key","encodeURIComponent","channelValueCheck","dmxConvert","strip","integers","response","method","params","headers","Content-Type","universe","pluginId","state","plugin_id","ReloadPids","rdm","GetSectionInfo","uid","section","SetSection","hint","option","int","GetSupportedPids","GetSupportedSections","UidIdentifyDevice","UidInfo","UidPersonalities","Uids","RunDiscovery","incremental","body","text","filter","start","slice"],"mappings":"AAoBA,GAAIA,KAAMC,QAAQC,OAAO,UAAW,WAEpCF,KAAIG,QAAQ,iBACV,SAASC,GACP,YACAA,GAAeC,KAAK,KAClBC,YAAa,2BACbC,WAAY,iBACXF,KAAK,eACNC,YAAa,4BACbC,WAAY,iBACXF,KAAK,iBACNC,YAAa,+BACbC,WAAY,oBACXF,KAAK,iBACNC,YAAa,oCACbC,WAAY,iBACXF,KAAK,wBACNC,YAAa,kCACbC,WAAY,uBACXF,KAAK,wBACNC,YAAa,kCACbC,WAAY,sBACXF,KAAK,qBACNC,YAAa,+BACbC,WAAY,oBACXF,KAAK,uBACNC,YAAa,iCACbC,WAAY,sBACXF,KAAK,0BACNC,YAAa,oCACbC,WAAY,wBACXF,KAAK,YACNC,YAAa,0BACbC,WAAY,gBACXF,KAAK,eACNC,YAAa,8BACbC,WAAY,mBACXC,WACDC,WAAY,SCvClBT,IAAIO,WAAW,YAAa,SAAU,OAAQ,YAAa,YACzD,SAASG,EAAQC,EAAMC,EAAWC,GAChC,YACAH,GAAOI,SACPJ,EAAOK,QAEPL,EAAOM,KAAO,SAASC,GACrBJ,EAAUK,KAAKD,GAGjB,IAAIE,GAAU,WACZR,EAAKS,IAAIC,WAAWC,KAAK,SAASC,GAChCb,EAAOI,MAAQS,IAEjBZ,EAAKS,IAAII,aAAaF,KAAK,SAASC,GAClCb,EAAOK,KAAOQ,EACdE,SAASC,MAAQH,EAAKI,cAAgB,MAAQJ,EAAKK,KAIvDT,KACAP,EAAUO,EAAS,QCrBvBnB,IAAIO,WAAW,qBACZ,SAAU,OAAQ,eACjB,SAASG,EAAQC,EAAMkB,GACrB,YACAnB,GAAOoB,SAAWD,EAAaE,MCJrC/B,IAAIO,WAAW,mBACZ,SAAU,OAAQ,eACjB,SAASG,EAAQC,EAAMkB,GACrB,YAGAnB,GAAOoB,SAAWD,EAAaE,MCNrC/B,IAAIO,WAAW,gBACZ,SAAU,OAAQ,eAAgB,YAAa,MAC9C,SAASG,EAAQC,EAAMkB,EAAcjB,EAAWoB,GAC9C,YACAtB,GAAOuB,OACPvB,EAAOoB,SAAWD,EAAaE,EAE/B,IAAIG,GAAWtB,EAAU,WACvBD,EAAKS,IAAIe,IAAIzB,EAAOoB,UAAUR,KAAK,SAASC,GAC1C,IAAK,GAAIa,GAAI,EAAGA,EAAIJ,EAAIK,mBAAoBD,IAC1C1B,EAAOuB,IAAIG,GACe,gBAAhBb,GAAKU,IAAIG,GACfb,EAAKU,IAAIG,GAAKJ,EAAIM,qBAGzB,IAEH5B,GAAO6B,IAAI,WAAY,WACrB3B,EAAU4B,OAAON,KAGnBxB,EAAO+B,SAAW,SAASL,GACzB,MAAIA,GAAI,IACC,QAEA,YCzBjBpC,IAAIO,WAAW,qBACZ,SAAU,OAAQ,eAAgB,UAAW,YAAa,MACzD,SAASG,EAAQC,EAAMkB,EAAca,EAAS9B,EAAWoB,GACvD,YACAtB,GAAOU,OACPV,EAAOiC,QACPjC,EAAOkC,KAAO,EACdlC,EAAOmC,OAAS,EAChBnC,EAAOoC,MAAO,EACdpC,EAAOsB,IAAMA,EACbtB,EAAOoB,SAAWD,EAAaE,EAE/B,KAAK,GAAIK,GAAI,EAAGA,EAAIJ,EAAIK,mBAAoBD,IAC1C1B,EAAOiC,KAAKP,GAAKA,EACjB1B,EAAOU,IAAIgB,GAAKJ,EAAIM,iBAGtB5B,GAAOqC,MAAQ,SAASC,GACtB,IAAK,GAAIZ,GAAI,EAAGA,EAAIJ,EAAIK,mBAAoBD,IAC1C1B,EAAOU,IAAIgB,GAAKY,CAElBtC,GAAOuC,SAGT,IAAIC,GAAStC,EAAU,WACrBD,EAAKS,IAAIe,IAAIzB,EAAOoB,UAAUR,KAAK,SAASC,GAC1C,IAAK,GAAIa,GAAI,EAAGA,EAAIJ,EAAIK,mBAAoBD,IACtCA,EAAIb,EAAKU,IAAIkB,OACfzC,EAAOU,IAAIgB,GAAKb,EAAKU,IAAIG,GAEzB1B,EAAOU,IAAIgB,GAAKJ,EAAIM,iBAGxB5B,GAAOoC,MAAO,KAEf,IAEHpC,GAAO+B,SAAW,SAASL,GACzB,MAAIA,GAAI,IACC,QAEA,SAIX1B,EAAO0C,KAAO,SAAShB,GACrB,MAAOM,GAAQW,KAAKD,KAAKhB,IAG3B1B,EAAOuC,OAAS,WACdtC,EAAK2C,KAAKnB,IAAIzB,EAAOoB,SAAUpB,EAAOU,MAGxCV,EAAO6C,KAAO,SAASC,GACrB,GAAU,IAANA,EAAS,CACX,GAAIC,GACFf,EAAQW,KAAKD,KAAKpB,EAAIK,mBAAqB3B,EAAOgD,MAC/ChD,GAAOmC,OAAS,IAAOY,GAC1B/C,EAAOmC,aAEAW,KAAMxB,EAAIM,mBACf5B,EAAOmC,SAAWb,EAAIM,mBACxB5B,EAAOmC,UAKbnC,EAAOiD,SAAW,WAChB,GAAIC,GACFlB,EAAQW,KAAKQ,MAA4B,IAArBnB,EAAQoB,WAAqBpD,EAAOgD,OACtDK,EAASH,EAAS,GAAKlD,EAAOgD,KAClC,OAAOK,GAAS,MAGlBrD,EAAOsD,SAAW,WAChB,GAAIJ,GAA8B,IAArBlB,EAAQoB,WAAqB,EAC1C,OAAOpB,GAAQW,KAAKQ,MAAMD,IAG5BlD,EAAOgD,MAAQhD,EAAOsD,WAEtBtD,EAAOkD,OACLA,MAASlD,EAAOiD,YAGlBjB,EAAQuB,EAAEvB,GAASwB,OAAO,WACxBxD,EAAOyD,OAAO,WACZzD,EAAOgD,MAAQhD,EAAOsD,WACtBtD,EAAOkD,OACLA,MAAOlD,EAAOiD,gBAKpBjD,EAAO6B,IAAI,WAAY,WACrB3B,EAAU4B,OAAOU,QC/FzBlD,IAAIO,WAAW,sBACZ,SAAU,OAAQ,eAAgB,MACjC,SAASG,EAAQC,EAAMkB,EAAcG,GACnC,YACAtB,GAAOoB,SAAWD,EAAaE,EAC/B,IAAIqC,EAKJA,GACE,qFAIF,IAAIC,IACFC,aAAc,SAASC,GACrB,MAAOvC,GAAIM,mBAAqBiC,GAC9BA,GAASvC,EAAIwC,mBAEjBC,cAAe,SAASF,GACtB,MAAOvC,GAAI0C,oBAAsBH,GAC/BA,GAASvC,EAAIK,oBAEjBsC,YAAa,SAASC,GACpB,GAAkBC,SAAdD,EAAO,GAAkB,CAC3B,GAAIE,GAASC,KAAKN,cAAcO,SAASJ,EAAO,GAAI,IACpD,KAAKE,EACH,OAAO,EAGX,GAAkBD,SAAdD,EAAO,GAAkB,CAC3B,GAAIK,GAASF,KAAKN,cAAcO,SAASJ,EAAO,GAAI,IACpD,KAAKK,EACH,OAAO,EAGX,GAAkBJ,SAAdD,EAAO,IAAkC,SAAdA,EAAO,GAAe,CACnD,GAAIM,GAASH,KAAKT,aAAaU,SAASJ,EAAO,GAAI,IACnD,KAAKM,EACH,OAAO,EAGX,OAAO,GAIXxE,GAAOyE,MAAQ,GACfzE,EAAO0E,MAAQ,SAASA,GACtB,GAAIC,EAEFA,GADY,cAAVD,EACS1E,EAAOyE,MAAMG,OAAO,EAAG5E,EAAOyE,MAAMhC,OAAS,GAE7CzC,EAAOyE,MAAQC,CAE5B,IAAIG,GAASnB,EAAYoB,KAAKH,EACf,QAAXE,EACF7E,EAAOyE,MAAQ,GACNd,EAAMM,YAAYY,KAC3B7E,EAAOyE,MAAQI,EAAO,KAI1B7E,EAAO+E,OAAS,WACd,GAAIxD,MACAmD,EAAQ1E,EAAOyE,MACfP,EAASR,EAAYoB,KAAKJ,EAC9B,IAAe,OAAXR,GAAmBP,EAAMM,YAAYC,GAAS,CAChD,GAAIc,GAAQV,SAASJ,EAAO,GAAI,IAC5Be,EAAMf,EAAO,GAAKI,SAASJ,EAAO,GAAI,IACxCI,SAASJ,EAAO,GAAI,IAClBL,EAAuB,SAAdK,EAAO,GAClB5C,EAAIwC,kBAAoBQ,SAASJ,EAAO,GAAI,GAC9C,OAAae,IAATD,GAAgBrB,EAAMC,aAAaC,IACrC5D,EAAKS,IAAIe,IAAIzB,EAAOoB,UAAUR,KAAK,SAASC,GAC1C,IAAK,GAAIa,GAAI,EAAGA,EAAIJ,EAAIK,mBAAoBD,IACtCA,EAAIb,EAAKU,IAAIkB,OACflB,EAAIG,GAAKb,EAAKU,IAAIG,GAElBH,EAAIG,GAAKJ,EAAIM,iBAGjB,KAAK,GAAIU,GAAI0C,EAAYC,GAAL3C,EAAUA,IAC5Bf,EAAIe,EAAI,GAAKuB,CAEf5D,GAAK2C,KAAKnB,IAAIzB,EAAOoB,SAAUG,GAC/BvB,EAAOyE,MAAQ,MAEV,IAEA,EAGT,OAAO,MC7FjBnF,IAAIO,WAAW,eACZ,SAAU,OAAQ,YACjB,SAASG,EAAQC,EAAME,GACrB,YACAH,GAAOI,SACPJ,EAAOkF,UACPlF,EAAOmF,WACPnF,EAAOoF,QAAU,WACfnF,EAAKS,IAAIC,WACNC,KAAK,SAASC,GACbb,EAAOI,MAAQS,KAGrBb,EAAOoF,UACPpF,EAAOqF,OAAS,WACdpF,EAAKqF,OAAOD,SACZrF,EAAOoF,WAETpF,EAAOuF,GAAK,SAASlE,GACnBlB,EAAUK,KAAK,WAAaa,IAE9BrB,EAAOwF,aAAe,SAASnE,EAAIoE,GACjCxF,EAAK2C,KAAK8C,YAAYrE,EAAIoE,GAC1BzF,EAAOoF,WAGTpF,EAAO2F,SAAW,SAASC,GACzB,MAAIA,IAEAC,mBAAoB,UAIpBA,mBAAoB,WCjChCvG,IAAIO,WAAW,mBAAoB,SAAU,OAAQ,UAAW,YAC9D,SAASG,EAAQC,EAAM+B,EAAS7B,GAC9B,YACAH,GAAO8F,SACP9F,EAAO+F,YACP/F,EAAOgG,aACPhG,EAAOiG,MAAQ,GACfjG,EAAOkG,MACL7E,GAAI,EACJ8E,KAAM,GACNC,UAAW,IAGbnG,EAAKS,IAAIC,WAAWC,KAAK,SAASC,GAChC,IAAK,GAAIwF,KAAKxF,GAAKyF,UACbzF,EAAKyF,UAAUC,eAAeF,KAC5BrG,EAAOkG,KAAK7E,KAAOiD,SAASzD,EAAKyF,UAAUD,GAAGhF,GAAI,KACpDrB,EAAOkG,KAAK7E,KAEdrB,EAAOgG,UAAUQ,KAAKlC,SAASzD,EAAKyF,UAAUD,GAAGhF,GAAI,QAK3DrB,EAAOyG,OAAS,WACgB,gBAAnBzG,GAAOkG,KAAK7E,IACK,KAA1BrB,EAAOkG,KAAKE,WACiC,KAA7CpG,EAAOgG,UAAUU,QAAQ1G,EAAOkG,KAAK7E,MACZ8C,SAArBnE,EAAOkG,KAAKC,MAA2C,KAArBnG,EAAOkG,KAAKC,QAChDnG,EAAOkG,KAAKC,KAAO,YAAcnG,EAAOkG,KAAK7E,IAE/CpB,EAAK2C,KAAK+D,YAAY3G,EAAOkG,MAC7B/F,EAAUK,KAAK,aAAeR,EAAOkG,KAAK7E,KACY,KAA7CrB,EAAOgG,UAAUU,QAAQ1G,EAAOkG,KAAK7E,IAC9CpB,EAAK2G,MAAMC,MAAM,gCACkB1C,SAA1BnE,EAAOkG,KAAKE,WACK,KAA1BpG,EAAOkG,KAAKE,YACZnG,EAAK2G,MAAMC,MAAM,oEAKrB5G,EAAKS,IAAIoF,QAAQlF,KAAK,SAASC,GAC7Bb,EAAO8F,MAAQjF,IAGjBb,EAAO8G,aAAe,SAASC,GAC7B,MAAIA,GACK,SAEA,SAIX/G,EAAOgH,SAAW,WACiC,KAA7ChH,EAAOgG,UAAUU,QAAQ1G,EAAOkG,KAAK7E,IACvCrB,EAAOiG,MAAQ,YAEfjG,EAAOiG,MAAQ,IAInBjG,EAAOiH,WAAa,WAClBjH,EAAOkG,KAAKE,UACVpE,EAAQuB,EAAE2D,KAAKlH,EAAO+F,SAAUoB,SAASC,KAAK,SChEtD9H,IAAIO,WAAW,kBACZ,SAAU,eAAgB,OACzB,SAASG,EAAQmB,EAAclB,GAC7B,YACAA,GAAKS,IAAI2G,WAAWlG,EAAaE,IAAIT,KAAK,SAASC,GACjDb,EAAOkF,OAASrE,EAAKqE,OACrBlF,EAAOmF,QAAUtE,EAAKsE,QACtBnF,EAAOmG,KAAOtF,EAAKsF,IAEnB,IAAImB,GAAcvG,SAASwG,eAAe,cAC1CD,GAAYE,YAAc3G,EAAKyG,YAC/BA,EAAYG,UACVH,EAAYG,UAAUC,QAAQ,OAAQ,YAG1C1H,EAAO2H,WAAa,SAASC,GAC3B,MAAIA,IAEA/B,mBAAoB,UAIpBA,mBAAoB,WCtBhCvG,IAAIO,WAAW,uBACZ,SAAU,OAAQ,eACjB,SAASG,EAAQC,EAAMkB,GACrB,YACAnB,GAAO6H,SAAW,WAChB7H,EAAOkG,MACL4B,OACAC,SACAC,UACAC,QAEFjI,EAAOkG,KAAK4B,IAAIzG,GAAKrB,EAAOkG,KAAK6B,MAAM1G,GAAKF,EAAaE,GACzDpB,EAAKS,IAAIwH,QAAQ/G,EAAaE,IAAIT,KAAK,SAASC,GAC9Cb,EAAOmI,cAAgBtH,IAEzBZ,EAAKS,IAAI0H,aAAajH,EAAaE,IAAIT,KAAK,SAASC,GACnDb,EAAOkG,KAAK4B,IAAI3B,KAAOnG,EAAOkG,KAAK6B,MAAM5B,KAAOtF,EAAKsF,KACrDnG,EAAOkG,KAAK4B,IAAIO,WAAaxH,EAAKwH,WAClCrI,EAAOkG,KAAK6B,MAAMM,WAAaxH,EAAKwH,WACpCrI,EAAOsI,YAAczH,EAAK0H,aAAaC,OAAO3H,EAAK4H,aACnDzI,EAAOkG,KAAK4B,IAAIQ,YACdzH,EAAK0H,aAAaC,OAAO3H,EAAK4H,YAChC,KAAK,GAAI/G,GAAI,EAAGA,EAAI1B,EAAOsI,YAAY7F,SAAUf,EAC/C1B,EAAOkG,KAAK8B,OAAOtG,GAAK,MAI9B1B,EAAO6H,WACP7H,EAAO0I,KAAO,WACZ,GAAIC,KACJA,GAAEtH,GAAKrB,EAAOkG,KAAK6B,MAAM1G,GACzBsH,EAAExC,KAAOnG,EAAOkG,KAAK6B,MAAM5B,KAC3BwC,EAAEN,WAAarI,EAAOkG,KAAK6B,MAAMM,WACjCM,EAAEvC,UAAY7C,EAAE2D,KAAKlH,EAAOkG,KAAK+B,IAAKd,SAASC,KAAK,KACpDuB,EAAEC,aAAerF,EAAE2D,KAAKlH,EAAOkG,KAAK8B,OAAQb,SAASC,KAAK,IAC1D,IAAIyB,KACJ7I,GAAOsI,YAAYQ,QAAQ,SAASC,EAASC,GAC3C,GAAiE,KAA7DhJ,EAAOkG,KAAK8B,OAAOtB,QAAQ1G,EAAOsI,YAAYU,GAAO3H,IAAY,CACnE,GAAI4H,GAAOjJ,EAAOsI,YAAYU,GAC1BE,EAAWlJ,EAAOkG,KAAK4B,IAAIQ,YAAYU,EACR,YAA/BC,EAAKE,SAASC,cACZ,EAAIH,EAAKE,SAAStF,MAAQ,MAC5B8E,EAAEM,EAAK5H,GAAK,mBAAqB4H,EAAKE,SAAStF,MACb,KAA9BgF,EAASnC,QAAQuC,EAAK5H,KACxBwH,EAASrC,KAAKyC,EAAK5H,KAIrB6H,EAASC,SAASC,eAAiBH,EAAKE,SAASC,eACnDT,EAAEM,EAAK5H,GAAK,kBAAoB4H,EAAKE,SAASC,aACZ,KAA9BP,EAASnC,QAAQuC,EAAK5H,KACxBwH,EAASrC,KAAKyC,EAAK5H,QAK3BsH,EAAEU,aAAe9F,EAAE2D,KAAK2B,EAAU1B,SAASC,KAAK,KAChDnH,EAAK2C,KAAK0G,eAAeX,GACzB3I,EAAO6H,eC1DfvI,IAAIO,WAAW,iBACZ,SAAU,OAAQ,eAAgB,UACjC,SAASG,EAAQC,EAAMkB,EAAca,GACnC,YACAhC,GAAOuJ,QACLC,IAAK,GACLnI,GAAIF,EAAaE,GACjB8E,KAAM,IAGRlG,EAAKS,IAAI0H,aAAajH,EAAaE,IAChCT,KAAK,SAASC,GACbb,EAAOuJ,OAAOpD,KAAOtF,EAAKsF,MAG9B,IAAIsD,GAAOzH,EAAQ0H,SAASD,IAC5BzJ,GAAOuJ,OAAOC,IAAMC,EAAK/B,QAAQ,yBAA0B,OChBjEpI,IAAIO,WAAW,gBACZ,SAAU,OAAQ,YACjB,SAASG,EAAQC,EAAME,GACrB,YACAH,GAAOK,QACPL,EAAOgG,aAEP/F,EAAKS,IAAIC,WAAWC,KAAK,SAASC,GAChCb,EAAOgG,UAAYnF,EAAKyF,YAG1BrG,EAAKS,IAAII,aAAaF,KAAK,SAASC,GAClCb,EAAOK,KAAOQ,IAGhBb,EAAO2J,SAAW,WAChB1J,EAAKqF,OAAOqE,WAAW/I,QAGzBZ,EAAO4J,WAAa,SAASvI,GAC3BlB,EAAUK,KAAK,aAAea,OCpBtC/B,IAAIuK,SAAS,OACX7F,mBAAsB,EACtBrC,mBAAsB,IACtBC,kBAAqB,EACrBkC,kBAAqB,MCHvBxE,IAAIwK,QAAQ,QAAS,QAAS,UAAW,MACvC,SAASC,EAAO/H,EAASV,GACvB,YAGA,IAAI0I,GAAa,SAASnJ,GACxB,GAAIoJ,KACJ,KAAK,GAAIC,KAAOrJ,GACVA,EAAK0F,eAAe2D,KACV,MAARA,GACM,iBAARA,GACQ,iBAARA,GACQ,cAARA,EAGAD,EAASzD,KAAK0D,EAAM,IAAMrJ,EAAKqJ,IAE/BD,EAASzD,KAAK0D,EAAM,IAAMC,mBAAmBtJ,EAAKqJ,KAIxD,OAAOD,GAAS7C,KAAK,MAEnBgD,EAAoB,SAAS1I,GAO/B,MANAA,GAAI4C,SAAS5C,EAAG,IACZA,EAAIJ,EAAIM,kBACVF,EAAIJ,EAAIM,kBACCF,EAAIJ,EAAIwC,oBACjBpC,EAAIJ,EAAIwC,mBAEHpC,GAEL2I,EAAa,SAAS9I,GAGxB,IAAK,GAFD+I,IAAQ,EACRC,KACK7I,EAAIJ,EAAIK,mBAAoBD,GAAKJ,EAAI0C,mBAAoBtC,IAAK,CACrE,GAAImC,GAAQuG,EAAkB7I,EAAIG,EAAI,KAClCmC,EAAQvC,EAAIM,oBACb0I,GACD5I,IAAMJ,EAAI0C,sBACVuG,EAAS7I,EAAI,GAAKmC,EAClByG,GAAQ,GAGZ,MAAOC,GAASnD,KAAK,KAEvB,QACE1G,KACEC,SAAU,WACR,MAAOoJ,GAAMrJ,IAAI,8BACdE,KAAK,SAAS4J,GACb,MAAOA,GAAS3J,QAGtBC,WAAY,WACV,MAAOiJ,GAAMrJ,IAAI,sBACdE,KAAK,SAAS4J,GACb,MAAOA,GAAS3J,QAGtBiF,MAAO,WACL,MAAOiE,GAAMrJ,IAAI,mBACdE,KAAK,SAAS4J,GACb,MAAOA,GAAS3J,QAGtBqH,QAAS,SAAS7G,GAChB,MAAO0I,IACLU,OAAQ,MACRlK,IAAK,kBACLmK,QACErJ,GAAMA,KAGPT,KAAK,SAAS4J,GACb,MAAOA,GAAS3J,QAGtBwG,WAAY,SAAShG,GACnB,MAAO0I,IACLU,OAAQ,MACRlK,IAAK,oBACLmK,QACErJ,GAAMA,KAGPT,KAAK,SAAS4J,GACb,MAAOA,GAAS3J,QAGtBY,IAAK,SAASJ,GACZ,MAAO0I,IACLU,OAAQ,MACRlK,IAAK,WACLmK,QACErE,EAAKhF,KAGNT,KAAK,SAAS4J,GACb,MAAOA,GAAS3J,QAGtBuH,aAAc,SAAS/G,GACrB,MAAO0I,IACLU,OAAQ,MACRlK,IAAK,sBACLmK,QACErJ,GAAMA,KAGPT,KAAK,SAAS4J,GACb,MAAOA,GAAS3J,SAIxB+B,MACE0G,eAAgB,SAASzI,GACvB,MAAOkJ,IACLU,OAAQ,OACRlK,IAAK,mBACLM,KAAMmJ,EAAWnJ,GACjB8J,SACEC,eAAgB,uCAEjBhK,KAAK,SAAS4J,GACf,MAAOA,GAAS3J,QAGpB8F,YAAa,SAAS9F,GACpB,MAAOkJ,IACLU,OAAQ,OACRlK,IAAK,gBACLM,KAAMmJ,EAAWnJ,GACjB8J,SACEC,eAAgB,uCAEjBhK,KAAK,SAAS4J,GACf,MAAOA,GAAS3J,QAGpBY,IAAK,SAASoJ,EAAUtJ,GACtB,GAAIV,IACFwF,EAAGwE,EACH/H,EAAGuH,EAAW9I,GAEhB,OAAOwI,IACLU,OAAQ,OACRlK,IAAK,WACLM,KAAMmJ,EAAWnJ,GACjB8J,SACEC,eAAgB,uCAEjBhK,KAAK,SAAS4J,GACf,MAAOA,GAAS3J,QAGpB6E,YAAa,SAASoF,EAAUC,GAC9B,GAAIlK,IACFkK,MAAOA,EACPC,UAAWF,EAEb,OAAOf,IACLU,OAAQ,OACRlK,IAAK,oBACLM,KAAMmJ,EAAWnJ,GACjB8J,SACEC,eAAgB,uCAEjBhK,KAAK,SAAS4J,GACf,MAAOA,GAAS3J,SAItByE,QACEqE,SAAU,WACR,MAAOI,GAAMrJ,IAAI,SACdE,KAAK,SAAS4J,GACb,MAAOA,GAAS3J,QAGtBwE,OAAQ,WACN,MAAO0E,GAAMrJ,IAAI,WACdE,KAAK,SAAS4J,GACb,MAAOA,GAAS3J,QAGtBoK,WAAY,WACV,MAAOlB,GAAMrJ,IAAI,gBACdE,KAAK,SAAS4J,GACb,MAAOA,GAAS3J,SAIxBqK,KAEEC,eAAgB,SAASN,EAAUO,EAAKC,GACtC,MAAOtB,IACLU,OAAQ,MACRlK,IAAK,yBACLmK,QACErJ,GAAMwJ,EACNO,IAAOA,EACPC,QAAWA,KAGZzK,KAAK,SAAS4J,GACb,MAAOA,GAAS3J,QAItByK,WAAY,SAAST,EAAUO,EAAKC,EAASE,EAAMC,GACjD,MAAOzB,IACLU,OAAQ,MACRlK,IAAK,6BACLmK,QACErJ,GAAMwJ,EACNO,IAAOA,EACPC,QAAWA,EACXE,KAAQA,EACRE,MAAOD,KAGR5K,KAAK,SAAS4J,GACb,MAAOA,GAAS3J,QAItB6K,iBAAkB,SAASb,EAAUO,GACnC,MAAOrB,IACLU,OAAQ,MACRlK,IAAK,2BACLmK,QACErJ,GAAMwJ,EACNO,IAAOA,KAGRxK,KAAK,SAAS4J,GACb,MAAOA,GAAS3J,QAItB8K,qBAAsB,SAASd,EAAUO,GACvC,MAAOrB,IACLU,OAAQ,MACRlK,IAAK,+BACLmK,QACErJ,GAAMwJ,EACNO,IAAOA,KAGRxK,KAAK,SAAS4J,GACb,MAAOA,GAAS3J,QAItB+K,kBAAmB,SAASf,EAAUO,GACpC,MAAOrB,IACLU,OAAQ,MACRlK,IAAK,gCACLmK,QACErJ,GAAMwJ,EACNO,IAAOA,KAGRxK,KAAK,SAAS4J,GACb,MAAOA,GAAS3J,QAItBgL,QAAS,SAAShB,EAAUO,GAC1B,MAAOrB,IACLU,OAAQ,MACRlK,IAAK,qBACLmK,QACErJ,GAAMwJ,EACNO,IAAOA,KAGRxK,KAAK,SAAS4J,GACb,MAAOA,GAAS3J,QAItBiL,iBAAkB,SAASjB,EAAUO,GACnC,MAAOrB,IACLU,OAAQ,MACRlK,IAAK,8BACLmK,QACErJ,GAAMwJ,EACNO,IAAOA,KAGRxK,KAAK,SAAS4J,GACb,MAAOA,GAAS3J,QAItBkL,KAAM,SAASlB,GACb,MAAOd,IACLU,OAAQ,MACRlK,IAAK,iBACLmK,QACErJ,GAAMwJ,KAGPjK,KAAK,SAAS4J,GACb,MAAOA,GAAS3J,QAItBmL,aAAc,SAASnB,EAAUoB,GAC/B,MAAOlC,IACLU,OAAQ,MACRlK,IAAK,qBACLmK,QACErJ,GAAMwJ,EACNoB,YAAeA,KAGhBrL,KAAK,SAAS4J,GACb,MAAOA,GAAS3J,SAIxB+F,OACEC,MAAO,SAASqF,EAAMlL,GACA,mBAATkL,GACT3I,EAAE,mBAAmB4I,KAAKD,GAE1B3I,EAAE,mBAAmB4I,KAAK,2BAEP,mBAAVnL,GACTuC,EAAE,oBAAoB4I,KAAKnL,GAE3BuC,EAAE,oBAAoB4I,KAAK,SAE7B5I,EAAE,eAAesD,MAAM,cCjVjCvH,IAAI8M,OAAO,YAAa,WACtB,YACA,OAAO,UAAS1H,EAAO2H,GAErB,MADAA,GAAQ/H,SAAS+H,EAAO,IACjB3H,EAAM4H,MAAMD","file":"app.min.js"}ola-0.10.5.nojsmin/olad/www/new/js/app.min.js0000644000175000017500000003064113155164317020342 0ustar wouterwoutervar ola=angular.module("olaApp",["ngRoute"]);ola.config(["$routeProvider",function(a){"use strict";a.when("/",{templateUrl:"/new/views/overview.html",controller:"overviewCtrl"}).when("/universes/",{templateUrl:"/new/views/universes.html",controller:"overviewCtrl"}).when("/universe/add",{templateUrl:"/new/views/universe-add.html",controller:"addUniverseCtrl"}).when("/universe/:id",{templateUrl:"/new/views/universe-overview.html",controller:"universeCtrl"}).when("/universe/:id/keypad",{templateUrl:"/new/views/universe-keypad.html",controller:"keypadUniverseCtrl"}).when("/universe/:id/faders",{templateUrl:"/new/views/universe-faders.html",controller:"faderUniverseCtrl"}).when("/universe/:id/rdm",{templateUrl:"/new/views/universe-rdm.html",controller:"rdmUniverseCtrl"}).when("/universe/:id/patch",{templateUrl:"/new/views/universe-patch.html",controller:"patchUniverseCtrl"}).when("/universe/:id/settings",{templateUrl:"/new/views/universe-settings.html",controller:"settingUniverseCtrl"}).when("/plugins",{templateUrl:"/new/views/plugins.html",controller:"pluginsCtrl"}).when("/plugin/:id",{templateUrl:"/new/views/plugin-info.html",controller:"pluginInfoCtrl"}).otherwise({redirectTo:"/"})}]),ola.controller("menuCtrl",["$scope","$ola","$interval","$location",function(a,b,c,d){"use strict";a.Items={},a.Info={},a.goTo=function(a){d.path(a)};var e=function(){b.get.ItemList().then(function(b){a.Items=b}),b.get.ServerInfo().then(function(b){a.Info=b,document.title=b.instance_name+" - "+b.ip})};e(),c(e,1e4)}]),ola.controller("patchUniverseCtrl",["$scope","$ola","$routeParams",function(a,b,c){"use strict";a.Universe=c.id}]),ola.controller("rdmUniverseCtrl",["$scope","$ola","$routeParams",function(a,b,c){"use strict";a.Universe=c.id}]),ola.controller("universeCtrl",["$scope","$ola","$routeParams","$interval","OLA",function(a,b,c,d,e){"use strict";a.dmx=[],a.Universe=c.id;var f=d(function(){b.get.Dmx(a.Universe).then(function(b){for(var c=0;c140?"black":"white"}}]),ola.controller("faderUniverseCtrl",["$scope","$ola","$routeParams","$window","$interval","OLA",function(a,b,c,d,e,f){"use strict";a.get=[],a.list=[],a.last=0,a.offset=0,a.send=!1,a.OLA=f,a.Universe=c.id;for(var g=0;g140?"black":"white"},a.ceil=function(a){return d.Math.ceil(a)},a.change=function(){b.post.Dmx(a.Universe,a.get)},a.page=function(b){if(1===b){var c=d.Math.ceil(f.MAX_CHANNEL_NUMBER/a.limit);a.offset+1!==c&&a.offset++}else b===f.MIN_CHANNEL_VALUE&&a.offset!==f.MIN_CHANNEL_VALUE&&a.offset--},a.getWidth=function(){var b=d.Math.floor(.99*d.innerWidth/a.limit),c=b-52/a.limit;return c+"px"},a.getLimit=function(){var a=.99*d.innerWidth/66;return d.Math.floor(a)},a.limit=a.getLimit(),a.width={width:a.getWidth()},d.$(d).resize(function(){a.$apply(function(){a.limit=a.getLimit(),a.width={width:a.getWidth()}})}),a.$on("$destroy",function(){e.cancel(h)})}]),ola.controller("keypadUniverseCtrl",["$scope","$ola","$routeParams","OLA",function(a,b,c,d){"use strict";a.Universe=c.id;var e;e=/^(?:([0-9]{1,3})(?:\s(THRU)\s(?:([0-9]{1,3}))?)?(?:\s(@)\s(?:([0-9]{1,3}|FULL))?)?)/;var f={channelValue:function(a){return d.MIN_CHANNEL_VALUE<=a&&a<=d.MAX_CHANNEL_VALUE},channelNumber:function(a){return d.MIN_CHANNEL_NUMBER<=a&&a<=d.MAX_CHANNEL_NUMBER},regexGroups:function(a){if(void 0!==a[1]){var b=this.channelNumber(parseInt(a[1],10));if(!b)return!1}if(void 0!==a[3]){var c=this.channelNumber(parseInt(a[3],10));if(!c)return!1}if(void 0!==a[5]&&"FULL"!==a[5]){var d=this.channelValue(parseInt(a[5],10));if(!d)return!1}return!0}};a.field="",a.input=function(b){var c;c="backspace"===b?a.field.substr(0,a.field.length-1):a.field+b;var d=e.exec(c);null===d?a.field="":f.regexGroups(d)&&(a.field=d[0])},a.submit=function(){var c=[],g=a.field,h=e.exec(g);if(null!==h&&f.regexGroups(h)){var i=parseInt(h[1],10),j=h[3]?parseInt(h[3],10):parseInt(h[1],10),k="FULL"===h[5]?d.MAX_CHANNEL_VALUE:parseInt(h[5],10);return j>=i&&f.channelValue(k)?(b.get.Dmx(a.Universe).then(function(e){for(var f=0;f=g;g++)c[g-1]=k;b.post.Dmx(a.Universe,c),a.field=""}),!0):!1}return!1}}]),ola.controller("pluginsCtrl",["$scope","$ola","$location",function(a,b,c){"use strict";a.Items={},a.active=[],a.enabled=[],a.getInfo=function(){b.get.ItemList().then(function(b){a.Items=b})},a.getInfo(),a.Reload=function(){b.action.Reload(),a.getInfo()},a.go=function(a){c.path("/plugin/"+a)},a.changeStatus=function(c,d){b.post.PluginState(c,d),a.getInfo()},a.getStyle=function(a){return a?{"background-color":"green"}:{"background-color":"red"}}}]),ola.controller("addUniverseCtrl",["$scope","$ola","$window","$location",function(a,b,c,d){"use strict";a.Ports={},a.addPorts=[],a.Universes=[],a.Class="",a.Data={id:0,name:"",add_ports:""},b.get.ItemList().then(function(b){for(var c in b.universes)b.universes.hasOwnProperty(c)&&(a.Data.id===parseInt(b.universes[c].id,10)&&a.Data.id++,a.Universes.push(parseInt(b.universes[c].id,10)))}),a.Submit=function(){"number"==typeof a.Data.id&&""!==a.Data.add_ports&&-1===a.Universes.indexOf(a.Data.id)?((void 0===a.Data.name||""===a.Data.name)&&(a.Data.name="Universe "+a.Data.id),b.post.AddUniverse(a.Data),d.path("/universe/"+a.Data.id)):-1!==a.Universes.indexOf(a.Data.id)?b.error.modal("Universe ID already exists."):(void 0===a.Data.add_ports||""===a.Data.add_ports)&&b.error.modal("There are no ports selected for the universe. This is required.")},b.get.Ports().then(function(b){a.Ports=b}),a.getDirection=function(a){return a?"Output":"Input"},a.updateId=function(){-1!==a.Universes.indexOf(a.Data.id)?a.Class="has-error":a.Class=""},a.TogglePort=function(){a.Data.add_ports=c.$.grep(a.addPorts,Boolean).join(",")}}]),ola.controller("pluginInfoCtrl",["$scope","$routeParams","$ola",function(a,b,c){"use strict";c.get.InfoPlugin(b.id).then(function(b){a.active=b.active,a.enabled=b.enabled,a.name=b.name;var c=document.getElementById("description");c.textContent=b.description,c.innerHTML=c.innerHTML.replace(/\\n/g,"
")}),a.stateColor=function(a){return a?{"background-color":"green"}:{"background-color":"red"}}}]),ola.controller("settingUniverseCtrl",["$scope","$ola","$routeParams",function(a,b,c){"use strict";a.loadData=function(){a.Data={old:{},model:{},Remove:[],Add:[]},a.Data.old.id=a.Data.model.id=c.id,b.get.PortsId(c.id).then(function(b){a.DeactivePorts=b}),b.get.UniverseInfo(c.id).then(function(b){a.Data.old.name=a.Data.model.name=b.name,a.Data.old.merge_mode=b.merge_mode,a.Data.model.merge_mode=b.merge_mode,a.ActivePorts=b.output_ports.concat(b.input_ports),a.Data.old.ActivePorts=b.output_ports.concat(b.input_ports);for(var c=0;cc.MAX_CHANNEL_VALUE&&(a=c.MAX_CHANNEL_VALUE),a},f=function(a){for(var b=!0,d=[],f=c.MAX_CHANNEL_NUMBER;f>=c.MIN_CHANNEL_NUMBER;f--){var g=e(a[f-1]);(g>c.MIN_CHANNEL_VALUE||!b||f===c.MIN_CHANNEL_NUMBER)&&(d[f-1]=g,b=!1)}return d.join(",")};return{get:{ItemList:function(){return a.get("/json/universe_plugin_list").then(function(a){return a.data})},ServerInfo:function(){return a.get("/json/server_stats").then(function(a){return a.data})},Ports:function(){return a.get("/json/get_ports").then(function(a){return a.data})},PortsId:function(b){return a({method:"GET",url:"/json/get_ports",params:{id:b}}).then(function(a){return a.data})},InfoPlugin:function(b){return a({method:"GET",url:"/json/plugin_info",params:{id:b}}).then(function(a){return a.data})},Dmx:function(b){return a({method:"GET",url:"/get_dmx",params:{u:b}}).then(function(a){return a.data})},UniverseInfo:function(b){return a({method:"GET",url:"/json/universe_info",params:{id:b}}).then(function(a){return a.data})}},post:{ModifyUniverse:function(b){return a({method:"POST",url:"/modify_universe",data:d(b),headers:{"Content-Type":"application/x-www-form-urlencoded"}}).then(function(a){return a.data})},AddUniverse:function(b){return a({method:"POST",url:"/new_universe",data:d(b),headers:{"Content-Type":"application/x-www-form-urlencoded"}}).then(function(a){return a.data})},Dmx:function(b,c){var e={u:b,d:f(c)};return a({method:"POST",url:"/set_dmx",data:d(e),headers:{"Content-Type":"application/x-www-form-urlencoded"}}).then(function(a){return a.data})},PluginState:function(b,c){var e={state:c,plugin_id:b};return a({method:"POST",url:"/set_plugin_state",data:d(e),headers:{"Content-Type":"application/x-www-form-urlencoded"}}).then(function(a){return a.data})}},action:{Shutdown:function(){return a.get("/quit").then(function(a){return a.data})},Reload:function(){return a.get("/reload").then(function(a){return a.data})},ReloadPids:function(){return a.get("/reload_pids").then(function(a){return a.data})}},rdm:{GetSectionInfo:function(b,c,d){return a({method:"GET",url:"/json/rdm/section_info",params:{id:b,uid:c,section:d}}).then(function(a){return a.data})},SetSection:function(b,c,d,e,f){return a({method:"GET",url:"/json/rdm/set_section_info",params:{id:b,uid:c,section:d,hint:e,"int":f}}).then(function(a){return a.data})},GetSupportedPids:function(b,c){return a({method:"GET",url:"/json/rdm/supported_pids",params:{id:b,uid:c}}).then(function(a){return a.data})},GetSupportedSections:function(b,c){return a({method:"GET",url:"/json/rdm/supported_sections",params:{id:b,uid:c}}).then(function(a){return a.data})},UidIdentifyDevice:function(b,c){return a({method:"GET",url:"/json/rdm/uid_identify_device",params:{id:b,uid:c}}).then(function(a){return a.data})},UidInfo:function(b,c){return a({method:"GET",url:"/json/rdm/uid_info",params:{id:b,uid:c}}).then(function(a){return a.data})},UidPersonalities:function(b,c){return a({method:"GET",url:"/json/rdm/uid_personalities",params:{id:b,uid:c}}).then(function(a){return a.data})},Uids:function(b){return a({method:"GET",url:"/json/rdm/uids",params:{id:b}}).then(function(a){return a.data})},RunDiscovery:function(b,c){return a({method:"GET",url:"/rdm/run_discovery",params:{id:b,incremental:c}}).then(function(a){return a.data})}},error:{modal:function(a,b){"undefined"!=typeof a?$("#errorModalBody").text(a):$("#errorModalBody").text("There has been an error"),"undefined"!=typeof b?$("#errorModalLabel").text(b):$("#errorModalLabel").text("Error"),$("#errorModal").modal("show")}}}}]),ola.filter("startFrom",function(){"use strict";return function(a,b){return b=parseInt(b,10),a.slice(b)}}); //# sourceMappingURL=app.min.js.mapola-0.10.5.nojsmin/olad/PluginLoader.h0000644000175000017500000000362413023355232017140 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * PluginLoader.h * Interface for the PluginLoader classes * Copyright (C) 2005 Simon Newton */ #ifndef OLAD_PLUGINLOADER_H_ #define OLAD_PLUGINLOADER_H_ #include #include "ola/base/Macro.h" namespace ola { /** * @brief The interface used to load plugins. */ class PluginLoader { public: PluginLoader() : m_plugin_adaptor(NULL) {} virtual ~PluginLoader() {} /** * @brief Set the PluginAdaptor to use for the plugins. * @param adaptor The PluginAdaptor, ownership is not transferred. */ void SetPluginAdaptor(class PluginAdaptor *adaptor) { m_plugin_adaptor = adaptor; } /** * @brief Load the plugins. * @returns A vector with a list of the plugins which were loaded. The * PluginLoader maintains ownership of each plugin. */ virtual std::vector LoadPlugins() = 0; /** * @brief Unload all previously loaded plugins. * * After this call completes, any plugins returned by LoadPlugins() must not * be used. */ virtual void UnloadPlugins() = 0; protected: class PluginAdaptor *m_plugin_adaptor; private: DISALLOW_COPY_AND_ASSIGN(PluginLoader); }; } // namespace ola #endif // OLAD_PLUGINLOADER_H_ ola-0.10.5.nojsmin/olad/PluginManager.h0000644000175000017500000001154513023355232017305 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * PluginManager.h * Interface to the PluginManager class * Copyright (C) 2005 Simon Newton */ #ifndef OLAD_PLUGINMANAGER_H_ #define OLAD_PLUGINMANAGER_H_ #include #include #include "ola/base/Macro.h" #include "ola/plugin_id.h" namespace ola { class PluginLoader; class PluginAdaptor; class AbstractPlugin; /** * @brief The manager of plugins. * * The plugin manager is responsible for loading the plugins (via * PluginLoaders) and retains ownership of the Plugin objects. * * Each plugin has a numeric ID associated with it. The plugin IDs can be found * in common/protocol/Ola.proto * * Plugins can be disabled through the preferences file. Some plugins may * conflict with others, in this case the first plugin will be started and the * rest of the conflicting plugins are ignored. * * Plugins are active if they weren't disabled, there were no conflicts that * prevented them from loading, and the call to Start() was successfull. */ class PluginManager { public: /** * @brief Create a new PluginManager. * @param plugin_loaders the list of PluginLoader to use. * @param plugin_adaptor the PluginAdaptor to pass to each plugin. */ PluginManager(const std::vector &plugin_loaders, PluginAdaptor *plugin_adaptor); /** * @brief Destructor. */ ~PluginManager(); /** * @brief Attempt to load all the plugins and start them. * * Some plugins may not be started due to conflicts or being disabled. */ void LoadAll(); /** * Unload all the plugins. */ void UnloadAll(); /** * @brief Return the list of loaded plugins. * @param[out] plugins the list of plugins. * * This list includes disabled and conflicting plugins. */ void Plugins(std::vector *plugins) const; /** * @brief Return a list of active plugins. * @param[out] plugins the list of active plugins. */ void ActivePlugins(std::vector *plugins) const; /** * @brief Return a list of enabled plugins. * @param[out] plugins the list of enabled plugins. */ void EnabledPlugins(std::vector *plugins) const; /** * @brief Lookup a plugin by ID. * @param plugin_id the id of the plugin to find. * @return the plugin matching the id or NULL if not found. */ AbstractPlugin* GetPlugin(ola_plugin_id plugin_id) const; /** * @brief Check if a plugin is active. * @param plugin_id the id of the plugin to check. * @returns true if the plugin is active, false otherwise. */ bool IsActive(ola_plugin_id plugin_id) const; /** * @brief Check if a plugin is enabled. * @param plugin_id the id of the plugin to check. * @returns true if the plugin is enabled, false otherwise. */ bool IsEnabled(ola_plugin_id plugin_id) const; /** * @brief Enable & start a plugin * @param plugin_id the id of the plugin to start. * @returns true if the plugin was started or was already running, false if * it couldn't be started. * * This call will enable a plugin, but may not start it due to conflicts with * existing plugins. */ bool EnableAndStartPlugin(ola_plugin_id plugin_id); /** * @brief Disable & stop a plugin. * @param plugin_id the id of the plugin to stop. */ void DisableAndStopPlugin(ola_plugin_id plugin_id); /** * @brief Return a list of plugins that conflict with this particular plugin. * @param plugin_id the id of the plugin to check. * @param[out] plugins the list of plugins that conflict with this one. */ void GetConflictList(ola_plugin_id plugin_id, std::vector *plugins); private: typedef std::map PluginMap; std::vector m_plugin_loaders; PluginMap m_loaded_plugins; // plugins that are loaded PluginMap m_active_plugins; // active plugins PluginMap m_enabled_plugins; // enabled plugins PluginAdaptor *m_plugin_adaptor; bool StartIfSafe(AbstractPlugin *plugin); AbstractPlugin* CheckForRunningConflicts(const AbstractPlugin *plugin) const; DISALLOW_COPY_AND_ASSIGN(PluginManager); }; } // namespace ola #endif // OLAD_PLUGINMANAGER_H_ ola-0.10.5.nojsmin/olad/RDMHTTPModule.cpp0000644000175000017500000032470613023355232017405 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * RDMHTTPModule.cpp * This module acts as the HTTP -> olad gateway for RDM commands. * Copyright (C) 2010 Simon Newton */ #include #include #include #include #include #include #include #include #include #include #include #include "ola/Callback.h" #include "ola/Constants.h" #include "ola/Logging.h" #include "ola/OlaCallbackClient.h" #include "ola/StringUtils.h" #include "ola/rdm/RDMEnums.h" #include "ola/rdm/RDMHelper.h" #include "ola/rdm/UID.h" #include "ola/rdm/UIDSet.h" #include "ola/thread/Mutex.h" #include "ola/web/Json.h" #include "ola/web/JsonSections.h" #include "olad/OlaServer.h" #include "olad/OladHTTPServer.h" #include "olad/RDMHTTPModule.h" namespace ola { using ola::OladHTTPServer; using ola::client::OlaUniverse; using ola::client::Result; using ola::http::HTTPRequest; using ola::http::HTTPResponse; using ola::http::HTTPServer; using ola::rdm::UID; using ola::thread::MutexLocker; using ola::web::BoolItem; using ola::web::GenericItem; using ola::web::HiddenItem; using ola::web::JsonArray; using ola::web::JsonObject; using ola::web::JsonSection; using ola::web::SelectItem; using ola::web::StringItem; using ola::web::UIntItem; using std::endl; using std::map; using std::ostringstream; using std::pair; using std::set; using std::string; using std::vector; const char RDMHTTPModule::BACKEND_DISCONNECTED_ERROR[] = "Failed to send request, client isn't connected"; // global URL params const char RDMHTTPModule::HINT_KEY[] = "hint"; const char RDMHTTPModule::ID_KEY[] = "id"; const char RDMHTTPModule::SECTION_KEY[] = "section"; const char RDMHTTPModule::UID_KEY[] = "uid"; // URL params for particular sections const char RDMHTTPModule::ADDRESS_FIELD[] = "address"; const char RDMHTTPModule::DISPLAY_INVERT_FIELD[] = "invert"; const char RDMHTTPModule::GENERIC_BOOL_FIELD[] = "bool"; const char RDMHTTPModule::GENERIC_STRING_FIELD[] = "string"; const char RDMHTTPModule::GENERIC_UINT_FIELD[] = "int"; const char RDMHTTPModule::IDENTIFY_DEVICE_FIELD[] = "identify_device"; const char RDMHTTPModule::LABEL_FIELD[] = "label"; const char RDMHTTPModule::LANGUAGE_FIELD[] = "language"; const char RDMHTTPModule::RECORD_SENSOR_FIELD[] = "record"; const char RDMHTTPModule::SUB_DEVICE_FIELD[] = "sub_device"; // section identifiers const char RDMHTTPModule::BOOT_SOFTWARE_SECTION[] = "boot_software"; const char RDMHTTPModule::CLOCK_SECTION[] = "clock"; const char RDMHTTPModule::COMMS_STATUS_SECTION[] = "comms_status"; const char RDMHTTPModule::DEVICE_HOURS_SECTION[] = "device_hours"; const char RDMHTTPModule::DEVICE_INFO_SECTION[] = "device_info"; const char RDMHTTPModule::DEVICE_LABEL_SECTION[] = "device_label"; const char RDMHTTPModule::DISPLAY_INVERT_SECTION[] = "display_invert"; const char RDMHTTPModule::DISPLAY_LEVEL_SECTION[] = "display_level"; const char RDMHTTPModule::DMX_ADDRESS_SECTION[] = "dmx_address"; const char RDMHTTPModule::DNS_DOMAIN_NAME_SECTION[] = "dns_domain_name"; const char RDMHTTPModule::DNS_HOSTNAME_SECTION[] = "dns_hostname"; const char RDMHTTPModule::FACTORY_DEFAULTS_SECTION[] = "factory_defaults"; const char RDMHTTPModule::IDENTIFY_DEVICE_SECTION[] = "identify_device"; const char RDMHTTPModule::LAMP_HOURS_SECTION[] = "lamp_hours"; const char RDMHTTPModule::LAMP_MODE_SECTION[] = "lamp_mode"; const char RDMHTTPModule::LAMP_STATE_SECTION[] = "lamp_state"; const char RDMHTTPModule::LAMP_STRIKES_SECTION[] = "lamp_strikes"; const char RDMHTTPModule::LANGUAGE_SECTION[] = "language"; const char RDMHTTPModule::MANUFACTURER_LABEL_SECTION[] = "manufacturer_label"; const char RDMHTTPModule::PAN_INVERT_SECTION[] = "pan_invert"; const char RDMHTTPModule::PAN_TILT_SWAP_SECTION[] = "pan_tilt_swap"; const char RDMHTTPModule::PERSONALITY_SECTION[] = "personality"; const char RDMHTTPModule::POWER_CYCLES_SECTION[] = "power_cycles"; const char RDMHTTPModule::POWER_STATE_SECTION[] = "power_state"; const char RDMHTTPModule::PRODUCT_DETAIL_SECTION[] = "product_detail"; const char RDMHTTPModule::PROXIED_DEVICES_SECTION[] = "proxied_devices"; const char RDMHTTPModule::RESET_DEVICE_SECTION[] = "reset_device"; const char RDMHTTPModule::SENSOR_SECTION[] = "sensor"; const char RDMHTTPModule::TILT_INVERT_SECTION[] = "tilt_invert"; // section names const char RDMHTTPModule::BOOT_SOFTWARE_SECTION_NAME[] = "Boot Software Version"; const char RDMHTTPModule::CLOCK_SECTION_NAME[] = "Clock"; const char RDMHTTPModule::COMMS_STATUS_SECTION_NAME[] = "Communication Status"; const char RDMHTTPModule::DEVICE_HOURS_SECTION_NAME[] = "Device Hours"; const char RDMHTTPModule::DEVICE_INFO_SECTION_NAME[] = "Device Info"; const char RDMHTTPModule::DEVICE_LABEL_SECTION_NAME[] = "Device Label"; const char RDMHTTPModule::DISPLAY_INVERT_SECTION_NAME[] = "Display Invert"; const char RDMHTTPModule::DISPLAY_LEVEL_SECTION_NAME[] = "Display Level"; const char RDMHTTPModule::DMX_ADDRESS_SECTION_NAME[] = "DMX Start Address"; const char RDMHTTPModule::DNS_DOMAIN_NAME_SECTION_NAME[] = "DNS Domain Name"; const char RDMHTTPModule::DNS_HOSTNAME_SECTION_NAME[] = "DNS Hostname"; const char RDMHTTPModule::FACTORY_DEFAULTS_SECTION_NAME[] = "Factory Defaults"; const char RDMHTTPModule::IDENTIFY_DEVICE_SECTION_NAME[] = "Identify Device"; const char RDMHTTPModule::LAMP_HOURS_SECTION_NAME[] = "Lamp Hours"; const char RDMHTTPModule::LAMP_MODE_SECTION_NAME[] = "Lamp On Mode"; const char RDMHTTPModule::LAMP_STATE_SECTION_NAME[] = "Lamp State"; const char RDMHTTPModule::LAMP_STRIKES_SECTION_NAME[] = "Lamp Strikes"; const char RDMHTTPModule::LANGUAGE_SECTION_NAME[] = "Language"; const char RDMHTTPModule::MANUFACTURER_LABEL_SECTION_NAME[] = "Manufacturer Label"; const char RDMHTTPModule::PAN_INVERT_SECTION_NAME[] = "Pan Invert"; const char RDMHTTPModule::PAN_TILT_SWAP_SECTION_NAME[] = "Pan/Tilt Swap"; const char RDMHTTPModule::PERSONALITY_SECTION_NAME[] = "DMX Personality"; const char RDMHTTPModule::POWER_CYCLES_SECTION_NAME[] = "Device Power Cycles"; const char RDMHTTPModule::POWER_STATE_SECTION_NAME[] = "Power State"; const char RDMHTTPModule::PRODUCT_DETAIL_SECTION_NAME[] = "Product Details"; const char RDMHTTPModule::PROXIED_DEVICES_SECTION_NAME[] = "Proxied Devices"; const char RDMHTTPModule::RESET_DEVICE_SECTION_NAME[] = "Reset Device"; const char RDMHTTPModule::TILT_INVERT_SECTION_NAME[] = "Tilt Invert"; RDMHTTPModule::RDMHTTPModule(HTTPServer *http_server, client::OlaClient *client) : m_server(http_server), m_client(client), m_shim(client), m_rdm_api(&m_shim), m_pid_store(NULL) { m_server->RegisterHandler( "/rdm/run_discovery", NewCallback(this, &RDMHTTPModule::RunRDMDiscovery)); m_server->RegisterHandler( "/json/rdm/uids", NewCallback(this, &RDMHTTPModule::JsonUIDs)); m_server->RegisterHandler( "/json/rdm/uid_info", NewCallback(this, &RDMHTTPModule::JsonUIDInfo)); // Deprecated for clarity, use uid_identify_device instead m_server->RegisterHandler( "/json/rdm/uid_identify", NewCallback(this, &RDMHTTPModule::JsonUIDIdentifyDevice)); m_server->RegisterHandler( "/json/rdm/uid_identify_device", NewCallback(this, &RDMHTTPModule::JsonUIDIdentifyDevice)); m_server->RegisterHandler( "/json/rdm/uid_personalities", NewCallback(this, &RDMHTTPModule::JsonUIDPersonalities)); m_server->RegisterHandler( "/json/rdm/supported_pids", NewCallback(this, &RDMHTTPModule::JsonSupportedPIDs)); m_server->RegisterHandler( "/json/rdm/supported_sections", NewCallback(this, &RDMHTTPModule::JsonSupportedSections)); m_server->RegisterHandler( "/json/rdm/section_info", NewCallback(this, &RDMHTTPModule::JsonSectionInfo)); m_server->RegisterHandler( "/json/rdm/set_section_info", NewCallback(this, &RDMHTTPModule::JsonSaveSectionInfo)); } /* * Teardown */ RDMHTTPModule::~RDMHTTPModule() { map::iterator uid_iter; for (uid_iter = m_universe_uids.begin(); uid_iter != m_universe_uids.end(); uid_iter++) { delete uid_iter->second; } m_universe_uids.clear(); } /** * @brief Can be called while the server is running. Ownership is not transferred. */ void RDMHTTPModule::SetPidStore(const ola::rdm::RootPidStore *pid_store) { MutexLocker lock(&m_pid_store_mu); m_pid_store = pid_store; } /** * @brief Run RDM discovery for a universe * @param request the HTTPRequest * @param response the HTTPResponse * @returns MHD_NO or MHD_YES */ int RDMHTTPModule::RunRDMDiscovery(const HTTPRequest *request, HTTPResponse *response) { if (request->CheckParameterExists(OladHTTPServer::HELP_PARAMETER)) { return OladHTTPServer::ServeUsage(response, "?id=[universe]&incremental=true"); } unsigned int universe_id; if (!CheckForInvalidId(request, &universe_id)) { return OladHTTPServer::ServeHelpRedirect(response); } string incremental_str = request->GetParameter("incremental"); bool incremental = incremental_str == "true"; m_client->RunDiscovery( universe_id, incremental ? client::DISCOVERY_INCREMENTAL : client::DISCOVERY_FULL, NewSingleCallback(this, &RDMHTTPModule::HandleUIDList, response, universe_id)); return MHD_YES; } /** * @brief Return the list of uids for this universe as json * @param request the HTTPRequest * @param response the HTTPResponse * @returns MHD_NO or MHD_YES */ int RDMHTTPModule::JsonUIDs(const HTTPRequest *request, HTTPResponse *response) { if (request->CheckParameterExists(OladHTTPServer::HELP_PARAMETER)) { return OladHTTPServer::ServeUsage(response, "?id=[universe]"); } unsigned int universe_id; if (!CheckForInvalidId(request, &universe_id)) { return OladHTTPServer::ServeHelpRedirect(response); } m_client->RunDiscovery( universe_id, client::DISCOVERY_CACHED, NewSingleCallback(this, &RDMHTTPModule::HandleUIDList, response, universe_id)); return MHD_YES; } /** * @brief Return the device info for this uid. * @param request the HTTPRequest * @param response the HTTPResponse * @returns MHD_NO or MHD_YES */ int RDMHTTPModule::JsonUIDInfo(const HTTPRequest *request, HTTPResponse *response) { if (request->CheckParameterExists(OladHTTPServer::HELP_PARAMETER)) { return OladHTTPServer::ServeUsage(response, "?id=[universe]&uid=[uid]"); } unsigned int universe_id; if (!CheckForInvalidId(request, &universe_id)) { return OladHTTPServer::ServeHelpRedirect(response); } UID *uid = NULL; if (!CheckForInvalidUid(request, &uid)) { return OladHTTPServer::ServeHelpRedirect(response); } string error; bool ok = m_rdm_api.GetDeviceInfo( universe_id, *uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::UIDInfoHandler, response), &error); delete uid; if (!ok) { return m_server->ServeError(response, BACKEND_DISCONNECTED_ERROR); } return MHD_YES; } /** * @brief Returns the identify state for the device. * @param request the HTTPRequest * @param response the HTTPResponse * @returns MHD_NO or MHD_YES */ int RDMHTTPModule::JsonUIDIdentifyDevice(const HTTPRequest *request, HTTPResponse *response) { if (request->CheckParameterExists(OladHTTPServer::HELP_PARAMETER)) { return OladHTTPServer::ServeUsage(response, "?id=[universe]&uid=[uid]"); } unsigned int universe_id; if (!CheckForInvalidId(request, &universe_id)) { return OladHTTPServer::ServeHelpRedirect(response); } UID *uid = NULL; if (!CheckForInvalidUid(request, &uid)) { return OladHTTPServer::ServeHelpRedirect(response); } string error; bool ok = m_rdm_api.GetIdentifyDevice( universe_id, *uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::UIDIdentifyDeviceHandler, response), &error); delete uid; if (!ok) { return m_server->ServeError(response, BACKEND_DISCONNECTED_ERROR); } return MHD_YES; } /** * @brief Returns the personalities on the device * @param request the HTTPRequest * @param response the HTTPResponse * @returns MHD_NO or MHD_YES */ int RDMHTTPModule::JsonUIDPersonalities(const HTTPRequest *request, HTTPResponse *response) { if (request->CheckParameterExists(OladHTTPServer::HELP_PARAMETER)) { return OladHTTPServer::ServeUsage(response, "?id=[universe]&uid=[uid]"); } unsigned int universe_id; if (!CheckForInvalidId(request, &universe_id)) { return OladHTTPServer::ServeHelpRedirect(response); } UID *uid = NULL; if (!CheckForInvalidUid(request, &uid)) { return OladHTTPServer::ServeHelpRedirect(response); } string error = GetPersonalities(request, response, universe_id, *uid, false, true); delete uid; if (!error.empty()) { return m_server->ServeError(response, BACKEND_DISCONNECTED_ERROR + error); } return MHD_YES; } /** * @brief Return a list of PIDs supported by this device. * * This isn't used by the UI but it's useful for debugging. * @param request the HTTPRequest * @param response the HTTPResponse * @returns MHD_NO or MHD_YES * @sa JsonSupportedSections */ int RDMHTTPModule::JsonSupportedPIDs(const HTTPRequest *request, HTTPResponse *response) { if (request->CheckParameterExists(OladHTTPServer::HELP_PARAMETER)) { return OladHTTPServer::ServeUsage(response, "?id=[universe]&uid=[uid]"); } unsigned int universe_id; if (!CheckForInvalidId(request, &universe_id)) { return OladHTTPServer::ServeHelpRedirect(response); } UID *uid = NULL; if (!CheckForInvalidUid(request, &uid)) { return OladHTTPServer::ServeHelpRedirect(response); } string error; bool ok = m_rdm_api.GetSupportedParameters( universe_id, *uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::SupportedParamsHandler, response), &error); delete uid; if (!ok) { return m_server->ServeError(response, BACKEND_DISCONNECTED_ERROR); } return MHD_YES; } /** * @brief Return a list of sections to display in the RDM control panel. * * We use the response from SUPPORTED_PARAMS and DEVICE_INFO to decide which * PIDs exist. * @param request the HTTPRequest * @param response the HTTPResponse * @returns MHD_NO or MHD_YES */ int RDMHTTPModule::JsonSupportedSections(const HTTPRequest *request, HTTPResponse *response) { if (request->CheckParameterExists(OladHTTPServer::HELP_PARAMETER)) { return OladHTTPServer::ServeUsage(response, "?id=[universe]&uid=[uid]"); } unsigned int universe_id; if (!CheckForInvalidId(request, &universe_id)) { return OladHTTPServer::ServeHelpRedirect(response); } UID *uid = NULL; if (!CheckForInvalidUid(request, &uid)) { return OladHTTPServer::ServeHelpRedirect(response); } string error; bool ok = m_rdm_api.GetSupportedParameters( universe_id, *uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::SupportedSectionsHandler, response, universe_id, *uid), &error); delete uid; if (!ok) { return m_server->ServeError(response, BACKEND_DISCONNECTED_ERROR); } return MHD_YES; } /** * @brief Get the information required to render a section in the RDM * controller panel */ int RDMHTTPModule::JsonSectionInfo(const HTTPRequest *request, HTTPResponse *response) { if (request->CheckParameterExists(OladHTTPServer::HELP_PARAMETER)) { return OladHTTPServer::ServeUsage(response, "?id=[universe]&uid=[uid]" "&section=[section]
See " "/json/rdm/supported_sections for " "sections"); } unsigned int universe_id; if (!CheckForInvalidId(request, &universe_id)) { return OladHTTPServer::ServeHelpRedirect(response); } UID *uid = NULL; if (!CheckForInvalidUid(request, &uid)) { return OladHTTPServer::ServeHelpRedirect(response); } string section_id = request->GetParameter(SECTION_KEY); string error; if (section_id == PROXIED_DEVICES_SECTION) { error = GetProxiedDevices(response, universe_id, *uid); } else if (section_id == COMMS_STATUS_SECTION) { error = GetCommStatus(response, universe_id, *uid); } else if (section_id == DEVICE_INFO_SECTION) { error = GetDeviceInfo(request, response, universe_id, *uid); } else if (section_id == PRODUCT_DETAIL_SECTION) { error = GetProductIds(request, response, universe_id, *uid); } else if (section_id == MANUFACTURER_LABEL_SECTION) { error = GetManufacturerLabel(request, response, universe_id, *uid); } else if (section_id == DEVICE_LABEL_SECTION) { error = GetDeviceLabel(request, response, universe_id, *uid); } else if (section_id == FACTORY_DEFAULTS_SECTION) { error = GetFactoryDefaults(response, universe_id, *uid); } else if (section_id == LANGUAGE_SECTION) { error = GetLanguage(response, universe_id, *uid); } else if (section_id == BOOT_SOFTWARE_SECTION) { error = GetBootSoftware(response, universe_id, *uid); } else if (section_id == PERSONALITY_SECTION) { error = GetPersonalities(request, response, universe_id, *uid, true); } else if (section_id == DMX_ADDRESS_SECTION) { error = GetStartAddress(request, response, universe_id, *uid); } else if (section_id == SENSOR_SECTION) { error = GetSensor(request, response, universe_id, *uid); } else if (section_id == DEVICE_HOURS_SECTION) { error = GetDeviceHours(request, response, universe_id, *uid); } else if (section_id == LAMP_HOURS_SECTION) { error = GetLampHours(request, response, universe_id, *uid); } else if (section_id == LAMP_MODE_SECTION) { error = GetLampMode(request, response, universe_id, *uid); } else if (section_id == LAMP_STATE_SECTION) { error = GetLampState(request, response, universe_id, *uid); } else if (section_id == LAMP_STRIKES_SECTION) { error = GetLampStrikes(request, response, universe_id, *uid); } else if (section_id == POWER_CYCLES_SECTION) { error = GetPowerCycles(request, response, universe_id, *uid); } else if (section_id == DISPLAY_INVERT_SECTION) { error = GetDisplayInvert(response, universe_id, *uid); } else if (section_id == DISPLAY_LEVEL_SECTION) { error = GetDisplayLevel(response, universe_id, *uid); } else if (section_id == PAN_INVERT_SECTION) { error = GetPanInvert(response, universe_id, *uid); } else if (section_id == TILT_INVERT_SECTION) { error = GetTiltInvert(response, universe_id, *uid); } else if (section_id == PAN_TILT_SWAP_SECTION) { error = GetPanTiltSwap(response, universe_id, *uid); } else if (section_id == CLOCK_SECTION) { error = GetClock(response, universe_id, *uid); } else if (section_id == IDENTIFY_DEVICE_SECTION) { error = GetIdentifyDevice(response, universe_id, *uid); } else if (section_id == POWER_STATE_SECTION) { error = GetPowerState(response, universe_id, *uid); } else if (section_id == RESET_DEVICE_SECTION) { // No get command available, so just generate the JSON error = GetResetDevice(response); } else if (section_id == DNS_HOSTNAME_SECTION) { error = GetDnsHostname(response, universe_id, *uid); } else if (section_id == DNS_DOMAIN_NAME_SECTION) { error = GetDnsDomainName(response, universe_id, *uid); } else { OLA_INFO << "Missing or unknown section id: " << section_id; delete uid; return OladHTTPServer::ServeHelpRedirect(response); } delete uid; if (!error.empty()) { return m_server->ServeError(response, BACKEND_DISCONNECTED_ERROR + error); } return MHD_YES; } /** * Save the information for a section or item. */ int RDMHTTPModule::JsonSaveSectionInfo(const HTTPRequest *request, HTTPResponse *response) { if (request->CheckParameterExists(OladHTTPServer::HELP_PARAMETER)) { return OladHTTPServer::ServeUsage(response, "?id=[universe]&uid=[uid]" "&section=[section]
See " "/json/rdm/supported_sections for " "sections"); } unsigned int universe_id; if (!CheckForInvalidId(request, &universe_id)) { return OladHTTPServer::ServeHelpRedirect(response); } UID *uid = NULL; if (!CheckForInvalidUid(request, &uid)) { return OladHTTPServer::ServeHelpRedirect(response); } string section_id = request->GetParameter(SECTION_KEY); string error; if (section_id == DEVICE_LABEL_SECTION) { error = SetDeviceLabel(request, response, universe_id, *uid); } else if (section_id == COMMS_STATUS_SECTION) { error = ClearCommsCounters(response, universe_id, *uid); } else if (section_id == FACTORY_DEFAULTS_SECTION) { error = SetFactoryDefault(response, universe_id, *uid); } else if (section_id == LANGUAGE_SECTION) { error = SetLanguage(request, response, universe_id, *uid); } else if (section_id == PERSONALITY_SECTION) { error = SetPersonality(request, response, universe_id, *uid); } else if (section_id == DMX_ADDRESS_SECTION) { error = SetStartAddress(request, response, universe_id, *uid); } else if (section_id == SENSOR_SECTION) { error = RecordSensor(request, response, universe_id, *uid); } else if (section_id == DEVICE_HOURS_SECTION) { error = SetDeviceHours(request, response, universe_id, *uid); } else if (section_id == LAMP_HOURS_SECTION) { error = SetLampHours(request, response, universe_id, *uid); } else if (section_id == LAMP_MODE_SECTION) { error = SetLampMode(request, response, universe_id, *uid); } else if (section_id == LAMP_STATE_SECTION) { error = SetLampState(request, response, universe_id, *uid); } else if (section_id == LAMP_STRIKES_SECTION) { error = SetLampStrikes(request, response, universe_id, *uid); } else if (section_id == POWER_CYCLES_SECTION) { error = SetPowerCycles(request, response, universe_id, *uid); } else if (section_id == DISPLAY_INVERT_SECTION) { error = SetDisplayInvert(request, response, universe_id, *uid); } else if (section_id == DISPLAY_LEVEL_SECTION) { error = SetDisplayLevel(request, response, universe_id, *uid); } else if (section_id == PAN_INVERT_SECTION) { error = SetPanInvert(request, response, universe_id, *uid); } else if (section_id == TILT_INVERT_SECTION) { error = SetTiltInvert(request, response, universe_id, *uid); } else if (section_id == PAN_TILT_SWAP_SECTION) { error = SetPanTiltSwap(request, response, universe_id, *uid); } else if (section_id == CLOCK_SECTION) { error = SyncClock(response, universe_id, *uid); } else if (section_id == IDENTIFY_DEVICE_SECTION) { error = SetIdentifyDevice(request, response, universe_id, *uid); } else if (section_id == POWER_STATE_SECTION) { error = SetPowerState(request, response, universe_id, *uid); } else if (section_id == RESET_DEVICE_SECTION) { error = SetResetDevice(request, response, universe_id, *uid); } else if (section_id == DNS_HOSTNAME_SECTION) { error = SetDnsHostname(request, response, universe_id, *uid); } else if (section_id == DNS_DOMAIN_NAME_SECTION) { error = SetDnsDomainName(request, response, universe_id, *uid); } else { OLA_INFO << "Missing or unknown section id: " << section_id; delete uid; return OladHTTPServer::ServeHelpRedirect(response); } delete uid; if (!error.empty()) { return RespondWithError(response, error); } return MHD_YES; } /** * This is called from the main http server whenever a new list of active * universes is received. It's used to prune the uid map so we don't bother * trying to resolve uids for universes that no longer exist. */ void RDMHTTPModule::PruneUniverseList(const vector &universes) { map::iterator uid_iter; for (uid_iter = m_universe_uids.begin(); uid_iter != m_universe_uids.end(); uid_iter++) { uid_iter->second->active = false; } vector::const_iterator iter; for (iter = universes.begin(); iter != universes.end(); ++iter) { uid_iter = m_universe_uids.find(iter->Id()); if (uid_iter != m_universe_uids.end()) { uid_iter->second->active = true; } } // clean up the uid map for those universes that no longer exist for (uid_iter = m_universe_uids.begin(); uid_iter != m_universe_uids.end();) { if (!uid_iter->second->active) { OLA_DEBUG << "removing " << uid_iter->first << " from the uid map"; delete uid_iter->second; m_universe_uids.erase(uid_iter++); } else { uid_iter++; } } } /* * @brief Handle the UID list response. * @param response the HTTPResponse that is associated with the request. * @param uids the UIDs for this response. * @param error an error string. */ void RDMHTTPModule::HandleUIDList(HTTPResponse *response, unsigned int universe_id, const Result &result, const ola::rdm::UIDSet &uids) { if (!result.Success()) { m_server->ServeError(response, result.Error()); return; } ola::rdm::UIDSet::Iterator iter = uids.Begin(); uid_resolution_state *uid_state = GetUniverseUidsOrCreate(universe_id); // mark all uids as inactive so we can remove the unused ones at the end map::iterator uid_iter; for (uid_iter = uid_state->resolved_uids.begin(); uid_iter != uid_state->resolved_uids.end(); ++uid_iter) uid_iter->second.active = false; JsonObject json; json.Add("universe", universe_id); JsonArray *json_uids = json.AddArray("uids"); for (; iter != uids.End(); ++iter) { uid_iter = uid_state->resolved_uids.find(*iter); string manufacturer = ""; string device = ""; if (uid_iter == uid_state->resolved_uids.end()) { // schedule resolution uid_state->pending_uids.push(std::make_pair(*iter, RESOLVE_MANUFACTURER)); uid_state->pending_uids.push(std::make_pair(*iter, RESOLVE_DEVICE)); resolved_uid uid_descriptor = {"", "", true}; uid_state->resolved_uids[*iter] = uid_descriptor; OLA_INFO << "Adding UID " << *iter << " to resolution queue"; } else { manufacturer = uid_iter->second.manufacturer; device = uid_iter->second.device; uid_iter->second.active = true; } JsonObject *json_uid = json_uids->AppendObject(); json_uid->Add("manufacturer_id", iter->ManufacturerId()); json_uid->Add("device_id", iter->DeviceId()); json_uid->Add("device", device); json_uid->Add("manufacturer", manufacturer); json_uid->Add("uid", iter->ToString()); } response->SetNoCache(); response->SetContentType(HTTPServer::CONTENT_TYPE_PLAIN); response->SendJson(json); delete response; // remove any old UIDs for (uid_iter = uid_state->resolved_uids.begin(); uid_iter != uid_state->resolved_uids.end();) { if (!uid_iter->second.active) { OLA_INFO << "Removed UID " << uid_iter->first; uid_state->resolved_uids.erase(uid_iter++); } else { ++uid_iter; } } if (!uid_state->uid_resolution_running) { ResolveNextUID(universe_id); } } /* * @brief Send the RDM command needed to resolve the next uid in the queue * @param universe_id the universe id to resolve the next UID for. */ void RDMHTTPModule::ResolveNextUID(unsigned int universe_id) { bool sent_request = false; string error; uid_resolution_state *uid_state = GetUniverseUids(universe_id); if (!uid_state) { return; } while (!sent_request) { if (uid_state->pending_uids.empty()) { uid_state->uid_resolution_running = false; return; } uid_state->uid_resolution_running = true; pair &uid_action_pair = uid_state->pending_uids.front(); if (uid_action_pair.second == RESOLVE_MANUFACTURER) { OLA_INFO << "sending manufacturer request for " << uid_action_pair.first; sent_request = m_rdm_api.GetManufacturerLabel( universe_id, uid_action_pair.first, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::UpdateUIDManufacturerLabel, universe_id, uid_action_pair.first), &error); uid_state->pending_uids.pop(); } else if (uid_action_pair.second == RESOLVE_DEVICE) { OLA_INFO << "sending device request for " << uid_action_pair.first; sent_request = m_rdm_api.GetDeviceLabel( universe_id, uid_action_pair.first, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::UpdateUIDDeviceLabel, universe_id, uid_action_pair.first), &error); uid_state->pending_uids.pop(); } else { OLA_WARN << "Unknown UID resolve action " << static_cast(uid_action_pair.second); } } } /* * @brief Handle the manufacturer label response. */ void RDMHTTPModule::UpdateUIDManufacturerLabel( unsigned int universe, UID uid, const ola::rdm::ResponseStatus &status, const string &manufacturer_label) { uid_resolution_state *uid_state = GetUniverseUids(universe); if (!uid_state) { return; } if (CheckForRDMSuccess(status)) { map::iterator uid_iter; uid_iter = uid_state->resolved_uids.find(uid); if (uid_iter != uid_state->resolved_uids.end()) { uid_iter->second.manufacturer = manufacturer_label; } } ResolveNextUID(universe); } /* * @brief Handle the device label response. */ void RDMHTTPModule::UpdateUIDDeviceLabel( unsigned int universe, UID uid, const ola::rdm::ResponseStatus &status, const string &device_label) { uid_resolution_state *uid_state = GetUniverseUids(universe); if (!uid_state) { return; } if (CheckForRDMSuccess(status)) { map::iterator uid_iter; uid_iter = uid_state->resolved_uids.find(uid); if (uid_iter != uid_state->resolved_uids.end()) { uid_iter->second.device = device_label; } } ResolveNextUID(universe); } /* * @brief Get the UID resolution state for a particular universe * @param universe the id of the universe to get the state for */ RDMHTTPModule::uid_resolution_state *RDMHTTPModule::GetUniverseUids( unsigned int universe) { map::iterator iter = m_universe_uids.find(universe); return iter == m_universe_uids.end() ? NULL : iter->second; } /* * @brief Get the UID resolution state for a particular universe or create one if it * doesn't exist. * @param universe the id of the universe to get the state for */ RDMHTTPModule::uid_resolution_state *RDMHTTPModule::GetUniverseUidsOrCreate( unsigned int universe) { map::iterator iter = m_universe_uids.find(universe); if (iter == m_universe_uids.end()) { OLA_DEBUG << "Adding a new state entry for " << universe; uid_resolution_state *state = new uid_resolution_state(); state->uid_resolution_running = false; state->active = true; pair p(universe, state); iter = m_universe_uids.insert(p).first; } return iter->second; } /** * @brief Handle the Device Info response and build the JSON */ void RDMHTTPModule::UIDInfoHandler(HTTPResponse *response, const ola::rdm::ResponseStatus &status, const ola::rdm::DeviceDescriptor &device) { if (CheckForRDMError(response, status)) { return; } JsonObject json; json.Add("error", ""); json.Add("address", device.dmx_start_address); json.Add("footprint", device.dmx_footprint); json.Add("personality", static_cast(device.current_personality)); json.Add("personality_count", static_cast(device.personality_count)); response->SetNoCache(); response->SetContentType(HTTPServer::CONTENT_TYPE_PLAIN); response->SendJson(json); delete response; } /** * @brief Handle the identify device response and build the JSON */ void RDMHTTPModule::UIDIdentifyDeviceHandler( HTTPResponse *response, const ola::rdm::ResponseStatus &status, bool value) { if (CheckForRDMError(response, status)) { return; } JsonObject json; json.Add("error", ""); json.Add("identify_device", value); response->SetNoCache(); response->SetContentType(HTTPServer::CONTENT_TYPE_PLAIN); response->SendJson(json); delete response; } /** * @brief Send the response to a DMX personality section */ void RDMHTTPModule::SendPersonalityResponse(HTTPResponse *response, personality_info *info) { JsonObject json; json.Add("error", ""); JsonArray *personalities = json.AddArray("personalities"); unsigned int i = 1; while (i <= info->total && i <= info->personalities.size()) { if (info->personalities[i - 1].first != INVALID_PERSONALITY) { JsonObject *personality = personalities->AppendObject(); personality->Add("name", info->personalities[i - 1].second); personality->Add("index", i); personality->Add("footprint", info->personalities[i - 1].first); } i++; } json.Add("selected", info->active); response->SetNoCache(); response->SetContentType(HTTPServer::CONTENT_TYPE_PLAIN); response->SendJson(json); delete info->uid; delete info; } /* * @brief Handle the response from a supported params request */ void RDMHTTPModule::SupportedParamsHandler( HTTPResponse *response, const ola::rdm::ResponseStatus &status, const vector &pids) { JsonObject json; if (CheckForRDMSuccess(status)) { JsonArray *pids_json = json.AddArray("pids"); vector::const_iterator iter = pids.begin(); for (; iter != pids.end(); ++iter) pids_json->Append(*iter); } response->SetNoCache(); response->SetContentType(HTTPServer::CONTENT_TYPE_PLAIN); response->SendJson(json); delete response; } /** * @brief Takes the supported PIDs for a device and come up with the list of * sections to display in the RDM panel */ void RDMHTTPModule::SupportedSectionsHandler( HTTPResponse *response, unsigned int universe_id, UID uid, const ola::rdm::ResponseStatus &status, const vector &pid_list) { string error; // nacks here are ok if the device doesn't support SUPPORTED_PARAMS if (!CheckForRDMSuccess(status) && !status.WasNacked()) { m_server->ServeError(response, BACKEND_DISCONNECTED_ERROR + error); return; } m_rdm_api.GetDeviceInfo( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::SupportedSectionsDeviceInfoHandler, response, pid_list), &error); if (!error.empty()) m_server->ServeError(response, BACKEND_DISCONNECTED_ERROR + error); } /** * @brief Handle the second part of the supported sections request. */ void RDMHTTPModule::SupportedSectionsDeviceInfoHandler( HTTPResponse *response, const vector pid_list, const ola::rdm::ResponseStatus &status, const ola::rdm::DeviceDescriptor &device) { vector sections; std::set pids; copy(pid_list.begin(), pid_list.end(), inserter(pids, pids.end())); // PID_DEVICE_INFO is required so we always add it string hint; if (pids.find(ola::rdm::PID_DEVICE_MODEL_DESCRIPTION) != pids.end()) { hint.push_back('m'); // m is for device model } AddSection(§ions, DEVICE_INFO_SECTION, DEVICE_INFO_SECTION_NAME, hint); AddSection(§ions, IDENTIFY_DEVICE_SECTION, IDENTIFY_DEVICE_SECTION_NAME); bool dmx_address_added = false; bool include_software_version = false; set::const_iterator iter = pids.begin(); for (; iter != pids.end(); ++iter) { switch (*iter) { case ola::rdm::PID_PROXIED_DEVICES: AddSection(§ions, PROXIED_DEVICES_SECTION, PROXIED_DEVICES_SECTION_NAME); break; case ola::rdm::PID_COMMS_STATUS: AddSection(§ions, COMMS_STATUS_SECTION, COMMS_STATUS_SECTION_NAME); break; case ola::rdm::PID_PRODUCT_DETAIL_ID_LIST: AddSection(§ions, PRODUCT_DETAIL_SECTION, PRODUCT_DETAIL_SECTION_NAME); break; case ola::rdm::PID_MANUFACTURER_LABEL: AddSection(§ions, MANUFACTURER_LABEL_SECTION, MANUFACTURER_LABEL_SECTION_NAME); break; case ola::rdm::PID_DEVICE_LABEL: AddSection(§ions, DEVICE_LABEL_SECTION, DEVICE_LABEL_SECTION_NAME); break; case ola::rdm::PID_FACTORY_DEFAULTS: AddSection(§ions, FACTORY_DEFAULTS_SECTION, FACTORY_DEFAULTS_SECTION_NAME); break; case ola::rdm::PID_LANGUAGE: AddSection(§ions, LANGUAGE_SECTION, LANGUAGE_SECTION_NAME); break; case ola::rdm::PID_BOOT_SOFTWARE_VERSION_ID: case ola::rdm::PID_BOOT_SOFTWARE_VERSION_LABEL: include_software_version = true; break; case ola::rdm::PID_DMX_PERSONALITY: if (pids.find(ola::rdm::PID_DMX_PERSONALITY_DESCRIPTION) == pids.end()) { AddSection(§ions, PERSONALITY_SECTION, PERSONALITY_SECTION_NAME); } else { AddSection(§ions, PERSONALITY_SECTION, PERSONALITY_SECTION_NAME, "l"); } break; case ola::rdm::PID_DMX_START_ADDRESS: AddSection(§ions, DMX_ADDRESS_SECTION, DMX_ADDRESS_SECTION_NAME); dmx_address_added = true; break; case ola::rdm::PID_DEVICE_HOURS: AddSection(§ions, DEVICE_HOURS_SECTION, DEVICE_HOURS_SECTION_NAME); break; case ola::rdm::PID_LAMP_HOURS: AddSection(§ions, LAMP_HOURS_SECTION, LAMP_HOURS_SECTION_NAME); break; case ola::rdm::PID_LAMP_STRIKES: AddSection(§ions, LAMP_STRIKES_SECTION, LAMP_STRIKES_SECTION_NAME); break; case ola::rdm::PID_LAMP_STATE: AddSection(§ions, LAMP_STATE_SECTION, LAMP_STATE_SECTION_NAME); break; case ola::rdm::PID_LAMP_ON_MODE: AddSection(§ions, LAMP_MODE_SECTION, LAMP_MODE_SECTION_NAME); break; case ola::rdm::PID_DEVICE_POWER_CYCLES: AddSection(§ions, POWER_CYCLES_SECTION, POWER_CYCLES_SECTION_NAME); break; case ola::rdm::PID_DISPLAY_INVERT: AddSection(§ions, DISPLAY_INVERT_SECTION, DISPLAY_INVERT_SECTION_NAME); break; case ola::rdm::PID_DISPLAY_LEVEL: AddSection(§ions, DISPLAY_LEVEL_SECTION, DISPLAY_LEVEL_SECTION_NAME); break; case ola::rdm::PID_PAN_INVERT: AddSection(§ions, PAN_INVERT_SECTION, PAN_INVERT_SECTION_NAME); break; case ola::rdm::PID_TILT_INVERT: AddSection(§ions, TILT_INVERT_SECTION, TILT_INVERT_SECTION_NAME); break; case ola::rdm::PID_PAN_TILT_SWAP: AddSection(§ions, PAN_TILT_SWAP_SECTION, PAN_TILT_SWAP_SECTION_NAME); break; case ola::rdm::PID_REAL_TIME_CLOCK: AddSection(§ions, CLOCK_SECTION, CLOCK_SECTION_NAME); break; case ola::rdm::PID_POWER_STATE: AddSection(§ions, POWER_STATE_SECTION, POWER_STATE_SECTION_NAME); break; case ola::rdm::PID_RESET_DEVICE: AddSection(§ions, RESET_DEVICE_SECTION, RESET_DEVICE_SECTION_NAME); break; case ola::rdm::PID_DNS_HOSTNAME: AddSection(§ions, DNS_HOSTNAME_SECTION, DNS_HOSTNAME_SECTION_NAME); break; case ola::rdm::PID_DNS_DOMAIN_NAME: AddSection(§ions, DNS_DOMAIN_NAME_SECTION, DNS_DOMAIN_NAME_SECTION_NAME); break; } } if (include_software_version) { AddSection(§ions, BOOT_SOFTWARE_SECTION, BOOT_SOFTWARE_SECTION_NAME); } if (CheckForRDMSuccess(status)) { if (device.dmx_footprint && !dmx_address_added) { AddSection(§ions, DMX_ADDRESS_SECTION, DMX_ADDRESS_SECTION_NAME); } if (device.sensor_count && pids.find(ola::rdm::PID_SENSOR_DEFINITION) != pids.end() && pids.find(ola::rdm::PID_SENSOR_VALUE) != pids.end()) { // sensors count from 1 for (unsigned int i = 0; i < device.sensor_count; ++i) { ostringstream heading, hint; hint << i; heading << "Sensor " << std::setfill(' ') << std::setw(3) << i; AddSection(§ions, SENSOR_SECTION, heading.str(), hint.str()); } } } sort(sections.begin(), sections.end(), lt_section_info()); JsonArray json; vector::const_iterator section_iter = sections.begin(); for (; section_iter != sections.end(); ++section_iter) { JsonObject *json_obj = json.AppendObject(); json_obj->Add("id", section_iter->id); json_obj->Add("name", section_iter->name); json_obj->Add("hint", section_iter->hint); } response->SetNoCache(); response->SetContentType(HTTPServer::CONTENT_TYPE_PLAIN); response->SendJson(json); delete response; } /* * @brief Handle the request for the communication status. */ string RDMHTTPModule::GetCommStatus(HTTPResponse *response, unsigned int universe_id, const UID &uid) { string error; m_rdm_api.GetCommStatus( universe_id, uid, NewSingleCallback(this, &RDMHTTPModule::CommStatusHandler, response), &error); return error; } /** * @brief Handle the response to a communication status call */ void RDMHTTPModule::CommStatusHandler(HTTPResponse *response, const ola::rdm::ResponseStatus &status, uint16_t short_messages, uint16_t length_mismatch, uint16_t checksum_fail) { if (CheckForRDMError(response, status)) { return; } JsonSection section; section.AddItem(new UIntItem("Short Messages", short_messages)); section.AddItem(new UIntItem("Length Mismatch", length_mismatch)); section.AddItem(new UIntItem("Checksum Failures", checksum_fail)); section.AddItem(new HiddenItem("1", GENERIC_UINT_FIELD)); section.SetSaveButton("Clear Counters"); RespondWithSection(response, section); } /** * @brief Clear the communication status counters */ string RDMHTTPModule::ClearCommsCounters(HTTPResponse *response, unsigned int universe_id, const UID &uid) { string error; m_rdm_api.ClearCommStatus( universe_id, uid, NewSingleCallback(this, &RDMHTTPModule::SetHandler, response), &error); return error; } /* * @brief Handle the request for the proxied devices */ string RDMHTTPModule::GetProxiedDevices(HTTPResponse *response, unsigned int universe_id, const UID &uid) { string error; m_rdm_api.GetProxiedDevices( universe_id, uid, NewSingleCallback(this, &RDMHTTPModule::ProxiedDevicesHandler, response, universe_id), &error); return error; } /** * @brief Handle the response to a proxied devices call. */ void RDMHTTPModule::ProxiedDevicesHandler( HTTPResponse *response, unsigned int universe_id, const ola::rdm::ResponseStatus &status, const vector &uids) { if (CheckForRDMError(response, status)) { return; } JsonSection section; uid_resolution_state *uid_state = GetUniverseUids(universe_id); vector::const_iterator iter = uids.begin(); unsigned int i = 1; for (; iter != uids.end(); ++iter, ++i) { string uid = iter->ToString(); // attempt to add device & manufacturer names if (uid_state) { map::iterator uid_iter = uid_state->resolved_uids.find(*iter); if (uid_iter != uid_state->resolved_uids.end()) { string device = uid_iter->second.device; string manufacturer = uid_iter->second.manufacturer; if (!(device.empty() && manufacturer.empty())) { ostringstream str; str << uid_iter->second.manufacturer; if ((!device.empty()) && (!manufacturer.empty())) { str << ", "; } str << uid_iter->second.device; str << " ["; str << iter->ToString(); str << "]"; uid = str.str(); } } } section.AddItem(new StringItem("Device " + IntToString(i), uid)); } RespondWithSection(response, section); } /* * @brief Handle the request for the device info section. */ string RDMHTTPModule::GetDeviceInfo(const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string hint = request->GetParameter(HINT_KEY); string error; device_info dev_info = {universe_id, uid, hint, "", ""}; m_rdm_api.GetSoftwareVersionLabel( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::GetSoftwareVersionHandler, response, dev_info), &error); return error; } /** * @brief Handle the response to a software version call. */ void RDMHTTPModule::GetSoftwareVersionHandler( HTTPResponse *response, device_info dev_info, const ola::rdm::ResponseStatus &status, const string &software_version) { string error; if (CheckForRDMSuccess(status)) { dev_info.software_version = software_version; } if (dev_info.hint.find('m') != string::npos) { m_rdm_api.GetDeviceModelDescription( dev_info.universe_id, dev_info.uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::GetDeviceModelHandler, response, dev_info), &error); } else { m_rdm_api.GetDeviceInfo( dev_info.universe_id, dev_info.uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::GetDeviceInfoHandler, response, dev_info), &error); } if (!error.empty()) { m_server->ServeError(response, BACKEND_DISCONNECTED_ERROR + error); } } /** * @brief Handle the response to a device model call. */ void RDMHTTPModule::GetDeviceModelHandler( HTTPResponse *response, device_info dev_info, const ola::rdm::ResponseStatus &status, const string &device_model) { string error; if (CheckForRDMSuccess(status)) { dev_info.device_model = device_model; } m_rdm_api.GetDeviceInfo( dev_info.universe_id, dev_info.uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::GetDeviceInfoHandler, response, dev_info), &error); if (!error.empty()) { m_server->ServeError(response, BACKEND_DISCONNECTED_ERROR + error); } } /** * @brief Handle the response to a device info call and build the response */ void RDMHTTPModule::GetDeviceInfoHandler( HTTPResponse *response, device_info dev_info, const ola::rdm::ResponseStatus &status, const ola::rdm::DeviceDescriptor &device) { JsonSection section; if (CheckForRDMError(response, status)) { return; } ostringstream stream; stream << static_cast(device.protocol_version_high) << "." << static_cast(device.protocol_version_low); section.AddItem(new StringItem("Protocol Version", stream.str())); stream.str(""); if (dev_info.device_model.empty()) { stream << device.device_model; } else { stream << dev_info.device_model << " (" << device.device_model << ")"; } section.AddItem(new StringItem("Device Model", stream.str())); section.AddItem(new StringItem( "Product Category", ola::rdm::ProductCategoryToString(device.product_category))); stream.str(""); if (dev_info.software_version.empty()) { stream << device.software_version; } else { stream << dev_info.software_version << " (" << device.software_version << ")"; } section.AddItem(new StringItem("Software Version", stream.str())); if (device.dmx_start_address == ola::rdm::ZERO_FOOTPRINT_DMX_ADDRESS) { section.AddItem(new StringItem("DMX Address", "N/A")); } else { section.AddItem(new UIntItem("DMX Address", device.dmx_start_address)); } section.AddItem(new UIntItem("DMX Footprint", device.dmx_footprint)); stream.str(""); stream << static_cast(device.current_personality) << " of " << static_cast(device.personality_count); section.AddItem(new StringItem("Personality", stream.str())); section.AddItem(new UIntItem("Sub Devices", device.sub_device_count)); section.AddItem(new UIntItem("Sensors", device.sensor_count)); section.AddItem(new StringItem("UID", dev_info.uid.ToString())); RespondWithSection(response, section); } /* * @brief Handle the request for the product details ids. */ string RDMHTTPModule::GetProductIds(OLA_UNUSED const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string error; m_rdm_api.GetProductDetailIdList( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::GetProductIdsHandler, response), &error); return error; } /** * @brief Handle the response to a product detail ids call and build the response. */ void RDMHTTPModule::GetProductIdsHandler( HTTPResponse *response, const ola::rdm::ResponseStatus &status, const vector &ids) { if (CheckForRDMError(response, status)) { return; } bool first = true; ostringstream product_ids; JsonSection section; vector::const_iterator iter = ids.begin(); for (; iter != ids.end(); ++iter) { string product_id = ola::rdm::ProductDetailToString(*iter); if (product_id.empty()) { continue; } if (first) { first = false; } else { product_ids << ", "; } product_ids << product_id; } section.AddItem(new StringItem("Product Detail IDs", product_ids.str())); RespondWithSection(response, section); } /** * @brief Handle the request for the Manufacturer label. */ string RDMHTTPModule::GetManufacturerLabel( OLA_UNUSED const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string error; m_rdm_api.GetManufacturerLabel( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::GetManufacturerLabelHandler, response, universe_id, uid), &error); return error; } /** * @brief Handle the response to a manufacturer label call and build the response */ void RDMHTTPModule::GetManufacturerLabelHandler( HTTPResponse *response, unsigned int universe_id, const UID uid, const ola::rdm::ResponseStatus &status, const string &label) { if (CheckForRDMError(response, status)) { return; } JsonSection section; section.AddItem(new StringItem("Manufacturer Label", label)); RespondWithSection(response, section); // update the map as well uid_resolution_state *uid_state = GetUniverseUids(universe_id); if (uid_state) { map::iterator uid_iter = uid_state->resolved_uids.find(uid); if (uid_iter != uid_state->resolved_uids.end()) { uid_iter->second.manufacturer = label; } } } /** * @brief Handle the request for the Device label. */ string RDMHTTPModule::GetDeviceLabel(OLA_UNUSED const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string error; m_rdm_api.GetDeviceLabel( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::GetDeviceLabelHandler, response, universe_id, uid), &error); return error; } /** * @brief Handle the response to a device label call and build the response */ void RDMHTTPModule::GetDeviceLabelHandler( HTTPResponse *response, unsigned int universe_id, const UID uid, const ola::rdm::ResponseStatus &status, const string &label) { if (CheckForRDMError(response, status)) { return; } JsonSection section; section.AddItem(new StringItem("Device Label", label, LABEL_FIELD)); RespondWithSection(response, section); // update the map as well uid_resolution_state *uid_state = GetUniverseUids(universe_id); if (uid_state) { map::iterator uid_iter = uid_state->resolved_uids.find(uid); if (uid_iter != uid_state->resolved_uids.end()) { uid_iter->second.device = label; } } } /* * @brief Set the device label */ string RDMHTTPModule::SetDeviceLabel(const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string label = request->GetParameter(LABEL_FIELD); string error; m_rdm_api.SetDeviceLabel( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, label, NewSingleCallback(this, &RDMHTTPModule::SetHandler, response), &error); return error; } /** * @brief Handle the request for the factory defaults section */ string RDMHTTPModule::GetFactoryDefaults(HTTPResponse *response, unsigned int universe_id, const UID &uid) { string error; m_rdm_api.GetFactoryDefaults( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::FactoryDefaultsHandler, response), &error); return error; } /** * @brief Handle the response to a factory defaults call and build the response */ void RDMHTTPModule::FactoryDefaultsHandler( HTTPResponse *response, const ola::rdm::ResponseStatus &status, bool defaults) { if (CheckForRDMError(response, status)) { return; } JsonSection section; section.AddItem(new StringItem("Using Defaults", defaults ? "Yes" : "No")); section.AddItem(new HiddenItem("1", GENERIC_UINT_FIELD)); section.SetSaveButton("Reset to Defaults"); RespondWithSection(response, section); } /* * @brief Reset to the factory defaults */ string RDMHTTPModule::SetFactoryDefault(HTTPResponse *response, unsigned int universe_id, const UID &uid) { string error; m_rdm_api.ResetToFactoryDefaults( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::SetHandler, response), &error); return error; } /** * @brief Handle the request for the language section. */ string RDMHTTPModule::GetLanguage(HTTPResponse *response, unsigned int universe_id, const UID &uid) { string error; m_rdm_api.GetLanguageCapabilities( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::GetSupportedLanguagesHandler, response, universe_id, uid), &error); return error; } /** * @brief Handle the response to language capability call. */ void RDMHTTPModule::GetSupportedLanguagesHandler( HTTPResponse *response, unsigned int universe_id, const UID uid, OLA_UNUSED const ola::rdm::ResponseStatus &status, const vector &languages) { string error; m_rdm_api.GetLanguage( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::GetLanguageHandler, response, languages), &error); if (!error.empty()) { m_server->ServeError(response, BACKEND_DISCONNECTED_ERROR + error); } } /** * @brief Handle the response to language call and build the response */ void RDMHTTPModule::GetLanguageHandler(HTTPResponse *response, vector languages, const ola::rdm::ResponseStatus &status, const string &language) { JsonSection section; SelectItem *item = new SelectItem("Language", LANGUAGE_FIELD); bool ok = CheckForRDMSuccess(status); vector::const_iterator iter = languages.begin(); unsigned int i = 0; for (; iter != languages.end(); ++iter, i++) { item->AddItem(*iter, *iter); if (ok && *iter == language) { item->SetSelectedOffset(i); } } if (ok && languages.empty()) { item->AddItem(language, language); item->SetSelectedOffset(0); } section.AddItem(item); RespondWithSection(response, section); } /* * @brief Set the language */ string RDMHTTPModule::SetLanguage(const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string label = request->GetParameter(LANGUAGE_FIELD); string error; m_rdm_api.SetLanguage( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, label, NewSingleCallback(this, &RDMHTTPModule::SetHandler, response), &error); return error; } /** * @brief Handle the request for the boot software section. */ string RDMHTTPModule::GetBootSoftware(HTTPResponse *response, unsigned int universe_id, const UID &uid) { string error; m_rdm_api.GetBootSoftwareVersionLabel( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::GetBootSoftwareLabelHandler, response, universe_id, uid), &error); return error; } /** * @brief Handle the response to a boot software label. */ void RDMHTTPModule::GetBootSoftwareLabelHandler( HTTPResponse *response, unsigned int universe_id, const UID uid, OLA_UNUSED const ola::rdm::ResponseStatus &status, const string &label) { string error; m_rdm_api.GetBootSoftwareVersion( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::GetBootSoftwareVersionHandler, response, label), &error); if (!error.empty()) { m_server->ServeError(response, BACKEND_DISCONNECTED_ERROR + error); } } /** * @brief Handle the response to a boot software version. */ void RDMHTTPModule::GetBootSoftwareVersionHandler( HTTPResponse *response, string label, const ola::rdm::ResponseStatus &status, uint32_t version) { ostringstream str; str << label; if (CheckForRDMSuccess(status)) { if (!label.empty()) { str << " (" << version << ")"; } else { str << version; } } JsonSection section; StringItem *item = new StringItem("Boot Software", str.str()); section.AddItem(item); RespondWithSection(response, section); } /** * @brief Handle the request for the personality section. */ string RDMHTTPModule::GetPersonalities(OLA_UNUSED const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid, bool return_as_section, bool include_descriptions) { string hint = request->GetParameter(HINT_KEY); string error; personality_info *info = new personality_info; info->universe_id = universe_id; info->uid = new UID(uid); info->include_descriptions = include_descriptions || (hint == "l"); info->return_as_section = return_as_section; info->active = 0; info->next = 1; info->total = 0; m_rdm_api.GetDMXPersonality( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::GetPersonalityHandler, response, info), &error); return error; } /** * @brief Handle the response to a dmx personality call. */ void RDMHTTPModule::GetPersonalityHandler( HTTPResponse *response, personality_info *info, const ola::rdm::ResponseStatus &status, uint8_t current, uint8_t total) { if (CheckForRDMError(response, status)) { delete info->uid; delete info; return; } info->active = current; info->total = total; if (info->include_descriptions) { GetNextPersonalityDescription(response, info); } else { SendPersonalityResponse(response, info); } } /** * @brief Get the description of the next dmx personality */ void RDMHTTPModule::GetNextPersonalityDescription(HTTPResponse *response, personality_info *info) { string error; while (info->next <= info->total) { bool r = m_rdm_api.GetDMXPersonalityDescription( info->universe_id, *(info->uid), ola::rdm::ROOT_RDM_DEVICE, info->next, NewSingleCallback(this, &RDMHTTPModule::GetPersonalityLabelHandler, response, info), &error); if (r) { return; } info->next++; } if (info->return_as_section) { SendSectionPersonalityResponse(response, info); } else { SendPersonalityResponse(response, info); } } /** * @brief Handle the response to a Personality label call. * * This fetches the next personality in the sequence, or sends the response if * we have all the info. */ void RDMHTTPModule::GetPersonalityLabelHandler( HTTPResponse *response, personality_info *info, const ola::rdm::ResponseStatus &status, OLA_UNUSED uint8_t personality, uint16_t slot_count, const string &label) { string description = ""; uint32_t slots = INVALID_PERSONALITY; if (CheckForRDMSuccess(status)) { slots = slot_count; description = label; } info->personalities.push_back(pair(slots, description)); if (info->next == info->total) { if (info->return_as_section) { SendSectionPersonalityResponse(response, info); } else { SendPersonalityResponse(response, info); } } else { info->next++; GetNextPersonalityDescription(response, info); } } /** * @brief Send the response to a dmx personality section */ void RDMHTTPModule::SendSectionPersonalityResponse(HTTPResponse *response, personality_info *info) { JsonSection section; SelectItem *item = new SelectItem("Personality", GENERIC_UINT_FIELD); for (unsigned int i = 1; i <= info->total; i++) { if (i <= info->personalities.size() && info->personalities[i - 1].first != INVALID_PERSONALITY) { ostringstream str; str << info->personalities[i - 1].second << " (" << info->personalities[i - 1].first << ")"; item->AddItem(str.str(), i); } else { item->AddItem(IntToString(i), i); } if (info->active == i) { item->SetSelectedOffset(i - 1); } } section.AddItem(item); RespondWithSection(response, section); delete info->uid; delete info; } /** * @brief Set the personality */ string RDMHTTPModule::SetPersonality(const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string personality_str = request->GetParameter(GENERIC_UINT_FIELD); uint8_t personality; if (!StringToInt(personality_str, &personality)) { return "Invalid personality"; } string error; m_rdm_api.SetDMXPersonality( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, personality, NewSingleCallback(this, &RDMHTTPModule::SetHandler, response), &error); return error; } /** * @brief Handle the request for the start address section. */ string RDMHTTPModule::GetStartAddress(OLA_UNUSED const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string error; m_rdm_api.GetDMXAddress( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::GetStartAddressHandler, response), &error); return error; } /** * @brief Handle the response to a dmx start address call and build the response */ void RDMHTTPModule::GetStartAddressHandler( HTTPResponse *response, const ola::rdm::ResponseStatus &status, uint16_t address) { if (CheckForRDMError(response, status)) { return; } JsonSection section; GenericItem *item = NULL; if (address == ola::rdm::ZERO_FOOTPRINT_DMX_ADDRESS) { item = new StringItem("DMX Start Address", "N/A"); } else { UIntItem *uint_item = new UIntItem("DMX Start Address", address, ADDRESS_FIELD); uint_item->SetMin(DMX_MIN_SLOT_NUMBER); uint_item->SetMax(DMX_MAX_SLOT_NUMBER); item = uint_item; } section.AddItem(item); RespondWithSection(response, section); } /* * @brief Set the DMX start address */ string RDMHTTPModule::SetStartAddress(const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string dmx_address = request->GetParameter(ADDRESS_FIELD); uint16_t address; if (!StringToInt(dmx_address, &address)) { return "Invalid start address"; } string error; m_rdm_api.SetDMXAddress( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, address, NewSingleCallback(this, &RDMHTTPModule::SetHandler, response), &error); return error; } /** * @brief Handle the request for the sensor section. */ string RDMHTTPModule::GetSensor(const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string hint = request->GetParameter(HINT_KEY); uint8_t sensor_id; if (!StringToInt(hint, &sensor_id)) { return "Invalid hint (sensor #)"; } string error; m_rdm_api.GetSensorDefinition( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, sensor_id, NewSingleCallback(this, &RDMHTTPModule::SensorDefinitionHandler, response, universe_id, uid, sensor_id), &error); return error; } /** * @brief Handle the response to a sensor definition request. */ void RDMHTTPModule::SensorDefinitionHandler( HTTPResponse *response, unsigned int universe_id, const UID uid, uint8_t sensor_id, const ola::rdm::ResponseStatus &status, const ola::rdm::SensorDescriptor &definition) { ola::rdm::SensorDescriptor *definition_arg = NULL; if (CheckForRDMSuccess(status)) { definition_arg = new ola::rdm::SensorDescriptor(); *definition_arg = definition; } string error; m_rdm_api.GetSensorValue( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, sensor_id, NewSingleCallback(this, &RDMHTTPModule::SensorValueHandler, response, definition_arg), &error); if (!error.empty()) { m_server->ServeError(response, BACKEND_DISCONNECTED_ERROR + error); } } /** * @brief Handle the response to a sensor value request & build the response. */ void RDMHTTPModule::SensorValueHandler( HTTPResponse *response, ola::rdm::SensorDescriptor *definition, const ola::rdm::ResponseStatus &status, const ola::rdm::SensorValueDescriptor &value) { if (CheckForRDMError(response, status)) { if (definition) { delete definition; } return; } JsonSection section; ostringstream str; if (definition) { section.AddItem(new StringItem("Description", definition->description)); } str << value.present_value; if (definition) { str << " " << ola::rdm::PrefixToString(definition->prefix) << " " << ola::rdm::UnitToString(definition->unit); } section.AddItem(new StringItem("Present Value", str.str())); if (definition) { section.AddItem(new StringItem( "Type", ola::rdm::SensorTypeToString(definition->type))); str.str(""); str << definition->range_min << " - " << definition->range_max << " " << ola::rdm::PrefixToString(definition->prefix) << " " << ola::rdm::UnitToString(definition->unit); section.AddItem(new StringItem("Range", str.str())); str.str(""); str << definition->normal_min << " - " << definition->normal_max << " " << ola::rdm::PrefixToString(definition->prefix) << " " << ola::rdm::UnitToString(definition->unit); section.AddItem(new StringItem("Normal Range", str.str())); if (definition->recorded_value_support & ola::rdm::SENSOR_RECORDED_VALUE) { str.str(""); str << value.recorded << " " << ola::rdm::PrefixToString(definition->prefix) << " " << ola::rdm::UnitToString(definition->unit); section.AddItem(new StringItem("Recorded Value", str.str())); } if (definition->recorded_value_support & ola::rdm::SENSOR_RECORDED_RANGE_VALUES) { str.str(""); str << value.lowest << " - " << value.highest << " " << ola::rdm::PrefixToString(definition->prefix) << " " << ola::rdm::UnitToString(definition->unit); section.AddItem(new StringItem("Min / Max Recorded Values", str.str())); } } if (definition && definition->recorded_value_support) { section.AddItem(new HiddenItem("1", RECORD_SENSOR_FIELD)); } section.SetSaveButton("Record Sensor"); RespondWithSection(response, section); delete definition; } /* * @brief Record a sensor value */ string RDMHTTPModule::RecordSensor(const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string hint = request->GetParameter(HINT_KEY); uint8_t sensor_id; if (!StringToInt(hint, &sensor_id)) { return "Invalid hint (sensor #)"; } string error; m_rdm_api.RecordSensors( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, sensor_id, NewSingleCallback(this, &RDMHTTPModule::SetHandler, response), &error); return error; } /** * @brief Handle the request for the device hours section. */ string RDMHTTPModule::GetDeviceHours(OLA_UNUSED const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string error; m_rdm_api.GetDeviceHours( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::GenericUIntHandler, response, string("Device Hours")), &error); return error; } /** * @brief Set the device hours */ string RDMHTTPModule::SetDeviceHours(const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string device_hours = request->GetParameter(GENERIC_UINT_FIELD); uint32_t dev_hours; if (!StringToInt(device_hours, &dev_hours)) { return "Invalid device hours"; } string error; m_rdm_api.SetDeviceHours( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, dev_hours, NewSingleCallback(this, &RDMHTTPModule::SetHandler, response), &error); return error; } /** * @brief Handle the request for the lamp hours section. */ string RDMHTTPModule::GetLampHours(OLA_UNUSED const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string error; m_rdm_api.GetLampHours( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::GenericUIntHandler, response, string("Lamp Hours")), &error); return error; } /** * @brief Set the lamp hours */ string RDMHTTPModule::SetLampHours(const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string lamp_hours_str = request->GetParameter(GENERIC_UINT_FIELD); uint32_t lamp_hours; if (!StringToInt(lamp_hours_str, &lamp_hours)) { return "Invalid lamp hours"; } string error; m_rdm_api.SetLampHours( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, lamp_hours, NewSingleCallback(this, &RDMHTTPModule::SetHandler, response), &error); return error; } /** * @brief Handle the request for the lamp strikes section */ string RDMHTTPModule::GetLampStrikes(OLA_UNUSED const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string error; m_rdm_api.GetLampStrikes( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::GenericUIntHandler, response, string("Lamp Strikes")), &error); return error; } /** * @brief Set the lamp strikes */ string RDMHTTPModule::SetLampStrikes(const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string lamp_strikes_str = request->GetParameter(GENERIC_UINT_FIELD); uint32_t lamp_strikes; if (!StringToInt(lamp_strikes_str, &lamp_strikes)) { return "Invalid lamp strikes"; } string error; m_rdm_api.SetLampStrikes( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, lamp_strikes, NewSingleCallback(this, &RDMHTTPModule::SetHandler, response), &error); return error; } /** * @brief Handle the request for the lamp state section */ string RDMHTTPModule::GetLampState(OLA_UNUSED const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string error; m_rdm_api.GetLampState( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::LampStateHandler, response), &error); return error; } /** * @brief Handle the response to lamp state call and build the response */ void RDMHTTPModule::LampStateHandler(HTTPResponse *response, const ola::rdm::ResponseStatus &status, uint8_t state) { if (CheckForRDMError(response, status)) { return; } JsonSection section; SelectItem *item = new SelectItem("Lamp State", GENERIC_UINT_FIELD); typedef struct { string label; ola::rdm::rdm_lamp_state state; } values_s; values_s possible_values[] = { {"Off", ola::rdm::LAMP_OFF}, {"On", ola::rdm::LAMP_ON}, {"Strike", ola::rdm::LAMP_STRIKE}, {"Standby", ola::rdm::LAMP_STANDBY}}; for (unsigned int i = 0; i < sizeof(possible_values) / sizeof(values_s); ++i) { item->AddItem(possible_values[i].label, possible_values[i].state); if (state == possible_values[i].state) { item->SetSelectedOffset(i); } } section.AddItem(item); RespondWithSection(response, section); } /** * @brief Set the lamp state */ string RDMHTTPModule::SetLampState(const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string lamp_state_str = request->GetParameter(GENERIC_UINT_FIELD); uint8_t lamp_state; if (!StringToInt(lamp_state_str, &lamp_state)) { return "Invalid lamp state"; } string error; m_rdm_api.SetLampState( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, lamp_state, NewSingleCallback(this, &RDMHTTPModule::SetHandler, response), &error); return error; } /** * @brief Handle the request for the lamp mode section */ string RDMHTTPModule::GetLampMode(OLA_UNUSED const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string error; m_rdm_api.GetLampMode( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::LampModeHandler, response), &error); return error; } /** * @brief Handle the response to lamp mode call and build the response */ void RDMHTTPModule::LampModeHandler(HTTPResponse *response, const ola::rdm::ResponseStatus &status, uint8_t mode) { if (CheckForRDMError(response, status)) { return; } JsonSection section; SelectItem *item = new SelectItem("Lamp Mode", GENERIC_UINT_FIELD); typedef struct { string label; ola::rdm::rdm_lamp_mode mode; } values_s; values_s possible_values[] = { {"Off", ola::rdm::LAMP_ON_MODE_OFF}, {"DMX", ola::rdm::LAMP_ON_MODE_DMX}, {"On", ola::rdm::LAMP_ON_MODE_ON}, {"On After Calibration", ola::rdm::LAMP_ON_MODE_ON_AFTER_CAL}}; for (unsigned int i = 0; i < sizeof(possible_values) / sizeof(values_s); ++i) { item->AddItem(possible_values[i].label, possible_values[i].mode); if (mode == possible_values[i].mode) { item->SetSelectedOffset(i); } } section.AddItem(item); RespondWithSection(response, section); } /** * @brief Set the lamp mode */ string RDMHTTPModule::SetLampMode(const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string lamp_mode_str = request->GetParameter(GENERIC_UINT_FIELD); uint8_t lamp_mode; if (!StringToInt(lamp_mode_str, &lamp_mode)) { return "Invalid lamp mode"; } string error; m_rdm_api.SetLampMode( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, lamp_mode, NewSingleCallback(this, &RDMHTTPModule::SetHandler, response), &error); return error; } /** * @brief Handle the request for the device power cycles section */ string RDMHTTPModule::GetPowerCycles(OLA_UNUSED const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string error; m_rdm_api.GetDevicePowerCycles( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::GenericUIntHandler, response, string("Device Power Cycles")), &error); return error; } /** * @brief Set the device power cycles */ string RDMHTTPModule::SetPowerCycles(const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string power_cycles_str = request->GetParameter(GENERIC_UINT_FIELD); uint32_t power_cycles; if (!StringToInt(power_cycles_str, &power_cycles)) { return "Invalid power cycles"; } string error; m_rdm_api.SetDevicePowerCycles( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, power_cycles, NewSingleCallback(this, &RDMHTTPModule::SetHandler, response), &error); return error; } /** * @brief Handle the request for the display invert section. */ string RDMHTTPModule::GetDisplayInvert(HTTPResponse *response, unsigned int universe_id, const UID &uid) { string error; m_rdm_api.GetDisplayInvert( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::DisplayInvertHandler, response), &error); return error; } /** * @brief Handle the response to display invert call and build the response */ void RDMHTTPModule::DisplayInvertHandler( HTTPResponse *response, const ola::rdm::ResponseStatus &status, uint8_t value) { if (CheckForRDMError(response, status)) { return; } JsonSection section; SelectItem *item = new SelectItem("Display Invert", DISPLAY_INVERT_FIELD); item->AddItem("Off", ola::rdm::DISPLAY_INVERT_OFF); item->AddItem("On", ola::rdm::DISPLAY_INVERT_ON); item->AddItem("Auto", ola::rdm::DISPLAY_INVERT_AUTO); if (value < ola::rdm::DISPLAY_INVERT_MAX) { item->SetSelectedOffset(value); } section.AddItem(item); RespondWithSection(response, section); } /** * @brief Set the display invert. */ string RDMHTTPModule::SetDisplayInvert(const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string invert_field = request->GetParameter(DISPLAY_INVERT_FIELD); uint8_t display_invert; if (!StringToInt(invert_field, &display_invert)) { return "Invalid display invert"; } string error; m_rdm_api.SetDisplayInvert( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, display_invert, NewSingleCallback(this, &RDMHTTPModule::SetHandler, response), &error); return error; } /** * @brief Handle the request for the display level section. */ string RDMHTTPModule::GetDisplayLevel(HTTPResponse *response, unsigned int universe_id, const UID &uid) { string error; m_rdm_api.GetDisplayLevel( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::DisplayLevelHandler, response), &error); return error; } /** * @brief Handle the response to display level call and build the response */ void RDMHTTPModule::DisplayLevelHandler(HTTPResponse *response, const ola::rdm::ResponseStatus &status, uint8_t value) { if (CheckForRDMError(response, status)) { return; } JsonSection section; UIntItem *item = new UIntItem("Display Level", value, GENERIC_UINT_FIELD); item->SetMin(std::numeric_limits::min()); item->SetMax(std::numeric_limits::max()); section.AddItem(item); RespondWithSection(response, section); } /** * @brief Set the display level. */ string RDMHTTPModule::SetDisplayLevel(const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string display_level_str = request->GetParameter(GENERIC_UINT_FIELD); uint8_t display_level; if (!StringToInt(display_level_str, &display_level)) { return "Invalid display level"; } string error; m_rdm_api.SetDisplayLevel( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, display_level, NewSingleCallback(this, &RDMHTTPModule::SetHandler, response), &error); return error; } /** * @brief Handle the request for the pan invert section. */ string RDMHTTPModule::GetPanInvert(HTTPResponse *response, unsigned int universe_id, const UID &uid) { string error; m_rdm_api.GetPanInvert( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::GenericUInt8BoolHandler, response, string("Pan Invert")), &error); return error; } /** * @brief Set the pan invert. */ string RDMHTTPModule::SetPanInvert(const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string mode = request->GetParameter(GENERIC_BOOL_FIELD); string error; m_rdm_api.SetPanInvert( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, mode == "1", NewSingleCallback(this, &RDMHTTPModule::SetHandler, response), &error); return error; } /** * @brief Handle the request for the tilt invert section. */ string RDMHTTPModule::GetTiltInvert(HTTPResponse *response, unsigned int universe_id, const UID &uid) { string error; m_rdm_api.GetTiltInvert( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::GenericUInt8BoolHandler, response, string("Tilt Invert")), &error); return error; } /** * @brief Set the tilt invert. */ string RDMHTTPModule::SetTiltInvert(const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string mode = request->GetParameter(GENERIC_BOOL_FIELD); string error; m_rdm_api.SetTiltInvert( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, mode == "1", NewSingleCallback(this, &RDMHTTPModule::SetHandler, response), &error); return error; } /** * @brief Handle the request for the pan/tilt swap section. */ string RDMHTTPModule::GetPanTiltSwap(HTTPResponse *response, unsigned int universe_id, const UID &uid) { string error; m_rdm_api.GetPanTiltSwap( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::GenericUInt8BoolHandler, response, string("Pan Tilt Swap")), &error); return error; } /** * @brief Set the pan/tilt swap. */ string RDMHTTPModule::SetPanTiltSwap(const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string mode = request->GetParameter(GENERIC_BOOL_FIELD); string error; m_rdm_api.SetPanTiltSwap( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, mode == "1", NewSingleCallback(this, &RDMHTTPModule::SetHandler, response), &error); return error; } /** * @brief Handle the request for the clock section. */ string RDMHTTPModule::GetClock(HTTPResponse *response, unsigned int universe_id, const UID &uid) { string error; m_rdm_api.GetClock( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::ClockHandler, response), &error); return error; } /** * @brief Handle the response to clock call and build the response */ void RDMHTTPModule::ClockHandler(HTTPResponse *response, const ola::rdm::ResponseStatus &status, const ola::rdm::ClockValue &clock) { if (CheckForRDMError(response, status)) { return; } JsonSection section; ostringstream str; str << std::setfill('0') << std::setw(2) << static_cast(clock.hour) << ":" << std::setw(2) << static_cast(clock.minute) << ":" << std::setw(2) << static_cast(clock.second) << " " << static_cast(clock.day) << "/" << static_cast(clock.month) << "/" << clock.year; section.AddItem(new StringItem("Clock", str.str())); section.AddItem(new HiddenItem("1", GENERIC_UINT_FIELD)); section.SetSaveButton("Sync to Server"); RespondWithSection(response, section); } /** * @brief Sync the clock */ string RDMHTTPModule::SyncClock(HTTPResponse *response, unsigned int universe_id, const UID &uid) { time_t now = time(NULL); struct tm now_tm; #ifdef _WIN32 memcpy(&now_tm, localtime(&now), sizeof(now_tm)); #else localtime_r(&now, &now_tm); #endif // _WIN32 ola::rdm::ClockValue clock_value; clock_value.year = now_tm.tm_year + 1900; clock_value.month = now_tm.tm_mon + 1; clock_value.day = now_tm.tm_mday; clock_value.hour = now_tm.tm_hour; clock_value.minute = now_tm.tm_min; clock_value.second = now_tm.tm_sec; string error; m_rdm_api.SetClock( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, clock_value, NewSingleCallback(this, &RDMHTTPModule::SetHandler, response), &error); return error; } /** * @brief Handle the request for the identify device section. */ string RDMHTTPModule::GetIdentifyDevice(HTTPResponse *response, unsigned int universe_id, const UID &uid) { string error; m_rdm_api.GetIdentifyDevice( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::GenericBoolHandler, response, string("Identify Device")), &error); return error; } /* * @brief Set identify device */ string RDMHTTPModule::SetIdentifyDevice(const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string mode = request->GetParameter(GENERIC_BOOL_FIELD); string error; m_rdm_api.IdentifyDevice( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, mode == "1", NewSingleCallback(this, &RDMHTTPModule::SetHandler, response), &error); return error; } /** * @brief Handle the request for the power state section. */ string RDMHTTPModule::GetPowerState(HTTPResponse *response, unsigned int universe_id, const UID &uid) { string error; m_rdm_api.GetPowerState( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::PowerStateHandler, response), &error); return error; } /** * @brief Handle the response to power state call and build the response */ void RDMHTTPModule::PowerStateHandler(HTTPResponse *response, const ola::rdm::ResponseStatus &status, uint8_t value) { if (CheckForRDMError(response, status)) { return; } JsonSection section; SelectItem *item = new SelectItem("Power State", GENERIC_UINT_FIELD); typedef struct { string label; ola::rdm::rdm_power_state state; } values_s; values_s possible_values[] = { {"Full Off", ola::rdm::POWER_STATE_FULL_OFF}, {"Shutdown", ola::rdm::POWER_STATE_SHUTDOWN}, {"Standby", ola::rdm::POWER_STATE_STANDBY}, {"Normal", ola::rdm::POWER_STATE_NORMAL}}; for (unsigned int i = 0; i < sizeof(possible_values) / sizeof(values_s); ++i) { item->AddItem(possible_values[i].label, possible_values[i].state); if (value == possible_values[i].state) { item->SetSelectedOffset(i); } } section.AddItem(item); RespondWithSection(response, section); } /* * @brief Set the power state. */ string RDMHTTPModule::SetPowerState(const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string power_state_str = request->GetParameter(GENERIC_UINT_FIELD); uint8_t power_state; ola::rdm::rdm_power_state power_state_enum; if (!StringToInt(power_state_str, &power_state) || !ola::rdm::UIntToPowerState(power_state, &power_state_enum)) { return "Invalid power state"; } string error; m_rdm_api.SetPowerState( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, power_state_enum, NewSingleCallback(this, &RDMHTTPModule::SetHandler, response), &error); return error; } /** * @brief Handle the request for the device reset section. */ string RDMHTTPModule::GetResetDevice(HTTPResponse *response) { JsonSection section = JsonSection(false); SelectItem *item = new SelectItem("Reset Device", GENERIC_UINT_FIELD); typedef struct { string label; ola::rdm::rdm_reset_device_mode state; } values_s; values_s possible_values[] = { {"Warm Reset", ola::rdm::RESET_WARM}, {"Cold Reset", ola::rdm::RESET_COLD}}; for (unsigned int i = 0; i < sizeof(possible_values) / sizeof(values_s); ++i) { item->AddItem(possible_values[i].label, possible_values[i].state); } section.AddItem(item); section.SetSaveButton("Reset Device"); RespondWithSection(response, section); return ""; } /* * @brief Set the reset device. */ string RDMHTTPModule::SetResetDevice(const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string reset_device_str = request->GetParameter(GENERIC_UINT_FIELD); uint8_t reset_device; ola::rdm::rdm_reset_device_mode reset_device_enum; if (!StringToInt(reset_device_str, &reset_device) || !ola::rdm::UIntToResetDevice(reset_device, &reset_device_enum)) { return "Invalid reset device"; } string error; m_rdm_api.SetResetDevice( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, reset_device_enum, NewSingleCallback(this, &RDMHTTPModule::SetHandler, response), &error); return error; } /** * @brief Handle the request for the DNS Hostname. */ string RDMHTTPModule::GetDnsHostname(HTTPResponse *response, unsigned int universe_id, const UID &uid) { string error; m_rdm_api.GetDnsHostname( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::GetDnsHostnameHandler, response), &error); return error; } /** * @brief Handle the response to a DNS hostname call and build the response */ void RDMHTTPModule::GetDnsHostnameHandler( HTTPResponse *response, const ola::rdm::ResponseStatus &status, const string &label) { if (CheckForRDMError(response, status)) { return; } JsonSection section; section.AddItem(new StringItem("Hostname", label, GENERIC_STRING_FIELD)); RespondWithSection(response, section); } /* * @brief Set the DNS hostname */ string RDMHTTPModule::SetDnsHostname(const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string label = request->GetParameter(GENERIC_STRING_FIELD); string error; m_rdm_api.SetDnsHostname( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, label, NewSingleCallback(this, &RDMHTTPModule::SetHandler, response), &error); return error; } /** * @brief Handle the request for the DNS domain name. */ string RDMHTTPModule::GetDnsDomainName(HTTPResponse *response, unsigned int universe_id, const UID &uid) { string error; m_rdm_api.GetDnsDomainName( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, NewSingleCallback(this, &RDMHTTPModule::GetDnsDomainNameHandler, response), &error); return error; } /** * @brief Handle the response to a DNS domain name call and build the response */ void RDMHTTPModule::GetDnsDomainNameHandler( HTTPResponse *response, const ola::rdm::ResponseStatus &status, const string &label) { if (CheckForRDMError(response, status)) { return; } JsonSection section; section.AddItem(new StringItem("Domain Name", label, GENERIC_STRING_FIELD)); RespondWithSection(response, section); } /* * @brief Set the DNS domain name */ string RDMHTTPModule::SetDnsDomainName(const HTTPRequest *request, HTTPResponse *response, unsigned int universe_id, const UID &uid) { string label = request->GetParameter(GENERIC_STRING_FIELD); string error; m_rdm_api.SetDnsDomainName( universe_id, uid, ola::rdm::ROOT_RDM_DEVICE, label, NewSingleCallback(this, &RDMHTTPModule::SetHandler, response), &error); return error; } /** * @brief Check if the id URL param exists and is valid. */ bool RDMHTTPModule::CheckForInvalidId(const HTTPRequest *request, unsigned int *universe_id) { string uni_id = request->GetParameter(ID_KEY); if (!StringToInt(uni_id, universe_id)) { OLA_INFO << "Invalid universe id: " << uni_id; return false; } return true; } /** * @brief Check that the uid URL param exists and is valid. */ bool RDMHTTPModule::CheckForInvalidUid(const HTTPRequest *request, UID **uid) { string uid_string = request->GetParameter(UID_KEY); *uid = UID::FromString(uid_string); if (*uid == NULL) { OLA_INFO << "Invalid UID: " << uid_string; return false; } return true; } /** * @brief Get the sub device from the HTTP request, or return ROOT_DEVICE if it * isn't valid. */ uint16_t RDMHTTPModule::SubDeviceOrRoot(const HTTPRequest *request) { string sub_device_str = request->GetParameter(SUB_DEVICE_FIELD); uint16_t sub_device; if (StringToInt(sub_device_str, &sub_device)) { return sub_device; } OLA_INFO << "Invalid sub device " << sub_device_str; return ola::rdm::ROOT_RDM_DEVICE; } /* * @brief Check the response to a Set RDM call and build the response. */ void RDMHTTPModule::SetHandler( HTTPResponse *response, const ola::rdm::ResponseStatus &status) { string error; CheckForRDMSuccessWithError(status, &error); RespondWithError(response, error); } /* * @brief Build a response to a RDM call that returns a uint32_t */ void RDMHTTPModule::GenericUIntHandler(HTTPResponse *response, string description, const ola::rdm::ResponseStatus &status, uint32_t value) { if (CheckForRDMError(response, status)) { return; } JsonSection section; section.AddItem(new UIntItem(description, value, GENERIC_UINT_FIELD)); RespondWithSection(response, section); } /* * @brief Build a response to a RDM call that returns a bool */ void RDMHTTPModule::GenericUInt8BoolHandler( HTTPResponse *response, string description, const ola::rdm::ResponseStatus &status, uint8_t value) { GenericBoolHandler(response, description, status, value > 0); } /* * @brief Build a response to a RDM call that returns a bool */ void RDMHTTPModule::GenericBoolHandler(HTTPResponse *response, string description, const ola::rdm::ResponseStatus &status, bool value) { if (CheckForRDMError(response, status)) { return; } JsonSection section; section.AddItem(new BoolItem(description, value, GENERIC_BOOL_FIELD)); RespondWithSection(response, section); } /** * @brief Check for an RDM error, and if it occurs, return a JSON response. * @return true if an error occured. */ bool RDMHTTPModule::CheckForRDMError(HTTPResponse *response, const ola::rdm::ResponseStatus &status) { string error; if (!CheckForRDMSuccessWithError(status, &error)) { RespondWithError(response, error); return true; } return false; } int RDMHTTPModule::RespondWithError(HTTPResponse *response, const string &error) { response->SetNoCache(); response->SetContentType(HTTPServer::CONTENT_TYPE_PLAIN); JsonObject json; json.Add("error", error); int r = response->SendJson(json); delete response; return r; } /** * @brief Build & send a response from a JsonSection */ void RDMHTTPModule::RespondWithSection(HTTPResponse *response, const ola::web::JsonSection §ion) { response->SetNoCache(); response->SetContentType(HTTPServer::CONTENT_TYPE_PLAIN); response->Append(section.AsString()); response->Send(); delete response; } /* * @brief Check the success of an RDM command * @returns true if this command was ok, false otherwise. */ bool RDMHTTPModule::CheckForRDMSuccess( const ola::rdm::ResponseStatus &status) { string error; if (!CheckForRDMSuccessWithError(status, &error)) { OLA_INFO << error; return false; } return true; } /* * @brief Check the success of an RDM command or return an error message. * * At the moment we're very strict in this method, some day this should be * relaxed to handle the corner cases. * @returns true if this command returns an ACK. false for any other condition. */ bool RDMHTTPModule::CheckForRDMSuccessWithError( const ola::rdm::ResponseStatus &status, string *error) { ostringstream str; if (!status.error.empty()) { str << "RDM command error: " << status.error; if (error) { *error = str.str(); } return false; } // TODO(simon): One day we should handle broadcast responses, ack timers etc. if (status.response_code != ola::rdm::RDM_COMPLETED_OK) { if (error) { *error = ola::rdm::StatusCodeToString(status.response_code); } } else { switch (status.response_type) { case ola::rdm::RDM_ACK: return true; case ola::rdm::RDM_ACK_TIMER: str << "Got ACK Timer for " << status.AckTimer() << " ms"; if (error) { *error = str.str(); } break; case ola::rdm::RDM_NACK_REASON: str << "Request was NACKED with code: " << ola::rdm::NackReasonToString(status.NackReason()); OLA_INFO << str.str(); if (error) { *error = str.str(); } } } return false; } /* * @brief Handle the RDM discovery response * @param response the HTTPResponse that is associated with the request. * @param error an error string. */ void RDMHTTPModule::HandleBoolResponse(HTTPResponse *response, const string &error) { if (!error.empty()) { m_server->ServeError(response, error); return; } response->SetNoCache(); response->SetContentType(HTTPServer::CONTENT_TYPE_PLAIN); response->Append("ok"); response->Send(); delete response; } /** * @brief Add a section to the supported section list */ void RDMHTTPModule::AddSection(vector *sections, const string §ion_id, const string §ion_name, const string &hint) { section_info info = {section_id, section_name, hint}; sections->push_back(info); } } // namespace ola ola-0.10.5.nojsmin/olad/AvahiDiscoveryAgent.cpp0000644000175000017500000003446413023355232021013 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * AvahiDiscoveryAgent.cpp * The Avahi implementation of DiscoveryAgentInterface. * Copyright (C) 2013 Simon Newton */ #include "olad/AvahiDiscoveryAgent.h" #include #include #include #include #include #include #include #include #include #include "ola/Clock.h" #include "ola/Logging.h" #include "ola/stl/STLUtils.h" #include "ola/StringUtils.h" namespace ola { using std::string; using std::vector; static std::string MakeServiceKey(const std::string &service_name, const std::string &type) { return service_name + "." + type; } /* * The userdata passed to the entry_callback function. */ struct EntryGroupParams { AvahiDiscoveryAgent *agent; string key; EntryGroupParams(AvahiDiscoveryAgent *agent, const string &key) : agent(agent), key(key) { } }; namespace { /* * Called when the client state changes. This is called once from * the thread that calls avahi_client_new, and then from the poll thread. */ static void client_callback(AvahiClient *client, AvahiClientState state, void *data) { AvahiDiscoveryAgent *agent = reinterpret_cast(data); agent->ClientStateChanged(state, client); } /* * Called when the group state changes. */ static void entry_callback(AvahiEntryGroup *group, AvahiEntryGroupState state, void *data) { if (!group) { return; } const EntryGroupParams *params = reinterpret_cast( data); if (!params) { OLA_FATAL << "entry_callback passed null userdata!"; return; } params->agent->GroupStateChanged(params->key, group, state); } static void reconnect_callback(AvahiTimeout*, void *data) { AvahiDiscoveryAgent *agent = reinterpret_cast(data); agent->ReconnectTimeout(); } } // namespace AvahiDiscoveryAgent::ServiceEntry::ServiceEntry( const std::string &service_name, const std::string &type_spec, uint16_t port, const RegisterOptions &options) : RegisterOptions(options), service_name(service_name), actual_service_name(service_name), port(port), group(NULL), state(AVAHI_ENTRY_GROUP_UNCOMMITED), params(NULL), m_type_spec(type_spec) { vector tokens; StringSplit(type_spec, &tokens, ","); m_type = tokens[0]; if (tokens.size() > 1) { copy(tokens.begin() + 1, tokens.end(), std::back_inserter(m_sub_types)); } } string AvahiDiscoveryAgent::ServiceEntry::key() const { return MakeServiceKey(actual_service_name, m_type_spec); } AvahiDiscoveryAgent::AvahiDiscoveryAgent() : m_threaded_poll(avahi_threaded_poll_new()), m_client(NULL), m_reconnect_timeout(NULL), m_backoff(new ExponentialBackoffPolicy(TimeInterval(1, 0), TimeInterval(60, 0))) { } AvahiDiscoveryAgent::~AvahiDiscoveryAgent() { avahi_threaded_poll_stop(m_threaded_poll); if (m_reconnect_timeout) { avahi_threaded_poll_get(m_threaded_poll)->timeout_free( m_reconnect_timeout); } DeregisterAllServices(); STLDeleteValues(&m_services); if (m_client) { avahi_client_free(m_client); } avahi_threaded_poll_free(m_threaded_poll); } bool AvahiDiscoveryAgent::Init() { CreateNewClient(); if (m_threaded_poll) { avahi_threaded_poll_start(m_threaded_poll); return true; } else { return false; } } void AvahiDiscoveryAgent::RegisterService(const string &service_name, const string &type, uint16_t port, const RegisterOptions &options) { if (!(m_threaded_poll && m_client)) { return; } const string key = MakeServiceKey(service_name, type); avahi_threaded_poll_lock(m_threaded_poll); ServiceEntry *service = STLFindOrNull(m_services, key); if (service) { OLA_WARN << "Service " << key << " is already registered"; avahi_threaded_poll_unlock(m_threaded_poll); return; } else { service = new ServiceEntry(service_name, type, port, options); STLInsertIfNotPresent(&m_services, key, service); } // If we're not running, then we'll register the service when the client // transitions to the running state. Otherwise register it now. if (m_client && avahi_client_get_state(m_client) == AVAHI_CLIENT_S_RUNNING) { InternalRegisterService(service); } avahi_threaded_poll_unlock(m_threaded_poll); } /* * This is a bit tricky because it can be called from either the main thread on * startup or from the poll thread. */ void AvahiDiscoveryAgent::ClientStateChanged(AvahiClientState state, AvahiClient *client) { // The first time this is called is from the avahi_client_new context. In // that case m_client is still null so we set it here. if (!m_client) { m_client = client; } OLA_INFO << "Client state changed to " << ClientStateToString(state); switch (state) { case AVAHI_CLIENT_S_RUNNING: // The server has startup successfully and registered its host // name on the network, so it's time to create our services. // register_stuff UpdateServices(); break; case AVAHI_CLIENT_FAILURE: DeregisterAllServices(); SetUpReconnectTimeout(); break; case AVAHI_CLIENT_S_COLLISION: // There was a hostname collision on the network. // Let's drop our registered services. When the server is back // in AVAHI_SERVER_RUNNING state we will register them again with the // new host name. DeregisterAllServices(); break; case AVAHI_CLIENT_S_REGISTERING: // The server records are now being established. This // might be caused by a host name change. We need to wait // for our own records to register until the host name is // properly established. DeregisterAllServices(); break; case AVAHI_CLIENT_CONNECTING: break; } } void AvahiDiscoveryAgent::GroupStateChanged(const string &service_key, AvahiEntryGroup *group, AvahiEntryGroupState state) { OLA_INFO << "State for " << service_key << ", group " << group << " changed to " << GroupStateToString(state); ServiceEntry *service = STLFindOrNull(m_services, service_key); if (!service) { OLA_WARN << "Unknown service " << service_key << " changed to state " << state; return; } if (service->group != group) { if (service->group) { OLA_WARN << "Service group for " << service_key << " : " << service->group << " does not match callback group " << group; } return; } service->state = state; switch (state) { case AVAHI_ENTRY_GROUP_ESTABLISHED: break; case AVAHI_ENTRY_GROUP_COLLISION: RenameAndRegister(service); break; case AVAHI_ENTRY_GROUP_FAILURE: OLA_WARN << "Failed to register " << service_key << " " << avahi_strerror(avahi_client_errno(m_client)); break; case AVAHI_ENTRY_GROUP_UNCOMMITED: case AVAHI_ENTRY_GROUP_REGISTERING: break; } } void AvahiDiscoveryAgent::ReconnectTimeout() { if (m_client) { avahi_client_free(m_client); m_client = NULL; } CreateNewClient(); } bool AvahiDiscoveryAgent::InternalRegisterService(ServiceEntry *service) { if (!service->params) { service->params = new EntryGroupParams(this, service->key()); } if (!service->group) { service->group = avahi_entry_group_new(m_client, entry_callback, service->params); if (!service->group) { OLA_WARN << "avahi_entry_group_new() failed: " << avahi_client_errno(m_client); return false; } } if (!avahi_entry_group_is_empty(service->group)) { OLA_INFO << "Service group was not empty!"; return false; } AvahiStringList *txt_args = NULL; RegisterOptions::TxtData::const_iterator iter = service->txt_data.begin(); for (; iter != service->txt_data.end(); ++iter) { txt_args = avahi_string_list_add_pair( txt_args, iter->first.c_str(), iter->second.c_str()); } // Populate the entry group int r = avahi_entry_group_add_service_strlst( service->group, service->if_index > 0 ? service->if_index : AVAHI_IF_UNSPEC, AVAHI_PROTO_INET, static_cast(0), service->actual_service_name.c_str(), service->type().c_str(), NULL, NULL, service->port, txt_args); avahi_string_list_free(txt_args); if (r) { if (r == AVAHI_ERR_COLLISION) { OLA_WARN << "Collision with local service!"; return RenameAndRegister(service); } OLA_WARN << "avahi_entry_group_add_service failed: " << avahi_strerror(r); avahi_entry_group_reset(service->group); return false; } // Add any subtypes const vector &sub_types = service->sub_types(); if (!sub_types.empty()) { vector::const_iterator iter = sub_types.begin(); for (; iter != sub_types.end(); ++iter) { const string sub_type = *iter + "._sub." + service->type(); OLA_INFO << "Adding " << sub_type; r = avahi_entry_group_add_service_subtype( service->group, service->if_index > 0 ? service->if_index : AVAHI_IF_UNSPEC, AVAHI_PROTO_INET, static_cast(0), service->actual_service_name.c_str(), service->type().c_str(), NULL, sub_type.c_str()); if (!r) { OLA_WARN << "Failed to add " << sub_type; } } } r = avahi_entry_group_commit(service->group); if (r) { avahi_entry_group_reset(service->group); OLA_WARN << "avahi_entry_group_commit failed: " << avahi_strerror(r); return false; } return true; } void AvahiDiscoveryAgent::CreateNewClient() { if (m_client) { OLA_WARN << "CreateNewClient called but m_client is not NULL"; return; } if (m_threaded_poll) { int error; // In the successful case, m_client is set in the ClientStateChanged method m_client = avahi_client_new(avahi_threaded_poll_get(m_threaded_poll), AVAHI_CLIENT_NO_FAIL, client_callback, this, &error); if (m_client) { m_backoff.Reset(); } else { OLA_WARN << "Failed to create Avahi client " << avahi_strerror(error); SetUpReconnectTimeout(); } } } void AvahiDiscoveryAgent::UpdateServices() { Services::iterator iter = m_services.begin(); for (; iter != m_services.end(); ++iter) { if (iter->second->state == AVAHI_ENTRY_GROUP_UNCOMMITED) { InternalRegisterService(iter->second); } } } /** * De-register all services and clean up the AvahiEntryGroup and * EntryGroupParams data. */ void AvahiDiscoveryAgent::DeregisterAllServices() { Services::iterator iter = m_services.begin(); for (; iter != m_services.end(); ++iter) { AvahiEntryGroup *group = iter->second->group; if (group) { avahi_entry_group_reset(group); avahi_entry_group_free(group); iter->second->group = NULL; } if (iter->second->params) { delete iter->second->params; iter->second->params = NULL; } iter->second->state = AVAHI_ENTRY_GROUP_UNCOMMITED; } } void AvahiDiscoveryAgent::SetUpReconnectTimeout() { // We don't strictly need an ExponentialBackoffPolicy here because the client // goes into the AVAHI_CLIENT_CONNECTING state if the server isn't running. // Still, it's a useful defense against spinning rapidly if something goes // wrong. TimeInterval delay = m_backoff.Next(); OLA_INFO << "Re-creating avahi client in " << delay << "s"; struct timeval tv; delay.AsTimeval(&tv); const AvahiPoll *poll = avahi_threaded_poll_get(m_threaded_poll); if (m_reconnect_timeout) { poll->timeout_update(m_reconnect_timeout, &tv); } else { m_reconnect_timeout = poll->timeout_new( avahi_threaded_poll_get(m_threaded_poll), &tv, reconnect_callback, this); } } bool AvahiDiscoveryAgent::RenameAndRegister(ServiceEntry *service) { char *new_name_str = avahi_alternative_service_name(service->actual_service_name.c_str()); string new_name(new_name_str); avahi_free(new_name_str); OLA_WARN << "Service name collision for " << service->actual_service_name << " renaming to " << new_name; service->actual_service_name = new_name; return InternalRegisterService(service); } string AvahiDiscoveryAgent::ClientStateToString(AvahiClientState state) { switch (state) { case AVAHI_CLIENT_S_REGISTERING: return "AVAHI_CLIENT_S_REGISTERING"; case AVAHI_CLIENT_S_RUNNING: return "AVAHI_CLIENT_S_RUNNING"; case AVAHI_CLIENT_S_COLLISION: return "AVAHI_CLIENT_S_COLLISION"; case AVAHI_CLIENT_FAILURE: return "AVAHI_CLIENT_FAILURE"; case AVAHI_CLIENT_CONNECTING: return "AVAHI_CLIENT_CONNECTING"; default: return "Unknown state"; } } string AvahiDiscoveryAgent::GroupStateToString(AvahiEntryGroupState state) { switch (state) { case AVAHI_ENTRY_GROUP_UNCOMMITED: return "AVAHI_ENTRY_GROUP_UNCOMMITED"; case AVAHI_ENTRY_GROUP_REGISTERING: return "AVAHI_ENTRY_GROUP_REGISTERING"; case AVAHI_ENTRY_GROUP_ESTABLISHED: return "AVAHI_ENTRY_GROUP_ESTABLISHED"; case AVAHI_ENTRY_GROUP_COLLISION: return "AVAHI_ENTRY_GROUP_COLLISION"; case AVAHI_ENTRY_GROUP_FAILURE: return "AVAHI_ENTRY_GROUP_FAILURE"; default: return "Unknown state"; } } } // namespace ola ola-0.10.5.nojsmin/olad/BonjourDiscoveryAgent.cpp0000644000175000017500000001262513023355232021374 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * BonjourDiscoveryAgent.cpp * The Bonjour implementation of DiscoveryAgentInterface. * Copyright (C) 2013 Simon Newton */ #define __STDC_LIMIT_MACROS // for UINT8_MAX & friends #include "olad/BonjourDiscoveryAgent.h" #include #include #include #include #include #include #include namespace ola { using ola::network::HostToNetwork; using ola::thread::Thread; using std::auto_ptr; using std::string; static void RegisterCallback(OLA_UNUSED DNSServiceRef service, OLA_UNUSED DNSServiceFlags flags, DNSServiceErrorType error_code, const char *name, const char *type, const char *domain, OLA_UNUSED void *context) { if (error_code != kDNSServiceErr_NoError) { OLA_WARN << "DNSServiceRegister for " << name << "." << type << domain << " returned error " << error_code; } else { OLA_INFO << "Registered: " << name << "." << type << domain; } } class DNSSDDescriptor : public ola::io::ReadFileDescriptor { public: explicit DNSSDDescriptor(DNSServiceRef service_ref) : m_service_ref(service_ref) { } int ReadDescriptor() const { return DNSServiceRefSockFD(m_service_ref); } void PerformRead(); private: DNSServiceRef m_service_ref; }; void DNSSDDescriptor::PerformRead() { DNSServiceErrorType error = DNSServiceProcessResult(m_service_ref); if (error != kDNSServiceErr_NoError) { // TODO(simon): Consider de-registering from the ss here? OLA_FATAL << "DNSServiceProcessResult returned " << error; } } BonjourDiscoveryAgent::RegisterArgs::RegisterArgs( const string &service_name, const string &type, uint16_t port, const RegisterOptions &options) : RegisterOptions(options), service_name(service_name), type(type), port(port) { } BonjourDiscoveryAgent::BonjourDiscoveryAgent() : m_thread(new ola::thread::CallbackThread( NewSingleCallback(this, &BonjourDiscoveryAgent::RunThread), Thread::Options("bonjour"))) { } BonjourDiscoveryAgent::~BonjourDiscoveryAgent() { m_ss.Terminate(); m_thread->Join(); m_thread.reset(); ServiceRefs::iterator iter = m_refs.begin(); for (; iter != m_refs.end(); ++iter) { m_ss.RemoveReadDescriptor(iter->descriptor); delete iter->descriptor; DNSServiceRefDeallocate(iter->service_ref); } } bool BonjourDiscoveryAgent::Init() { m_thread->Start(); return true; } void BonjourDiscoveryAgent::RegisterService(const string &service_name, const string &type, uint16_t port, const RegisterOptions &options) { RegisterArgs *args = new RegisterArgs(service_name, type, port, options); m_ss.Execute(NewSingleCallback( this, &BonjourDiscoveryAgent::InternalRegisterService, args)); } void BonjourDiscoveryAgent::InternalRegisterService(RegisterArgs *args_ptr) { auto_ptr args(args_ptr); OLA_INFO << "Adding " << args->service_name << ", " << args->type; ServiceRef ref; const string txt_data = BuildTxtRecord(args->txt_data); DNSServiceErrorType error = DNSServiceRegister( &ref.service_ref, 0, args->if_index, args->service_name.c_str(), args->type.c_str(), args->domain.c_str(), NULL, // use default host name HostToNetwork(args->port), txt_data.size(), txt_data.c_str(), &RegisterCallback, // call back function NULL); // no context if (error != kDNSServiceErr_NoError) { OLA_WARN << "DNSServiceRegister returned " << error; return; } ref.descriptor = new DNSSDDescriptor(ref.service_ref); m_ss.AddReadDescriptor(ref.descriptor); m_refs.push_back(ref); } string BonjourDiscoveryAgent::BuildTxtRecord( const RegisterOptions::TxtData &txt_data) { RegisterOptions::TxtData::const_iterator iter = txt_data.begin(); string output; for (; iter != txt_data.end(); ++iter) { unsigned int pair_size = iter->first.size() + iter->second.size() + 1; if (pair_size > UINT8_MAX) { OLA_WARN << "Discovery data of " << iter->first << ": " << iter->second << " exceeed " << static_cast(UINT8_MAX) << " bytes. Data skipped"; continue; } output.append(1, static_cast(pair_size)); output.append(iter->first); output.append("="); output.append(iter->second); } return output; } void BonjourDiscoveryAgent::RunThread() { m_ss.Run(); m_ss.DrainCallbacks(); } } // namespace ola ola-0.10.5.nojsmin/olad/ClientBroker.cpp0000644000175000017500000000632213023355232017467 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ClientBroker.cpp * Acts as the glue between clients and the RDM request path. * Copyright (C) 2010 Simon Newton */ #include #include #include #include "ola/Logging.h" #include "ola/stl/STLUtils.h" #include "olad/ClientBroker.h" namespace ola { using std::set; using std::string; using std::vector; void ClientBroker::AddClient(const Client *client) { m_clients.insert(client); } void ClientBroker::RemoveClient(const Client *client) { m_clients.erase(client); } void ClientBroker::SendRDMRequest(const Client *client, Universe *universe, ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *callback) { if (!STLContains(m_clients, client)) { OLA_WARN << "Making an RDM call but the client doesn't exist in the " << "broker!"; } universe->SendRDMRequest( request, NewSingleCallback(this, &ClientBroker::RequestComplete, client, callback)); } void ClientBroker::RunRDMDiscovery(const Client *client, Universe *universe, bool full_discovery, ola::rdm::RDMDiscoveryCallback *callback) { if (!STLContains(m_clients, client)) { OLA_WARN << "Running RDM discovery but the client doesn't exist in the " << "broker!"; } universe->RunRDMDiscovery( NewSingleCallback(this, &ClientBroker::DiscoveryComplete, client, callback), full_discovery); } /* * Return from an RDM call. * @param key the client associated with this request * @param callback the callback to run if the key still exists * @param code the code of the RDM request * @param response the RDM response */ void ClientBroker::RequestComplete(const Client *client, ola::rdm::RDMCallback *callback, ola::rdm::RDMReply *reply) { if (!STLContains(m_clients, client)) { OLA_DEBUG << "Client no longer exists, cleaning up from RDM response"; delete callback; } else { callback->Run(reply); } } void ClientBroker::DiscoveryComplete( const Client *client, ola::rdm::RDMDiscoveryCallback *callback, const ola::rdm::UIDSet &uids) { if (!STLContains(m_clients, client)) { OLA_DEBUG << "Client no longer exists, cleaning up from RDM discovery"; delete callback; } else { callback->Run(uids); } } } // namespace ola ola-0.10.5.nojsmin/olad/testdata/0000755000175000017500000000000013155164170016213 5ustar wouterwouterola-0.10.5.nojsmin/olad/testdata/test_preferences.conf0000644000175000017500000000014313023355232022413 0ustar wouterwouter# this is a comment foo = bar baz = bat # this is another comment multi = 1 multi = 2 multi = 3 ola-0.10.5.nojsmin/olad/DiscoveryAgent.cpp0000644000175000017500000000252713023355232020035 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DiscoveryAgent.cpp * The Interface for DNS-SD Registration & Discovery * Copyright (C) 2013 Simon Newton */ #include "olad/DiscoveryAgent.h" #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #ifdef HAVE_DNSSD #include "olad/BonjourDiscoveryAgent.h" #endif // HAVE_DNSSD #ifdef HAVE_AVAHI #include "olad/AvahiDiscoveryAgent.h" #endif // HAVE_AVAHI namespace ola { DiscoveryAgentInterface* DiscoveryAgentFactory::New() { #ifdef HAVE_DNSSD return new BonjourDiscoveryAgent(); #endif // HAVE_DNSSD #ifdef HAVE_AVAHI return new AvahiDiscoveryAgent(); #endif // HAVE_AVAHI return NULL; } } // namespace ola ola-0.10.5.nojsmin/olad/DiscoveryAgent.h0000644000175000017500000000647213023355232017505 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DiscoveryAgent.h * The Interface for DNS-SD Registration & Discovery * Copyright (C) 2013 Simon Newton */ #ifndef OLAD_DISCOVERYAGENT_H_ #define OLAD_DISCOVERYAGENT_H_ #include #include #include #include namespace ola { /** * @brief The interface to DNS-SD operations like register, browse etc. */ class DiscoveryAgentInterface { public: virtual ~DiscoveryAgentInterface() {} /** * @brief Initialize the DiscoveryAgent. */ virtual bool Init() = 0; /** * @brief Options for the RegisterService method * * This controls options like the interface index, domain and TXT record * data. */ struct RegisterOptions { /** * @typedef TxtData * The data type that stores the key : values for the TXT record. */ typedef std::map TxtData; /** * @brief A constant which represents all Interfaces. */ static const int ALL_INTERFACES = 0; int if_index; /**< The interface index to register on */ /** * @brief The domain to use. * * The empty string uses the system default domain. */ std::string domain; TxtData txt_data; /**< The TXT record data. */ RegisterOptions() : if_index(ALL_INTERFACES), domain("") { } RegisterOptions(const RegisterOptions &options) : if_index(options.if_index), domain(options.domain), txt_data(options.txt_data) { } }; /** * @brief Register a service * @param service_name the name of the service * @param type the service type * @param port the port the service is on * @param options extra options that control registration. */ // TODO(simon): Think about what sort of error handling we want here virtual void RegisterService(const std::string &service_name, const std::string &type, uint16_t port, const RegisterOptions &options) = 0; }; /** * @brief A Factory which produces implementations of DiscoveryAgentInterface. * * The exact type of object returns depends on what implementation of DNS-SD was * available at build time. */ class DiscoveryAgentFactory { public: DiscoveryAgentFactory() {} /** * @brief Create a new DiscoveryAgent. * * This returns a DiscoveryAgent appropriate for the platform. It can * either be a BonjourDiscoveryAgent or a AvahiDiscoveryAgent. */ DiscoveryAgentInterface* New(); private: DISALLOW_COPY_AND_ASSIGN(DiscoveryAgentFactory); }; } // namespace ola #endif // OLAD_DISCOVERYAGENT_H_ ola-0.10.5.nojsmin/olad/DynamicPluginLoader.h0000644000175000017500000000270413023355232020443 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * DynamicPluginLoader.h * Interface for the DynamicPluginLoader class * Copyright (C) 2005 Simon Newton */ #ifndef OLAD_DYNAMICPLUGINLOADER_H_ #define OLAD_DYNAMICPLUGINLOADER_H_ #include #include "ola/base/Macro.h" #include "olad/PluginLoader.h" namespace ola { /** * @brief A PluginLoader which loads from shared (dynamic) libraries. */ class DynamicPluginLoader: public PluginLoader { public: DynamicPluginLoader() {} ~DynamicPluginLoader(); std::vector LoadPlugins(); void UnloadPlugins(); private: void PopulatePlugins(); std::vector m_plugins; DISALLOW_COPY_AND_ASSIGN(DynamicPluginLoader); }; } // namespace ola #endif // OLAD_DYNAMICPLUGINLOADER_H_ ola-0.10.5.nojsmin/olad/OlaDaemon.h0000644000175000017500000000564713023355232016421 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OlaDaemon.h * The OLA Daemon class. * Copyright (C) 2005 Simon Newton */ #ifndef OLAD_OLADAEMON_H_ #define OLAD_OLADAEMON_H_ #include #include #include #include "ola/Constants.h" #include "ola/ExportMap.h" #include "ola/base/Macro.h" #include "ola/io/SelectServer.h" #include "ola/network/SocketAddress.h" #include "olad/OlaServer.h" namespace ola { class OlaDaemon { public: /** * @brief Create a new OlaDaemon. * @param options The Options for the new OlaDaemon. * @param export_map an optional ExportMap. */ OlaDaemon(const OlaServer::Options &options, ExportMap *export_map = NULL); /** * @brief Destroy this object. */ ~OlaDaemon(); /** * @brief Initialise the daemon. * @return true on success, false on failure. */ bool Init(); /** * @brief Shutdown the daemon. */ void Shutdown(); /** * @brief Run the daemon. */ void Run(); /** * @brief Return the socket address the RPC server is listening on. * @returns A socket address, which is empty if the server hasn't been * initialized. */ ola::network::GenericSocketAddress RPCAddress() const; /** * @brief Get the SelectServer the daemon is using. * @returns A SelectServer object. */ ola::io::SelectServer* GetSelectServer() { return &m_ss; } /** * @brief Get the OlaServer the daemon is using. * @returns An OlaServer object. */ OlaServer *GetOlaServer() const { return m_server.get(); } static const unsigned int DEFAULT_RPC_PORT = OLA_DEFAULT_PORT; private: const OlaServer::Options m_options; class ExportMap *m_export_map; ola::io::SelectServer m_ss; std::vector m_plugin_loaders; // Populated in Init() std::auto_ptr m_preferences_factory; std::auto_ptr m_server; std::string DefaultConfigDir(); bool InitConfigDir(const std::string &path); static const char OLA_CONFIG_DIR[]; static const char CONFIG_DIR_KEY[]; static const char UID_KEY[]; static const char USER_NAME_KEY[]; static const char GID_KEY[]; static const char GROUP_NAME_KEY[]; DISALLOW_COPY_AND_ASSIGN(OlaDaemon); }; } // namespace ola #endif // OLAD_OLADAEMON_H_ ola-0.10.5.nojsmin/olad/AvahiDiscoveryAgent.h0000644000175000017500000000705413023355232020453 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * AvahiDiscoveryAgent.h * The Avahi implementation of DiscoveryAgentInterface. * Copyright (C) 2013 Simon Newton */ #ifndef OLAD_AVAHIDISCOVERYAGENT_H_ #define OLAD_AVAHIDISCOVERYAGENT_H_ #include #include #include #include #include #include #include #include #include "olad/DiscoveryAgent.h" namespace ola { /** * @brief An implementation of DiscoveryAgentInterface that uses the Avahi * client library. */ class AvahiDiscoveryAgent : public DiscoveryAgentInterface { public: AvahiDiscoveryAgent(); ~AvahiDiscoveryAgent(); bool Init(); void RegisterService(const std::string &service_name, const std::string &type, uint16_t port, const RegisterOptions &options); /** * @brief Called when the Avahi client state changes */ void ClientStateChanged(AvahiClientState state, AvahiClient *client); /** * @brief Called when an entry group state changes. */ void GroupStateChanged(const std::string &service_key, AvahiEntryGroup *group, AvahiEntryGroupState state); /** * @brief Called when the reconnect timeout expires. */ void ReconnectTimeout(); private: // The structure used to track services. struct ServiceEntry : public RegisterOptions { public: const std::string service_name; // This may differ from the service name if there was a collision. std::string actual_service_name; const uint16_t port; AvahiEntryGroup *group; AvahiEntryGroupState state; struct EntryGroupParams *params; ServiceEntry(const std::string &service_name, const std::string &type_spec, uint16_t port, const RegisterOptions &options); std::string key() const; const std::string &type() const { return m_type; } const std::vector sub_types() const { return m_sub_types; } private: std::string m_type_spec; // type[,subtype] std::string m_type; std::vector m_sub_types; }; typedef std::map Services; AvahiThreadedPoll *m_threaded_poll; AvahiClient *m_client; AvahiTimeout *m_reconnect_timeout; Services m_services; BackoffGenerator m_backoff; bool InternalRegisterService(ServiceEntry *service); void CreateNewClient(); void UpdateServices(); void DeregisterAllServices(); void SetUpReconnectTimeout(); bool RenameAndRegister(ServiceEntry *service); static std::string ClientStateToString(AvahiClientState state); static std::string GroupStateToString(AvahiEntryGroupState state); DISALLOW_COPY_AND_ASSIGN(AvahiDiscoveryAgent); }; } // namespace ola #endif // OLAD_AVAHIDISCOVERYAGENT_H_ ola-0.10.5.nojsmin/olad/PluginManagerTest.cpp0000644000175000017500000001301113023355232020466 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * PluginManagerTest.cpp * Test fixture for the PluginManager classes * Copyright (C) 2005 Simon Newton */ #include #include #include #include #include "olad/Plugin.h" #include "olad/PluginAdaptor.h" #include "olad/PluginLoader.h" #include "olad/PluginManager.h" #include "olad/Preferences.h" #include "olad/plugin_api/TestCommon.h" #include "ola/testing/TestUtils.h" using ola::AbstractPlugin; using ola::PluginLoader; using ola::PluginManager; using std::set; using std::string; using std::vector; class PluginManagerTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(PluginManagerTest); CPPUNIT_TEST(testPluginManager); CPPUNIT_TEST(testConflictingPlugins); CPPUNIT_TEST_SUITE_END(); public: void testPluginManager(); void testConflictingPlugins(); void setUp() { ola::InitLogging(ola::OLA_LOG_INFO, ola::OLA_LOG_STDERR); } private: void VerifyPluginCounts(PluginManager *manager, size_t loaded_plugins, size_t active_plugins, const ola::testing::SourceLine &source_line) { vector plugins; manager->Plugins(&plugins); ola::testing::_AssertEquals(source_line, loaded_plugins, plugins.size(), "Loaded plugin count differs"); plugins.clear(); manager->ActivePlugins(&plugins); ola::testing::_AssertEquals(source_line, active_plugins, plugins.size(), "Active plugin count differs"); } }; CPPUNIT_TEST_SUITE_REGISTRATION(PluginManagerTest); /* * A Mock Loader */ class MockLoader: public ola::PluginLoader { public: explicit MockLoader(const vector &plugins): PluginLoader(), m_plugins(plugins) { } vector LoadPlugins() { return m_plugins; } void UnloadPlugins() {} private: vector m_plugins; }; /* * Check that we can load & unload plugins correctly. */ void PluginManagerTest::testPluginManager() { ola::MemoryPreferencesFactory factory; ola::PluginAdaptor adaptor(NULL, NULL, NULL, &factory, NULL, NULL); TestMockPlugin plugin1(&adaptor, ola::OLA_PLUGIN_ARTNET); TestMockPlugin plugin2(&adaptor, ola::OLA_PLUGIN_ESPNET, false); vector our_plugins; our_plugins.push_back(&plugin1); our_plugins.push_back(&plugin2); MockLoader loader(our_plugins); vector loaders; loaders.push_back(&loader); PluginManager manager(loaders, &adaptor); manager.LoadAll(); VerifyPluginCounts(&manager, 2, 1, OLA_SOURCELINE()); OLA_ASSERT(plugin1.IsRunning()); OLA_ASSERT_FALSE(plugin2.IsRunning()); manager.UnloadAll(); VerifyPluginCounts(&manager, 0, 0, OLA_SOURCELINE()); } /* * Check that we detect conflicting plugins */ void PluginManagerTest::testConflictingPlugins() { ola::MemoryPreferencesFactory factory; ola::PluginAdaptor adaptor(NULL, NULL, NULL, &factory, NULL, NULL); set conflict_set1, conflict_set2, conflict_set3; conflict_set1.insert(ola::OLA_PLUGIN_ARTNET); TestMockPlugin plugin1(&adaptor, ola::OLA_PLUGIN_DUMMY, conflict_set1); TestMockPlugin plugin2(&adaptor, ola::OLA_PLUGIN_ARTNET); conflict_set2.insert(ola::OLA_PLUGIN_ARTNET); TestMockPlugin plugin3(&adaptor, ola::OLA_PLUGIN_SHOWNET, conflict_set2); conflict_set3.insert(ola::OLA_PLUGIN_DUMMY); TestMockPlugin plugin4(&adaptor, ola::OLA_PLUGIN_SANDNET, conflict_set3); vector our_plugins; our_plugins.push_back(&plugin1); our_plugins.push_back(&plugin2); our_plugins.push_back(&plugin3); our_plugins.push_back(&plugin4); MockLoader loader(our_plugins); vector loaders; loaders.push_back(&loader); PluginManager manager(loaders, &adaptor); manager.LoadAll(); VerifyPluginCounts(&manager, 4, 2, OLA_SOURCELINE()); OLA_ASSERT_TRUE(plugin1.IsRunning()); OLA_ASSERT_FALSE(plugin2.IsRunning()); OLA_ASSERT_TRUE(plugin3.IsRunning()); // Try to enable the sandnet plugin, that conflicts with the dummy plugin OLA_ASSERT_FALSE(manager.EnableAndStartPlugin(ola::OLA_PLUGIN_SANDNET)); VerifyPluginCounts(&manager, 4, 2, OLA_SOURCELINE()); // Now disable the dummy plugin manager.DisableAndStopPlugin(ola::OLA_PLUGIN_DUMMY); VerifyPluginCounts(&manager, 4, 1, OLA_SOURCELINE()); OLA_ASSERT_FALSE(plugin1.IsRunning()); // Try to load sandnet again OLA_ASSERT_TRUE(manager.EnableAndStartPlugin(ola::OLA_PLUGIN_SANDNET)); VerifyPluginCounts(&manager, 4, 2, OLA_SOURCELINE()); OLA_ASSERT_TRUE(plugin4.IsRunning()); manager.UnloadAll(); VerifyPluginCounts(&manager, 0, 0, OLA_SOURCELINE()); } ola-0.10.5.nojsmin/olad/PluginManager.cpp0000644000175000017500000001607513023355232017643 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * PluginManager.cpp * This class is responsible for loading and unloading the plugins * Copyright (C) 2005 Simon Newton */ #include "olad/PluginManager.h" #include #include #include "ola/Logging.h" #include "ola/stl/STLUtils.h" #include "olad/Plugin.h" #include "olad/PluginAdaptor.h" #include "olad/PluginLoader.h" namespace ola { using std::vector; using std::set; PluginManager::PluginManager(const vector &plugin_loaders, class PluginAdaptor *plugin_adaptor) : m_plugin_loaders(plugin_loaders), m_plugin_adaptor(plugin_adaptor) { } PluginManager::~PluginManager() { UnloadAll(); } void PluginManager::LoadAll() { m_enabled_plugins.clear(); // The first pass populates the m_plugin map, and builds a list of enabled // plugins. vector::iterator iter; for (iter = m_plugin_loaders.begin(); iter != m_plugin_loaders.end(); ++iter) { (*iter)->SetPluginAdaptor(m_plugin_adaptor); vector plugins = (*iter)->LoadPlugins(); vector::iterator plugin_iter = plugins.begin(); for (; plugin_iter != plugins.end(); ++plugin_iter) { AbstractPlugin *plugin = *plugin_iter; if (!STLInsertIfNotPresent(&m_loaded_plugins, plugin->Id(), plugin)) { OLA_WARN << "Skipping plugin " << plugin->Name() << " because it's already been loaded"; delete plugin; continue; } if (!plugin->LoadPreferences()) { OLA_WARN << "Failed to load preferences for " << plugin->Name(); continue; } if (!plugin->IsEnabled()) { OLA_INFO << "Skipping " << plugin->Name() << " because it was disabled"; continue; } STLInsertIfNotPresent(&m_enabled_plugins, plugin->Id(), plugin); } } // The second pass checks for conflicts and starts each plugin PluginMap::iterator plugin_iter = m_enabled_plugins.begin(); for (; plugin_iter != m_enabled_plugins.end(); ++plugin_iter) { StartIfSafe(plugin_iter->second); } } void PluginManager::UnloadAll() { PluginMap::iterator plugin_iter = m_loaded_plugins.begin(); for (; plugin_iter != m_loaded_plugins.end(); ++plugin_iter) { plugin_iter->second->Stop(); } m_loaded_plugins.clear(); m_active_plugins.clear(); m_enabled_plugins.clear(); vector::iterator iter = m_plugin_loaders.begin(); for (; iter != m_plugin_loaders.end(); ++iter) { (*iter)->SetPluginAdaptor(NULL); (*iter)->UnloadPlugins(); } } void PluginManager::Plugins(vector *plugins) const { plugins->clear(); STLValues(m_loaded_plugins, plugins); } void PluginManager::ActivePlugins(vector *plugins) const { plugins->clear(); STLValues(m_active_plugins, plugins); } void PluginManager::EnabledPlugins(vector *plugins) const { plugins->clear(); STLValues(m_enabled_plugins, plugins); } AbstractPlugin* PluginManager::GetPlugin(ola_plugin_id plugin_id) const { return STLFindOrNull(m_loaded_plugins, plugin_id); } bool PluginManager::IsActive(ola_plugin_id plugin_id) const { return STLContains(m_active_plugins, plugin_id); } bool PluginManager::IsEnabled(ola_plugin_id plugin_id) const { return STLContains(m_enabled_plugins, plugin_id); } void PluginManager::DisableAndStopPlugin(ola_plugin_id plugin_id) { AbstractPlugin *plugin = STLFindOrNull(m_loaded_plugins, plugin_id); if (!plugin_id) { return; } if (STLRemove(&m_active_plugins, plugin_id)) { plugin->Stop(); } if (STLRemove(&m_enabled_plugins, plugin_id)) { plugin->SetEnabledState(false); } } bool PluginManager::EnableAndStartPlugin(ola_plugin_id plugin_id) { if (STLContains(m_active_plugins, plugin_id)) { // Already running, nothing to do. return true; } AbstractPlugin *plugin = STLFindOrNull(m_loaded_plugins, plugin_id); if (!plugin) { return false; } if (STLInsertIfNotPresent(&m_enabled_plugins, plugin_id, plugin)) { plugin->SetEnabledState(true); } return StartIfSafe(plugin); } void PluginManager::GetConflictList(ola_plugin_id plugin_id, vector *plugins) { PluginMap::iterator iter = m_loaded_plugins.begin(); for (; iter != m_loaded_plugins.end(); ++iter) { set conflict_list; iter->second->ConflictsWith(&conflict_list); if (iter->second->Id() == plugin_id) { set::const_iterator id_iter = conflict_list.begin(); for (; id_iter != conflict_list.end(); ++id_iter) { AbstractPlugin *plugin = GetPlugin(*id_iter); if (plugin) { plugins->push_back(plugin); } } } else { if (STLContains(conflict_list, plugin_id)) { plugins->push_back(iter->second); } } } } bool PluginManager::StartIfSafe(AbstractPlugin *plugin) { AbstractPlugin *conflicting_plugin = CheckForRunningConflicts(plugin); if (conflicting_plugin) { OLA_WARN << "Not enabling " << plugin->Name() << " because it conflicts with " << conflicting_plugin->Name() << " which is already running"; return false; } OLA_INFO << "Trying to start " << plugin->Name(); bool ok = plugin->Start(); if (!ok) { OLA_WARN << "Failed to start " << plugin->Name(); } else { OLA_INFO << "Started " << plugin->Name(); STLReplace(&m_active_plugins, plugin->Id(), plugin); } return ok; } /* * @brief Check if this plugin conflicts with any of the running plugins. * @param plugin The plugin to check * @returns The first conflicting plugin, or NULL if there aren't any. */ AbstractPlugin* PluginManager::CheckForRunningConflicts( const AbstractPlugin *plugin) const { PluginMap::const_iterator iter = m_active_plugins.begin(); for (; iter != m_active_plugins.end(); ++iter) { set conflict_list; iter->second->ConflictsWith(&conflict_list); if (STLContains(conflict_list, plugin->Id())) { return iter->second; } } set conflict_list; plugin->ConflictsWith(&conflict_list); set::const_iterator set_iter = conflict_list.begin(); for (; set_iter != conflict_list.end(); ++set_iter) { AbstractPlugin *conflicting_plugin = STLFindOrNull( m_active_plugins, *set_iter); if (conflicting_plugin) { return conflicting_plugin; } } return NULL; } } // namespace ola ola-0.10.5.nojsmin/olad/ClientBroker.h0000644000175000017500000000744413023355232017142 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ClientBroker.h * The client broker exists to handle the case where a client may disconnect * while a RDM call is in flight. When the call completes, the client broker * will detect that the client has disconnected and not run the callback (which * would now point to an invalid memory location). * Copyright (C) 2010 Simon Newton */ #ifndef OLAD_CLIENTBROKER_H_ #define OLAD_CLIENTBROKER_H_ #include #include #include #include "ola/base/Macro.h" #include "ola/rdm/RDMCommand.h" #include "ola/rdm/RDMControllerInterface.h" #include "ola/Callback.h" #include "olad/Universe.h" #include "olad/plugin_api/Client.h" namespace ola { /** * @brief Handles async client operations. * * Since some client operations such as RDM commands are asynchronous, * we can run into problems if the client disconnects while the operation * is in progress. This is because the completion callback will hold a pointer * to a client which has been deleted. * * The ClientBroker acts as an in-between by holding a list of active clients * and proxying RDM calls. When the RDM call returns, if the client responsible * for the call has been deleted, we delete the callback rather then executing * it. */ class ClientBroker { public: ClientBroker() {} ~ClientBroker() {} /** * @brief Add a client to the broker. * @param client the Client to add. Ownership is not transferred. */ void AddClient(const Client *client); /** * @brief Remove a client from the broker. * @param client The Client to remove. */ void RemoveClient(const Client *client); /** * @brief Make an RDM call. * @param client the Client responsible for making the call. * @param universe the universe to send the RDM request on. * @param request the RDM request. * @param callback the callback to run when the request completes. Ownership * is transferred. */ void SendRDMRequest(const Client *client, Universe *universe, ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *callback); /** * @brief Make an RDM call. * @param client the Client responsible for making the call. * @param universe the universe to send the RDM request on. * @param full_discovery true for full discovery, false for incremental. * @param callback the callback to run when the request completes. Ownership * is transferred. */ void RunRDMDiscovery(const Client *client, Universe *universe, bool full_discovery, ola::rdm::RDMDiscoveryCallback *callback); private: typedef std::set client_set; client_set m_clients; void RequestComplete(const Client *key, ola::rdm::RDMCallback *callback, ola::rdm::RDMReply *reply); void DiscoveryComplete(const Client *key, ola::rdm::RDMDiscoveryCallback *on_complete, const ola::rdm::UIDSet &uids); DISALLOW_COPY_AND_ASSIGN(ClientBroker); }; } // namespace ola #endif // OLAD_CLIENTBROKER_H_ ola-0.10.5.nojsmin/olad/Olad.cpp0000644000175000017500000001277013023355232015767 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Olad.cpp * Main file for olad, parses the options, forks if required and runs the * daemon. * Copyright (C) 2005 Simon Newton * */ #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #include #include #include #include #include #include "ola/Logging.h" #include "ola/base/Credentials.h" #include "ola/base/Flags.h" #include "ola/base/Init.h" #include "ola/base/SysExits.h" #include "ola/base/Version.h" #include "ola/thread/SignalThread.h" #include "olad/OlaDaemon.h" using ola::OlaDaemon; using ola::thread::SignalThread; using std::cout; using std::endl; DEFINE_default_bool(http, true, "Disable the HTTP server."); DEFINE_default_bool(http_quit, true, "Disable the HTTP /quit handler."); #ifndef _WIN32 DEFINE_s_default_bool(daemon, f, false, "Fork and run in the background."); #endif // _WIN32 DEFINE_s_string(http_data_dir, d, "", "The path to the static www content."); DEFINE_s_string(interface, i, "", "The interface name (e.g. eth0) or IP of the network interface " "to use."); DEFINE_string(pid_location, "", "The directory containing the PID definitions."); DEFINE_s_uint16(http_port, p, ola::OlaServer::DEFAULT_HTTP_PORT, "The port to run the http server on. Defaults to 9090."); /** * This is called by the SelectServer loop to start up the SignalThread. If the * thread fails to start, we terminate the SelectServer */ void StartSignalThread(ola::io::SelectServer *ss, SignalThread *signal_thread) { if (!signal_thread->Start()) { ss->Terminate(); } } /* * Main */ int main(int argc, char *argv[]) { // Take a copy of the arguments otherwise the export map is incorrect. const int original_argc = argc; char *original_argv[original_argc]; for (int i = 0; i < original_argc; i++) { original_argv[i] = argv[i]; } // We don't use the longer form for ServerInit here because we need to check // for root and possibly daemonise before doing the rest of the work from // ServerInit. ola::SetHelpString("[options]", "Start the OLA Daemon."); ola::ParseFlags(&argc, argv); ola::InitLoggingFromFlags(); OLA_INFO << "OLA Daemon version " << ola::base::Version::GetVersion(); #ifndef OLAD_SKIP_ROOT_CHECK uid_t uid; ola::GetEUID(&uid); if (ola::SupportsUIDs() && !uid) { OLA_FATAL << "Attempting to run as root, aborting."; return ola::EXIT_UNAVAILABLE; } #endif // OLAD_SKIP_ROOT_CHECK #ifndef _WIN32 if (FLAGS_daemon) ola::Daemonise(); #endif // _WIN32 ola::ExportMap export_map; if (!ola::ServerInit(original_argc, original_argv, &export_map)) { return ola::EXIT_UNAVAILABLE; } // We need to block signals before we start any threads. // Signal setup is complex. First of all we need to install NULL handlers to // the signals are blocked before we start *any* threads. It's safest if we // do this before creating the OlaDaemon. SignalThread signal_thread; signal_thread.InstallSignalHandler(SIGINT, NULL); signal_thread.InstallSignalHandler(SIGTERM, NULL); #ifndef _WIN32 signal_thread.InstallSignalHandler(SIGHUP, NULL); signal_thread.InstallSignalHandler( SIGUSR1, ola::NewCallback(&ola::IncrementLogLevel)); #endif // _WIN32 ola::OlaServer::Options options; options.http_enable = FLAGS_http; options.http_enable_quit = FLAGS_http_quit; options.http_port = FLAGS_http_port; options.http_data_dir = FLAGS_http_data_dir.str(); options.network_interface = FLAGS_interface.str(); options.pid_data_dir = FLAGS_pid_location.str(); std::auto_ptr olad(new OlaDaemon(options, &export_map)); if (!olad.get()) { return ola::EXIT_UNAVAILABLE; } // Now that the OlaDaemon has been created, we can reset the signal handlers // to do what we actually want them to. signal_thread.InstallSignalHandler( SIGINT, ola::NewCallback(olad->GetSelectServer(), &ola::io::SelectServer::Terminate)); signal_thread.InstallSignalHandler( SIGTERM, ola::NewCallback(olad->GetSelectServer(), &ola::io::SelectServer::Terminate)); // We can't start the signal thread here, otherwise there is a race // condition if a signal arrives before we enter the SelectServer Run() // method. Instead we schedule it to start from the SelectServer loop. olad->GetSelectServer()->Execute(ola::NewSingleCallback( &StartSignalThread, olad->GetSelectServer(), &signal_thread)); if (!olad->Init()) { return ola::EXIT_UNAVAILABLE; } #ifndef _WIN32 // Finally the OlaServer is not-null. signal_thread.InstallSignalHandler( SIGHUP, ola::NewCallback(olad->GetOlaServer(), &ola::OlaServer::ReloadPlugins)); #endif // _WIN32 olad->Run(); return ola::EXIT_OK; } ola-0.10.5.nojsmin/olad/OlaServer.cpp0000644000175000017500000003545213023355232017014 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OlaServer.cpp * OlaServer is the main OLA Server class * Copyright (C) 2005 Simon Newton */ #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #include #include #include #include #include #include #include "common/protocol/Ola.pb.h" #include "common/rpc/RpcChannel.h" #include "common/rpc/RpcServer.h" #include "common/rpc/RpcSession.h" #include "ola/Constants.h" #include "ola/ExportMap.h" #include "ola/Logging.h" #include "ola/base/Flags.h" #include "ola/network/InterfacePicker.h" #include "ola/network/Socket.h" #include "ola/rdm/PidStore.h" #include "ola/rdm/UID.h" #include "ola/stl/STLUtils.h" #include "olad/ClientBroker.h" #include "olad/DiscoveryAgent.h" #include "olad/OlaServer.h" #include "olad/OlaServerServiceImpl.h" #include "olad/Plugin.h" #include "olad/PluginAdaptor.h" #include "olad/PluginManager.h" #include "olad/Port.h" #include "olad/PortBroker.h" #include "olad/Preferences.h" #include "olad/Universe.h" #include "olad/plugin_api/Client.h" #include "olad/plugin_api/DeviceManager.h" #include "olad/plugin_api/PortManager.h" #include "olad/plugin_api/UniverseStore.h" #ifdef HAVE_LIBMICROHTTPD #include "olad/OladHTTPServer.h" #endif // HAVE_LIBMICROHTTPD DEFINE_s_uint16(rpc_port, r, ola::OlaServer::DEFAULT_RPC_PORT, "The port to listen for RPCs on. Defaults to 9010."); DEFINE_default_bool(register_with_dns_sd, true, "Don't register the web service using DNS-SD (Bonjour)."); namespace ola { using ola::proto::OlaClientService_Stub; using ola::rdm::RootPidStore; using ola::rpc::RpcChannel; using ola::rpc::RpcSession; using ola::rpc::RpcServer; using std::auto_ptr; using std::pair; using std::vector; const char OlaServer::INSTANCE_NAME_KEY[] = "instance-name"; const char OlaServer::K_INSTANCE_NAME_VAR[] = "server-instance-name"; const char OlaServer::K_UID_VAR[] = "server-uid"; const char OlaServer::SERVER_PREFERENCES[] = "server"; const char OlaServer::UNIVERSE_PREFERENCES[] = "universe"; // The Bonjour API expects [,] so we use that form here. const char OlaServer::K_DISCOVERY_SERVICE_TYPE[] = "_http._tcp,_ola"; const unsigned int OlaServer::K_HOUSEKEEPING_TIMEOUT_MS = 10000; OlaServer::OlaServer(const vector &plugin_loaders, PreferencesFactory *preferences_factory, ola::io::SelectServer *select_server, const Options &ola_options, ola::network::TCPAcceptingSocket *socket, ExportMap *export_map) : m_options(ola_options), m_plugin_loaders(plugin_loaders), m_preferences_factory(preferences_factory), m_ss(select_server), m_accepting_socket(socket), m_export_map(export_map), m_default_uid(OPEN_LIGHTING_ESTA_CODE, 0), m_server_preferences(NULL), m_universe_preferences(NULL), m_housekeeping_timeout(ola::thread::INVALID_TIMEOUT) { if (!m_export_map) { m_our_export_map.reset(new ExportMap()); m_export_map = m_our_export_map.get(); } } OlaServer::~OlaServer() { m_ss->DrainCallbacks(); #ifdef HAVE_LIBMICROHTTPD if (m_httpd.get()) { m_httpd->Stop(); m_httpd.reset(); } #endif // HAVE_LIBMICROHTTPD // Order is important during shutdown. // Shutdown the RPC server first since it depends on almost everything else. m_rpc_server.reset(); if (m_housekeeping_timeout != ola::thread::INVALID_TIMEOUT) { m_ss->RemoveTimeout(m_housekeeping_timeout); } StopPlugins(); m_broker.reset(); m_port_broker.reset(); if (m_universe_store.get()) { m_universe_store->DeleteAll(); m_universe_store.reset(); } if (m_server_preferences) { m_server_preferences->Save(); } if (m_universe_preferences) { m_universe_preferences->Save(); } m_port_manager.reset(); m_plugin_adaptor.reset(); m_device_manager.reset(); m_plugin_manager.reset(); m_service_impl.reset(); } bool OlaServer::Init() { if (m_service_impl.get()) { return false; } if (!m_ss) { return false; } // TODO(simon): run without preferences & PluginLoader if (m_plugin_loaders.empty() || !m_preferences_factory) { return false; } auto_ptr pid_store( RootPidStore::LoadFromDirectory(m_options.pid_data_dir)); if (!pid_store.get()) { OLA_WARN << "No PID definitions loaded"; } #ifndef _WIN32 signal(SIGPIPE, SIG_IGN); #endif // _WIN32 // fetch the interface info ola::network::Interface iface; { auto_ptr picker( ola::network::InterfacePicker::NewPicker()); if (!picker->ChooseInterface(&iface, m_options.network_interface)) { OLA_WARN << "No network interface found"; } else { // default to using the ip as a id m_default_uid = ola::rdm::UID(OPEN_LIGHTING_ESTA_CODE, iface.ip_address.AsInt()); } } m_export_map->GetStringVar(K_UID_VAR)->Set(m_default_uid.ToString()); OLA_INFO << "Server UID is " << m_default_uid; m_server_preferences = m_preferences_factory->NewPreference( SERVER_PREFERENCES); m_server_preferences->Load(); if (m_server_preferences->SetDefaultValue(INSTANCE_NAME_KEY, StringValidator(), OLA_DEFAULT_INSTANCE_NAME)) { m_server_preferences->Save(); } m_instance_name = m_server_preferences->GetValue(INSTANCE_NAME_KEY); m_export_map->GetStringVar(K_INSTANCE_NAME_VAR)->Set(m_instance_name); OLA_INFO << "Server instance name is " << m_instance_name; Preferences *universe_preferences = m_preferences_factory->NewPreference( UNIVERSE_PREFERENCES); universe_preferences->Load(); auto_ptr universe_store( new UniverseStore(universe_preferences, m_export_map)); auto_ptr port_broker(new PortBroker()); auto_ptr port_manager( new PortManager(universe_store.get(), port_broker.get())); auto_ptr broker(new ClientBroker()); auto_ptr device_manager( new DeviceManager(m_preferences_factory, port_manager.get())); auto_ptr plugin_adaptor( new PluginAdaptor(device_manager.get(), m_ss, m_export_map, m_preferences_factory, port_broker.get(), &m_instance_name)); auto_ptr plugin_manager( new PluginManager(m_plugin_loaders, plugin_adaptor.get())); auto_ptr service_impl(new OlaServerServiceImpl( universe_store.get(), device_manager.get(), plugin_manager.get(), port_manager.get(), broker.get(), m_ss->WakeUpTime(), NewCallback(this, &OlaServer::ReloadPluginsInternal))); // Initialize the RPC server. RpcServer::Options rpc_options; rpc_options.listen_socket = m_accepting_socket; rpc_options.listen_port = FLAGS_rpc_port; rpc_options.export_map = m_export_map; auto_ptr rpc_server( new RpcServer(m_ss, service_impl.get(), this, rpc_options)); if (!rpc_server->Init()) { OLA_WARN << "Failed to init RPC server"; return false; } // Discovery auto_ptr discovery_agent; if (FLAGS_register_with_dns_sd) { DiscoveryAgentFactory discovery_agent_factory; discovery_agent.reset(discovery_agent_factory.New()); if (discovery_agent.get()) { if (!discovery_agent->Init()) { OLA_WARN << "Failed to Init DiscoveryAgent"; return false; } } } bool web_server_started = false; // Initializing the web server causes a call to NewClient. We need to have // the broker in place for the call, otherwise we'll segfault. m_broker.reset(broker.release()); #ifdef HAVE_LIBMICROHTTPD if (m_options.http_enable) { if (StartHttpServer(rpc_server.get(), iface)) { web_server_started = true; } else { OLA_WARN << "Failed to start the HTTP server."; m_broker.reset(); return false; } } #endif // HAVE_LIBMICROHTTPD if (web_server_started && discovery_agent.get()) { DiscoveryAgentInterface::RegisterOptions options; options.txt_data["path"] = "/"; discovery_agent->RegisterService( m_instance_name, K_DISCOVERY_SERVICE_TYPE, m_options.http_port, options); } // Ok, we've created and initialized everything correctly by this point. Now // we save all the pointers and schedule the last of the callbacks. m_device_manager.reset(device_manager.release()); m_discovery_agent.reset(discovery_agent.release()); m_plugin_adaptor.reset(plugin_adaptor.release()); m_plugin_manager.reset(plugin_manager.release()); m_port_broker.reset(port_broker.release()); m_port_manager.reset(port_manager.release()); m_rpc_server.reset(rpc_server.release()); m_service_impl.reset(service_impl.release()); m_universe_store.reset(universe_store.release()); UpdatePidStore(pid_store.release()); if (m_housekeeping_timeout != ola::thread::INVALID_TIMEOUT) { m_ss->RemoveTimeout(m_housekeeping_timeout); } m_housekeeping_timeout = m_ss->RegisterRepeatingTimeout( K_HOUSEKEEPING_TIMEOUT_MS, ola::NewCallback(this, &OlaServer::RunHousekeeping)); // The plugin load procedure can take a while so we run it in the main loop. m_ss->Execute( ola::NewSingleCallback(m_plugin_manager.get(), &PluginManager::LoadAll)); return true; } void OlaServer::ReloadPlugins() { m_ss->Execute(NewCallback(this, &OlaServer::ReloadPluginsInternal)); } void OlaServer::ReloadPidStore() { // We load the PIDs in this thread, and then hand the RootPidStore over to // the main thread. This avoids doing disk I/O in the network thread. const RootPidStore* pid_store = RootPidStore::LoadFromDirectory( m_options.pid_data_dir); if (!pid_store) { return; } m_ss->Execute(NewCallback(this, &OlaServer::UpdatePidStore, pid_store)); } void OlaServer::NewConnection(ola::io::ConnectedDescriptor *descriptor) { if (!descriptor) { return; } InternalNewConnection(m_rpc_server.get(), descriptor); } ola::network::GenericSocketAddress OlaServer::LocalRPCAddress() const { if (m_rpc_server.get()) { return m_rpc_server->ListenAddress(); } else { return ola::network::GenericSocketAddress(); } } void OlaServer::NewClient(RpcSession *session) { OlaClientService_Stub *stub = new OlaClientService_Stub(session->Channel()); Client *client = new Client(stub, m_default_uid); session->SetData(static_cast(client)); m_broker->AddClient(client); } void OlaServer::ClientRemoved(RpcSession *session) { auto_ptr client(reinterpret_cast(session->GetData())); session->SetData(NULL); m_broker->RemoveClient(client.get()); vector universe_list; m_universe_store->GetList(&universe_list); vector::iterator uni_iter; for (uni_iter = universe_list.begin(); uni_iter != universe_list.end(); ++uni_iter) { (*uni_iter)->RemoveSourceClient(client.get()); (*uni_iter)->RemoveSinkClient(client.get()); } } /* * Run the garbage collector */ bool OlaServer::RunHousekeeping() { OLA_DEBUG << "Garbage collecting"; m_universe_store->GarbageCollectUniverses(); // Give the universes an opportunity to run discovery vector universes; m_universe_store->GetList(&universes); vector::iterator iter = universes.begin(); const TimeStamp *now = m_ss->WakeUpTime(); for (; iter != universes.end(); ++iter) { (*iter)->CleanStaleSourceClients(); if ((*iter)->IsActive() && (*iter)->RDMDiscoveryInterval().Seconds() && *now - (*iter)->LastRDMDiscovery() > (*iter)->RDMDiscoveryInterval()) { // run incremental discovery (*iter)->RunRDMDiscovery(NULL, false); } } return true; } #ifdef HAVE_LIBMICROHTTPD bool OlaServer::StartHttpServer(ola::rpc::RpcServer *server, const ola::network::Interface &iface) { if (!m_options.http_enable) { return true; } // create a pipe for the HTTP server to communicate with the main // server on. auto_ptr pipe_descriptor( new ola::io::PipeDescriptor()); if (!pipe_descriptor->Init()) { return false; } // ownership of the pipe_descriptor is transferred here. OladHTTPServer::OladHTTPServerOptions options; options.port = m_options.http_port ? m_options.http_port : DEFAULT_HTTP_PORT; options.data_dir = (m_options.http_data_dir.empty() ? HTTP_DATA_DIR : m_options.http_data_dir); options.enable_quit = m_options.http_enable_quit; auto_ptr httpd( new OladHTTPServer(m_export_map, options, pipe_descriptor->OppositeEnd(), this, iface)); if (httpd->Init()) { httpd->Start(); // register the pipe descriptor as a client InternalNewConnection(server, pipe_descriptor.release()); m_httpd.reset(httpd.release()); return true; } else { pipe_descriptor->Close(); return false; } } #endif // HAVE_LIBMICROHTTPD void OlaServer::StopPlugins() { if (m_plugin_manager.get()) { m_plugin_manager->UnloadAll(); } if (m_device_manager.get()) { if (m_device_manager->DeviceCount()) { OLA_WARN << "Some devices failed to unload, we're probably leaking " << "memory now"; } m_device_manager->UnregisterAllDevices(); } } /* * Add a new ConnectedDescriptor to this Server. * @param socket the new ConnectedDescriptor */ bool OlaServer::InternalNewConnection( ola::rpc::RpcServer *server, ola::io::ConnectedDescriptor *descriptor) { if (server) { return server->AddClient(descriptor); } else { delete descriptor; return false; } } void OlaServer::ReloadPluginsInternal() { OLA_INFO << "Reloading plugins"; StopPlugins(); m_plugin_manager->LoadAll(); } void OlaServer::UpdatePidStore(const RootPidStore *pid_store) { OLA_INFO << "Updated PID definitions."; #ifdef HAVE_LIBMICROHTTPD if (m_httpd.get()) { m_httpd->SetPidStore(pid_store); } #endif // HAVE_LIBMICROHTTPD m_pid_store.reset(pid_store); OLA_INFO << "PID store is at " << m_pid_store.get(); } } // namespace ola ola-0.10.5.nojsmin/olad/OlaServer.h0000644000175000017500000001577313023355232016465 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OlaServer.h * Interface for the ola server class * Copyright (C) 2005 Simon Newton */ #ifndef OLAD_OLASERVER_H_ #define OLAD_OLASERVER_H_ #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace ola { namespace rpc { class RpcSession; class RpcServer; } #ifdef HAVE_LIBMICROHTTPD typedef class OladHTTPServer OladHTTPServer_t; #else typedef int OladHTTPServer_t; #endif // HAVE_LIBMICROHTTPD /** * @brief The main OlaServer class. */ class OlaServer : public ola::rpc::RpcSessionHandlerInterface { public: /** * @brief Options for the OlaServer. */ struct Options { bool http_enable; /** @brief Run the HTTP server */ bool http_localhost_only; /** @brief Restrict access to localhost only */ bool http_enable_quit; /** @brief Enable /quit URL */ unsigned int http_port; /** @brief Port to run the HTTP server on */ /** @brief Directory that contains the static content */ std::string http_data_dir; std::string network_interface; std::string pid_data_dir; /** @brief Directory with the PID definitions */ }; /** * @brief Create a new instance of the OlaServer. * @param plugin_loaders A list of PluginLoaders to use to find plugins. * @param preferences_factory The factory to use when creating Preference * objects. * @param ss The SelectServer. * @param ola_options The OlaServer options. * @param socket An optional TCPAcceptingSocket in the listen state to use * for client RPC calls. Ownership is transferred. * @param export_map An optional ExportMap. If set to NULL a new ExportMap * will be created. */ OlaServer(const std::vector &plugin_loaders, class PreferencesFactory *preferences_factory, ola::io::SelectServer *ss, const Options &ola_options, ola::network::TCPAcceptingSocket *socket = NULL, ExportMap *export_map = NULL); /** * @brief Shutdown the server */ ~OlaServer(); /** * @brief Initialize the OlaServer. * @returns true if initialization succeeded, false if it failed. */ bool Init(); /** * @brief Reload all plugins. * * This method is thread safe. */ void ReloadPlugins(); /** * @brief Reload the pid store. * * This method is thread safe. */ void ReloadPidStore(); /** * @brief Stop the OLA Server. * * This terminates the underlying SelectServer. */ void StopServer() { m_ss->Terminate(); } /** * @brief Add a new ConnectedDescriptor to this Server. * @param descriptor the new ConnectedDescriptor, ownership is transferred. */ void NewConnection(ola::io::ConnectedDescriptor *descriptor); /** * @brief Return the socket address the RPC server is listening on. * @returns A socket address, which is empty if the server hasn't been * initialized. */ ola::network::GenericSocketAddress LocalRPCAddress() const; // Called by the RpcServer when clients connect or disconnect. void NewClient(ola::rpc::RpcSession *session); void ClientRemoved(ola::rpc::RpcSession *session); /** * @brief Get the instance name * @return a string which is the instance name */ const std::string InstanceName() { return m_instance_name; } /** * @brief Get the preferences factory * @return a pointer to the preferences factory */ const PreferencesFactory* GetPreferencesFactory() { return m_preferences_factory; } static const unsigned int DEFAULT_HTTP_PORT = 9090; static const unsigned int DEFAULT_RPC_PORT = OLA_DEFAULT_PORT; private : struct ClientEntry { ola::io::ConnectedDescriptor *client_descriptor; class OlaClientService *client_service; }; typedef std::map ClientMap; // These are all passed to the constructor. const Options m_options; std::vector m_plugin_loaders; class PreferencesFactory *m_preferences_factory; ola::io::SelectServer *m_ss; ola::network::TCPAcceptingSocket *m_accepting_socket; class ExportMap *m_export_map; std::auto_ptr m_our_export_map; ola::rdm::UID m_default_uid; // These are all populated in Init. std::auto_ptr m_device_manager; std::auto_ptr m_plugin_manager; std::auto_ptr m_plugin_adaptor; std::auto_ptr m_universe_store; std::auto_ptr m_port_manager; std::auto_ptr m_service_impl; std::auto_ptr m_broker; std::auto_ptr m_port_broker; std::auto_ptr m_pid_store; std::auto_ptr m_discovery_agent; std::auto_ptr m_rpc_server; class Preferences *m_server_preferences; class Preferences *m_universe_preferences; std::string m_instance_name; ola::thread::timeout_id m_housekeeping_timeout; std::auto_ptr m_httpd; bool RunHousekeeping(); #ifdef HAVE_LIBMICROHTTPD bool StartHttpServer(ola::rpc::RpcServer *server, const ola::network::Interface &iface); #endif // HAVE_LIBMICROHTTPD /** * @brief Stop and unload all the plugins */ void StopPlugins(); bool InternalNewConnection(ola::rpc::RpcServer *server, ola::io::ConnectedDescriptor *descriptor); void ReloadPluginsInternal(); /** * @brief Update the Pid store with the new values. */ void UpdatePidStore(const ola::rdm::RootPidStore *pid_store); static const char INSTANCE_NAME_KEY[]; static const char K_INSTANCE_NAME_VAR[]; static const char K_DISCOVERY_SERVICE_TYPE[]; static const char K_UID_VAR[]; static const char SERVER_PREFERENCES[]; static const char UNIVERSE_PREFERENCES[]; static const unsigned int K_HOUSEKEEPING_TIMEOUT_MS; DISALLOW_COPY_AND_ASSIGN(OlaServer); }; } // namespace ola #endif // OLAD_OLASERVER_H_ ola-0.10.5.nojsmin/olad/OlaDaemon.cpp0000644000175000017500000001306113023355232016741 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OlaDaemon.cpp * This is the main ola daemon * Copyright (C) 2005 Simon Newton */ #if HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #include #include #include #include #include #ifdef _WIN32 #include #endif // _WIN32 #include #include "ola/ExportMap.h" #include "ola/Logging.h" #include "ola/base/Credentials.h" #include "ola/base/Flags.h" #include "ola/file/Util.h" #include "ola/network/SocketAddress.h" #include "ola/stl/STLUtils.h" #include "olad/DynamicPluginLoader.h" #include "olad/OlaDaemon.h" #include "olad/OlaServerServiceImpl.h" #include "olad/PluginLoader.h" #include "olad/Preferences.h" DEFINE_s_string(config_dir, c, "", "The path to the config directory, Defaults to ~/.ola/ " \ "on *nix and %LOCALAPPDATA%\\.ola\\ on Windows."); namespace ola { using ola::io::SelectServer; using ola::network::IPV4Address; using ola::network::IPV4SocketAddress; using ola::network::TCPAcceptingSocket; using ola::thread::MutexLocker; using std::auto_ptr; using std::string; const char OlaDaemon::OLA_CONFIG_DIR[] = ".ola"; const char OlaDaemon::CONFIG_DIR_KEY[] = "config-dir"; const char OlaDaemon::UID_KEY[] = "uid"; const char OlaDaemon::GID_KEY[] = "gid"; const char OlaDaemon::USER_NAME_KEY[] = "user"; const char OlaDaemon::GROUP_NAME_KEY[] = "group"; OlaDaemon::OlaDaemon(const OlaServer::Options &options, ExportMap *export_map) : m_options(options), m_export_map(export_map), m_ss(m_export_map) { if (m_export_map) { uid_t uid; if (GetUID(&uid)) { m_export_map->GetIntegerVar(UID_KEY)->Set(uid); PasswdEntry passwd; if (GetPasswdUID(uid, &passwd)) { m_export_map->GetStringVar(USER_NAME_KEY)->Set(passwd.pw_name); } } gid_t gid; if (GetGID(&gid)) { m_export_map->GetIntegerVar(GID_KEY)->Set(gid); GroupEntry group; if (GetGroupGID(gid, &group)) { m_export_map->GetStringVar(GROUP_NAME_KEY)->Set(group.gr_name); } } } } OlaDaemon::~OlaDaemon() { Shutdown(); } bool OlaDaemon::Init() { if (m_server.get()) { return false; } string config_dir = FLAGS_config_dir; if (config_dir.empty()) { const string default_dir = DefaultConfigDir(); if (default_dir.empty()) { OLA_FATAL << "Unable to determine home directory"; return false; } else { config_dir = default_dir; } } // Ignore the return code so this isn't fatal // in macports the home directory isn't writeable InitConfigDir(config_dir); OLA_INFO << "Using configs in " << config_dir; if (m_export_map) { m_export_map->GetStringVar(CONFIG_DIR_KEY)->Set(config_dir); } auto_ptr preferences_factory( new FileBackedPreferencesFactory(config_dir)); // Order is important here as we won't load the same plugin twice. m_plugin_loaders.push_back(new DynamicPluginLoader()); auto_ptr server( new OlaServer(m_plugin_loaders, preferences_factory.get(), &m_ss, m_options, NULL, m_export_map)); bool ok = server->Init(); if (ok) { // Set the members m_preferences_factory.reset(preferences_factory.release()); m_server.reset(server.release()); } else { STLDeleteElements(&m_plugin_loaders); } return ok; } void OlaDaemon::Shutdown() { m_server.reset(); m_preferences_factory.reset(); STLDeleteElements(&m_plugin_loaders); } void OlaDaemon::Run() { m_ss.Run(); } ola::network::GenericSocketAddress OlaDaemon::RPCAddress() const { if (m_server.get()) { return m_server->LocalRPCAddress(); } else { return ola::network::GenericSocketAddress(); } } /* * Return the home directory for the current user */ string OlaDaemon::DefaultConfigDir() { if (SupportsUIDs()) { PasswdEntry passwd_entry; uid_t uid; if (!GetUID(&uid)) return ""; if (!GetPasswdUID(uid, &passwd_entry)) return ""; return passwd_entry.pw_dir + ola::file::PATH_SEPARATOR + OLA_CONFIG_DIR; } else { #ifdef _WIN32 char path[MAX_PATH]; if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, path))) { return string(path) + ola::file::PATH_SEPARATOR + OLA_CONFIG_DIR; } else { return ""; } #else return ""; #endif // _WIN32 } } /* * Create the config dir if it doesn't exist. This doesn't create parent * directories. */ bool OlaDaemon::InitConfigDir(const string &path) { if (chdir(path.c_str())) { // try and create it #ifdef _WIN32 if (mkdir(path.c_str())) { #else if (mkdir(path.c_str(), 0755)) { #endif // _WIN32 OLA_FATAL << "Couldn't mkdir " << path; return false; } if (chdir(path.c_str())) { OLA_FATAL << path << " doesn't exist"; return false; } } return true; } } // namespace ola ola-0.10.5.nojsmin/olad/OladHTTPServer.h0000644000175000017500000001764613023355232017332 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OladHTTPServer.h * Interface for the OLA HTTP class * Copyright (C) 2005 Simon Newton */ #ifndef OLAD_OLADHTTPSERVER_H_ #define OLAD_OLADHTTPSERVER_H_ #include #include #include #include "ola/ExportMap.h" #include "ola/client/OlaClient.h" #include "ola/base/Macro.h" #include "ola/http/HTTPServer.h" #include "ola/http/OlaHTTPServer.h" #include "ola/network/Interface.h" #include "ola/rdm/PidStore.h" #include "olad/RDMHTTPModule.h" namespace ola { /* * This is the main OLA HTTP Server */ class OladHTTPServer: public ola::http::OlaHTTPServer { public: struct OladHTTPServerOptions: public ola::http::HTTPServer::HTTPServerOptions { public: bool enable_quit; OladHTTPServerOptions() : ola::http::HTTPServer::HTTPServerOptions(), enable_quit(true) { } }; OladHTTPServer(ExportMap *export_map, const OladHTTPServerOptions &options, ola::io::ConnectedDescriptor *client_socket, class OlaServer *ola_server, const ola::network::Interface &iface); virtual ~OladHTTPServer(); bool Init(); void SetPidStore(const ola::rdm::RootPidStore *pid_store); int JsonServerStats(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response); int JsonUniversePluginList(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response); int JsonPluginInfo(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response); int SetPluginState(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response); int JsonUniverseInfo(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response); int JsonAvailablePorts(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response); int CreateNewUniverse(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response); int ModifyUniverse(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response); int GetDmx(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response); int HandleSetDmx(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response); int DisplayQuit(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response); int ReloadPlugins(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response); int ReloadPidStore(const ola::http::HTTPRequest *request, ola::http::HTTPResponse *response); void HandlePluginList(ola::http::HTTPResponse *response, const client::Result &result, const std::vector &plugins); void HandleUniverseList(ola::http::HTTPResponse *response, ola::web::JsonObject *json, const client::Result &result, const std::vector &universes); void HandlePartialPluginInfo(ola::http::HTTPResponse *response, int plugin_id, const client::Result &result, const std::string &description); void HandlePluginInfo(ola::http::HTTPResponse *response, std::string description, const client::Result &result, const ola::client::PluginState &state); void HandleUniverseInfo(ola::http::HTTPResponse *response, const client::Result &result, const client::OlaUniverse &universe); void HandlePortsForUniverse(ola::http::HTTPResponse *response, ola::web::JsonObject *json, unsigned int universe_id, const client::Result &result, const std::vector &devices); void HandleCandidatePorts(ola::http::HTTPResponse *response, const client::Result &result, const std::vector &devices); void CreateUniverseComplete(ola::http::HTTPResponse *response, unsigned int universe_id, bool included_name, class ActionQueue *action_queue); void SendCreateUniverseResponse(ola::http::HTTPResponse *response, unsigned int universe_id, bool included_name, class ActionQueue *action_queue); void ModifyUniverseComplete(ola::http::HTTPResponse *response, class ActionQueue *action_queue); void SendModifyUniverseResponse(ola::http::HTTPResponse *response, class ActionQueue *action_queue); /** * Serve a help redirect * @param response the response to use */ inline static int ServeHelpRedirect(ola::http::HTTPResponse *response) { return ola::http::HTTPServer::ServeRedirect(response, HELP_REDIRECTION); } static int ServeUsage(ola::http::HTTPResponse *response, const std::string &details); static const char HELP_PARAMETER[]; private: class ola::io::ConnectedDescriptor *m_client_socket; ola::client::OlaClient m_client; class OlaServer *m_ola_server; bool m_enable_quit; ola::network::Interface m_interface; RDMHTTPModule m_rdm_module; time_t m_start_time_t; void HandleGetDmx(ola::http::HTTPResponse *response, const client::Result &result, const client::DMXMetadata &metadata, const DmxBuffer &buffer); void HandleBoolResponse(ola::http::HTTPResponse *response, const client::Result &result); void PortToJson(ola::web::JsonObject *object, const client::OlaDevice &device, const client::OlaPort &port, bool is_output); void AddPatchActions(ActionQueue *action_queue, const std::string port_id_string, unsigned int universe, client::PatchAction port_action); void AddPriorityActions(ActionQueue *action_queue, const ola::http::HTTPRequest *request); typedef struct { unsigned int device_alias; unsigned int port; client::PortDirection direction; std::string string_id; } port_identifier; void DecodePortIds(const std::string &port_ids, std::vector *ports); void RegisterHandler( const std::string &path, int (OladHTTPServer::*method)(const ola::http::HTTPRequest*, ola::http::HTTPResponse*)); static const char HELP_REDIRECTION[]; static const char K_BACKEND_DISCONNECTED_ERROR[]; static const unsigned int K_UNIVERSE_NAME_LIMIT = 100; static const char K_PRIORITY_VALUE_SUFFIX[]; static const char K_PRIORITY_MODE_SUFFIX[]; DISALLOW_COPY_AND_ASSIGN(OladHTTPServer); }; } // namespace ola #endif // OLAD_OLADHTTPSERVER_H_ ola-0.10.5.nojsmin/olad/BonjourDiscoveryAgent.h0000644000175000017500000000470513023355232021041 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * BonjourDiscoveryAgent.h * The Bonjour implementation of DiscoveryAgentInterface. * Copyright (C) 2013 Simon Newton */ #ifndef OLAD_BONJOURDISCOVERYAGENT_H_ #define OLAD_BONJOURDISCOVERYAGENT_H_ #include #include #include #include #include #include #include #include "olad/DiscoveryAgent.h" namespace ola { namespace thread { class CallbackThread; } /** * @brief An implementation of DiscoveryAgentInterface that uses the Apple * dns_sd.h library. */ class BonjourDiscoveryAgent : public DiscoveryAgentInterface { public: BonjourDiscoveryAgent(); ~BonjourDiscoveryAgent(); bool Init(); void RegisterService(const std::string &service_name, const std::string &type, uint16_t port, const RegisterOptions &options); private: struct RegisterArgs : public RegisterOptions { std::string service_name; std::string type; uint16_t port; RegisterArgs(const std::string &service_name, const std::string &type, uint16_t port, const RegisterOptions &options); }; struct ServiceRef { // DNSServiceRef is just a pointer. DNSServiceRef service_ref; class DNSSDDescriptor *descriptor; }; typedef std::vector ServiceRefs; ola::io::SelectServer m_ss; std::auto_ptr m_thread; ServiceRefs m_refs; void InternalRegisterService(RegisterArgs *args); std::string BuildTxtRecord(const RegisterOptions::TxtData &txt_data); void RunThread(); DISALLOW_COPY_AND_ASSIGN(BonjourDiscoveryAgent); }; } // namespace ola #endif // OLAD_BONJOURDISCOVERYAGENT_H_ ola-0.10.5.nojsmin/olad/HttpServerActions.h0000644000175000017500000001242713023355232020203 0ustar wouterwouter/* * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * HttpServerActions.h * The list of actions the Ola Server performs. * Copyright (C) 2005 Simon Newton */ #ifndef OLAD_HTTPSERVERACTIONS_H_ #define OLAD_HTTPSERVERACTIONS_H_ #include #include #include "ola/ActionQueue.h" #include "ola/client/OlaClient.h" #include "ola/base/Macro.h" namespace ola { /* * The base action */ class BaseHttpAction: public Action { public: explicit BaseHttpAction(client::OlaClient *client): Action(), m_client(client), m_failed(false), m_on_done(NULL) { } virtual ~BaseHttpAction() {} bool Failed() const { return m_failed; } void Perform(SingleUseCallback0 *on_done); void CallbackComplete(const client::Result &result); protected: client::OlaClient *m_client; void RequestComplete(bool failure); virtual void DoAction() = 0; private: bool m_failed; SingleUseCallback0 *m_on_done; DISALLOW_COPY_AND_ASSIGN(BaseHttpAction); }; /* * An action that sets the name of a universe */ class SetNameAction: public BaseHttpAction { public: SetNameAction(client::OlaClient *client, unsigned int universe, const std::string &name, bool is_fatal): BaseHttpAction(client), m_universe(universe), m_name(name), m_is_fatal(is_fatal) { } bool IsFatal() const { return m_is_fatal; } protected: void DoAction(); private: unsigned int m_universe; std::string m_name; bool m_is_fatal; DISALLOW_COPY_AND_ASSIGN(SetNameAction); }; /* * An action that sets the merge mode of a universe */ class SetMergeModeAction: public BaseHttpAction { public: SetMergeModeAction(client::OlaClient *client, unsigned int universe, client::OlaUniverse::merge_mode mode): BaseHttpAction(client), m_universe(universe), m_merge_mode(mode) { } bool IsFatal() const { return false; } protected: void DoAction(); private: unsigned int m_universe; client::OlaUniverse::merge_mode m_merge_mode; DISALLOW_COPY_AND_ASSIGN(SetMergeModeAction); }; /* * An action that adds or removes a port from a universe. */ class PatchPortAction: public BaseHttpAction { public: PatchPortAction(client::OlaClient *client, unsigned int device_alias, unsigned int port, client::PortDirection direction, unsigned int universe, client::PatchAction action): BaseHttpAction(client), m_device_alias(device_alias), m_port(port), m_direction(direction), m_universe(universe), m_action(action) { } bool IsFatal() const { return false; } protected: void DoAction(); private: unsigned int m_device_alias; unsigned int m_port; client::PortDirection m_direction; unsigned int m_universe; client::PatchAction m_action; DISALLOW_COPY_AND_ASSIGN(PatchPortAction); }; /* * An action that sets a port priority to inherit mode. */ class PortPriorityInheritAction: public BaseHttpAction { public: PortPriorityInheritAction(client::OlaClient *client, unsigned int device_alias, unsigned int port, client::PortDirection direction): BaseHttpAction(client), m_device_alias(device_alias), m_port(port), m_direction(direction) { } bool IsFatal() const { return false; } protected: void DoAction(); private: unsigned int m_device_alias; unsigned int m_port; client::PortDirection m_direction; DISALLOW_COPY_AND_ASSIGN(PortPriorityInheritAction); }; /* * An action that sets a port priority to override mode. */ class PortPriorityStaticAction: public BaseHttpAction { public: PortPriorityStaticAction(client::OlaClient *client, unsigned int device_alias, unsigned int port, client::PortDirection direction, uint8_t overide_value): BaseHttpAction(client), m_device_alias(device_alias), m_port(port), m_direction(direction), m_override_value(overide_value) { } bool IsFatal() const { return false; } protected: void DoAction(); private: unsigned int m_device_alias; unsigned int m_port; client::PortDirection m_direction; uint8_t m_override_value; DISALLOW_COPY_AND_ASSIGN(PortPriorityStaticAction); }; } // namespace ola #endif // OLAD_HTTPSERVERACTIONS_H_ ola-0.10.5.nojsmin/tools/0000755000175000017500000000000013134123605014616 5ustar wouterwouterola-0.10.5.nojsmin/tools/Makefile.mk0000644000175000017500000000056213023355232016667 0ustar wouterwouterinclude tools/ja-rule/Makefile.mk include tools/logic/Makefile.mk include tools/ola_trigger/Makefile.mk include tools/rdm/Makefile.mk if !USING_WIN32 include tools/e133/Makefile.mk include tools/usbpro/Makefile.mk include tools/rdmpro/Makefile.mk endif dist_noinst_DATA += \ tools/ola_mon/index.html \ tools/ola_mon/ola_mon.conf \ tools/ola_mon/ola_mon.py ola-0.10.5.nojsmin/tools/rdm/0000755000175000017500000000000013155164170015405 5ustar wouterwouterola-0.10.5.nojsmin/tools/rdm/Makefile.mk0000644000175000017500000000642513023355232017455 0ustar wouterwoutermodule_files = \ tools/rdm/DMXSender.py \ tools/rdm/ExpectedResults.py \ tools/rdm/ModelCollector.py \ tools/rdm/ResponderTest.py \ tools/rdm/TestCategory.py \ tools/rdm/TestDefinitions.py \ tools/rdm/TestHelpers.py \ tools/rdm/TestLogger.py \ tools/rdm/TestMixins.py \ tools/rdm/TestRunner.py \ tools/rdm/TimingStats.py \ tools/rdm/TestState.py \ tools/rdm/__init__.py # These files are installed to the directory from DataLocation.py testserver_static_files = \ tools/rdm/static/MIT-LICENSE.txt \ tools/rdm/static/common.css \ tools/rdm/static/jquery-1.7.2.min.js \ tools/rdm/static/jquery-ui-1.8.21.custom.css \ tools/rdm/static/jquery-ui-1.8.21.custom.min.js \ tools/rdm/static/rdm_tests.js \ tools/rdm/static/rdmtests.html \ tools/rdm/static/ui.multiselect.css \ tools/rdm/static/ui.multiselect.js # These files are installed to the images directory under the directory from # DataLocation.py testserver_image_files = \ tools/rdm/static/images/discovery.png \ tools/rdm/static/images/external.png \ tools/rdm/static/images/favicon.ico \ tools/rdm/static/images/loader.gif \ tools/rdm/static/images/logo.png \ tools/rdm/static/images/ui-bg_flat_0_aaaaaa_40x100.png \ tools/rdm/static/images/ui-bg_flat_0_eeeeee_40x100.png \ tools/rdm/static/images/ui-bg_flat_55_c0402a_40x100.png \ tools/rdm/static/images/ui-bg_flat_55_eeeeee_40x100.png \ tools/rdm/static/images/ui-bg_glass_100_f8f8f8_1x400.png \ tools/rdm/static/images/ui-bg_glass_35_dddddd_1x400.png \ tools/rdm/static/images/ui-bg_glass_60_eeeeee_1x400.png \ tools/rdm/static/images/ui-bg_inset-hard_75_999999_1x100.png \ tools/rdm/static/images/ui-bg_inset-soft_50_c9c9c9_1x100.png \ tools/rdm/static/images/ui-icons_3383bb_256x240.png \ tools/rdm/static/images/ui-icons_454545_256x240.png \ tools/rdm/static/images/ui-icons_70b2e1_256x240.png \ tools/rdm/static/images/ui-icons_999999_256x240.png \ tools/rdm/static/images/ui-icons_fbc856_256x240.png launcher_files = \ tools/rdm/launch_tests.py \ tools/rdm/setup_patch.py \ tools/rdm/skel_config/ola-usbserial.conf EXTRA_DIST += $(launcher_files) CLEANFILES += tools/rdm/*.pyc if INSTALL_RDM_TESTS built_sources += tools/rdm/DataLocation.py # Create DataLocation.py with the directory of the static files. tools/rdm/DataLocation.py: tools/rdm/Makefile.mk mkdir -p $(top_builddir)/tools/rdm echo "location = '${datadir}/ola/rdm-server'" > $(top_builddir)/tools/rdm/DataLocation.py # RDM Test modules rdmtestsdir = $(pkgpythondir)/testing/rdm rdmtests_PYTHON = $(module_files) nodist_rdmtests_PYTHON = tools/rdm/DataLocation.py # Hack to put the top level __init__.py file in place rdminitdir = $(pkgpythondir)/testing rdminit_PYTHON = tools/rdm/__init__.py # RDM Test Scripts rdmtestsexecdir = $(bindir) dist_rdmtestsexec_SCRIPTS = \ tools/rdm/rdm_model_collector.py \ tools/rdm/rdm_responder_test.py \ tools/rdm/rdm_test_server.py # Data files for the RDM Test Server tools_rdm_testserver_staticdir = $(datadir)/ola/rdm-server dist_tools_rdm_testserver_static_DATA = $(testserver_static_files) tools_rdm_testserver_imagesdir = $(datadir)/ola/rdm-server/images dist_tools_rdm_testserver_images_DATA = $(testserver_image_files) endif ola-0.10.5.nojsmin/tools/rdm/skel_config/0000755000175000017500000000000013155164170017670 5ustar wouterwouterola-0.10.5.nojsmin/tools/rdm/skel_config/ola-usbserial.conf0000644000175000017500000000023613023355232023275 0ustar wouterwouterdevice_dir = /dev device_prefix = ttyUSB device_prefix = cu.usbserial- dmx_tri_fps_limit = 40 pro_fps_limit = 190 tri_use_raw_rdm = true ultra_fps_limit = 40 ola-0.10.5.nojsmin/tools/rdm/TestMixins.py0000644000175000017500000010224013023355232020060 0ustar wouterwouter# 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # TestMixins.py # Copyright (C) 2010 Simon Newton import struct from ExpectedResults import (AckGetResult, AckDiscoveryResult, BroadcastResult, DUBResult, NackSetResult, TimeoutResult, UnsupportedResult) from ResponderTest import ResponderTestFixture from TestCategory import TestCategory from TestHelpers import ContainsUnprintable from ola import PidStore from ola.DMXConstants import DMX_UNIVERSE_SIZE from ola.DUBDecoder import DecodeResponse from ola.OlaClient import OlaClient, RDMNack from ola.PidStore import ROOT_DEVICE from ola.RDMConstants import RDM_MAX_STRING_LENGTH from ola.UID import UID '''Mixins used by the test definitions. This module contains classes which can be inherited from to simplify writing test definitions. ''' __author__ = 'nomis52@gmail.com (Simon Newton)' MAX_DMX_ADDRESS = DMX_UNIVERSE_SIZE def UnsupportedSetNacks(pid): """Responders use either NR_UNSUPPORTED_COMMAND_CLASS or NR_UNKNOWN_PID.""" return [ NackSetResult(pid.value, RDMNack.NR_UNSUPPORTED_COMMAND_CLASS), NackSetResult(pid.value, RDMNack.NR_UNKNOWN_PID), ] # Generic GET Mixins # These don't care about the format of the message. # ----------------------------------------------------------------------------- class UnsupportedGetMixin(object): """Check that Get fails with NR_UNSUPPORTED_COMMAND_CLASS.""" def Test(self): self.AddIfGetSupported( self.NackGetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS)) self.SendRawGet(PidStore.ROOT_DEVICE, self.pid) class GetMixin(object): """GET Mixin for an optional PID. Verify EXPECTED_FIELDS is in the response. This mixin also sets one or more properties if PROVIDES is defined. The target class needs to defined EXPECTED_FIELDS and optionally PROVIDES. If ALLOWED_NACKS is non-empty, this adds a custom NackGetResult to the list of allowed results for each entry. """ ALLOWED_NACKS = [] def Test(self): results = [self.AckGetResult(field_names=self.EXPECTED_FIELDS)] for nack in self.ALLOWED_NACKS: results.append(self.NackGetResult(nack)) self.AddIfGetSupported(results) self.SendGet(PidStore.ROOT_DEVICE, self.pid) def VerifyResult(self, response, fields): if response.WasAcked() and self.PROVIDES: for i in xrange(0, min(len(self.PROVIDES), len(self.EXPECTED_FIELDS))): self.SetProperty(self.PROVIDES[i], fields[self.EXPECTED_FIELDS[i]]) class GetStringMixin(GetMixin): """GET Mixin for an optional string PID. Verify EXPECTED_FIELDS are in the response. This mixin also sets a property if PROVIDES is defined. The target class needs to defined EXPECTED_FIELDS and optionally PROVIDES. """ MIN_LENGTH = 0 MAX_LENGTH = RDM_MAX_STRING_LENGTH def VerifyResult(self, response, fields): if not response.WasAcked(): return string_field = fields[self.EXPECTED_FIELDS[0]] if self.PROVIDES: self.SetProperty(self.PROVIDES[0], string_field) if ContainsUnprintable(string_field): self.AddAdvisory( '%s field in %s contains unprintable characters, was %s' % (self.EXPECTED_FIELDS[0].capitalize(), self.PID, string_field.encode('string-escape'))) if self.MIN_LENGTH and len(string_field) < self.MIN_LENGTH: self.SetFailed( '%s field in %s was shorter than expected, was %d, expected %d' % (self.EXPECTED_FIELDS[0].capitalize(), self.PID, len(string_field), self.MIN_LENGTH)) if self.MAX_LENGTH and len(string_field) > self.MAX_LENGTH: self.SetFailed( '%s field in %s was longer than expected, was %d, expected %d' % (self.EXPECTED_FIELDS[0].capitalize(), self.PID, len(string_field), self.MAX_LENGTH)) class GetRequiredMixin(object): """GET Mixin for a required PID. Verify EXPECTED_FIELDS is in the response. This mixin also sets a property if PROVIDES is defined. The target class needs to defined EXPECTED_FIELDS and optionally PROVIDES. """ def Test(self): self.AddExpectedResults( self.AckGetResult(field_names=self.EXPECTED_FIELDS)) self.SendGet(PidStore.ROOT_DEVICE, self.pid) def VerifyResult(self, response, fields): if response.WasAcked() and self.PROVIDES: for i in xrange(0, min(len(self.PROVIDES), len(self.EXPECTED_FIELDS))): self.SetProperty(self.PROVIDES[i], fields[self.EXPECTED_FIELDS[i]]) class GetRequiredStringMixin(GetRequiredMixin): """GET Mixin for a required string PID. Verify EXPECTED_FIELDS is in the response. This mixin also sets a property if PROVIDES is defined. The target class needs to defined EXPECTED_FIELDS and optionally PROVIDES. """ MIN_LENGTH = 0 MAX_LENGTH = RDM_MAX_STRING_LENGTH def VerifyResult(self, response, fields): if not response.WasAcked(): return string_field = fields[self.EXPECTED_FIELDS[0]] if self.PROVIDES: for i in xrange(0, min(len(self.PROVIDES), len(self.EXPECTED_FIELDS))): self.SetProperty(self.PROVIDES[i], fields[self.EXPECTED_FIELDS[i]]) if ContainsUnprintable(string_field): self.AddAdvisory( '%s field in %s contains unprintable characters, was %s' % (self.EXPECTED_FIELDS[0].capitalize(), self.PID, string_field.encode('string-escape'))) if self.MIN_LENGTH and len(string_field) < self.MIN_LENGTH: self.SetFailed( '%s field in %s was shorter than expected, was %d, expected %d' % (self.EXPECTED_FIELDS[0].capitalize(), self.PID, len(string_field), self.MIN_LENGTH)) if self.MAX_LENGTH and len(string_field) > self.MAX_LENGTH: self.SetFailed( '%s field in %s was longer than expected, was %d, expected %d' % (self.EXPECTED_FIELDS[0].capitalize(), self.PID, len(string_field), self.MAX_LENGTH)) class GetWithDataMixin(object): """GET a PID with junk param data. If ALLOWED_NACKS is non-empty, this adds a custom NackGetResult to the list of allowed results for each entry. """ DATA = 'foo' ALLOWED_NACKS = [] def Test(self): results = [ self.NackGetResult(RDMNack.NR_FORMAT_ERROR), self.AckGetResult( warning='Get %s with data returned an ack' % self.pid.name) ] for nack in self.ALLOWED_NACKS: results.append(self.NackGetResult(nack)) self.AddIfGetSupported(results) self.SendRawGet(PidStore.ROOT_DEVICE, self.pid, self.DATA) class GetMandatoryPIDWithDataMixin(object): """GET a mandatory PID with junk param data.""" DATA = 'foo' def Test(self): # PID must return something as this PID is required (can't return # unsupported) self.AddExpectedResults([ self.NackGetResult(RDMNack.NR_FORMAT_ERROR), self.AckGetResult( warning='Get %s with data returned an ack' % self.pid.name) ]) self.SendRawGet(PidStore.ROOT_DEVICE, self.pid, self.DATA) class GetWithNoDataMixin(object): """GET with no data, expect NR_FORMAT_ERROR.""" def Test(self): self.AddIfGetSupported(self.NackGetResult(RDMNack.NR_FORMAT_ERROR)) self.SendRawGet(PidStore.ROOT_DEVICE, self.pid) class AllSubDevicesGetMixin(object): """Send a GET to ALL_SUB_DEVICES.""" DATA = [] def Test(self): # E1.20, section 9.2.2 results = [self.NackGetResult(RDMNack.NR_SUB_DEVICE_OUT_OF_RANGE)] # Some devices check the PID before the sub device. if not self.PidSupported(): results.append(self.NackGetResult(RDMNack.NR_UNKNOWN_PID)) self.AddExpectedResults(results) self.SendGet(PidStore.ALL_SUB_DEVICES, self.pid, self.DATA) # Generic SET Mixins # These don't care about the format of the message. # ----------------------------------------------------------------------------- class UnsupportedSetMixin(object): """Check that SET fails with NR_UNSUPPORTED_COMMAND_CLASS.""" def Test(self): self.AddExpectedResults(UnsupportedSetNacks(self.pid)) self.SendRawSet(PidStore.ROOT_DEVICE, self.pid) class SetWithDataMixin(ResponderTestFixture): """SET a PID with random param data.""" DATA = 'foo' def Test(self): self.AddIfSetSupported([ self.NackSetResult(RDMNack.NR_FORMAT_ERROR), self.AckSetResult( warning='Set %s with data returned an ack' % self.pid.name) ]) self.SendRawSet(PidStore.ROOT_DEVICE, self.pid, self.DATA) class SetWithNoDataMixin(object): """Attempt a set with no data.""" def Test(self): self.AddIfSetSupported(self.NackSetResult(RDMNack.NR_FORMAT_ERROR)) self.SendRawSet(PidStore.ROOT_DEVICE, self.pid, '') # TODO(simon): add a method to check this didn't change the value # Generic Label Mixins # These all work in conjunction with the IsSupportedMixin # ----------------------------------------------------------------------------- class SetLabelMixin(object): """Set a PID and make sure the label is updated. If PROVIDES is non empty, the first property will be used to indicate if the set action is supported. If an ack is returned it'll be set to true, otherwise false. """ TEST_LABEL = 'test label' PROVIDES = [] SET, VERIFY, RESET = xrange(3) def ExpectedResults(self): return [ self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS), self.AckSetResult(action=self.VerifySet) ] def Test(self): self._test_state = self.SET self.AddIfSetSupported(self.ExpectedResults()) self.SendSet(PidStore.ROOT_DEVICE, self.pid, [self.TEST_LABEL]) def VerifySet(self): self._test_state = self.VERIFY self.AddExpectedResults(self.AckGetResult(field_names=['label'])) self.SendGet(PidStore.ROOT_DEVICE, self.pid) def VerifyResult(self, response, fields): if self._test_state == self.SET: if self.PROVIDES: self.SetProperty(self.PROVIDES[0], response.WasAcked()) return elif self._test_state == self.RESET: return new_label = fields['label'] if self.TEST_LABEL == new_label: return if (len(new_label) < len(self.TEST_LABEL) and self.TEST_LABEL.startswith(new_label)): self.AddAdvisory('Label for %s was truncated to %d characters' % (self.pid, len(new_label))) else: self.SetFailed('Labels didn\'t match, expected "%s", got "%s"' % (self.TEST_LABEL.encode('string-escape'), new_label.encode('string-escape'))) def ResetState(self): if not self.OldValue(): return self._test_state = self.RESET self.AddExpectedResults(self.AckSetResult()) self.SendSet(PidStore.ROOT_DEVICE, self.pid, [self.OldValue()]) self._wrapper.Run() class NonUnicastSetLabelMixin(SetLabelMixin): """Send a SET device label to a broadcast or vendorcast uid.""" def Test(self): if not self.Property('set_device_label_supported'): self.SetNotRun('Previous set label was nacked') self.Stop() return self._test_state = self.SET self.AddExpectedResults(BroadcastResult(action=self.VerifySet)) self.SendDirectedSet(self.Uid(), PidStore.ROOT_DEVICE, self.pid, [self.TEST_LABEL]) class SetOversizedLabelMixin(object): """Send an over-sized SET label command.""" LONG_STRING = 'this is a string which is more than 32 characters' def Test(self): self.verify_result = False self.AddIfSetSupported([ self.NackSetResult(RDMNack.NR_FORMAT_ERROR), self.NackSetResult(RDMNack.NR_PACKET_SIZE_UNSUPPORTED), self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS), self.AckSetResult(action=self.VerifySet), ]) self.SendRawSet(PidStore.ROOT_DEVICE, self.pid, self.LONG_STRING) def VerifySet(self): """If we got an ACK back, we send a GET to check what the result was.""" self.verify_result = True self.AddExpectedResults(self.AckGetResult(field_names=['label'])) self.SendGet(PidStore.ROOT_DEVICE, self.pid) def VerifyResult(self, response, fields): if not self.verify_result: return if 'label' not in fields: self.SetFailed('Missing label field in response') else: if fields['label'] != self.LONG_STRING[0:RDM_MAX_STRING_LENGTH]: self.AddWarning( 'Setting an oversized %s set the first %d characters' % (self.PID, len(fields['label']))) # Generic Set Mixins # These all work in conjunction with the IsSupportedMixin # ----------------------------------------------------------------------------- class SetMixin(object): """The base class for set mixins.""" def OldValue(self): self.SetBroken('base method of SetMixin called') def NewValue(self): self.SetBroken('base method of SetMixin called') def Test(self): self.AddIfSetSupported([ self.AckSetResult(action=self.VerifySet), self.NackSetResult( RDMNack.NR_UNSUPPORTED_COMMAND_CLASS, advisory='SET for %s returned unsupported command class' % self.PID), ]) self.SendSet(PidStore.ROOT_DEVICE, self.pid, [self.NewValue()]) def VerifySet(self): self.AddExpectedResults( self.AckGetResult( field_names=self.EXPECTED_FIELDS, field_values={self.EXPECTED_FIELDS[0]: self.NewValue()})) self.SendGet(PidStore.ROOT_DEVICE, self.pid) def ResetState(self): old_value = self.OldValue() if old_value is None: return self.AddExpectedResults(self.AckSetResult()) self.SendSet(PidStore.ROOT_DEVICE, self.pid, [old_value]) self._wrapper.Run() class SetBoolMixin(SetMixin): """Attempt to SET a bool field.""" VALUE = True def NewValue(self): """Decide the new value to set based on the old one. This ensures we change it. """ value = self.OldValue() if value is not None: return not value return self.VALUE class SetUInt8Mixin(SetMixin): """Attempt to SET a uint8 field.""" VALUE = True def NewValue(self): """Decide the new value to set based on the old one. This ensures we change it. """ value = self.OldValue() if value is not None: return (value + 1) % 0xff return self.VALUE class SetUInt16Mixin(SetMixin): """Attempt to SET a uint16 field.""" VALUE = True def NewValue(self): """Decide the new value to set based on the old one. This ensures we change it. """ value = self.OldValue() if value is not None: return (value + 1) % 0xffff return self.VALUE class SetUInt32Mixin(SetMixin): """Attempt to SET a uint32 field.""" VALUE = 100 def NewValue(self): """Decide the new value to set based on the old one. This ensures we change it. """ value = self.OldValue() if value is not None: return (value + 1) % 0xffffffff return self.VALUE # Start address mixins # ----------------------------------------------------------------------------- class SetStartAddressMixin(object): """Set the dmx start address.""" SET, VERIFY, RESET = xrange(3) def CalculateNewAddress(self, current_address, footprint): if footprint == MAX_DMX_ADDRESS: start_address = 1 else: start_address = current_address + 1 if start_address + footprint > MAX_DMX_ADDRESS + 1: start_address = 1 return start_address def VerifySet(self): self._test_state = self.VERIFY self.AddExpectedResults( self.AckGetResult(field_values={'dmx_address': self.start_address}, action=self.VerifyDeviceInfo)) self.SendGet(PidStore.ROOT_DEVICE, self.pid) def VerifyDeviceInfo(self): device_info_pid = self.LookupPid('DEVICE_INFO') self.AddExpectedResults( AckGetResult( device_info_pid.value, field_values={'dmx_start_address': self.start_address})) self.SendGet(PidStore.ROOT_DEVICE, device_info_pid) def ResetState(self): old_address = self.Property('dmx_address') if not old_address or old_address == 0xffff: return self._test_state = self.RESET self.AddExpectedResults(self.AckSetResult()) self.SendSet(PidStore.ROOT_DEVICE, self.pid, [self.Property('dmx_address')]) self._wrapper.Run() class SetNonUnicastStartAddressMixin(SetStartAddressMixin): """Send a set dmx start address to a non unicast uid.""" def Test(self): footprint = self.Property('dmx_footprint') current_address = self.Property('dmx_address') if footprint == 0 or current_address == 0xffff: self.SetNotRun("Device doesn't use a DMX address") self.Stop() return if not self.Property('set_dmx_address_supported'): self.SetNotRun('Previous set start address was nacked') self.Stop() return self._test_state = self.SET self.start_address = self.CalculateNewAddress(current_address, footprint) self.AddExpectedResults(BroadcastResult(action=self.VerifySet)) self.SendDirectedSet(self.Uid(), PidStore.ROOT_DEVICE, self.pid, [self.start_address]) # Identify Device Mixin # ----------------------------------------------------------------------------- class SetNonUnicastIdentifyMixin(object): """Sets the identify device state. To avoid sending a broadcast identify on (which may strike all lamps in a large rig), we instead turn identify on and then send a broadcast off. """ REQUIRES = ['identify_state'] def States(self): return [ self.TurnOn, self.VerifyOn, self.TurnOff, self.VerifyOff, ] def NextState(self): self._current_state += 1 try: return self.States()[self._current_state] except IndexError: return None def Test(self): self._current_state = -1 self.NextState()() def TurnOn(self): self.AddExpectedResults( self.AckSetResult(action=self.NextState())) self.SendSet(PidStore.ROOT_DEVICE, self.pid, [True]) def VerifyOn(self): self.AddExpectedResults( self.AckGetResult(field_values={'identify_state': True}, action=self.NextState())) self.SendGet(PidStore.ROOT_DEVICE, self.pid) def TurnOff(self): self.AddExpectedResults(BroadcastResult(action=self.NextState())) self.SendDirectedSet(self.Uid(), PidStore.ROOT_DEVICE, self.pid, [False]) def VerifyOff(self): self.AddExpectedResults( self.AckGetResult(field_values={'identify_state': False})) self.SendGet(PidStore.ROOT_DEVICE, self.pid) def ResetState(self): # reset back to the old value self.SendSet(PidStore.ROOT_DEVICE, self.pid, [self.Property('identify_state')]) self._wrapper.Run() # Sensor mixins # ----------------------------------------------------------------------------- class SetUndefinedSensorValues(object): """Attempt to set sensor values for all sensors that weren't defined.""" def Test(self): sensors = self.Property('sensor_definitions') self._missing_sensors = [] for i in xrange(0, 0xff): if i not in sensors: self._missing_sensors.append(i) if self._missing_sensors: # loop and get all values self._DoAction() else: self.SetNotRun('All sensors declared') self.Stop() return def _DoAction(self): if not self._missing_sensors: self.Stop() return self.AddIfSetSupported([ self.NackSetResult(RDMNack.NR_DATA_OUT_OF_RANGE, action=self._DoAction), # SET SENSOR_VALUE may not be supported self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS, action=self._DoAction), ]) self.SendSet(PidStore.ROOT_DEVICE, self.pid, [self._missing_sensors.pop(0)]) # Preset Status mixins # ----------------------------------------------------------------------------- class SetPresetStatusMixin(object): REQUIRES = ['preset_info'] def BuildPresetStatus(self, scene): preset_info = self.Property('preset_info') fade_time = 0 wait_time = 0 if preset_info: fade_time = preset_info['min_preset_fade_time'] wait_time = preset_info['min_preset_wait_time'] return struct.pack('!HHHHB', scene, int(fade_time), int(fade_time), int(wait_time), 0) # Discovery Mixins # ----------------------------------------------------------------------------- class DiscoveryMixin(ResponderTestFixture): """UnMute the device, send a DUB, confirm the UID, then mute again. This mixin requires: LowerBound() the lower UID to use in the DUB UpperBound() the upprt UID to use in the DUB And Optionally: DUBResponseCode(response_code): called when the discovery request completes. ExpectResponse(): returns true if we expect the device to answer the DUB request, false otherwise. Target: returns the UID to address the UID command to, defaults to ffff:ffffffff """ PID = 'DISC_UNIQUE_BRANCH' # Global Mute here ensures we run after all devices have been muted REQUIRES = ['mute_supported', 'unmute_supported', 'global_mute'] def DUBResponseCode(self, response_code): pass def ExpectResponse(self): return True def Target(self): return UID.AllDevices() def UnMuteDevice(self, next_method): unmute_pid = self.LookupPid('DISC_UN_MUTE') self.AddExpectedResults([ AckDiscoveryResult(unmute_pid.value, action=next_method), ]) self.SendDiscovery(PidStore.ROOT_DEVICE, unmute_pid) def Test(self): self._muting = True if not (self.Property('unmute_supported') and self.Property('mute_supported')): self.SetNotRun('Controller does not support mute / unmute commands') self.Stop() return self.UnMuteDevice(self.SendDUB) def SendDUB(self): self._muting = False results = [UnsupportedResult()] if self.ExpectResponse(): results.append(DUBResult()) else: results.append(TimeoutResult()) self.AddExpectedResults(results) self.SendDirectedDiscovery(self.Target(), PidStore.ROOT_DEVICE, self.pid, [self.LowerBound(), self.UpperBound()]) def VerifyResult(self, response, fields): if self._muting: return self.DUBResponseCode(response.response_code) if (response.response_code == OlaClient.RDM_PLUGIN_DISCOVERY_NOT_SUPPORTED): return if not self.ExpectResponse(): return if len(response.frames) != 1: self.SetFailed('Multiple DUB responses returned') return uid = DecodeResponse(bytearray(response.frames[0].data)) if uid is None or uid != self._uid: self.SetFailed('Missing UID in DUB response') self.LogDebug(' Located UID: %s' % uid) def ResetState(self): # mute the device again mute_pid = self.LookupPid('DISC_MUTE') self.SendDiscovery(PidStore.ROOT_DEVICE, mute_pid) self._wrapper.Run() # E1.37-1 Mixins # ----------------------------------------------------------------------------- class SetDmxFailModeMixin(object): PID = 'DMX_FAIL_MODE' REQUIRES = ['dmx_fail_settings', 'preset_info', 'set_dmx_fail_mode_supported'] CATEGORY = TestCategory.DMX_SETUP INFINITE_TIME = 6553.5 # 0xffff * 10^-1 (multiplier) def ResetState(self): if not self.PidSupported(): return settings = self.Property('dmx_fail_settings') if settings is None: self.SetBroken('Failed to restore DMX_FAIL_MODE settings') return for key in ('scene_number', 'hold_time', 'loss_of_signal_delay', 'level'): if key not in settings: self.SetBroken( 'Failed to restore DMX_FAIL_MODE settings, missing %s' % key) return self.SendSet( ROOT_DEVICE, self.pid, [settings['scene_number'], settings['loss_of_signal_delay'], settings['hold_time'], settings['level']]) self._wrapper.Run() class SetDmxStartupModeMixin(object): PID = 'DMX_STARTUP_MODE' REQUIRES = ['dmx_startup_settings', 'preset_info', 'set_dmx_startup_mode_supported'] CATEGORY = TestCategory.DMX_SETUP INFINITE_TIME = 6553.5 # 0xffff * 10^-1 (multiplier) def ResetState(self): if not self.PidSupported(): return settings = self.Property('dmx_startup_settings') if settings is None: self.SetBroken('Failed to restore DMX_STARTUP_MODE settings') return for key in ('scene_number', 'hold_time', 'startup_delay', 'level'): if key not in settings: self.SetBroken( 'Failed to restore DMX_STARTUP_MODE settings, missing %s' % key) return self.SendSet( ROOT_DEVICE, self.pid, [settings['scene_number'], settings['startup_delay'], settings['hold_time'], settings['level']]) self._wrapper.Run() class SetMaximumLevelMixin(object): PID = 'MAXIMUM_LEVEL' REQUIRES = ['maximum_level', 'set_maximum_level_supported'] CATEGORY = TestCategory.DIMMER_SETTINGS def ResetState(self): if (not self.PidSupported() or not self.Property('set_maximum_level_supported')): return level = self.Property('maximum_level') if level is not None: self.SendSet(ROOT_DEVICE, self.pid, [level]) self._wrapper.Run() class SetMinimumLevelMixin(object): PID = 'MINIMUM_LEVEL' REQUIRES = ['minimum_level_settings', 'set_minimum_level_supported', 'split_levels_supported'] CATEGORY = TestCategory.DIMMER_SETTINGS def MinLevelIncreasing(self): return self.settings['minimum_level_increasing'] def MinLevelDecreasing(self): return self.settings['minimum_level_decreasing'] def OnBelowMin(self): return self.settings['on_below_minimum'] def ExpectedResults(self): return self.AckSetResult(action=self.GetMinLevel) def ShouldSkip(self): return False def Test(self): self.settings = self.Property('minimum_level_settings') if self.settings is None: self.SetNotRun('Unable to determine current minimum level settings') return set_supported = self.Property('set_minimum_level_supported') if set_supported is None or not set_supported: self.SetNotRun('SET MINIMUM_LEVEL not supported') return if self.ShouldSkip(): return self.AddIfSetSupported(self.ExpectedResults()) self.SendSet( ROOT_DEVICE, self.pid, [self.MinLevelIncreasing(), self.MinLevelDecreasing(), self.OnBelowMin()]) def GetMinLevel(self): min_level_decreasing = self.MinLevelDecreasing() if not self.Property('split_levels_supported'): min_level_decreasing = self.MinLevelIncreasing() self.AddIfGetSupported(self.AckGetResult( field_values={ 'minimum_level_increasing': self.MinLevelIncreasing(), 'minimum_level_decreasing': min_level_decreasing, 'on_below_minimum': self.OnBelowMin() } )) self.SendGet(ROOT_DEVICE, self.pid) def ResetState(self): if not self.PidSupported(): return self.SendSet( ROOT_DEVICE, self.pid, [self.settings['minimum_level_increasing'], self.settings['minimum_level_decreasing'], self.settings['on_below_minimum']]) self._wrapper.Run() class GetZeroUInt8Mixin(object): """Get a UInt8 parameter with value 0, expect NR_DATA_OUT_OF_RANGE""" CATEGORY = TestCategory.ERROR_CONDITIONS DATA = struct.pack('!B', 0) def Test(self): self.AddIfGetSupported(self.NackGetResult(RDMNack.NR_DATA_OUT_OF_RANGE)) self.SendRawGet(ROOT_DEVICE, self.pid, self.DATA) class GetZeroUInt16Mixin(GetZeroUInt8Mixin): """Get a UInt16 parameter with value 0, expect NR_DATA_OUT_OF_RANGE""" DATA = struct.pack('!H', 0) class GetZeroUInt32Mixin(GetZeroUInt8Mixin): """Get a UInt32 parameter with value 0, expect NR_DATA_OUT_OF_RANGE""" DATA = struct.pack('!I', 0) class SetZeroUInt8Mixin(object): """Set a UInt8 parameter with value 0, expect NR_DATA_OUT_OF_RANGE""" CATEGORY = TestCategory.ERROR_CONDITIONS DATA = struct.pack('!B', 0) def Test(self): self.AddIfSetSupported(self.NackSetResult(RDMNack.NR_DATA_OUT_OF_RANGE)) self.SendRawSet(ROOT_DEVICE, self.pid, self.DATA) class SetZeroUInt16Mixin(SetZeroUInt8Mixin): """Set a UInt16 parameter with value 0, expect NR_DATA_OUT_OF_RANGE""" DATA = struct.pack('!H', 0) class SetZeroUInt32Mixin(SetZeroUInt8Mixin): """Set a UInt32 parameter with value 0, expect NR_DATA_OUT_OF_RANGE""" DATA = struct.pack('!I', 0) class GetOutOfRangeByteMixin(object): """The subclass provides the NumberOfSettings() method.""" CATEGORY = TestCategory.ERROR_CONDITIONS def NumberOfSettings(self): # By default we use the first property from REQUIRES return self.Property(self.REQUIRES[0]) def Test(self): settings_supported = self.NumberOfSettings() if settings_supported is None: self.SetNotRun('Unable to determine number of %s' % self.LABEL) return if settings_supported == 255: self.SetNotRun('All %s are supported' % self.LABEL) return self.AddIfGetSupported(self.NackGetResult(RDMNack.NR_DATA_OUT_OF_RANGE)) self.SendGet(ROOT_DEVICE, self.pid, [settings_supported + 1]) class SetOutOfRangeByteMixin(object): """The subclass provides the NumberOfSettings() method.""" CATEGORY = TestCategory.ERROR_CONDITIONS def NumberOfSettings(self): # By default we use the first property from REQUIRES return self.Property(self.REQUIRES[0]) def Test(self): settings_supported = self.NumberOfSettings() if settings_supported is None: self.SetNotRun('Unable to determine number of %s' % self.LABEL) return if settings_supported == 255: self.SetNotRun('All %s are supported' % self.LABEL) return self.AddIfSetSupported(self.NackSetResult(RDMNack.NR_DATA_OUT_OF_RANGE)) self.SendSet(ROOT_DEVICE, self.pid, [settings_supported + 1]) class GetSettingDescriptionsMixin(object): """Perform a GET for each setting in a list. The list is returned by ListOfSettings which subclasses must implement. See GetSettingDescriptionsMixinRange and GetSettingDescriptionsMixinList for some implementations. If there are no entries in the list, it will fetch FIRST_INDEX_OFFSET and expect a NACK. Subclasses must define EXPECTED_FIELDS, the first of which is the field used to validate the index against and DESCRIPTION_FIELD, which is the field to check for unprintable characters. If ALLOWED_NACKS is non-empty, this adds a custom NackGetResult to the list of allowed results for each entry. """ ALLOWED_NACKS = [] FIRST_INDEX_OFFSET = 1 def ListOfSettings(self): self.SetBroken('base method of GetSettingDescriptionsMixin called') def Test(self): self.items = self.ListOfSettings() if not self.items: # Try to GET first item, this should NACK self.AddIfGetSupported(self.NackGetResult(RDMNack.NR_DATA_OUT_OF_RANGE)) self.SendGet(ROOT_DEVICE, self.pid, [self.FIRST_INDEX_OFFSET]) return # Otherwise fetch the description for each known setting. self._GetNextDescription() def _GetNextDescription(self): if not self.items: self.Stop() return results = [self.AckGetResult(field_names=self.EXPECTED_FIELDS, action=self._GetNextDescription)] for nack in self.ALLOWED_NACKS: results.append(self.NackGetResult(nack, action=self._GetNextDescription)) self.AddIfGetSupported(results) self.current_item = self.items.pop() self.SendGet(ROOT_DEVICE, self.pid, [self.current_item]) def VerifyResult(self, response, fields): if not response.WasAcked(): return if fields[self.EXPECTED_FIELDS[0]] != self.current_item: self.AddWarning( '%s mismatch, sent %d, received %d' % (self.pid, self.current_item, fields[self.EXPECTED_FIELDS[0]])) if ContainsUnprintable(fields[self.DESCRIPTION_FIELD]): self.AddAdvisory( '%s field in %s for %s %d contains unprintable characters, was %s' % (self.DESCRIPTION_FIELD.capitalize(), self.PID, self.DESCRIPTION_FIELD, self.current_item, fields[self.DESCRIPTION_FIELD].encode('string-escape'))) class GetSettingDescriptionsRangeMixin(GetSettingDescriptionsMixin): """Perform a GET for each setting in a range. The range is a count, it will check FIRST_INDEX_OFFSET to FIRST_INDEX_OFFSET + NumberOfSettings(). """ def NumberOfSettings(self): # By default we use the first property from REQUIRES return self.Property(self.REQUIRES[0]) def ListOfSettings(self): # We generate a range from FIRST_INDEX_OFFSET to NumberOfSettings() if self.NumberOfSettings() is None: return [] else: return range(self.FIRST_INDEX_OFFSET, self.NumberOfSettings() + self.FIRST_INDEX_OFFSET) class GetSettingDescriptionsListMixin(GetSettingDescriptionsMixin): """Perform a GET for each setting in a list. The list is an array of settings, which don't need to be sequential """ def ListOfSettings(self): # By default we use the first property from REQUIRES return self.Property(self.REQUIRES[0]) ola-0.10.5.nojsmin/tools/rdm/TestHelpers.py0000644000175000017500000000204613023355232020216 0ustar wouterwouter# 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # TestHelpers.py # Copyright (C) 2013 Peter Newman __author__ = 'nomis52@gmail.com (Simon Newton)' def ContainsUnprintable(s): """Check if a string s contain unprintable characters.""" if type(s) == str: return s != s.encode('string-escape') elif type(s) == unicode: return s != s.encode('unicode-escape') else: return False ola-0.10.5.nojsmin/tools/rdm/ExpectedResults.py0000644000175000017500000003511313023355232021100 0ustar wouterwouter# 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # ExpectedResults.py # Copyright (C) 2011 Simon Newton # # Expected result classes are broken down as follows: # # BaseExpectedResult - the base class # BroadcastResult - expects the request to be broadcast # SuccessfulResult - expects a well formed response from the device # NackResult - parent NACK class # NackGetResult - expects GET_COMMAND_RESPONSE with a NACK # NackSetResult - expects SET_COMMAND_RESPONSE with a NACK # AckResult - parent ACK class # AckGetResult - expects GET_COMMAND_RESPONSE with an ACK # AckSetResult - expects SET_COMMAND_RESPONSE with an ACK # QueuedMessageResult - expects an ACK or NACK for any PID other than # QUEUED_MESSAGE from ola.OlaClient import OlaClient from ola.PidStore import RDM_DISCOVERY, RDM_GET, RDM_SET, GetStore COMMAND_CLASS_DICT = { RDM_GET: 'Get', RDM_SET: 'Set', RDM_DISCOVERY: 'Discovery', } def _CommandClassToString(command_class): return COMMAND_CLASS_DICT[command_class] class BaseExpectedResult(object): """The base class for expected results.""" def __init__(self, action=None, warning=None, advisory=None): """Create the base expected result object. Args: action: The action to run if this result matches warning: A warning message to log is this result matches advisory: An advisory message to log is this result matches """ self._action = action self._warning_messae = warning self._advisory_message = advisory @property def action(self): return self._action @property def warning(self): return self._warning_messae @property def advisory(self): return self._advisory_message def Matches(self, response, unpacked_data): """Check if the response we receieved matches this object. Args: response: An RDMResponse object unpacked_data: A dict of field name : value mappings that were present in the response. """ raise TypeError('Base method called') class BroadcastResult(BaseExpectedResult): """This checks that the request was broadcast.""" def __str__(self): return 'RDM_WAS_BROADCAST' def Matches(self, response, unpacked_data): return OlaClient.RDM_WAS_BROADCAST == response.response_code class TimeoutResult(BaseExpectedResult): """This checks that the request timed out.""" def __str__(self): return 'RDM_TIMEOUT' def Matches(self, response, unpacked_data): return OlaClient.RDM_TIMEOUT == response.response_code class InvalidResponse(BaseExpectedResult): """This checks that we got an invalid response back.""" def __str__(self): return 'RDM_INVALID_RESPONSE' def Matches(self, response, unpacked_data): return OlaClient.RDM_INVALID_RESPONSE == response.response_code class UnsupportedResult(BaseExpectedResult): """This checks that the request was unsupported.""" def __str__(self): return 'RDM_PLUGIN_DISCOVERY_NOT_SUPPORTED' def Matches(self, response, unpacked_data): return (OlaClient.RDM_PLUGIN_DISCOVERY_NOT_SUPPORTED == response.response_code) class DUBResult(BaseExpectedResult): """Checks that the result was a DUB response.""" def __str__(self): return 'RDM_DUB_RESPONSE' def Matches(self, response, unpacked_data): return OlaClient.RDM_DUB_RESPONSE == response.response_code class SuccessfulResult(BaseExpectedResult): """This checks that we received a valid response from the device. This doesn't check that the response was a certain type, but simply that the message was formed correctly. Other classes inherit from this an perform more specific checking. """ def __str__(self): return 'RDM_COMPLETED_OK' def Matches(self, response, unpacked_data): return response.response_code == OlaClient.RDM_COMPLETED_OK class QueuedMessageResult(SuccessfulResult): """This checks for a valid response to a QUEUED_MESSAGE request.""" def __str__(self): return 'It\'s complicated' def Matches(self, response, unpacked_data): ok = super(QueuedMessageResult, self).Matches(response, unpacked_data) if not ok: return False pid_store = GetStore() queued_message_pid = pid_store.GetName('QUEUED_MESSAGE') return ((response.response_type == OlaClient.RDM_NACK_REASON or response.response_type == OlaClient.RDM_ACK) and response.pid != queued_message_pid.value) class NackResult(SuccessfulResult): """This checks that the device nacked the request.""" def __init__(self, command_class, pid_id, nack_reason, action=None, warning=None, advisory=None): """Create an NackResult object. Args: command_class: RDM_GET or RDM_SET pid_id: The pid id we expect to have been nack'ed nack_reason: The RDMNack object we expect. action: The action to run if this result matches warning: A warning message to log is this result matches advisory: An advisory message to log is this result matches """ super(NackResult, self).__init__(action, warning, advisory) self._command_class = command_class self._pid_id = pid_id self._nack_reason = nack_reason def __str__(self): return ('CC: %s, PID 0x%04hx, NACK %s' % (_CommandClassToString(self._command_class), self._pid_id, self._nack_reason)) def Matches(self, response, unpacked_data): ok = super(NackResult, self).Matches(response, unpacked_data) return (ok and response.response_type == OlaClient.RDM_NACK_REASON and response.command_class == self._command_class and response.pid == self._pid_id and response.nack_reason == self._nack_reason) class NackDiscoveryResult(NackResult): """This checks that the device nacked a Discovery request.""" def __init__(self, pid_id, nack_reason, action=None, warning=None, advisory=None): """Create an expected result object which is a NACK for a Discovery request. Args: pid_id: The pid id we expect to have been nack'ed nack_reason: The RDMNack object we expect. action: The action to run if this result matches warning: A warning message to log is this result matches advisory: An advisory message to log is this result matches """ super(NackDiscoveryResult, self).__init__(RDM_DISCOVERY, pid_id, nack_reason, action, warning, advisory) class NackGetResult(NackResult): """This checks that the device nacked a GET request.""" def __init__(self, pid_id, nack_reason, action=None, warning=None, advisory=None): """Create an expected result object which is a NACK for a GET request. Args: pid_id: The pid id we expect to have been nack'ed nack_reason: The RDMNack object we expect. action: The action to run if this result matches warning: A warning message to log is this result matches advisory: An advisory message to log is this result matches """ super(NackGetResult, self).__init__(RDM_GET, pid_id, nack_reason, action, warning, advisory) class NackSetResult(NackResult): """This checks that the device nacked a SET request.""" def __init__(self, pid_id, nack_reason, action=None, warning=None, advisory=None): """Create an expected result object which is a NACK for a SET request. Args: pid_id: The pid id we expect to have been nack'ed nack_reason: The RDMNack object we expect. action: The action to run if this result matches warning: A warning message to log is this result matches advisory: An advisory message to log is this result matches """ super(NackSetResult, self).__init__(RDM_SET, pid_id, nack_reason, action, warning, advisory) class AckResult(SuccessfulResult): """This checks that the device ack'ed the request.""" def __init__(self, command_class, pid_id, field_names=[], field_values={}, action=None, warning=None, advisory=None): """Create an expected result object that matches an ACK. Args: command_class: RDM_GET or RDM_SET pid_id: The pid id we expect field_names: Check that these fields are present in the response field_values: Check that fields & values are present in the response action: The action to run if this result matches warning: A warning message to log is this result matches advisory: An advisory message to log is this result matches """ super(AckResult, self).__init__(action, warning, advisory) self._command_class = command_class self._pid_id = pid_id self._field_names = field_names self._field_values = field_values def __str__(self): return ('CC: %s, PID 0x%04hx, ACK, fields %s, values %s' % ( _CommandClassToString(self._command_class), self._pid_id, self._field_names, self._field_values)) def Matches(self, response, unpacked_data): ok = super(AckResult, self).Matches(response, unpacked_data) if (not ok or response.response_type != OlaClient.RDM_ACK or response.command_class != self._command_class or response.pid != self._pid_id): return False # unpacked_data may be either a list of dicts, or a dict if isinstance(unpacked_data, list): for item in unpacked_data: field_keys = set(item.keys()) for field in self._field_names: if field not in field_keys: return False else: field_keys = set(unpacked_data.keys()) for field in self._field_names: if field not in field_keys: return False for field, value in self._field_values.iteritems(): if field not in unpacked_data: return False if value != unpacked_data[field]: return False return True class AckDiscoveryResult(AckResult): """This checks that the device ack'ed a DISCOVERY request.""" def __init__(self, pid_id, field_names=[], field_values={}, action=None, warning=None, advisory=None): """Create an expected result object which is an ACK for a DISCOVERY request. Args: pid_id: The pid id we expect field_names: Check that these fields are present in the response field_values: Check that fields & values are present in the response action: The action to run if this result matches warning: A warning message to log is this result matches advisory: An advisory message to log is this result matches """ super(AckDiscoveryResult, self).__init__(RDM_DISCOVERY, pid_id, field_names, field_values, action, warning, advisory) class AckGetResult(AckResult): """This checks that the device ack'ed a GET request.""" def __init__(self, pid_id, field_names=[], field_values={}, action=None, warning=None, advisory=None): """Create an expected result object which is an ACK for a GET request. Args: pid_id: The pid id we expect field_names: Check that these fields are present in the response field_values: Check that fields & values are present in the response action: The action to run if this result matches warning: A warning message to log is this result matches advisory: An advisory message to log is this result matches """ super(AckGetResult, self).__init__(RDM_GET, pid_id, field_names, field_values, action, warning, advisory) class AckSetResult(AckResult): """This checks that the device ack'ed a SET request.""" def __init__(self, pid_id, field_names=[], field_values={}, action=None, warning=None, advisory=None): """Create an expected result object which is an ACK for a SET request. Args: pid_id: The pid id we expect field_names: Check that these fields are present in the response field_values: Check that fields & values are present in the response action: The action to run if this result matches warning: A warning message to log is this result matches advisory: An advisory message to log is this result matches """ super(AckSetResult, self).__init__(RDM_SET, pid_id, field_names, field_values, action, warning, advisory) ola-0.10.5.nojsmin/tools/rdm/rdm_test_server.py0000755000175000017500000010116413023355232021167 0ustar wouterwouter#!/usr/bin/env python # 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # rdm_test_server.py # Copyright (C) 2012 Ravindra Nath Kakarla & Simon Newton import cgi import json import logging import mimetypes import os import pprint import re import stat import sys import textwrap import traceback import urlparse from datetime import datetime from optparse import OptionParser from threading import Condition, Event, Lock, Thread from time import time from wsgiref.simple_server import make_server from ola.UID import UID from ola.ClientWrapper import ClientWrapper, SelectServer from ola.OlaClient import OlaClient, OLADNotRunningException from ola import PidStore from ola.testing.rdm.DMXSender import DMXSender from ola.testing.rdm import DataLocation from ola.testing.rdm import TestDefinitions from ola.testing.rdm import TestLogger from ola.testing.rdm import TestRunner from ola.testing.rdm.ModelCollector import ModelCollector from ola.testing.rdm.TestState import TestState __author__ = 'ravindhranath@gmail.com (Ravindra Nath Kakarla)' settings = { 'PORT': 9099, } class Error(Exception): """Base exception class.""" class ServerException(Error): """Indicates a problem handling the request.""" class OLAFuture(object): def __init__(self): self._event = Event() self._data = None def set(self, data): self._data = data self._event.set() def wait(self): self._event.wait() def result(self): return self._data class OLAThread(Thread): """The thread which runs the OLA Client.""" def __init__(self, ola_client): super(OLAThread, self).__init__() self._client = ola_client self._ss = None # Created in run() def run(self): self._ss = SelectServer() self._ss.AddReadDescriptor(self._client.GetSocket(), self._client.SocketReady) self._ss.Run() logging.info('OLA thread finished') def Stop(self): if self._ss is None: logging.critical('OLAThread.Stop() called before thread was running') return logging.info('Stopping OLA thread') self._ss.Terminate() def Execute(self, cb): self._ss.Execute(cb) def FetchUniverses(self): return self.MakeSyncClientCall(self._client.FetchUniverses) def FetchUIDList(self, *args): return self.MakeSyncClientCall(self._client.FetchUIDList, *args) def RunRDMDiscovery(self, *args): return self.MakeSyncClientCall(self._client.RunRDMDiscovery, *args) def MakeSyncClientCall(self, method, *method_args): """Turns an async call into a sync (blocking one). Args: wrapper: the ClientWrapper object method: the method to call *method_args: Any arguments to pass to the method Returns: The arguments that would have been passed to the callback function. """ future = OLAFuture() def Callback(*args, **kwargs): future.set(args) def RunMethod(): method(*method_args, callback=Callback) self._ss.Execute(RunMethod) future.wait() return future.result() class RDMTestThread(Thread): """The RDMResponder tests are closely coupled to the Wrapper (yuck!). So we need to run this all in a separate thread. This is all a bit of a hack and you'll get into trouble if multiple things are running at once... """ RUNNING, COMPLETED, ERROR = range(3) TESTS, COLLECTOR = range(2) def __init__(self, pid_store, logs_directory): super(RDMTestThread, self).__init__() self._pid_store = pid_store self._logs_directory = logs_directory self._terminate = False self._request = None # Guards _terminate and _request self._cv = Condition() self._wrapper = None self._test_state_lock = Lock() # Guards _test_state self._test_state = {} def Stop(self): self._cv.acquire() self._terminate = True self._cv.notify() self._cv.release() def ScheduleTests(self, universe, uid, test_filter, broadcast_write_delay, inter_test_delay, dmx_frame_rate, slot_count): """Schedule the tests to be run. Callable from any thread. Callbable by any thread. Returns: An error message, or None if the tests were scheduled. """ if not self._CheckIfConnected(): return 'Lost connection to OLAD' self._cv.acquire() if self._request is not None: self._cv.release() return 'Existing request pending' self._request = lambda: self._RunTests(universe, uid, test_filter, broadcast_write_delay, inter_test_delay, dmx_frame_rate, slot_count) self._cv.notify() self._cv.release() return None def ScheduleCollector(self, universe, skip_queued_messages): """Schedule the collector to run on a universe. Callable by any thread. Returns: An error message, or None if the collection was scheduled. """ if not self._CheckIfConnected(): return 'Lost connection to OLAD' self._cv.acquire() if self._request is not None: self._cv.release() return 'Existing request pending' self._request = lambda: self._RunCollector(universe, skip_queued_messages) self._cv.notify() self._cv.release() return None def Stat(self): """Check the state of the tests. Callable by any thread. Returns: The status of the tests. """ self._test_state_lock.acquire() state = dict(self._test_state) self._test_state_lock.release() return state def run(self): self._wrapper = ClientWrapper() self._collector = ModelCollector(self._wrapper, self._pid_store) while True: self._cv.acquire() if self._terminate: logging.info('quitting test thread') self._cv.release() return if self._request is not None: request = self._request self._request = None self._cv.release() request() continue # Nothing to do, go into the wait self._cv.wait() self._cv.release() def _UpdateStats(self, tests_completed, total_tests): self._test_state_lock.acquire() self._test_state['tests_completed'] = tests_completed self._test_state['total_tests'] = total_tests self._test_state_lock.release() def _RunTests(self, universe, uid, test_filter, broadcast_write_delay, inter_test_delay, dmx_frame_rate, slot_count): self._test_state_lock.acquire() self._test_state = { 'action': self.TESTS, 'tests_completed': 0, 'total_tests': None, 'state': self.RUNNING, 'duration': 0, } start_time = datetime.now() self._test_state_lock.release() runner = TestRunner.TestRunner(universe, uid, broadcast_write_delay, inter_test_delay, self._pid_store, self._wrapper) for test in TestRunner.GetTestClasses(TestDefinitions): runner.RegisterTest(test) dmx_sender = None if dmx_frame_rate > 0 and slot_count > 0: logging.info('Starting DMXSender with slot count %d and FPS of %d' % (slot_count, dmx_frame_rate)) dmx_sender = DMXSender(self._wrapper, universe, dmx_frame_rate, slot_count) try: tests, device = runner.RunTests(test_filter, False, self._UpdateStats) except Exception as e: self._test_state_lock.acquire() self._test_state['state'] = self.ERROR self._test_state['exception'] = str(e) self._test_state['traceback'] = traceback.format_exc() self._test_state_lock.release() return finally: if dmx_sender is not None: dmx_sender.Stop() timestamp = int(time()) end_time = datetime.now() test_parameters = { 'broadcast_write_delay': broadcast_write_delay, 'inter_test_delay': inter_test_delay, 'dmx_frame_rate': dmx_frame_rate, 'dmx_slot_count': slot_count, } log_saver = TestLogger.TestLogger(self._logs_directory) logs_saved = True try: log_saver.SaveLog(uid, timestamp, end_time, tests, device, test_parameters) except TestLogger.TestLoggerException: logs_saved = False self._test_state_lock.acquire() # We can't use total_seconds() since it requires Python 2.7 time_delta = end_time - start_time self._test_state['duration'] = ( time_delta.seconds + time_delta.days * 24 * 3600) self._test_state['state'] = self.COMPLETED self._test_state['tests'] = tests self._test_state['logs_saved'] = logs_saved self._test_state['timestamp'] = timestamp self._test_state['uid'] = uid self._test_state_lock.release() def _RunCollector(self, universe, skip_queued_messages): """Run the device model collector for a universe.""" logging.info('Collecting for %d' % universe) self._test_state_lock.acquire() self._test_state = { 'action': self.COLLECTOR, 'state': self.RUNNING, } self._test_state_lock.release() try: output = self._collector.Run(universe, skip_queued_messages) except Exception as e: self._test_state_lock.acquire() self._test_state['state'] = self.ERROR self._test_state['exception'] = str(e) self._test_state['traceback'] = traceback.format_exc() self._test_state_lock.release() return self._test_state_lock.acquire() self._test_state['state'] = self.COMPLETED self._test_state['output'] = output self._test_state_lock.release() def _CheckIfConnected(self): """Check if the client is connected to olad. Returns: True if connected, False otherwise. """ # TODO(simon): add this check, remember it needs locking. return True class HTTPRequest(object): """Represents a HTTP Request.""" def __init__(self, environ): self._environ = environ self._params = None self._post_params = None def Path(self): """Return the path for the request.""" return self._environ['PATH_INFO'] def GetParam(self, param, default=None): """This only returns the first value for each param. Args: param: the name of the url parameter. default: the value to return if the parameter wasn't supplied. Returns: The value of the url param, or None if it wasn't present. """ if self._params is None: self._params = {} get_params = urlparse.parse_qs(self._environ['QUERY_STRING']) for p in get_params: self._params[p] = get_params[p][0] return self._params.get(param, default) def PostParam(self, param, default=None): """Lookup the value of a POST parameter. Args: param: the name of the post parameter. default: the value to return if the parameter wasn't supplied. Returns: The value of the post param, or None if it wasn't present. """ if self._post_params is None: self._post_params = {} try: request_body_size = int(self._environ.get('CONTENT_LENGTH', 0)) except (ValueError): request_body_size = 0 request_body = self._environ['wsgi.input'].read(request_body_size) post_params = urlparse.parse_qs(request_body) for p in post_params: self._post_params[p] = post_params[p][0] return self._post_params.get(param, default) class HTTPResponse(object): """Represents a HTTP Response.""" OK = '200 OK' ERROR = '500 Error' DENIED = '403 Denied' NOT_FOUND = '404 Not Found' PERMANENT_REDIRECT = '301 Moved Permanently' def __init__(self): self._status = None self._headers = {} self._content_type = None self._data = [] def SetStatus(self, status): self._status = status def GetStatus(self): return self._status def SetHeader(self, header, value): self._headers[header] = value def GetHeaders(self): headers = [] for header, value in self._headers.iteritems(): headers.append((header, value)) return headers def AppendData(self, data): self._data.append(data) def Data(self): return self._data class RequestHandler(object): """The base request handler class.""" def HandleRequest(self, request, response): pass class RedirectHandler(RequestHandler): """Serve a 301 redirect.""" def __init__(self, new_location): self._new_location = new_location def HandleRequest(self, request, response): response.SetStatus(HTTPResponse.PERMANENT_REDIRECT) response.SetHeader('Location', self._new_location) class StaticFileHandler(RequestHandler): """A class which handles requests for static files.""" PREFIX = '/static/' def __init__(self, static_dir): self._static_dir = static_dir def HandleRequest(self, request, response): path = request.Path() if not path.startswith(self.PREFIX): response.SetStatus(HTTPResponse.NOT_FOUND) return # Strip off /static path = path[len(self.PREFIX):] # This is important as it ensures we can't access arbitary files filename = os.path.abspath(os.path.join(self._static_dir, path)) if (not filename.startswith(self._static_dir) or not os.path.exists(filename) or not os.path.isfile(filename)): response.SetStatus(HTTPResponse.NOT_FOUND) return elif not os.access(filename, os.R_OK): response.SetStatus(HTTPResponse.DENIED) return else: mimetype, encoding = mimetypes.guess_type(filename) if mimetype: response.SetHeader('Content-type', mimetype) if encoding: response.SetHeader('Content-encoding', encoding) stats = os.stat(filename) response.SetStatus(HTTPResponse.OK) response.SetHeader('Content-length', str(stats.st_size)) response.AppendData(open(filename, 'rb').read()) class JsonRequestHandler(RequestHandler): """A class which handles JSON requests.""" def HandleRequest(self, request, response): response.SetHeader('Cache-Control', 'no-cache') response.SetHeader('Content-type', 'application/json') try: json_data = self.GetJson(request, response) response.AppendData(json.dumps(json_data, sort_keys=True)) except ServerException as e: # For JSON requests, rather than returning 500s we return the error as # JSON response.SetStatus(HTTPResponse.OK) json_data = { 'status': False, 'error': str(e), } response.AppendData(json.dumps(json_data, sort_keys=True)) def RaiseExceptionIfMissing(self, request, param): """Helper method to raise an exception if the param is missing.""" value = request.GetParam(param) if value is None: raise ServerException('Missing parameter: %s' % param) return value def GetJson(self, request, response): """Subclasses implement this.""" pass class OLAServerRequestHandler(JsonRequestHandler): """Catches OLADNotRunningException and handles them gracefully.""" def __init__(self, ola_thread): self._thread = ola_thread def GetThread(self): return self._thread def HandleRequest(self, request, response): try: super(OLAServerRequestHandler, self).HandleRequest(request, response) except OLADNotRunningException: response.SetStatus(HTTPResponse.OK) json_data = { 'status': False, 'error': 'The OLA Server instance is no longer running', } response.AppendData(json.dumps(json_data, sort_keys=True)) class TestDefinitionsHandler(JsonRequestHandler): """Return a JSON list of test definitions.""" def GetJson(self, request, response): response.SetStatus(HTTPResponse.OK) tests = [t.__name__ for t in TestRunner.GetTestClasses(TestDefinitions)] return { 'test_defs': tests, 'status': True, } class GetUniversesHandler(OLAServerRequestHandler): """Return a JSON list of universes.""" def GetJson(self, request, response): def UniverseToJson(u): return { '_id': u.id, '_name': u.name, '_merge_mode': u.merge_mode, } status, universes = self.GetThread().FetchUniverses() if not status.Succeeded(): raise ServerException('Failed to fetch universes from server') response.SetStatus(HTTPResponse.OK) return { 'universes': [UniverseToJson(u) for u in universes], 'status': True, } class GetDevicesHandler(OLAServerRequestHandler): """Return a JSON list of RDM devices.""" def GetJson(self, request, response): universe_param = request.GetParam('u') if universe_param is None: raise ServerException('Missing universe parameter: u') try: universe = int(universe_param) except ValueError: raise ServerException('Invalid universe parameter: u') status, uids = self.GetThread().FetchUIDList(universe) if not status.Succeeded(): raise ServerException('Invalid universe ID!') response.SetStatus(HTTPResponse.OK) return { 'uids': [str(u) for u in uids], 'status': True, } class RunDiscoveryHandler(OLAServerRequestHandler): """Runs the RDM Discovery process.""" def GetJson(self, request, response): universe_param = request.GetParam('u') if universe_param is None: raise ServerException('Missing universe parameter: u') try: universe = int(universe_param) except ValueError: raise ServerException('Invalid universe parameter: u') status, uids = self.GetThread().RunRDMDiscovery(universe, True) if not status.Succeeded(): raise ServerException('Invalid universe ID!') response.SetStatus(HTTPResponse.OK) return { 'uids': [str(u) for u in uids], 'status': True, } class DownloadModelDataHandler(RequestHandler): """Take the data in the form and return it as a downloadable file.""" def HandleRequest(self, request, response): print dir(request) model_data = request.PostParam('model_data') or '' logging.info(model_data) filename = 'model-data.%s.txt' % int(time()) response.SetStatus(HTTPResponse.OK) response.SetHeader('Content-disposition', 'attachment; filename="%s"' % filename) response.SetHeader('Content-type', 'text/plain') response.SetHeader('Content-length', '%d' % len(model_data)) response.AppendData(model_data) class DownloadResultsHandler(RequestHandler): """A class which handles requests to download test results.""" def HandleRequest(self, request, response): uid_param = request.GetParam('uid') or '' uid = UID.FromString(uid_param) if uid is None: raise ServerException('Missing uid parameter: uid') timestamp = request.GetParam('timestamp') if timestamp is None: raise ServerException('Missing timestamp parameter: timestamp') include_debug = request.GetParam('debug') include_description = request.GetParam('description') category = request.GetParam('category') test_state = request.GetParam('state') reader = TestLogger.TestLogger(settings['log_directory']) try: output = reader.ReadAndFormat(uid, timestamp, category, test_state, include_debug, include_description) except TestLogger.TestLoggerException as e: raise ServerException(e) filename = ('%04x-%08x.%s.txt' % (uid.manufacturer_id, uid.device_id, timestamp)) response.SetStatus(HTTPResponse.OK) response.SetHeader('Content-disposition', 'attachment; filename="%s"' % filename) response.SetHeader('Content-type', 'text/plain') response.SetHeader('Content-length', '%d' % len(output)) response.AppendData(output) class RunTestsHandler(OLAServerRequestHandler): """Run the RDM tests.""" def __init__(self, ola_thread, test_thread): super(RunTestsHandler, self).__init__(ola_thread) self._test_thread = test_thread def GetJson(self, request, response): """Check if this is a RunTests or StatTests request.""" path = request.Path() if path == '/RunTests': return self.RunTests(request, response) if path == '/RunCollector': return self.RunCollector(request, response) elif path == '/StatTests': return self.StatTests(request, response) elif path == '/StatCollector': return self.StatCollector(request, response) else: logging.error('Got invalid request for %s' % path) raise ServerException('Invalid request') def StatTests(self, request, response): """Return the status of the running tests.""" response.SetStatus(HTTPResponse.OK) status = self._test_thread.Stat() if status is None: return {} json_data = {'status': True} if status['state'] == RDMTestThread.COMPLETED: json_data['UID'] = str(status['uid']) json_data['duration'] = status['duration'] json_data['completed'] = True json_data['logs_disabled'] = not status['logs_saved'] json_data['timestamp'] = status['timestamp'], self._FormatTestResults(status['tests'], json_data) elif status['state'] == RDMTestThread.ERROR: json_data['completed'] = True json_data['exception'] = status['exception'] json_data['traceback'] = status.get('traceback', '') else: json_data['completed'] = False json_data['tests_completed'] = status['tests_completed'] json_data['total_tests'] = status['total_tests'] return json_data def StatCollector(self, request, response): """Return the status of the running collector process.""" response.SetStatus(HTTPResponse.OK) status = self._test_thread.Stat() if status is None: return {} json_data = {'status': True} if status['state'] == RDMTestThread.COMPLETED: json_data['completed'] = True json_data['output'] = pprint.pformat(status['output']) elif status['state'] == RDMTestThread.ERROR: json_data['completed'] = True json_data['exception'] = status['exception'] json_data['traceback'] = status.get('traceback', '') else: json_data['completed'] = False return json_data def RunCollector(self, request, response): """Handle a /RunCollector request.""" universe = self._CheckValidUniverse(request) skip_queued = request.GetParam('skip_queued') if skip_queued is None or skip_queued.lower() == 'false': skip_queued = False else: skip_queued = True ret = self._test_thread.ScheduleCollector(universe, skip_queued) if ret is not None: raise ServerException(ret) response.SetStatus(HTTPResponse.OK) return {'status': True} def RunTests(self, request, response): """Handle a /RunTests request.""" universe = self._CheckValidUniverse(request) uid_param = self.RaiseExceptionIfMissing(request, 'uid') uid = UID.FromString(uid_param) if uid is None: raise ServerException('Invalid uid: %s' % uid_param) # The tests to run, None means all test_filter = request.GetParam('t') if test_filter is not None: if test_filter == 'all': test_filter = None else: test_filter = set(test_filter.split(',')) broadcast_write_delay = request.GetParam('broadcast_write_delay') if broadcast_write_delay is None: broadcast_write_delay = 0 try: broadcast_write_delay = int(broadcast_write_delay) except ValueError: raise ServerException('Invalid broadcast write delay') inter_test_delay = request.GetParam('inter_test_delay') if inter_test_delay is None: inter_test_delay = 0 try: inter_test_delay = int(inter_test_delay) except ValueError: raise ServerException('Invalid inter-test delay') slot_count = request.GetParam('slot_count') if slot_count is None: slot_count = 0 try: slot_count = int(slot_count) except ValueError: raise ServerException('Invalid slot count') if slot_count not in range(0, 513): raise ServerException('Slot count not in range 0..512') dmx_frame_rate = request.GetParam('dmx_frame_rate') if dmx_frame_rate is None: dmx_frame_rate = 0 try: dmx_frame_rate = int(dmx_frame_rate) except ValueError: raise ServerException('Invalid DMX frame rate') ret = self._test_thread.ScheduleTests(universe, uid, test_filter, broadcast_write_delay, inter_test_delay, dmx_frame_rate, slot_count) if ret is not None: raise ServerException(ret) response.SetStatus(HTTPResponse.OK) return {'status': True} def _CheckValidUniverse(self, request): """Check that the universe paramter is present and refers to a valid universe. Args: request: the HTTPRequest object. Returns: The santitized universe id. Raises: ServerException if the universe isn't valid or doesn't exist. """ universe_param = self.RaiseExceptionIfMissing(request, 'u') try: universe = int(universe_param) except ValueError: raise ServerException('Invalid universe parameter: u') status, universes = self.GetThread().FetchUniverses() if not status.Succeeded(): raise ServerException('Failed to fetch universes from server') if universe not in [u.id for u in universes]: raise ServerException("Universe %d doesn't exist" % universe) return universe def _FormatTestResults(self, tests, json_data): results = [] stats_by_catg = {} passed = 0 failed = 0 broken = 0 not_run = 0 for test in tests: state = test.state.__str__() category = test.category.__str__() stats_by_catg.setdefault(category, {'passed': 0, 'total': 0}) if test.state == TestState.PASSED: passed += 1 stats_by_catg[category]['passed'] += 1 stats_by_catg[category]['total'] += 1 elif test.state == TestState.FAILED: failed += 1 stats_by_catg[category]['total'] += 1 elif test.state == TestState.BROKEN: broken += 1 stats_by_catg[category]['total'] += 1 elif test.state == TestState.NOT_RUN: not_run += 1 results.append({ 'definition': test.__str__(), 'state': state, 'category': category, 'warnings': [cgi.escape(w) for w in test.warnings], 'advisories': [cgi.escape(a) for a in test.advisories], 'debug': [cgi.escape(d) for d in test._debug], 'doc': cgi.escape(test.__doc__), } ) stats = { 'total': len(tests), 'passed': passed, 'failed': failed, 'broken': broken, 'not_run': not_run, } json_data.update({ 'test_results': results, 'stats': stats, 'stats_by_catg': stats_by_catg, }) class Application(object): """Creates a new Application.""" def __init__(self): # dict of path to handler self._handlers = {} self._regex_handlers = [] def RegisterHandler(self, path, handler): self._handlers[path] = handler def RegisterRegex(self, path_regex, handler): self._regex_handlers.append((path_regex, handler)) def HandleRequest(self, environ, start_response): """Create a new TestServerApplication, passing in the OLA Wrapper.""" request = HTTPRequest(environ) response = HTTPResponse() self.DispatchRequest(request, response) start_response(response.GetStatus(), response.GetHeaders()) return response.Data() def DispatchRequest(self, request, response): path = request.Path() if path in self._handlers: self._handlers[path](request, response) return else: for pattern, handler in self._regex_handlers: if re.match(pattern, path): handler(request, response) return response.SetStatus(HTTPResponse.NOT_FOUND) def BuildApplication(ola_thread, test_thread): """Construct the application and add the handlers.""" app = Application() app.RegisterHandler('/', RedirectHandler('/static/rdmtests.html').HandleRequest) app.RegisterHandler( '/favicon.ico', RedirectHandler('/static/images/favicon.ico').HandleRequest) app.RegisterHandler('/GetTestDefs', TestDefinitionsHandler().HandleRequest) app.RegisterHandler('/GetUnivInfo', GetUniversesHandler(ola_thread).HandleRequest) app.RegisterHandler('/GetDevices', GetDevicesHandler(ola_thread).HandleRequest) app.RegisterHandler('/RunDiscovery', RunDiscoveryHandler(ola_thread).HandleRequest) app.RegisterHandler('/DownloadResults', DownloadResultsHandler().HandleRequest) app.RegisterHandler('/DownloadModelData', DownloadModelDataHandler().HandleRequest) run_tests_handler = RunTestsHandler(ola_thread, test_thread) app.RegisterHandler('/RunCollector', run_tests_handler.HandleRequest) app.RegisterHandler('/RunTests', run_tests_handler.HandleRequest) app.RegisterHandler('/StatCollector', run_tests_handler.HandleRequest) app.RegisterHandler('/StatTests', run_tests_handler.HandleRequest) app.RegisterRegex('/static/.*', StaticFileHandler(settings['www_dir']).HandleRequest) return app def parse_options(): """Parse Command Line options""" usage = 'Usage: %prog [options]' description = textwrap.dedent("""\ Starts the TestServer (A simple Web Server) which run a series of tests on a RDM responder and displays the results in a Web UI. This requires the OLA server to be running, and the RDM device to have been detected. You can confirm this by running ola_rdm_discover -u UNIVERSE. This will send SET commands to the broadcast UIDs which means the start address, device label etc. will be changed for all devices connected to the responder. Think twice about running this on your production lighting rig. """) parser = OptionParser(usage, description=description) parser.add_option('-p', '--pid-location', metavar='DIR', help='The directory to load the PID definitions from.') parser.add_option('-d', '--www-dir', default=DataLocation.location, help='The root directory to serve static files.') parser.add_option('-l', '--log-directory', default=os.path.abspath('/tmp/ola-rdm-logs'), help='The directory to store log files.') parser.add_option('--world-writeable', action="store_true", help='Make the log directory world writeable.') options, args = parser.parse_args() return options def SetupLogDirectory(options): """Setup the log dir.""" # Setup the log dir, or display an error log_directory = options.log_directory if not os.path.exists(log_directory): try: os.makedirs(log_directory) if options.world_writeable: stat_result = os.stat(log_directory) os.chmod(log_directory, stat_result.st_mode | stat.S_IWOTH) except OSError: logging.error( 'Failed to create %s for RDM logs. Logging will be disabled.' % options.log_directory) elif not os.path.isdir(options.log_directory): logging.error('Log directory invalid: %s. Logging will be disabled.' % options.log_directory) elif not os.access(options.log_directory, os.W_OK): logging.error( 'Unable to write to log directory: %s. Logging will be disabled.' % options.log_directory) def main(): options = parse_options() settings.update(options.__dict__) pid_store = PidStore.GetStore(options.pid_location, ('pids.proto', 'draft_pids.proto')) logging.basicConfig(level=logging.INFO, format='%(message)s') SetupLogDirectory(options) # Check olad status logging.info('Checking olad status') try: ola_client = OlaClient() except OLADNotRunningException: logging.error('Error creating connection with olad. Is it running?') sys.exit(127) ola_thread = OLAThread(ola_client) ola_thread.start() test_thread = RDMTestThread(pid_store, settings['log_directory']) test_thread.start() app = BuildApplication(ola_thread, test_thread) httpd = make_server('', settings['PORT'], app.HandleRequest) logging.info('Running RDM Tests Server on %s:%s' % ('127.0.0.1', httpd.server_port)) try: httpd.serve_forever() except KeyboardInterrupt: pass ola_thread.Stop() test_thread.Stop() ola_thread.join() test_thread.join() if __name__ == '__main__': main() ola-0.10.5.nojsmin/tools/rdm/TestCategory.py0000644000175000017500000000426413023355232020375 0ustar wouterwouter# 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # TestCategory.py # Copyright (C) 2011 Simon Newton __author__ = 'nomis52@gmail.com (Simon Newton)' class TestCategory(object): """The category a test is part of.""" SYMBOLS_TO_VALUES = { # These correspond to categories in the E1.20 document 'NETWORK_MANAGEMENT': 'Network Management', 'STATUS_COLLECTION': 'Status Collection', 'RDM_INFORMATION': 'RDM Information', 'PRODUCT_INFORMATION': 'Product Information', 'DMX_SETUP': 'DMX512 Setup', 'DIMMER_SETTINGS': 'Dimmer Settings', 'IP_DNS_CONFIGURATION': 'IP and DNS Configuration', 'SENSORS': 'Sensors', 'POWER_LAMP_SETTINGS': 'Power / Lamp Settings', 'DISPLAY_SETTINGS': 'Display Settings', 'CONFIGURATION': 'Configuration', 'CONTROL': 'Control', # And others for things that don't quite fit 'CORE': 'Core Functionality', 'ERROR_CONDITIONS': 'Error Conditions', 'SUB_DEVICES': 'Sub Devices', 'UNCLASSIFIED': 'Unclassified', } CATEGORIES_ = [] def __init__(self, category): self._category = category def __str__(self): return self._category def __hash__(self): return hash(self._category) @staticmethod def Categories(): """Return a list of all TestCategories.""" return TestCategory.CATEGORIES_ # Make the symbols accessible, i.e. TestCategory.STATUS_COLLECTION for symbol, description in TestCategory.SYMBOLS_TO_VALUES.iteritems(): obj = TestCategory(description) setattr(TestCategory, symbol, obj) TestCategory.CATEGORIES_.append(obj) ola-0.10.5.nojsmin/tools/rdm/rdm_model_collector.py0000755000175000017500000000536513023355232021776 0ustar wouterwouter#!/usr/bin/env python # 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # rdm_model_collector.py # Copyright (C) 2011 Simon Newton import getopt import logging import pprint import sys import textwrap from ola import PidStore from ola.testing.rdm.ModelCollector import ModelCollector from ola.ClientWrapper import ClientWrapper '''Quick script to collect information about responders.''' __author__ = 'nomis52@gmail.com (Simon Newton)' def Usage(): print textwrap.dedent("""\ Usage: rdm_model_collector.py --universe Collect information about responders attached to a universe and output in a format that can be imported into the RDM manufacturer index (http://rdm.openlighting.org/) -d, --debug Print extra debug info. -h, --help Display this help message and exit. -p, --pid-location The directory to read PID definitions from. --skip-queued-messages Don't attempt to fetch queued messages for the device. -u, --universe Universe number.""") def main(): try: opts, args = getopt.getopt( sys.argv[1:], 'dhp:u:', ['debug', 'help', 'skip-queued-messages', 'pid-location=', 'universe=']) except getopt.GetoptError, err: print str(err) Usage() sys.exit(2) universe = None pid_location = None level = logging.INFO skip_queued_messages = False for o, a in opts: if o in ('-d', '--debug'): level = logging.DEBUG elif o in ('-h', '--help'): Usage() sys.exit() elif o in ('--skip-queued-messages'): skip_queued_messages = True elif o in ('-p', '--pid-location',): pid_location = a elif o in ('-u', '--universe'): universe = int(a) if universe is None: Usage() sys.exit() logging.basicConfig( level=level, format='%(message)s') client_wrapper = ClientWrapper() pid_store = PidStore.GetStore(pid_location) controller = ModelCollector(client_wrapper, pid_store) data = controller.Run(universe, skip_queued_messages) pprint.pprint(data) if __name__ == '__main__': main() ola-0.10.5.nojsmin/tools/rdm/TestLogger.py0000644000175000017500000002030513023355232020031 0ustar wouterwouter# 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # TestLogger.py # Copyright (C) 2012 Simon Newton import logging import os import pickle import re from ola import Version from ola.testing.rdm.TestState import TestState __author__ = 'nomis52@gmail.com (Simon Newton)' class Error(Exception): """Base exception class.""" class TestLoggerException(Error): """Indicates a problem with the log reader.""" class TestLogger(object): """Reads/saves test results to/from files.""" FILE_NAME_RE = r'[0-9a-f]{4}-[0-9a-f]{8}\.[0-9]{10}\.log$' def __init__(self, log_dir): """ Args: log_dir: where to store the logs """ self._log_dir = log_dir def UIDToString(self, uid): """Converts a UID to a string in the form -. This is different from the __str__() method in UID since the : causes problems on some filesystems. """ return '%04x-%08x' % (uid.manufacturer_id, uid.device_id) def SaveLog(self, uid, timestamp, end_time, tests, device, test_parameters): """Log the results to a file. Args: uid: the UID timestamp: the timestamp for the logs as an int end_time: the datetime object when the tests completed. tests: The list of Test objects device: The device properties test_parameters: a dict of values representing the parameters for the test. Can contain things like the broadcast_write_delay, timing info etc. Raises: TestLoggerException if we failed to write the file. """ test_results = [] for test in tests: test_results.append({ 'advisories': test.advisories, 'category': test.category.__str__(), 'debug': test._debug, 'definition': test.__str__(), 'doc': test.__doc__, 'state': test.state.__str__(), 'warnings': test.warnings, }) output = dict(test_parameters) output['test_results'] = test_results output['timestamp'] = end_time.strftime('%F %r %z') output['uid'] = uid output['version'] = Version.version output['properties'] = device.AsDict() filename = '%s.%d.log' % (self.UIDToString(uid), timestamp) filename = os.path.join(self._log_dir, filename) try: log_file = open(filename, 'w') except IOError as e: raise TestLoggerException( 'Failed to write to %s: %s' % (filename, e.message)) pickle.dump(output, log_file) logging.info('Wrote log file %s' % (log_file.name)) log_file.close() def ReadLog(self, uid, timestamp): """Load the test data for this particular responder & time. Args: uid: timestamp: Returns: The formatted data. Don't rely on the format of this data being the same. """ log_name = "%s.%s.log" % (self.UIDToString(uid), timestamp) if not self._CheckFilename(log_name): raise TestLoggerException('Invalid log file requested!') filename = os.path.abspath( os.path.join(self._log_dir, log_name)) if not os.path.isfile(filename): raise TestLoggerException('Missing log file! Please re-run tests') try: f = open(filename, 'rb') except IOError as e: raise TestLoggerException(e) return pickle.load(f) def ReadAndFormat(self, uid, timestamp, category, test_state, include_debug=True, include_description=True, include_summary=True): """Read the data from the log and produce a text report. Args: uid: timestamp: the timestamp for the logs Returns: The text version of the results. """ test_data = self.ReadLog(uid, timestamp) formatted_output = self._FormatData(test_data, category, test_state, include_debug, include_description, include_summary) return formatted_output def _CheckFilename(self, filename): """Check if a test log filename is valid.""" return re.match(self.FILE_NAME_RE, filename) is not None def _FormatData(self, test_data, requested_category, requested_test_state, include_debug, include_description, include_summary): """Format the data nicely.""" results_log = [] warnings = [] advisories = [] count_by_category = {} broken = 0 failed = 0 not_run = 0 passed = 0 results_log.append('OLA RDM Responder Tests\n') if requested_category is None or requested_category.lower() == 'all': requested_category = None if requested_test_state is None or requested_test_state.lower() == 'all': requested_test_state = None tests = test_data.get('test_results', []) total = len(tests) for test in tests: category = test['category'] state = test['state'] counts = count_by_category.setdefault(category, {'passed': 0, 'total': 0}) if state == str(TestState.PASSED): counts['passed'] += 1 counts['total'] += 1 passed += 1 elif state == str(TestState.NOT_RUN): not_run += 1 elif state == str(TestState.FAILED): counts['total'] += 1 failed += 1 elif state == str(TestState.BROKEN): counts['total'] += 1 broken += 1 if requested_category is not None and requested_category != category: continue if requested_test_state is not None and requested_test_state != state: continue results_log.append('%s: %s' % (test['definition'], test['state'].upper())) if include_description: results_log.append(str(test['doc'])) if include_debug: results_log.extend(str(l) for l in test.get('debug', [])) results_log.append('') warnings.extend(str(s) for s in test.get('warnings', [])) advisories.extend(str(s) for s in test.get('advisories', [])) results_log.append('------------------- Summary --------------------') results_log.append('OLA Version: %s' % test_data['version']) results_log.append('Test Run: %s' % test_data['timestamp']) results_log.append('UID: %s' % test_data['uid']) manufacturer_label = test_data['properties'].get('manufacturer_label', None) if manufacturer_label: results_log.append('Manufacturer: %s' % manufacturer_label.encode('string-escape')) model_description = test_data['properties'].get('model_description', None) if model_description: results_log.append('Model Description: %s' % model_description.encode('string-escape')) software_version = test_data['properties'].get('software_version', None) if software_version: results_log.append('Software Version: %s' % software_version) results_log.append("------------------- Warnings --------------------") results_log.extend(warnings) results_log.append("------------------ Advisories -------------------") results_log.extend(advisories) if include_summary: results_log.append("----------------- By Category -------------------") for category, counts in sorted(count_by_category.items()): cat_passed = counts['passed'] cat_total = counts['total'] try: percent = int(round(100.0 * cat_passed / cat_total)) except ZeroDivisionError: percent = '-' results_log.append(' %26s: %3d / %3d %s%%' % (category, cat_passed, cat_total, percent)) results_log.append("-------------------------------------------------") results_log.append('%d / %d tests run, %d passed, %d failed, %d broken' % (total - not_run, total, passed, failed, broken)) return '\n'.join(results_log) ola-0.10.5.nojsmin/tools/rdm/rdm_responder_test.py0000755000175000017500000002555513023355232021673 0ustar wouterwouter#!/usr/bin/env python # 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # rdm_responder_test.py # Copyright (C) 2010 Simon Newton from ola.testing.rdm import TestDefinitions, TestRunner from ola.testing.rdm.DMXSender import DMXSender from ola.testing.rdm.TestState import TestState import datetime import logging import re import sys import textwrap import time from TimingStats import TimingStats from ola import PidStore from ola import Version from ola.ClientWrapper import ClientWrapper from ola.UID import UID from optparse import OptionParser '''Automated testing for RDM responders.''' __author__ = 'nomis52@gmail.com (Simon Newton)' def ParseOptions(): usage = 'Usage: %prog [options] ' description = textwrap.dedent("""\ Run a series of tests on a RDM responder to check the behaviour. This requires the OLA server to be running, and the RDM device to have been detected. You can confirm this by running ola_rdm_discover -u UNIVERSE. This will send SET commands to the broadcast UIDs which means the start address, device label etc. will be changed for all devices connected to the responder. Think twice about running this on your production lighting rig. """) parser = OptionParser(usage, description=description) parser.add_option('-c', '--slot-count', default=10, help='Number of slots to send when sending DMX.') parser.add_option('-d', '--debug', action='store_true', help='Print debug information to assist in diagnosing ' 'failures.') parser.add_option('-f', '--dmx-frame-rate', default=0, type='int', help='Send DMX frames at this rate in the background.') parser.add_option('-l', '--log', metavar='FILE', help='Also log to the file named FILE.uid.timestamp.') parser.add_option('--list-tests', action='store_true', help='Display a list of all tests') parser.add_option('-p', '--pid-location', metavar='DIR', help='The location of the PID definitions.') parser.add_option('-s', '--skip-check', action='store_true', help='Skip the check for multiple devices.') parser.add_option('-t', '--tests', metavar='TEST1,TEST2', help='A comma separated list of tests to run.') parser.add_option('--timestamp', action='store_true', help='Add timestamps to each test.') parser.add_option('--timing', action='store_true', help='Display summary timing information') parser.add_option('--no-factory-defaults', action='store_true', help="Don't run the SET factory defaults tests") parser.add_option('-w', '--broadcast-write-delay', default=0, type='int', help='The time in ms to wait after sending broadcast set ' 'commands.') parser.add_option('-u', '--universe', default=0, type='int', help='The universe number to use, default is universe 0.') parser.add_option('--inter-test-delay', default=0, type='int', help='The delay in ms to wait between tests, defaults to ' '0.') options, args = parser.parse_args() if options.list_tests: return options if not args: parser.print_help() sys.exit(2) uid = UID.FromString(args[0]) if uid is None: parser.print_usage() print 'Invalid UID: %s' % args[0] sys.exit(2) options.uid = uid return options class MyFilter(object): """Filter out the ascii coloring.""" def filter(self, record): msg = record.msg record.msg = re.sub('\x1b\[\d*m', '', str(msg)) return True def SetupLogging(options): """Setup the logging for test results.""" level = logging.INFO if options.debug: level = logging.DEBUG logging.basicConfig( level=level, format='%(message)s') if options.log: file_name = '%s.%s.%d' % (options.log, options.uid, time.time()) file_handler = logging.FileHandler(file_name, 'w') file_handler.addFilter(MyFilter()) if options.debug: file_handler.setLevel(logging.DEBUG) logging.getLogger('').addHandler(file_handler) def LogTimingParam(parameter, data): # if non-0 print the stats if data['max']: data['param'] = parameter logging.info(' %s:' % parameter) logging.info(' Mean: %(mean).1f, StdDev %(std).1f, Median %(median).1f' % data) logging.info(' Min: %(min).1f, Max %(max).1f, 99%%: %(99).1f' % data) def LogAllTimingParams(response_type, stats): if not stats.Count(): return logging.info('%s [%d frames]' % (response_type, stats.Count())) LogTimingParam('Response Time', stats.ResponseTime()) LogTimingParam('Break', stats.Break()) LogTimingParam('Mark', stats.Mark()) LogTimingParam('Data', stats.Data()) def DisplayTiming(timing_stats): """Print timing information.""" logging.info('--------------- Response Timing ----------------') stats = timing_stats.GetStatsForType(TimingStats.GET) LogAllTimingParams('GET_RESPONSE', stats) stats = timing_stats.GetStatsForType(TimingStats.SET) LogAllTimingParams('SET_RESPONSE', stats) stats = timing_stats.GetStatsForType(TimingStats.DISCOVERY) LogAllTimingParams('DISCOVERY_RESPONSE', stats) stats = timing_stats.GetStatsForType(TimingStats.DUB) LogAllTimingParams('DISCOVERY_UNIQUE_BRANCH', stats) def DisplaySummary(options, runner, tests, device): """Log a summary of the tests.""" by_category = {} warnings = [] advisories = [] count_by_state = {} for test in tests: state = test.state count_by_state[state] = count_by_state.get(state, 0) + 1 warnings.extend(test.warnings) advisories.extend(test.advisories) by_category.setdefault(test.category, {}) by_category[test.category][state] = ( 1 + by_category[test.category].get(state, 0)) total = sum(count_by_state.values()) logging.info('------------------- Summary --------------------') now = datetime.datetime.now() logging.info('Test Run: %s' % now.strftime('%F %r %z')) logging.info('UID: %s' % options.uid) manufacturer_label = getattr(device, 'manufacturer_label', None) if manufacturer_label: logging.info('Manufacturer: %s' % manufacturer_label.encode('string-escape')) model_description = getattr(device, 'model_description', None) if model_description: logging.info('Model Description: %s' % model_description.encode('string-escape')) software_version = getattr(device, 'software_version', None) if software_version: logging.info('Software Version: %s' % software_version) if options.timing: timing_stats = runner.TimingStats() DisplayTiming(timing_stats) logging.info('------------------- Warnings --------------------') for warning in sorted(warnings): logging.info(warning) logging.info('------------------ Advisories -------------------') for advisory in sorted(advisories): logging.info(advisory) logging.info('------------------ By Category ------------------') for category, counts in by_category.iteritems(): passed = counts.get(TestState.PASSED, 0) total_run = (passed + counts.get(TestState.FAILED, 0)) if total_run == 0: continue percent = 1.0 * passed / total_run logging.info(' %26s: %3d / %3d %.0f%%' % (category, passed, total_run, percent * 100)) logging.info('-------------------------------------------------') logging.info('%d / %d tests run, %d passed, %d failed, %d broken' % ( total - count_by_state.get(TestState.NOT_RUN, 0), total, count_by_state.get(TestState.PASSED, 0), count_by_state.get(TestState.FAILED, 0), count_by_state.get(TestState.BROKEN, 0))) def main(): options = ParseOptions() test_classes = TestRunner.GetTestClasses(TestDefinitions) if options.list_tests: for test_name in sorted(c.__name__ for c in test_classes): print test_name sys.exit(0) SetupLogging(options) logging.info('OLA Responder Tests Version %s' % Version.version) pid_store = PidStore.GetStore(options.pid_location, ('pids.proto', 'draft_pids.proto')) wrapper = ClientWrapper() global uid_ok uid_ok = False def UIDList(state, uids): wrapper.Stop() global uid_ok if not state.Succeeded(): logging.error('Fetch failed: %s' % state.message) return for uid in uids: if uid == options.uid: logging.debug('Found UID %s' % options.uid) uid_ok = True if not uid_ok: logging.error('UID %s not found in universe %d' % (options.uid, options.universe)) return if len(uids) > 1: logging.info( 'The following devices were detected and will be reconfigured') for uid in uids: logging.info(' %s' % uid) if not options.skip_check: logging.info('Continue ? [Y/n]') response = raw_input().strip().lower() uid_ok = response == 'y' or response == '' logging.debug('Fetching UID list from server') wrapper.Client().FetchUIDList(options.universe, UIDList) wrapper.Run() wrapper.Reset() if not uid_ok: sys.exit() test_filter = None if options.tests is not None: logging.info('Restricting tests to %s' % options.tests) test_filter = set(options.tests.split(',')) logging.info( 'Starting tests, universe %d, UID %s, broadcast write delay %dms, ' 'inter-test delay %dms' % (options.universe, options.uid, options.broadcast_write_delay, options.inter_test_delay)) runner = TestRunner.TestRunner(options.universe, options.uid, options.broadcast_write_delay, options.inter_test_delay, pid_store, wrapper, options.timestamp) for test_class in test_classes: runner.RegisterTest(test_class) DMXSender(wrapper, options.universe, options.dmx_frame_rate, options.slot_count) tests, device = runner.RunTests(test_filter, options.no_factory_defaults) DisplaySummary(options, runner, tests, device) if __name__ == '__main__': main() ola-0.10.5.nojsmin/tools/rdm/TestDefinitions.py0000644000175000017500000072325013023355232021076 0ustar wouterwouter# 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # TestDefinitions.py # Copyright (C) 2010 Simon Newton import datetime import operator import struct from ExpectedResults import (AckGetResult, BroadcastResult, NackGetResult, InvalidResponse, TimeoutResult, UnsupportedResult, RDM_GET, RDM_SET) from ResponderTest import ResponderTestFixture, TestFixture from ResponderTest import OptionalParameterTestFixture from TestCategory import TestCategory from ola import PidStore from ola import RDMConstants from ola.RDMConstants import (RDM_MIN_HOSTNAME_LENGTH, RDM_MAX_HOSTNAME_LENGTH, RDM_MAX_DOMAIN_NAME_LENGTH, RDM_MANUFACTURER_PID_MIN, RDM_MANUFACTURER_PID_MAX, RDM_INTERFACE_INDEX_MIN, RDM_INTERFACE_INDEX_MAX, INTERFACE_HARDWARE_TYPE_ETHERNET, RDM_ZERO_FOOTPRINT_DMX_ADDRESS, RDM_MANUFACTURER_SD_MIN, RDM_MANUFACTURER_SD_MAX) from ola.OlaClient import OlaClient, RDMNack from ola.PidStore import ROOT_DEVICE from ola.UID import UID from TestHelpers import ContainsUnprintable import TestMixins from TestMixins import MAX_DMX_ADDRESS '''This defines all the tests for RDM responders.''' __author__ = 'nomis52@gmail.com (Simon Newton)' MAX_PERSONALITY_NUMBER = 255 # Mute Tests # ----------------------------------------------------------------------------- class MuteDevice(ResponderTestFixture): """Mute device and verify response.""" CATEGORY = TestCategory.NETWORK_MANAGEMENT PID = 'DISC_MUTE' PROVIDES = ['mute_supported', 'mute_control_fields'] def Test(self): self.AddExpectedResults([ self.AckDiscoveryResult(), UnsupportedResult( warning='RDM Controller does not support DISCOVERY commands') ]) self.SendDiscovery(ROOT_DEVICE, self.pid) def VerifyResult(self, response, fields): supported = (response.response_code != OlaClient.RDM_PLUGIN_DISCOVERY_NOT_SUPPORTED) self.SetProperty('mute_supported', supported) if supported: self.SetProperty('mute_control_fields', fields['control_field']) binding_uids = fields.get('binding_uid', []) if binding_uids: if (binding_uids[0]['binding_uid'].manufacturer_id != self.uid.manufacturer_id): self.AddWarning( 'Binding UID manufacturer ID 0x%04hx does not equal device ' 'manufacturer ID of 0x%04hx' % ( binding_uids[0]['binding_uid'].manufacturer_id, self.uid.manufacturer_id)) class MuteDeviceWithData(ResponderTestFixture): """Mute device with param data.""" CATEGORY = TestCategory.NETWORK_MANAGEMENT PID = 'DISC_MUTE' def Test(self): # Section 6.3.4 of E1.20 self.AddExpectedResults([ TimeoutResult(), UnsupportedResult() ]) self.SendRawDiscovery(ROOT_DEVICE, self.pid, 'x') class UnMuteDevice(ResponderTestFixture): """UnMute device and verify response.""" CATEGORY = TestCategory.NETWORK_MANAGEMENT PID = 'DISC_UN_MUTE' PROVIDES = ['unmute_supported'] REQUIRES = ['mute_control_fields'] def Test(self): self.AddExpectedResults([ self.AckDiscoveryResult(), UnsupportedResult() ]) self.SendDiscovery(ROOT_DEVICE, self.pid) def VerifyResult(self, response, fields): supported = (response.response_code != OlaClient.RDM_PLUGIN_DISCOVERY_NOT_SUPPORTED) self.SetProperty('unmute_supported', supported) if supported: if fields['control_field'] != self.Property('mute_control_fields'): self.AddWarning( "Mute / Unmute control fields don't match. 0x%hx != 0x%hx" % (self.Property('mute_control_fields'), fields['control_field'])) class UnMuteDeviceWithData(ResponderTestFixture): """UnMute device info with param data.""" CATEGORY = TestCategory.NETWORK_MANAGEMENT PID = 'DISC_UN_MUTE' def Test(self): # Section 6.3.4 of E1.20 self.AddExpectedResults([ TimeoutResult(), UnsupportedResult() ]) self.SendRawDiscovery(ROOT_DEVICE, self.pid, 'x') class RequestsWhileUnmuted(ResponderTestFixture): """Unmute the device, send a GET DEVICE_INFO request, mute device again.""" CATEGORY = TestCategory.NETWORK_MANAGEMENT PID = 'DISC_UN_MUTE' # This requires sub_device_count so that we know DEVICE_INFO is supported REQUIRES = ['mute_supported', 'unmute_supported', 'sub_device_count'] def Test(self): if not (self.Property('unmute_supported') and self.Property('mute_supported')): self.SetNotRun('Controller does not support mute / unmute commands') return self.AddExpectedResults(self.AckDiscoveryResult(action=self.GetDeviceInfo)) self.SendDiscovery(ROOT_DEVICE, self.pid) def GetDeviceInfo(self): device_info_pid = self.LookupPid('DEVICE_INFO') self.AddExpectedResults(AckGetResult(device_info_pid.value)) self.SendGet(ROOT_DEVICE, device_info_pid) def ResetState(self): # Mute the device again mute_pid = self.LookupPid('DISC_MUTE') self.SendDiscovery(ROOT_DEVICE, mute_pid) self._wrapper.Run() # Invalid DISCOVERY_PIDs # ----------------------------------------------------------------------------- class InvalidDiscoveryPID(ResponderTestFixture): """Send an invalid Discovery CC PID, see E1.20 6.3.4""" CATEGORY = TestCategory.ERROR_CONDITIONS # We need to mock out a PID here class MockPid(object): def __init__(self): self.value = 0x000f def ValidateAddressing(request_params, request_type): return True def __str__(self): return '0x%04hx' % self.value def Test(self): mock_pid = self.MockPid() self.AddExpectedResults([ TimeoutResult(), UnsupportedResult() ]) self.SendRawDiscovery(ROOT_DEVICE, mock_pid) # DUB Tests # ----------------------------------------------------------------------------- class MuteAllDevices(ResponderTestFixture): """Mute all devices, so we can perform DUB tests""" PID = 'DISC_MUTE' REQUIRES = ['mute_supported'] # This is a fake property used to ensure this tests runs before the DUB tests. PROVIDES = ['global_mute'] def Test(self): # Set the fake property self.SetProperty(self.PROVIDES[0], True) if not (self.Property('mute_supported')): self.SetNotRun('RDM Controller does not support DISCOVERY commands') self.Stop() return self.AddExpectedResults([ BroadcastResult(), UnsupportedResult() ]) self.SendDirectedDiscovery( UID.AllDevices(), PidStore.ROOT_DEVICE, self.pid) class DUBFullTree(TestMixins.DiscoveryMixin, ResponderTestFixture): """Confirm the device responds within the entire DUB range.""" CATEGORY = TestCategory.NETWORK_MANAGEMENT PROVIDES = ['dub_supported'] def LowerBound(self): return UID(0, 0) def UpperBound(self): return UID.AllDevices() def DUBResponseCode(self, response_code): self.SetProperty( 'dub_supported', response_code != OlaClient.RDM_PLUGIN_DISCOVERY_NOT_SUPPORTED) class DUBManufacturerTree(TestMixins.DiscoveryMixin, ResponderTestFixture): """Confirm the device responds within it's manufacturer DUB range.""" CATEGORY = TestCategory.NETWORK_MANAGEMENT REQUIRES = ['dub_supported'] + TestMixins.DiscoveryMixin.REQUIRES def LowerBound(self): return UID(self.uid.manufacturer_id, 0) def UpperBound(self): return UID.VendorcastAddress(self.uid.manufacturer_id) class DUBSingleUID(TestMixins.DiscoveryMixin, ResponderTestFixture): """Confirm the device responds to just it's own range.""" CATEGORY = TestCategory.NETWORK_MANAGEMENT CATEGORY = TestCategory.NETWORK_MANAGEMENT REQUIRES = ['dub_supported'] + TestMixins.DiscoveryMixin.REQUIRES def LowerBound(self): return self.uid def UpperBound(self): return self.uid class DUBSingleLowerUID(TestMixins.DiscoveryMixin, ResponderTestFixture): """DUB from - 1 to - 1.""" CATEGORY = TestCategory.NETWORK_MANAGEMENT CATEGORY = TestCategory.NETWORK_MANAGEMENT REQUIRES = ['dub_supported'] + TestMixins.DiscoveryMixin.REQUIRES def LowerBound(self): return UID.PreviousUID(self.uid) def UpperBound(self): return UID.PreviousUID(self.uid) def ExpectResponse(self): return False class DUBSingleUpperUID(TestMixins.DiscoveryMixin, ResponderTestFixture): """DUB from + 1 to + 1.""" CATEGORY = TestCategory.NETWORK_MANAGEMENT CATEGORY = TestCategory.NETWORK_MANAGEMENT REQUIRES = ['dub_supported'] + TestMixins.DiscoveryMixin.REQUIRES def LowerBound(self): return UID.NextUID(self.uid) def UpperBound(self): return UID.NextUID(self.uid) def ExpectResponse(self): return False class DUBAffirmativeLowerBound(TestMixins.DiscoveryMixin, ResponderTestFixture): """DUB from to ffff:ffffffff.""" CATEGORY = TestCategory.NETWORK_MANAGEMENT REQUIRES = ['dub_supported'] + TestMixins.DiscoveryMixin.REQUIRES def LowerBound(self): return self.uid def UpperBound(self): return UID.AllDevices() class DUBNegativeLowerBound(TestMixins.DiscoveryMixin, ResponderTestFixture): """DUB from + 1 to ffff:ffffffff.""" CATEGORY = TestCategory.NETWORK_MANAGEMENT REQUIRES = ['dub_supported'] + TestMixins.DiscoveryMixin.REQUIRES def LowerBound(self): return UID.NextUID(self.uid) def UpperBound(self): return UID.AllDevices() def ExpectResponse(self): return False class DUBAffirmativeUpperBound(TestMixins.DiscoveryMixin, ResponderTestFixture): """DUB from 0000:00000000 to .""" CATEGORY = TestCategory.NETWORK_MANAGEMENT REQUIRES = ['dub_supported'] + TestMixins.DiscoveryMixin.REQUIRES def LowerBound(self): return UID(0, 0) def UpperBound(self): return self.uid class DUBNegativeUpperBound(TestMixins.DiscoveryMixin, ResponderTestFixture): """DUB from 0000:00000000 to - 1.""" CATEGORY = TestCategory.NETWORK_MANAGEMENT REQUIRES = ['dub_supported'] + TestMixins.DiscoveryMixin.REQUIRES def LowerBound(self): return UID(0, 0) def UpperBound(self): return UID.PreviousUID(self.uid) def ExpectResponse(self): return False class DUBDifferentManufacturer(TestMixins.DiscoveryMixin, ResponderTestFixture): """DUB with a different manufacturer's range.""" CATEGORY = TestCategory.NETWORK_MANAGEMENT REQUIRES = ['dub_supported'] + TestMixins.DiscoveryMixin.REQUIRES def LowerBound(self): return UID(self.uid.manufacturer_id - 1, 0) def UpperBound(self): return UID(self.uid.manufacturer_id - 1, 0xffffffff) def ExpectResponse(self): return False class DUBSignedComparisons(TestMixins.DiscoveryMixin, ResponderTestFixture): """DUB to check UIDs aren't using signed values.""" CATEGORY = TestCategory.NETWORK_MANAGEMENT REQUIRES = ['dub_supported'] + TestMixins.DiscoveryMixin.REQUIRES def LowerBound(self): # Section 5.1 of E1.20 limits the manufacturer ID range to 0 - 0x7fff so # this should be safe for all cases. return UID(0x8000, 0) def UpperBound(self): return UID.AllDevices() def ExpectResponse(self): return False class DUBNegativeVendorcast(TestMixins.DiscoveryMixin, ResponderTestFixture): """DUB to another manufacturer's vendorcast address.""" CATEGORY = TestCategory.NETWORK_MANAGEMENT REQUIRES = ['dub_supported'] + TestMixins.DiscoveryMixin.REQUIRES def LowerBound(self): return UID(0, 0) def UpperBound(self): return UID.AllDevices() def ExpectResponse(self): return False def Target(self): return UID(self.uid.manufacturer_id - 1, 0xffffffff) class DUBPositiveVendorcast(TestMixins.DiscoveryMixin, ResponderTestFixture): """DUB to this manufacturer's vendorcast address.""" CATEGORY = TestCategory.NETWORK_MANAGEMENT REQUIRES = ['dub_supported'] + TestMixins.DiscoveryMixin.REQUIRES def LowerBound(self): return UID(0, 0) def UpperBound(self): return UID.AllDevices() def Target(self): return UID(self.uid.manufacturer_id, 0xffffffff) class DUBPositiveUnicast(TestMixins.DiscoveryMixin, ResponderTestFixture): """DUB to the device's address.""" CATEGORY = TestCategory.NETWORK_MANAGEMENT REQUIRES = ['dub_supported'] + TestMixins.DiscoveryMixin.REQUIRES def LowerBound(self): return UID(0, 0) def UpperBound(self): return UID.AllDevices() def Target(self): return self.uid class DUBInvertedFullTree(TestMixins.DiscoveryMixin, ResponderTestFixture): """DUB from ffff:ffffffff to 0000:00000000.""" CATEGORY = TestCategory.NETWORK_MANAGEMENT REQUIRES = ['dub_supported'] + TestMixins.DiscoveryMixin.REQUIRES def LowerBound(self): return UID.AllDevices() def UpperBound(self): return UID(0, 0) def ExpectResponse(self): return False class DUBInvertedRange(TestMixins.DiscoveryMixin, ResponderTestFixture): """DUB from + 1 to - 1.""" CATEGORY = TestCategory.NETWORK_MANAGEMENT REQUIRES = ['dub_supported'] + TestMixins.DiscoveryMixin.REQUIRES def LowerBound(self): return UID.NextUID(self.uid) def UpperBound(self): return UID.PreviousUID(self.uid) def ExpectResponse(self): return False class DUBInvertedLowerUID(TestMixins.DiscoveryMixin, ResponderTestFixture): """DUB from to - 1.""" CATEGORY = TestCategory.NETWORK_MANAGEMENT REQUIRES = ['dub_supported'] + TestMixins.DiscoveryMixin.REQUIRES def LowerBound(self): return self.uid def UpperBound(self): return UID.PreviousUID(self.uid) def ExpectResponse(self): return False class DUBInvertedUpperUID(TestMixins.DiscoveryMixin, ResponderTestFixture): """DUB from + 1 to .""" CATEGORY = TestCategory.NETWORK_MANAGEMENT REQUIRES = ['dub_supported'] + TestMixins.DiscoveryMixin.REQUIRES def LowerBound(self): return UID.NextUID(self.uid) def UpperBound(self): return self.uid def ExpectResponse(self): return False # Device Info tests # ----------------------------------------------------------------------------- class DeviceInfoTest(object): """The base device info test class.""" PID = 'DEVICE_INFO' FIELDS = ['device_model', 'product_category', 'software_version', 'dmx_footprint', 'current_personality', 'personality_count', 'dmx_start_address', 'sub_device_count', 'sensor_count'] FIELD_VALUES = { 'protocol_major': 1, 'protocol_minor': 0, } class GetDeviceInfo(ResponderTestFixture, DeviceInfoTest): """GET device info & verify.""" CATEGORY = TestCategory.CORE PROVIDES = [ 'current_personality', 'dmx_footprint', 'dmx_start_address', 'personality_count', 'sensor_count', 'software_version', 'sub_device_count', ] def Test(self): self.AddExpectedResults(self.AckGetResult( field_names=self.FIELDS, field_values=self.FIELD_VALUES)) self.SendGet(ROOT_DEVICE, self.pid) def VerifyResult(self, unused_response, fields): """Check the footprint, personalities & sub devices.""" for property in self.PROVIDES: self.SetPropertyFromDict(fields, property) footprint = fields['dmx_footprint'] if footprint > MAX_DMX_ADDRESS: self.AddWarning('DMX Footprint of %d, was more than 512' % footprint) if footprint > 0: personality_count = fields['personality_count'] current_personality = fields['current_personality'] if personality_count == 0: self.AddAdvisory('DMX Footprint non 0, but no personalities listed') if current_personality == 0: self.AddWarning('Current personality should be >= 1, was %d' % current_personality) elif current_personality > personality_count: self.AddWarning('Current personality (%d) should be less than the ' 'personality count (%d)' % (current_personality, personality_count)) start_address = fields['dmx_start_address'] if (start_address == 0 or (start_address > MAX_DMX_ADDRESS and start_address != RDM_ZERO_FOOTPRINT_DMX_ADDRESS)): self.AddWarning('Invalid DMX address %d in DEVICE_INFO' % start_address) sub_devices = fields['sub_device_count'] if sub_devices > 512: self.AddWarning('Sub device count > 512, was %d' % sub_devices) class GetDeviceInfoWithData(ResponderTestFixture, DeviceInfoTest): """GET device info with param data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PROVIDES = ['supports_over_sized_pdl'] def Test(self): self.AddExpectedResults([ self.NackGetResult(RDMNack.NR_FORMAT_ERROR), self.AckGetResult( field_names=self.FIELDS, field_values=self.FIELD_VALUES, warning='Get %s with data returned an ack' % self.pid.name) ]) self.SendRawGet(ROOT_DEVICE, self.pid, 'x') def VerifyResult(self, response, fields): self.SetProperty('supports_over_sized_pdl', True) class GetMaxPacketSize(ResponderTestFixture, DeviceInfoTest): """Check if the responder can handle a packet of the maximum size.""" CATEGORY = TestCategory.ERROR_CONDITIONS MAX_PDL = 231 PROVIDES = ['supports_max_sized_pdl'] def Test(self): self.AddExpectedResults([ self.NackGetResult(RDMNack.NR_FORMAT_ERROR), self.NackGetResult(RDMNack.NR_PACKET_SIZE_UNSUPPORTED), self.AckGetResult(), # Some crazy devices continue to ack InvalidResponse( advisory='Responder returned an invalid response to a command with ' 'PDL of %d' % self.MAX_PDL ), TimeoutResult( advisory='Responder timed out to a command with PDL of %d' % self.MAX_PDL), ]) self.SendRawGet(ROOT_DEVICE, self.pid, 'x' * self.MAX_PDL) def VerifyResult(self, response, fields): ok = response not in [OlaClient.RDM_INVALID_RESPONSE, OlaClient.RDM_TIMEOUT] self.SetProperty('supports_max_sized_pdl', ok) class DetermineMaxPacketSize(ResponderTestFixture, DeviceInfoTest): """Binary search the pdl length space to determine the max packet size.""" CATEGORY = TestCategory.ERROR_CONDITIONS REQUIRES = ['supports_over_sized_pdl', 'supports_max_sized_pdl'] def Test(self): if self.Property('supports_max_sized_pdl'): self.SetNotRun('Device supports full sized packet') return self._lower = 1 self._upper = GetMaxPacketSize.MAX_PDL self.SendGet() def SendGet(self): if self._lower + 1 == self._upper: self.AddWarning('Max PDL supported is < %d, was %d' % (GetMaxPacketSize.MAX_PDL, self._lower)) self.Stop() return self._current = (self._lower + self._upper) / 2 self.AddExpectedResults([ self.NackGetResult(RDMNack.NR_FORMAT_ERROR, action=self.GetPassed), self.AckGetResult(action=self.GetPassed), InvalidResponse(action=self.GetFailed), TimeoutResult(action=self.GetFailed), ]) self.SendRawGet(ROOT_DEVICE, self.pid, 'x' * self._current) def GetPassed(self): self._lower = self._current self.SendGet() def GetFailed(self): self._upper = self._current self.SendGet() class SetDeviceInfo(ResponderTestFixture, DeviceInfoTest): """SET device info.""" CATEGORY = TestCategory.ERROR_CONDITIONS def Test(self): self.AddExpectedResults(TestMixins.UnsupportedSetNacks(self.pid)) self.SendRawSet(ROOT_DEVICE, self.pid) class AllSubDevicesGetDeviceInfo(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get Device Info to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'DEVICE_INFO' # Supported Parameters Tests & Mixin # ----------------------------------------------------------------------------- class GetSupportedParameters(ResponderTestFixture): """GET supported parameters.""" CATEGORY = TestCategory.CORE PID = 'SUPPORTED_PARAMETERS' PROVIDES = ['manufacturer_parameters', 'supported_parameters', 'acks_supported_parameters'] # Declaring support for any of these is a warning: MANDATORY_PIDS = ['SUPPORTED_PARAMETERS', 'PARAMETER_DESCRIPTION', 'DEVICE_INFO', 'SOFTWARE_VERSION_LABEL', 'DMX_START_ADDRESS', 'IDENTIFY_DEVICE'] # Banned PIDs, these are PID values that can not appear in the list of # supported parameters (these are used for discovery) BANNED_PIDS = ['DISC_UNIQUE_BRANCH', 'DISC_MUTE', 'DISC_UN_MUTE'] # If responders support any of the PIDs in these groups, they should really # support all of them. PID_GROUPS = [ ('PROXIED_DEVICE_COUNT', 'PROXIED_DEVICES'), ('LANGUAGE_CAPABILITIES', 'LANGUAGE'), ('DMX_PERSONALITY', 'DMX_PERSONALITY_DESCRIPTION'), ('SENSOR_DEFINITION', 'SENSOR_VALUE'), ('SELF_TEST_DESCRIPTION', 'PERFORM_SELFTEST'), ] # If the first PID is supported, the PIDs in the group must be. PID_DEPENDENCIES = [ ('RECORD_SENSORS', ['SENSOR_VALUE']), ('DEFAULT_SLOT_VALUE', ['SLOT_DESCRIPTION']), ('CURVE', ['CURVE_DESCRIPTION']), ('OUTPUT_RESPONSE_TIME', ['OUTPUT_RESPONSE_TIME_DESCRIPTION']), ('MODULATION_FREQUENCY', ['MODULATION_FREQUENCY_DESCRIPTION']), ('LOCK_STATE', ['LOCK_STATE_DESCRIPTION']), ] # If any of the PIDs in the group are supported, the first one must be too. PID_REVERSE_DEPENDENCIES = [ ('LIST_INTERFACES', ['INTERFACE_LABEL', 'INTERFACE_HARDWARE_ADDRESS_TYPE1', 'IPV4_DHCP_MODE', 'IPV4_ZEROCONF_MODE', 'IPV4_CURRENT_ADDRESS', 'IPV4_STATIC_ADDRESS', 'INTERFACE_RENEW_DHCP', 'INTERFACE_RELEASE_DHCP', 'INTERFACE_APPLY_CONFIGURATION', 'IPV4_DEFAULT_ROUTE', 'DNS_IPV4_NAME_SERVER', 'DNS_HOSTNAME', 'DNS_DOMAIN_NAME']), ] def Test(self): self.AddExpectedResults([ # TODO(simon): We should cross check this against support for anything # more than the required set of parameters at the end of all tests. self.NackGetResult(RDMNack.NR_UNKNOWN_PID), self.AckGetResult(), ]) self.SendGet(ROOT_DEVICE, self.pid) def VerifyResult(self, response, fields): if not response.WasAcked(): self.SetProperty('manufacturer_parameters', []) self.SetProperty('supported_parameters', []) self.SetProperty('acks_supported_parameters', False) return self.SetProperty('acks_supported_parameters', True) mandatory_pids = {} for p in self.MANDATORY_PIDS: pid = self.LookupPid(p) mandatory_pids[pid.value] = pid banned_pids = {} for p in self.BANNED_PIDS: pid = self.LookupPid(p) banned_pids[pid.value] = pid supported_parameters = [] manufacturer_parameters = [] count_by_pid = {} for item in fields['params']: param_id = item['param_id'] count_by_pid[param_id] = count_by_pid.get(param_id, 0) + 1 if param_id in banned_pids: self.AddWarning('%s listed in supported parameters' % banned_pids[param_id].name) continue if param_id in mandatory_pids: self.AddAdvisory('%s listed in supported parameters' % mandatory_pids[param_id].name) continue supported_parameters.append(param_id) if (param_id >= RDM_MANUFACTURER_PID_MIN and param_id <= RDM_MANUFACTURER_PID_MAX): manufacturer_parameters.append(param_id) # Check for duplicate PIDs for pid, count in count_by_pid.iteritems(): if count > 1: pid_obj = self.LookupPidValue(pid) if pid_obj: self.AddAdvisory('%s listed %d times in supported parameters' % (pid_obj, count)) else: self.AddAdvisory('PID 0x%hx listed %d times in supported parameters' % (pid, count)) self.SetProperty('manufacturer_parameters', manufacturer_parameters) self.SetProperty('supported_parameters', supported_parameters) for pid_names in self.PID_GROUPS: supported_pids = [] unsupported_pids = [] for pid_name in pid_names: pid = self.LookupPid(pid_name) if pid.value in supported_parameters: supported_pids.append(pid_name) else: unsupported_pids.append(pid_name) if supported_pids and unsupported_pids: self.AddAdvisory( '%s supported but %s is not' % (','.join(supported_pids), ','.join(unsupported_pids))) for p, dependent_pids in self.PID_DEPENDENCIES: if self.LookupPid(p).value not in supported_parameters: continue unsupported_pids = [] for pid_name in dependent_pids: pid = self.LookupPid(pid_name) if pid is None: self.SetBroken('Failed to lookup info for PID %s' % pid_name) return if pid.value not in supported_parameters: unsupported_pids.append(pid_name) if unsupported_pids: self.AddAdvisory('%s supported but %s is not' % (p, ','.join(unsupported_pids))) for p, rev_dependent_pids in self.PID_REVERSE_DEPENDENCIES: if self.LookupPid(p).value in supported_parameters: continue dependent_pids = [] for pid_name in rev_dependent_pids: pid = self.LookupPid(pid_name) if pid is None: self.SetBroken('Failed to lookup info for PID %s' % pid_name) return if pid.value in supported_parameters: dependent_pids.append(pid_name) if (dependent_pids and (self.LookupPid(p).value in supported_parameters)): self.AddAdvisory('%s supported but %s is not' % (','.join(unsupported_pids), p)) class GetSupportedParametersWithData(ResponderTestFixture): """GET supported parameters with param data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'SUPPORTED_PARAMETERS' REQUIRES = ['acks_supported_parameters'] def Test(self): if self.Property('acks_supported_parameters'): self.AddExpectedResults([ self.NackGetResult(RDMNack.NR_FORMAT_ERROR), self.AckGetResult( warning='Get %s with data returned an ack' % self.pid.name) ]) else: self.AddExpectedResults(self.NackGetResult(RDMNack.NR_UNKNOWN_PID)) self.SendRawGet(ROOT_DEVICE, self.pid, 'foo') class SetSupportedParameters(ResponderTestFixture): """Attempt to SET supported parameters.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'SUPPORTED_PARAMETERS' def Test(self): self.AddExpectedResults(TestMixins.UnsupportedSetNacks(self.pid)) self.SendRawSet(ROOT_DEVICE, self.pid) class AllSubDevicesGetSupportedParameters(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get SUPPORTED_PARAMETERS to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'SUPPORTED_PARAMETERS' class GetSubDeviceSupportedParameters(ResponderTestFixture): """Check that SUPPORTED_PARAMETERS is consistent across sub devices.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'SUPPORTED_PARAMETERS' REQUIRES = ['sub_device_addresses'] PROVIDES = ['sub_device_supported_parameters'] # E1.37, 2.1 Sub devices are required to support these. MANDATORY_PIDS = ['SUPPORTED_PARAMETERS', 'DEVICE_INFO', 'SOFTWARE_VERSION_LABEL', 'IDENTIFY_DEVICE'] def Test(self): self._sub_devices = self.Property('sub_device_addresses').keys() self._sub_devices.reverse() self._params = {} self._GetSupportedParams() def _GetSupportedParams(self): if not self._sub_devices: self._CheckForConsistency() self.Stop() return self.AddExpectedResults(self.AckGetResult(action=self._GetSupportedParams)) self.SendGet(self._sub_devices[-1], self.pid) def VerifyResult(self, response, fields): sub_device = self._sub_devices.pop() supported_params = set() for p in fields['params']: supported_params.add(p['param_id']) self._params[sub_device] = supported_params def _CheckForConsistency(self): if not self._params: return supported_pids = set() for pids in self._params.itervalues(): if not supported_pids: supported_pids = pids elif supported_pids != pids: self.SetFailed('SUPPORTED_PARAMETERS for sub-devices do not match') return mandatory_pids = set(self.LookupPid(p).value for p in self.MANDATORY_PIDS) missing_pids = mandatory_pids - supported_pids if missing_pids: self.SetFailed("Missing PIDs %s from sub device's supported pid list" % ', '.join('0x%04hx' % p for p in missing_pids)) return self.SetProperty('sub_device_supported_parameters', supported_pids) # Sub Devices Test # ----------------------------------------------------------------------------- class FindSubDevices(ResponderTestFixture): """Locate the sub devices by sending DEVICE_INFO messages.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'DEVICE_INFO' PROVIDES = ['sub_device_addresses', 'sub_device_footprints'] REQUIRES = ['sub_device_count'] def Test(self): self._device_count = self.Property('sub_device_count') self._sub_device_addresses = {} # Index to start address mapping self._sub_device_footprints = {} # Index to footprint mapping self._current_index = 0 # the current sub device we're trying to query self._CheckForSubDevice() def _CheckForSubDevice(self): # For each supported param message we should either see a sub device out of # range or an ack if len(self._sub_device_addresses) == self._device_count: if self._device_count == 0: self.SetNotRun('No sub devices declared') self.SetProperty('sub_device_addresses', self._sub_device_addresses) self.SetProperty('sub_device_footprints', self._sub_device_footprints) self.Stop() return if self._current_index >= PidStore.MAX_VALID_SUB_DEVICE: self.SetFailed('Only found %d of %d sub devices' % (len(self._sub_device_addresses), self._device_count)) self.Stop() return self.AddExpectedResults([ self.NackGetResult(RDMNack.NR_SUB_DEVICE_OUT_OF_RANGE, action=self._CheckForSubDevice), self.AckGetResult(action=self._CheckForSubDevice) ]) self._current_index += 1 self.SendGet(self._current_index, self.pid) def VerifyResult(self, response, fields): if response.WasAcked(): if fields['sub_device_count'] != self._device_count: self.SetFailed( 'For sub-device %d, DEVICE_INFO reported %d sub devices ' ' but the root device reported %s. See section 10.5.1' % (self._current_index, fields['sub_device_count'], self._device_count)) self.Stop() self._sub_device_addresses[self._current_index] = ( fields['dmx_start_address']) self._sub_device_footprints[self._current_index] = fields['dmx_footprint'] # Clear Status ID # ----------------------------------------------------------------------------- class GetClearStatusMessages(TestMixins.UnsupportedGetMixin, OptionalParameterTestFixture): """GET clear status id.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'CLEAR_STATUS_ID' class ClearStatusMessagesWithData(TestMixins.SetWithDataMixin, OptionalParameterTestFixture): """Clear the status message queue with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'CLEAR_STATUS_ID' class ClearStatusMessages(TestMixins.SetWithNoDataMixin, OptionalParameterTestFixture): """Clear the status message queue.""" CATEGORY = TestCategory.STATUS_COLLECTION PID = 'CLEAR_STATUS_ID' def Test(self): # I don't believe there is a reliable way to check that the queue is # cleared. Note that this PID should only clear status messages, not # responses to ACK_TIMERS so we can't check if the message count is 0. self.AddIfSetSupported(self.AckSetResult()) self.SendSet(ROOT_DEVICE, self.pid, []) # Parameter Description # ----------------------------------------------------------------------------- class GetParamDescription(ResponderTestFixture): """Check that GET parameter description works for any manufacturer params.""" CATEGORY = TestCategory.RDM_INFORMATION PID = 'PARAMETER_DESCRIPTION' REQUIRES = ['manufacturer_parameters'] def Test(self): self.params = self.Property('manufacturer_parameters')[:] if len(self.params) == 0: self.SetNotRun('No manufacturer params found') return self._GetParam() def _GetParam(self): if len(self.params) == 0: self.Stop() return self.AddExpectedResults( self.AckGetResult(action=self._GetParam)) self.current_param = self.params.pop() self.SendGet(ROOT_DEVICE, self.pid, [self.current_param]) def VerifyResult(self, response, fields): if not response.WasAcked(): return if self.current_param != fields['pid']: self.SetFailed('Request for pid 0x%hx returned pid 0x%hx' % (self.current_param, fields['pid'])) if fields['type'] != 0: self.AddWarning('type field in parameter description is not 0, was %d' % fields['type']) if fields['command_class'] > 3: self.AddWarning( 'command class field in parameter description should be 1, 2 or 3, ' 'was %d' % fields['command_class']) if ContainsUnprintable(fields['description']): self.AddAdvisory( 'Description field in %s contains unprintable characters, was %s' % (self.PID, fields['description'].encode('string-escape'))) class GetParamDescriptionForNonManufacturerPid(ResponderTestFixture): """GET parameter description for a non-manufacturer pid.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'PARAMETER_DESCRIPTION' REQUIRES = ['manufacturer_parameters'] def Test(self): device_info_pid = self.LookupPid('DEVICE_INFO') results = [ self.NackGetResult(RDMNack.NR_UNKNOWN_PID), self.NackGetResult( RDMNack.NR_DATA_OUT_OF_RANGE, advisory='Parameter Description appears to be supported but no' 'manufacturer PIDs were declared'), ] if self.Property('manufacturer_parameters'): results = self.NackGetResult(RDMNack.NR_DATA_OUT_OF_RANGE) self.AddExpectedResults(results) self.SendGet(ROOT_DEVICE, self.pid, [device_info_pid.value]) class GetParamDescriptionWithData(ResponderTestFixture): """GET parameter description with param data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'PARAMETER_DESCRIPTION' REQUIRES = ['manufacturer_parameters'] def Test(self): results = [ self.NackGetResult(RDMNack.NR_UNKNOWN_PID), self.NackGetResult(RDMNack.NR_FORMAT_ERROR, advisory='Parameter Description appears to be ' 'supported but no manufacturer PIDs were ' 'declared'), ] if self.Property('manufacturer_parameters'): results = self.NackGetResult(RDMNack.NR_FORMAT_ERROR) self.AddExpectedResults(results) self.SendRawGet(ROOT_DEVICE, self.pid, 'foo') class SetParamDescription(TestMixins.UnsupportedSetMixin, ResponderTestFixture): """SET the parameter description.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'PARAMETER_DESCRIPTION' class AllSubDevicesGetParamDescription(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get PARAMETER_DESCRIPTION to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'PARAMETER_DESCRIPTION' DATA = [0x8000] # Proxied Device Count # ----------------------------------------------------------------------------- class GetProxiedDeviceCount(OptionalParameterTestFixture): """GET the proxied device count.""" CATEGORY = TestCategory.NETWORK_MANAGEMENT PID = 'PROXIED_DEVICE_COUNT' REQUIRES = ['proxied_devices'] def Test(self): self.AddIfGetSupported(self.AckGetResult()) self.SendGet(ROOT_DEVICE, self.pid) def VerifyResult(self, response, unpacked_data): if not response.WasAcked(): return proxied_devices = self.Property('proxied_devices') if proxied_devices is None: self.AddWarning( 'PROXIED_DEVICE_COUNT ack\'ed but PROXIED_DEVICES didn\'t') return if not unpacked_data['list_changed']: # We expect the count to match the length of the list previously returned if unpacked_data['device_count'] != len(proxied_devices): self.SetFailed( 'Proxied device count doesn\'t match number of devices returned') class GetProxiedDeviceCountWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """GET the proxied device count with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'PROXIED_DEVICE_COUNT' class SetProxiedDeviceCount(TestMixins.UnsupportedSetMixin, ResponderTestFixture): """SET the count of proxied devices.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'PROXIED_DEVICE_COUNT' class AllSubDevicesGetProxiedDeviceCount(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get PROXIED_DEVICE_COUNT to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'PROXIED_DEVICE_COUNT' # Proxied Devices # ----------------------------------------------------------------------------- class GetProxiedDevices(TestMixins.GetMixin, OptionalParameterTestFixture): """GET the list of proxied devices.""" CATEGORY = TestCategory.NETWORK_MANAGEMENT PID = 'PROXIED_DEVICES' EXPECTED_FIELDS = ['uids'] PROVIDES = ['proxied_devices'] class GetProxiedDevicesWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """GET the list of proxied devices with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'PROXIED_DEVICES' class SetProxiedDevices(TestMixins.UnsupportedSetMixin, ResponderTestFixture): """SET the list of proxied devices.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'PROXIED_DEVICES' class AllSubDevicesGetProxiedDevices(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get PROXIED_DEVICES to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'PROXIED_DEVICES' # Comms Status # ----------------------------------------------------------------------------- class GetCommsStatus(OptionalParameterTestFixture): """GET the comms status.""" CATEGORY = TestCategory.STATUS_COLLECTION PID = 'COMMS_STATUS' def Test(self): self.AddIfGetSupported(self.AckGetResult()) self.SendGet(ROOT_DEVICE, self.pid) class GetCommsStatusWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """GET the comms status with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'COMMS_STATUS' class ClearCommsStatus(OptionalParameterTestFixture): """Clear the comms status.""" CATEGORY = TestCategory.STATUS_COLLECTION PID = 'COMMS_STATUS' def Test(self): self.AddIfSetSupported(self.AckSetResult(action=self.VerifySet)) self.SendSet(ROOT_DEVICE, self.pid) def VerifySet(self): self.AddIfGetSupported( self.AckGetResult(field_values={ 'short_message': 0, 'length_mismatch': 0, 'checksum_fail': 0 })) self.SendGet(ROOT_DEVICE, self.pid) class ClearCommsStatusWithData(TestMixins.SetWithDataMixin, OptionalParameterTestFixture): """Clear the comms status with data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'COMMS_STATUS' class AllSubDevicesGetClearCommsStatus(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get COMMS_STATUS to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'COMMS_STATUS' # Product Detail Id List # ----------------------------------------------------------------------------- class GetProductDetailIdList(OptionalParameterTestFixture): """GET the list of product detail ids.""" CATEGORY = TestCategory.PRODUCT_INFORMATION PID = 'PRODUCT_DETAIL_ID_LIST' def Test(self): self.AddIfGetSupported(self.AckGetResult(field_names=['detail_ids'])) self.SendGet(ROOT_DEVICE, self.pid) class GetProductDetailIdListWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """GET product detail id list with param data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'PRODUCT_DETAIL_ID_LIST' class SetProductDetailIdList(TestMixins.UnsupportedSetMixin, ResponderTestFixture): """SET product detail id list.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'PRODUCT_DETAIL_ID_LIST' class AllSubDevicesGetProductDetailIdList(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get PRODUCT_DETAIL_ID_LIST to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'PRODUCT_DETAIL_ID_LIST' # Device Model Description # ----------------------------------------------------------------------------- class GetDeviceModelDescription(TestMixins.GetStringMixin, OptionalParameterTestFixture): """GET the device model description.""" CATEGORY = TestCategory.PRODUCT_INFORMATION PID = 'DEVICE_MODEL_DESCRIPTION' EXPECTED_FIELDS = ['description'] PROVIDES = ['model_description'] class GetDeviceModelDescriptionWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """Get device model description with param data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'DEVICE_MODEL_DESCRIPTION' class SetDeviceModelDescription(TestMixins.UnsupportedSetMixin, OptionalParameterTestFixture): """Attempt to SET the device model description with no data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'DEVICE_MODEL_DESCRIPTION' class SetDeviceModelDescriptionWithData(TestMixins.UnsupportedSetMixin, OptionalParameterTestFixture): """SET the device model description with data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'DEVICE_MODEL_DESCRIPTION' DATA = 'FOO BAR' class AllSubDevicesGetModelDescription(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get DEVICE_MODEL_DESCRIPTION to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'DEVICE_MODEL_DESCRIPTION' # Manufacturer Label # ----------------------------------------------------------------------------- class GetManufacturerLabel(TestMixins.GetStringMixin, OptionalParameterTestFixture): """GET the manufacturer label.""" CATEGORY = TestCategory.PRODUCT_INFORMATION PID = 'MANUFACTURER_LABEL' EXPECTED_FIELDS = ['label'] PROVIDES = ['manufacturer_label'] class GetManufacturerLabelWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """Get manufacturer label with param data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'MANUFACTURER_LABEL' class SetManufacturerLabel(TestMixins.UnsupportedSetMixin, OptionalParameterTestFixture): """Attempt to SET the manufacturer label with no data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'MANUFACTURER_LABEL' class SetManufacturerLabelWithData(TestMixins.UnsupportedSetMixin, OptionalParameterTestFixture): """SET the manufacturer label with data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'MANUFACTURER_LABEL' DATA = 'FOO BAR' class AllSubDevicesGetManufacturerLabel(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get MANUFACTURER_LABEL to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'MANUFACTURER_LABEL' # Device Label # ----------------------------------------------------------------------------- class GetDeviceLabel(TestMixins.GetStringMixin, OptionalParameterTestFixture): """GET the device label.""" CATEGORY = TestCategory.PRODUCT_INFORMATION PID = 'DEVICE_LABEL' PROVIDES = ['device_label'] EXPECTED_FIELDS = ['label'] class GetDeviceLabelWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """GET the device label with param data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'DEVICE_LABEL' class SetDeviceLabel(TestMixins.SetLabelMixin, OptionalParameterTestFixture): """SET the device label.""" CATEGORY = TestCategory.PRODUCT_INFORMATION PID = 'DEVICE_LABEL' REQUIRES = ['device_label'] PROVIDES = ['set_device_label_supported'] def OldValue(self): return self.Property('device_label') class AllSubDevicesGetDeviceLabel(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get DEVICE_LABEL to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'DEVICE_LABEL' class SetVendorcastDeviceLabel(TestMixins.NonUnicastSetLabelMixin, OptionalParameterTestFixture): """SET the device label using the vendorcast address.""" CATEGORY = TestCategory.PRODUCT_INFORMATION PID = 'DEVICE_LABEL' REQUIRES = ['device_label', 'set_device_label_supported'] TEST_LABEL = 'vendorcast label' def Uid(self): return UID.VendorcastAddress(self._uid.manufacturer_id) def OldValue(self): return self.Property('device_label') class SetBroadcastDeviceLabel(TestMixins.NonUnicastSetLabelMixin, OptionalParameterTestFixture): """SET the device label using the broadcast address.""" CATEGORY = TestCategory.PRODUCT_INFORMATION PID = 'DEVICE_LABEL' REQUIRES = ['device_label', 'set_device_label_supported'] TEST_LABEL = 'broadcast label' def Uid(self): return UID.AllDevices() def OldValue(self): return self.Property('device_label') class SetFullSizeDeviceLabel(TestMixins.SetLabelMixin, OptionalParameterTestFixture): """SET the device label.""" CATEGORY = TestCategory.PRODUCT_INFORMATION PID = 'DEVICE_LABEL' REQUIRES = ['device_label'] TEST_LABEL = 'this is a string with 32 charact' def OldValue(self): return self.Property('device_label') class SetNonAsciiDeviceLabel(TestMixins.SetLabelMixin, OptionalParameterTestFixture): """SET the device label to something that contains non-ascii data.""" CATEGORY = TestCategory.PRODUCT_INFORMATION PID = 'DEVICE_LABEL' REQUIRES = ['device_label'] TEST_LABEL = 'string with\x0d non ascii\xc0' def ExpectedResults(self): return [ self.NackSetResult(RDMNack.NR_DATA_OUT_OF_RANGE), self.NackSetResult(RDMNack.NR_FORMAT_ERROR), self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS), self.AckSetResult(action=self.VerifySet) ] def OldValue(self): return self.Property('device_label') class SetEmptyDeviceLabel(TestMixins.SetLabelMixin, OptionalParameterTestFixture): """SET the device label with no data.""" CATEGORY = TestCategory.PRODUCT_INFORMATION PID = 'DEVICE_LABEL' REQUIRES = ['device_label'] TEST_LABEL = '' def OldValue(self): return self.Property('device_label') class SetOversizedDeviceLabel(TestMixins.SetOversizedLabelMixin, OptionalParameterTestFixture): """SET the device label with more than 32 bytes of data.""" CATEGORY = TestCategory.ERROR_CONDITIONS REQUIRES = ['device_label'] PID = 'DEVICE_LABEL' def OldValue(self): return self.Property('device_label') # Language Capabilities # ----------------------------------------------------------------------------- class GetLanguageCapabilities(OptionalParameterTestFixture): """GET the language capabilities pid.""" CATEGORY = TestCategory.PRODUCT_INFORMATION PID = 'LANGUAGE_CAPABILITIES' PROVIDES = ['languages_capabilities'] def Test(self): self.languages = [] self.AddIfGetSupported(self.AckGetResult(field_names=['languages'])) self.SendGet(ROOT_DEVICE, self.pid) def VerifyResult(self, response, fields): if not response.WasAcked(): self.SetProperty('languages_capabilities', []) return self.languages = [f['language'] for f in fields['languages']] if len(self.languages) == 0: self.AddWarning('No languages returned for LANGUAGE_CAPABILITIES') language_set = set() for language in self.languages: if language in language_set: self.AddAdvisory('%s listed twice in language capabilities' % language) language_set.add(language) if ContainsUnprintable(language): self.AddAdvisory( 'Language name in languague capabilities contains unprintable ' 'characters, was %s' % language.encode('string-escape')) self.SetProperty('languages_capabilities', language_set) class GetLanguageCapabilitiesWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """GET the language capabilities pid with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'LANGUAGE_CAPABILITIES' class AllSubDevicesGetLanguageCapablities(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get LANGUAGE_CAPABILITIES to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'LANGUAGE_CAPABILITIES' # Language # ----------------------------------------------------------------------------- class GetLanguage(TestMixins.GetStringMixin, OptionalParameterTestFixture): """GET the language.""" CATEGORY = TestCategory.PRODUCT_INFORMATION PID = 'LANGUAGE' PROVIDES = ['language'] EXPECTED_FIELDS = ['language'] class GetLanguageWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """GET the language with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'LANGUAGE' class SetLanguage(OptionalParameterTestFixture): """SET the language.""" CATEGORY = TestCategory.PRODUCT_INFORMATION PID = 'LANGUAGE' REQUIRES = ['language', 'languages_capabilities'] def Test(self): ack = self.AckSetResult(action=self.VerifySet) nack = self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS) available_langugages = list(self.Property('languages_capabilities')) if available_langugages: if len(available_langugages) > 1: # If the responder only supports 1 lang, we may not be able to set it self.AddIfSetSupported(ack) self.new_language = available_langugages[0] if self.new_language == self.Property('language'): self.new_language = available_langugages[1] else: self.new_language = available_langugages[0] self.AddIfSetSupported([ack, nack]) else: # Get languages returned no languages so we expect a nack self.AddIfSetSupported(nack) self.new_language = 'en' self.SendSet(ROOT_DEVICE, self.pid, [self.new_language]) def VerifySet(self): self.AddExpectedResults( self.AckGetResult(field_values={'language': self.new_language})) self.SendGet(ROOT_DEVICE, self.pid) class SetNonAsciiLanguage(OptionalParameterTestFixture): """Try to set the language to non-ascii characters.""" CATEGORY = TestCategory.PRODUCT_INFORMATION PID = 'LANGUAGE' def Test(self): self.AddIfSetSupported(self.NackSetResult(RDMNack.NR_DATA_OUT_OF_RANGE)) self.SendSet(ROOT_DEVICE, self.pid, ['\x0d\xc0']) class SetUnsupportedLanguage(OptionalParameterTestFixture): """Try to set a language that doesn't exist in Language Capabilities.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'LANGUAGE' REQUIRES = ['languages_capabilities'] def Test(self): if 'zz' in self.Property('languages_capabilities'): self.SetBroken('zz exists in the list of available languages') self.Stop() return self.AddIfSetSupported([ self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS), self.NackSetResult(RDMNack.NR_DATA_OUT_OF_RANGE), ]) self.SendSet(ROOT_DEVICE, self.pid, ['zz']) class AllSubDevicesGetLanguage(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get LANGUAGE to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'LANGUAGE' # Software Version Label # ----------------------------------------------------------------------------- class GetSoftwareVersionLabel(TestMixins.GetRequiredStringMixin, ResponderTestFixture): """GET the software version label.""" CATEGORY = TestCategory.PRODUCT_INFORMATION PID = 'SOFTWARE_VERSION_LABEL' EXPECTED_FIELDS = ['label'] class GetSoftwareVersionLabelWithData(TestMixins.GetMandatoryPIDWithDataMixin, ResponderTestFixture): """GET the software_version_label with param data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'SOFTWARE_VERSION_LABEL' class SetSoftwareVersionLabel(TestMixins.UnsupportedSetMixin, ResponderTestFixture): """Attempt to SET the software version label.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'SOFTWARE_VERSION_LABEL' class AllSubDevicesGetSoftwareVersionLabel(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get SOFTWARE_VERSION_LABEL to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'SOFTWARE_VERSION_LABEL' class GetSubDeviceSoftwareVersionLabel(ResponderTestFixture): """Check that SOFTWARE_VERSION_LABEL is supported on all sub devices.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'SOFTWARE_VERSION_LABEL' REQUIRES = ['sub_device_addresses'] def Test(self): self._sub_devices = self.Property('sub_device_addresses').keys() self._sub_devices.reverse() self._GetSoftwareVersion() def _GetSoftwareVersion(self): if not self._sub_devices: self.Stop() return self.AddExpectedResults(self.AckGetResult(action=self._GetSoftwareVersion)) sub_device = self._sub_devices.pop() self.SendGet(sub_device, self.pid) # Boot Software Version # ----------------------------------------------------------------------------- class GetBootSoftwareVersion(OptionalParameterTestFixture): """GET the boot software version.""" CATEGORY = TestCategory.PRODUCT_INFORMATION PID = 'BOOT_SOFTWARE_VERSION_ID' def Test(self): self.AddIfGetSupported(self.AckGetResult(field_names=['version'])) self.SendGet(ROOT_DEVICE, self.pid) class GetBootSoftwareVersionWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """GET the boot software version with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'BOOT_SOFTWARE_VERSION_ID' class SetBootSoftwareVersion(TestMixins.UnsupportedSetMixin, ResponderTestFixture): """Attempt to SET the boot software version.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'BOOT_SOFTWARE_VERSION_ID' class AllSubDevicesGetBootSoftwareVersion(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get BOOT_SOFTWARE_VERSION_ID to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'BOOT_SOFTWARE_VERSION_ID' # Boot Software Version Label # ----------------------------------------------------------------------------- class GetBootSoftwareLabel(TestMixins.GetStringMixin, OptionalParameterTestFixture): """GET the boot software label.""" CATEGORY = TestCategory.PRODUCT_INFORMATION PID = 'BOOT_SOFTWARE_VERSION_LABEL' EXPECTED_FIELDS = ['label'] class GetBootSoftwareLabelWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """GET the boot software label with param data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'BOOT_SOFTWARE_VERSION_LABEL' class SetBootSoftwareLabel(TestMixins.UnsupportedSetMixin, OptionalParameterTestFixture): """SET the boot software label.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'BOOT_SOFTWARE_VERSION_LABEL' class AllSubDevicesGetBootSoftwareVersionLabel(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get BOOT_SOFTWARE_VERSION_LABEL to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'BOOT_SOFTWARE_VERSION_LABEL' # DMX Personality & DMX Personality Description # ----------------------------------------------------------------------------- class GetZeroPersonalityDescription(TestMixins.GetZeroUInt8Mixin, OptionalParameterTestFixture): """GET DMX_PERSONALITY_DESCRIPTION for personality 0.""" PID = 'DMX_PERSONALITY_DESCRIPTION' class GetOutOfRangePersonalityDescription(TestMixins.GetOutOfRangeByteMixin, OptionalParameterTestFixture): """GET the personality description for the N + 1 personality.""" PID = 'DMX_PERSONALITY_DESCRIPTION' REQUIRES = ['personality_count'] class AllSubDevicesGetPersonalityDescription(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get DMX_PERSONALITY_DESCRIPTION to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'DMX_PERSONALITY_DESCRIPTION' DATA = [1] class GetPersonalityDescription(OptionalParameterTestFixture): """GET the personality description for the current personality.""" CATEGORY = TestCategory.DMX_SETUP PID = 'DMX_PERSONALITY_DESCRIPTION' REQUIRES = ['current_personality', 'dmx_footprint', 'personality_count'] def Test(self): personality_count = self.Property('personality_count') current_personality = self.Property('current_personality') if current_personality == 0 and personality_count > 0: # It's probably off by one, so fix it current_personality = 1 if personality_count > 0: # Cross check against what we got from device info self.AddIfGetSupported(self.AckGetResult(field_values={ 'personality': current_personality, 'slots_required': self.Property('dmx_footprint'), })) self.SendGet(ROOT_DEVICE, self.pid, [current_personality]) else: self.AddIfGetSupported(self.NackGetResult(RDMNack.NR_DATA_OUT_OF_RANGE)) self.SendGet(ROOT_DEVICE, self.pid, [1]) def VerifyResult(self, response, fields): if not response.WasAcked(): return if ContainsUnprintable(fields['name']): self.AddAdvisory( 'Name field in %s contains unprintable characters, was %s' % (self.PID, fields['name'].encode('string-escape'))) class GetPersonality(OptionalParameterTestFixture): """Get the current personality settings.""" CATEGORY = TestCategory.DMX_SETUP PID = 'DMX_PERSONALITY' REQUIRES = ['current_personality', 'personality_count'] def Test(self): self.AddIfGetSupported(self.AckGetResult( field_names=['current_personality', 'personality_count'])) self.SendGet(ROOT_DEVICE, self.pid) def VerifyResult(self, response, fields): if not response.WasAcked(): return current_personality = self.Property('current_personality') personality_count = self.Property('personality_count') warning_str = ("Personality information in device info doesn't match that " "in dmx_personality") if current_personality != fields['current_personality']: self.SetFailed('%s: current_personality %d != %d' % ( warning_str, current_personality, fields['current_personality'])) if personality_count != fields['personality_count']: self.SetFailed('%s: personality_count %d != %d' % ( warning_str, personality_count, fields['personality_count'])) class GetPersonalityWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """Get DMX_PERSONALITY with invalid data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'DMX_PERSONALITY' class GetPersonalityDescriptions(OptionalParameterTestFixture): """Get information about all the personalities.""" CATEGORY = TestCategory.DMX_SETUP PID = 'DMX_PERSONALITY_DESCRIPTION' REQUIRES = ['personality_count'] PROVIDES = ['personalities'] def Test(self): self._personalities = [] self._personality_count = self.Property('personality_count') self._current_index = 0 self._GetPersonality() def _GetPersonality(self): self._current_index += 1 if self._current_index > self._personality_count: if self._personality_count == 0: self.SetNotRun('No personalities declared') self.SetProperty('personalities', self._personalities) self.Stop() return if self._current_index >= MAX_PERSONALITY_NUMBER: # This should never happen because personality_count is a uint8 self.SetFailed('Could not find all personalities') self.Stop() return self.AddIfGetSupported(self.AckGetResult( field_names=['slots_required', 'name'], field_values={'personality': self._current_index}, action=self._GetPersonality)) self.SendGet(ROOT_DEVICE, self.pid, [self._current_index]) def VerifyResult(self, response, fields): """Save the personality for other tests to use.""" if response.WasAcked(): self._personalities.append(fields) if ContainsUnprintable(fields['name']): self.AddAdvisory( 'Name field in %s contains unprintable characters, was %s' % (self.PID, fields['name'].encode('string-escape'))) class SetPersonality(OptionalParameterTestFixture): """Set the personality.""" CATEGORY = TestCategory.DMX_SETUP PID = 'DMX_PERSONALITY' REQUIRES = ['current_personality', 'personalities'] def Test(self): self._personalities = list(self.Property('personalities')) self._consumes_slots = False for personality in self._personalities: if personality['slots_required'] > 0: self._consumes_slots = True break if len(self._personalities) > 0: self._CheckPersonality() return # Check we get a NR_UNKNOWN_PID self.AddExpectedResults(self.NackSetResult(RDMNack.NR_UNKNOWN_PID)) self.new_personality = {'personality': 1} # can use anything here really self.SendSet(ROOT_DEVICE, self.pid, [1]) def _CheckPersonality(self): if not self._personalities: # End of the list, we're done self.Stop() return self.AddIfSetSupported(self.AckSetResult(action=self.VerifySet)) self.SendSet(ROOT_DEVICE, self.pid, [self._personalities[0]['personality']]) def VerifySet(self): self.AddIfGetSupported( self.AckGetResult( field_values={ 'current_personality': self._personalities[0]['personality'], }, action=self.VerifyDeviceInfo)) self.SendGet(ROOT_DEVICE, self.pid) def VerifyDeviceInfo(self): device_info_pid = self.LookupPid('DEVICE_INFO') next_action = self.NextPersonality if self._personalities[0]['slots_required'] == 0: # If this personality has a footprint of 0, verify the start address is # 0xffff next_action = self.VerifyFootprint0StartAddress self.AddExpectedResults( AckGetResult( device_info_pid.value, field_values={ 'current_personality': self._personalities[0]['personality'], 'dmx_footprint': self._personalities[0]['slots_required'], }, action=next_action)) self.SendGet(ROOT_DEVICE, device_info_pid) def VerifyFootprint0StartAddress(self): address_pid = self.LookupPid('DMX_START_ADDRESS') expected_results = [ AckGetResult( address_pid.value, field_values={'dmx_address': RDM_ZERO_FOOTPRINT_DMX_ADDRESS}, action=self.NextPersonality), ] if not self._consumes_slots: expected_results.append( NackGetResult(address_pid.value, RDMNack.NR_UNKNOWN_PID, action=self.NextPersonality) ) self.AddExpectedResults(expected_results) self.SendGet(ROOT_DEVICE, address_pid) def NextPersonality(self): self._personalities = self._personalities[1:] self._CheckPersonality() def ResetState(self): # Reset back to the old value personality = self.Property('current_personality') if personality == 0 or personality > 255: return self.SendSet(ROOT_DEVICE, self.pid, [self.Property('current_personality')]) self._wrapper.Run() class SetZeroPersonality(TestMixins.SetZeroUInt8Mixin, OptionalParameterTestFixture): """Set DMX_PERSONALITY for personality 0.""" PID = 'DMX_PERSONALITY' class SetOutOfRangePersonality(TestMixins.SetOutOfRangeByteMixin, OptionalParameterTestFixture): """Set DMX_PERSONALITY to an out-of-range value.""" PID = 'DMX_PERSONALITY' REQUIRES = ['personality_count'] LABEL = 'personalities' class SetOversizedPersonality(OptionalParameterTestFixture): """Send an over-sized SET personality command.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'DMX_PERSONALITY' def Test(self): self.AddIfSetSupported(self.NackSetResult(RDMNack.NR_FORMAT_ERROR)) self.SendRawSet(ROOT_DEVICE, self.pid, 'foo') class AllSubDevicesGetPersonality(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get DMX_PERSONALITY to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'DMX_PERSONALITY' # DMX Start Address tests # ----------------------------------------------------------------------------- class GetStartAddress(ResponderTestFixture): """GET the DMX start address.""" CATEGORY = TestCategory.DMX_SETUP PID = 'DMX_START_ADDRESS' REQUIRES = ['dmx_footprint', 'dmx_start_address'] PROVIDES = ['dmx_address'] def Test(self): if self.Property('dmx_footprint') > 0: results = self.AckGetResult(field_names=['dmx_address']) else: results = [ self.AckGetResult(field_values={ 'dmx_address': RDM_ZERO_FOOTPRINT_DMX_ADDRESS}), self.NackGetResult(RDMNack.NR_UNKNOWN_PID), self.NackGetResult(RDMNack.NR_DATA_OUT_OF_RANGE), ] self.AddExpectedResults(results) self.SendGet(ROOT_DEVICE, self.pid) def VerifyResult(self, response, fields): if not response.WasAcked(): self.SetProperty('dmx_address', None) return if self.Property('dmx_start_address') != fields['dmx_address']: self.SetFailed( 'DMX_START_ADDRESS (%d) doesn\'t match what was in DEVICE_INFO (%d)' % (fields['dmx_address'], self.Property('dmx_start_address'))) self.SetPropertyFromDict(fields, 'dmx_address') class GetStartAddressWithData(ResponderTestFixture): """GET the DMX start address with data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'DMX_START_ADDRESS' REQUIRES = ['dmx_footprint'] def Test(self): if self.Property('dmx_footprint') > 0: # If we have a footprint, PID must return something as this PID is # required (can't return unsupported) results = [ self.NackGetResult(RDMNack.NR_FORMAT_ERROR), self.AckGetResult( warning='Get %s with data returned an ack' % self.pid.name) ] else: # If we don't have a footprint, PID may return something, or may return # unsupported, as this PID becomes optional results = [ self.NackGetResult(RDMNack.NR_UNKNOWN_PID), self.NackGetResult(RDMNack.NR_FORMAT_ERROR), self.AckGetResult( warning='Get %s with data returned an ack' % self.pid.name), ] self.AddExpectedResults(results) self.SendRawGet(PidStore.ROOT_DEVICE, self.pid, 'foo') class SetStartAddress(TestMixins.SetStartAddressMixin, ResponderTestFixture): """Set the DMX start address.""" CATEGORY = TestCategory.DMX_SETUP PID = 'DMX_START_ADDRESS' REQUIRES = ['dmx_footprint', 'dmx_address'] PROVIDES = ['set_dmx_address_supported'] def Test(self): footprint = self.Property('dmx_footprint') current_address = self.Property('dmx_address') self.start_address = 1 if footprint == 0 or current_address == RDM_ZERO_FOOTPRINT_DMX_ADDRESS: results = [ self.NackSetResult(RDMNack.NR_UNKNOWN_PID), self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS), self.NackSetResult(RDMNack.NR_DATA_OUT_OF_RANGE) ] else: self.start_address = self.CalculateNewAddress(current_address, footprint) results = self.AckSetResult(action=self.VerifySet) self._test_state = self.SET self.AddExpectedResults(results) self.SendSet(ROOT_DEVICE, self.pid, [self.start_address]) def VerifyResult(self, response, fields): if self._test_state == self.SET: self.SetProperty(self.PROVIDES[0], response.WasAcked()) class SetVendorcastStartAddress(TestMixins.SetNonUnicastStartAddressMixin, ResponderTestFixture): """SET the dmx start address using the vendorcast address.""" CATEGORY = TestCategory.DMX_SETUP PID = 'DMX_START_ADDRESS' REQUIRES = ['dmx_footprint', 'dmx_address', 'set_dmx_address_supported'] def Uid(self): return UID.VendorcastAddress(self._uid.manufacturer_id) class SetBroadcastStartAddress(TestMixins.SetNonUnicastStartAddressMixin, ResponderTestFixture): """SET the dmx start address using the broadcast address.""" CATEGORY = TestCategory.DMX_SETUP PID = 'DMX_START_ADDRESS' REQUIRES = ['dmx_footprint', 'dmx_address', 'set_dmx_address_supported'] def Uid(self): return UID.AllDevices() class SetOutOfRangeStartAddress(ResponderTestFixture): """Check that the DMX address can't be set to > 512.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'DMX_START_ADDRESS' # We depend on dmx_address to make sure this runs after GetStartAddress DEPS = [GetStartAddress] REQUIRES = ['dmx_footprint'] def Test(self): if self.Property('dmx_footprint') > 0: self.AddExpectedResults(self.NackSetResult(RDMNack.NR_DATA_OUT_OF_RANGE)) else: self.AddExpectedResults([ self.NackSetResult(RDMNack.NR_UNKNOWN_PID), self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS), self.NackSetResult(RDMNack.NR_DATA_OUT_OF_RANGE) ]) data = struct.pack('!H', MAX_DMX_ADDRESS + 1) self.SendRawSet(ROOT_DEVICE, self.pid, data) class SetZeroStartAddress(ResponderTestFixture): """Check the DMX address can't be set to 0.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'DMX_START_ADDRESS' # We depend on dmx_address to make sure this runs after GetStartAddress DEPS = [GetStartAddress] REQUIRES = ['dmx_footprint'] def Test(self): if self.Property('dmx_footprint') > 0: self.AddExpectedResults(self.NackSetResult(RDMNack.NR_DATA_OUT_OF_RANGE)) else: self.AddExpectedResults([ self.NackSetResult(RDMNack.NR_UNKNOWN_PID), self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS), self.NackSetResult(RDMNack.NR_DATA_OUT_OF_RANGE) ]) data = struct.pack('!H', 0) self.SendRawSet(ROOT_DEVICE, self.pid, data) class SetOversizedStartAddress(ResponderTestFixture): """Send an over-sized SET dmx start address.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'DMX_START_ADDRESS' # We depend on dmx_address to make sure this runs after GetStartAddress DEPS = [GetStartAddress] REQUIRES = ['dmx_footprint'] def Test(self): if self.Property('dmx_footprint') > 0: self.AddExpectedResults(self.NackSetResult(RDMNack.NR_FORMAT_ERROR)) else: self.AddExpectedResults([ self.NackSetResult(RDMNack.NR_UNKNOWN_PID), self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS), self.NackSetResult(RDMNack.NR_FORMAT_ERROR), ]) self.SendRawSet(ROOT_DEVICE, self.pid, 'foo') class AllSubDevicesGetStartAddress(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get DMX_START_ADDRESS to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'DMX_START_ADDRESS' # Slot Info # ----------------------------------------------------------------------------- class GetSlotInfo(OptionalParameterTestFixture): """Get SLOT_INFO.""" CATEGORY = TestCategory.DMX_SETUP PID = 'SLOT_INFO' PROVIDES = ['defined_slots', 'undefined_definition_slots', 'undefined_type_sec_slots'] def Test(self): self.AddIfGetSupported(self.AckGetResult()) self.SendGet(ROOT_DEVICE, self.pid) def VerifyResult(self, response, fields): if not response.WasAcked(): self.SetProperty('defined_slots', set()) self.SetProperty('undefined_definition_slots', []) self.SetProperty('undefined_type_sec_slots', []) return slots = [d['slot_offset'] for d in fields['slots']] self.SetProperty('defined_slots', set(slots)) undefined_definition_slots = [] undefined_type_sec_slots = [] for slot in fields['slots']: if slot['slot_type'] not in RDMConstants.SLOT_TYPE_TO_NAME: self.AddWarning('Unknown slot type %d for slot %d' % (slot['slot_type'], slot['slot_offset'])) if slot['slot_type'] == RDMConstants.SLOT_TYPES['ST_PRIMARY']: # slot_label_id must be valid if ((slot['slot_label_id'] not in RDMConstants.SLOT_DEFINITION_TO_NAME) and (slot['slot_label_id'] < RDM_MANUFACTURER_SD_MIN or slot['slot_label_id'] > RDM_MANUFACTURER_SD_MAX)): self.AddWarning('Unknown slot id %d for slot %d' % (slot['slot_label_id'], slot['slot_offset'])) if (slot['slot_label_id'] == RDMConstants.SLOT_DEFINITIONS['SD_UNDEFINED']): undefined_definition_slots.append(slot['slot_offset']) else: # slot_label_id must reference a defined slot if slot['slot_label_id'] not in slots: self.AddWarning( 'Slot %d is of type secondary and references an unknown slot %d' % (slot['slot_offset'], slot['slot_label_id'])) if slot['slot_type'] == RDMConstants.SLOT_TYPES['ST_SEC_UNDEFINED']: undefined_type_sec_slots.append(slot['slot_offset']) self.SetProperty('undefined_definition_slots', undefined_definition_slots) self.SetProperty('undefined_type_sec_slots', undefined_type_sec_slots) class GetSlotInfoWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """Get SLOT_INFO with invalid data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'SLOT_INFO' class SetSlotInfo(TestMixins.UnsupportedSetMixin, OptionalParameterTestFixture): """Set SLOT_INFO.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'SLOT_INFO' class AllSubDevicesGetSlotInfo(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get SLOT_INFO to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'SLOT_INFO' # Slot Description # ----------------------------------------------------------------------------- class GetSlotDescriptions(TestMixins.GetSettingDescriptionsRangeMixin, OptionalParameterTestFixture): """Get the slot descriptions for all defined slots.""" CATEGORY = TestCategory.DMX_SETUP PID = 'SLOT_DESCRIPTION' REQUIRES = ['dmx_footprint'] FIRST_INDEX_OFFSET = 0 EXPECTED_FIELDS = ['slot_number'] DESCRIPTION_FIELD = 'name' ALLOWED_NACKS = [RDMNack.NR_DATA_OUT_OF_RANGE] class GetSlotDescriptionWithNoData(TestMixins.GetWithNoDataMixin, OptionalParameterTestFixture): """Get the slot description with no slot number specified.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'SLOT_DESCRIPTION' class GetSlotDescriptionWithTooMuchData(OptionalParameterTestFixture): """Get the slot description with more than 2 bytes of data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'SLOT_DESCRIPTION' def Test(self): self.AddIfGetSupported(self.NackGetResult(RDMNack.NR_FORMAT_ERROR)) self.SendRawGet(ROOT_DEVICE, self.pid, 'foo') class GetUndefinedSlotDefinitionDescriptions(OptionalParameterTestFixture): """Get the slot description for all slots with undefined definition.""" CATEGORY = TestCategory.DMX_SETUP PID = 'SLOT_DESCRIPTION' REQUIRES = ['undefined_definition_slots'] def Test(self): self.undef_slots = self.Property('undefined_definition_slots')[:] if len(self.undef_slots) == 0: self.SetNotRun('No undefined definition slots found') return self._GetSlotDescription() def _GetSlotDescription(self): if len(self.undef_slots) == 0: self.Stop() return self.AddExpectedResults([ self.AckGetResult(action=self._GetSlotDescription), self.NackGetResult(RDMNack.NR_UNKNOWN_PID, action=self._GetSlotDescription), self.NackGetResult(RDMNack.NR_DATA_OUT_OF_RANGE, action=self._GetSlotDescription) ]) self.current_slot = self.undef_slots.pop() self.SendGet(ROOT_DEVICE, self.pid, [self.current_slot]) def VerifyResult(self, response, fields): if not response.WasAcked(): if response.nack_reason == RDMNack.NR_UNKNOWN_PID: self.AddWarning( '%s not supported for slot %d with undefined ' 'definition' % (self.pid, self.current_slot)) if response.nack_reason == RDMNack.NR_DATA_OUT_OF_RANGE: self.AddWarning( 'Slot description for slot %d with undefined definition was missing' % (self.current_slot)) return if not fields['name']: self.AddWarning( 'Slot description for slot %d with undefined definition was blank' % (self.current_slot)) return class GetUndefinedSecondarySlotTypeDescriptions(OptionalParameterTestFixture): """Get the slot description for all secondary slots with an undefined type.""" CATEGORY = TestCategory.DMX_SETUP PID = 'SLOT_DESCRIPTION' REQUIRES = ['undefined_type_sec_slots'] def Test(self): self.undef_sec_slots = self.Property('undefined_type_sec_slots')[:] if len(self.undef_sec_slots) == 0: self.SetNotRun('No undefined type secondary slots found') return self._GetSlotDescription() def _GetSlotDescription(self): if len(self.undef_sec_slots) == 0: self.Stop() return self.AddExpectedResults([ self.AckGetResult(action=self._GetSlotDescription), self.NackGetResult(RDMNack.NR_UNKNOWN_PID, action=self._GetSlotDescription), self.NackGetResult(RDMNack.NR_DATA_OUT_OF_RANGE, action=self._GetSlotDescription) ]) self.current_slot = self.undef_sec_slots.pop() self.SendGet(ROOT_DEVICE, self.pid, [self.current_slot]) def VerifyResult(self, response, fields): if not response.WasAcked(): if response.nack_reason == RDMNack.NR_UNKNOWN_PID: self.AddAdvisory( '%s not supported for secondary slot %d with undefined type' % (self.pid, self.current_slot)) if response.nack_reason == RDMNack.NR_DATA_OUT_OF_RANGE: self.AddAdvisory( 'Slot description for secondary slot %d with undefined type was ' 'missing' % (self.current_slot)) return if not fields['name']: self.AddAdvisory( 'Slot description for secondary slot %d with undefined type was ' 'blank' % (self.current_slot)) return class SetSlotDescription(TestMixins.UnsupportedSetMixin, OptionalParameterTestFixture): """Set SLOT_DESCRIPTION.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'SLOT_DESCRIPTION' class AllSubDevicesGetSlotDescription(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get SLOT_DESCRIPTION to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'SLOT_DESCRIPTION' DATA = [1] # Default Slot Value # ----------------------------------------------------------------------------- class GetDefaultSlotValues(OptionalParameterTestFixture): """Get DEFAULT_SLOT_VALUE.""" CATEGORY = TestCategory.DMX_SETUP PID = 'DEFAULT_SLOT_VALUE' REQUIRES = ['defined_slots'] def Test(self): self.AddIfGetSupported(self.AckGetResult()) self.SendGet(ROOT_DEVICE, self.pid) def VerifyResult(self, response, fields): if not response.WasAcked(): return defined_slots = self.Property('defined_slots') default_slots = set() for slot in fields['slot_values']: if slot['slot_offset'] not in defined_slots: self.AddAdvisory( "DEFAULT_SLOT_VALUE contained slot %d, which wasn't in SLOT_INFO" % slot['slot_offset']) default_slots.add(slot['slot_offset']) for slot_offset in defined_slots: if slot_offset not in default_slots: self.AddAdvisory( "SLOT_INFO contained slot %d, which wasn't in DEFAULT_SLOT_VALUE" % slot_offset) class GetDefaultSlotInfoWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """Get DEFAULT_SLOT_VALUE with invalid data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'DEFAULT_SLOT_VALUE' class SetDefaultSlotInfo(TestMixins.UnsupportedSetMixin, OptionalParameterTestFixture): """Set DEFAULT_SLOT_VALUE.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'DEFAULT_SLOT_VALUE' class AllSubDevicesGetDefaultSlotValue(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get DEFAULT_SLOT_VALUE to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'DEFAULT_SLOT_VALUE' DATA = [1] # Sensor Consistency Checks # ----------------------------------------------------------------------------- class CheckSensorConsistency(ResponderTestFixture): """Check that sensor support is consistent.""" CATEGORY = TestCategory.SENSORS REQUIRES = ['sensor_count', 'sensor_recording_supported', 'supported_parameters'] def IsSupported(self, pid): return pid.value in self.Property('supported_parameters') def CheckConsistency(self, pid_name, check_for_support=True): pid = self.LookupPid(pid_name) if (check_for_support and (not self.IsSupported(pid)) and self.Property('sensor_count')) > 0: self.AddAdvisory('%s not supported but sensor count was > 0' % pid) if self.IsSupported(pid) and self.Property('sensor_count') == 0: self.AddAdvisory('%s supported but sensor count was 0' % pid) def Test(self): self.CheckConsistency('SENSOR_DEFINITION') self.CheckConsistency('SENSOR_VALUE') self.CheckConsistency('RECORD_SENSORS', self.Property('sensor_recording_supported')) self.SetPassed() self.Stop() # Sensor Definition # ----------------------------------------------------------------------------- class GetSensorDefinition(OptionalParameterTestFixture): """Fetch all the sensor definitions.""" CATEGORY = TestCategory.SENSORS PID = 'SENSOR_DEFINITION' REQUIRES = ['sensor_count'] PROVIDES = ['sensor_definitions', 'sensor_recording_supported'] MAX_SENSOR_INDEX = 0xfe RECORDED_VALUE_MASK = 0x01 PREDICATE_DICT = { '==': operator.eq, '<': operator.lt, '>': operator.gt, } def Test(self): # Default to false self._sensors = {} # Stores the discovered sensors self._current_index = -1 # The current sensor we're trying to query self._sensor_holes = [] # Indices of sensors that are missing self._CheckForSensor() def _MissingSensorWarning(self): max_sensor = max(self._sensors.keys()) missing_sensors = [i for i in self._sensor_holes if i < max_sensor] if missing_sensors: self.AddWarning('Sensors missing in positions %s' % missing_sensors) def _CheckForSensor(self): if self.PidSupported(): # If this PID is supported we attempt to locate all sensors if self._current_index == self.MAX_SENSOR_INDEX: if len(self._sensors) < self.Property('sensor_count'): self.AddWarning('Only found %d/%d sensors' % (len(self._sensors), self.Property('sensor_count'))) elif len(self._sensors) > self.Property('sensor_count'): self.AddWarning('Found too many %d/%d sensors' % (len(self._sensors), self.Property('sensor_count'))) self.SetProperty('sensor_definitions', self._sensors) supports_recording = False for sensor_def in self._sensors.itervalues(): supports_recording |= ( sensor_def['supports_recording'] & self.RECORDED_VALUE_MASK) self.SetProperty('sensor_recording_supported', supports_recording) self._MissingSensorWarning() self.Stop() return # For each message we should either see a NR_DATA_OUT_OF_RANGE or an ack self.AddExpectedResults([ self.NackGetResult(RDMNack.NR_DATA_OUT_OF_RANGE, action=self._AddToHoles), self.AckGetResult(action=self._CheckForSensor) ]) else: # Not supported, just check we get a NR_UNKNOWN_PID self.AddExpectedResults(self.NackGetResult(RDMNack.NR_UNKNOWN_PID)) self.SetProperty('sensor_definitions', {}) self._current_index += 1 self.SendGet(ROOT_DEVICE, self.pid, [self._current_index]) def _AddToHoles(self): self._sensor_holes.append(self._current_index) self._CheckForSensor() def VerifyResult(self, response, fields): if not response.WasAcked(): return sensor_number = fields['sensor_number'] if self._current_index != sensor_number: self.AddWarning( 'Requested sensor %d, message returned sensor %d' % (self._current_index, fields['sensor_number'])) return self._sensors[self._current_index] = fields # Perform sanity checks on the sensor infomation if fields['type'] not in RDMConstants.SENSOR_TYPE_TO_NAME: if fields['type'] >= 0x80: self.AddAdvisory('Using a manufacturer specific type %d for sensor %d,' ' is there no suitable defined type?' % (fields['type'], sensor_number)) else: self.AddWarning('Unknown type %d for sensor %d' % (fields['type'], sensor_number)) if fields['unit'] not in RDMConstants.UNIT_TO_NAME: if fields['unit'] >= 0x80: self.AddAdvisory('Using a manufacturer specific unit %d for sensor %d,' ' is there no suitable defined unit?' % (fields['unit'], sensor_number)) else: self.AddWarning('Unknown unit %d for sensor %d' % (fields['unit'], sensor_number)) if fields['prefix'] not in RDMConstants.PREFIX_TO_NAME: self.AddWarning('Unknown prefix %d for sensor %d' % (fields['prefix'], sensor_number)) self.CheckCondition(sensor_number, fields, 'range_min', '>', 'range_max') self.CheckCondition(sensor_number, fields, 'range_min', '==', 'range_max') self.CheckCondition(sensor_number, fields, 'normal_min', '>', 'normal_max') self.CheckCondition(sensor_number, fields, 'normal_min', '==', 'normal_max') self.CheckCondition(sensor_number, fields, 'normal_min', '<', 'range_min') self.CheckCondition(sensor_number, fields, 'normal_max', '>', 'range_max') if fields['supports_recording'] & 0xfc: self.AddWarning('bits 7-2 in the recorded message support fields are set' ' for sensor %d' % sensor_number) if ContainsUnprintable(fields['name']): self.AddAdvisory( 'Name field in sensor definition for sensor %d contains unprintable' ' characters, was %s' % (self._current_index, fields['name'].encode('string-escape'))) def CheckCondition(self, sensor_number, fields, lhs, predicate_str, rhs): """Check for a condition and add a warning if it isn't true.""" predicate = self.PREDICATE_DICT[predicate_str] if predicate(fields[lhs], fields[rhs]): self.AddAdvisory( 'Sensor %d, %s (%d) %s %s (%d)' % (sensor_number, lhs, fields[lhs], predicate_str, rhs, fields[rhs])) class GetSensorDefinitionWithNoData(TestMixins.GetWithNoDataMixin, OptionalParameterTestFixture): """Get the sensor definition with no data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'SENSOR_DEFINITION' class GetSensorDefinitionWithTooMuchData(OptionalParameterTestFixture): """Get the sensor definition with more than 1 byte of data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'SENSOR_DEFINITION' def Test(self): self.AddIfGetSupported(self.NackGetResult(RDMNack.NR_FORMAT_ERROR)) self.SendRawGet(ROOT_DEVICE, self.pid, 'foo') class GetInvalidSensorDefinition(OptionalParameterTestFixture): """Get the sensor definition with the all sensor value (0xff).""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'SENSOR_DEFINITION' def Test(self): self.AddIfGetSupported(self.NackGetResult(RDMNack.NR_DATA_OUT_OF_RANGE)) data = struct.pack('!B', 0xff) self.SendRawGet(ROOT_DEVICE, self.pid, data) class SetSensorDefinition(TestMixins.UnsupportedSetMixin, OptionalParameterTestFixture): """SET the sensor definition.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'SENSOR_DEFINITION' class AllSubDevicesGetSensorDefinition(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get SENSOR_DEFINITION to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'SENSOR_DEFINITION' DATA = [1] # Sensor Value # ----------------------------------------------------------------------------- class GetSensorValues(OptionalParameterTestFixture): """Get values for all defined sensors.""" CATEGORY = TestCategory.SENSORS PID = 'SENSOR_VALUE' REQUIRES = ['sensor_definitions'] PROVIDES = ['sensor_values'] HIGHEST_LOWEST_MASK = 0x02 RECORDED_VALUE_MASK = 0x01 def Test(self): # The head of the list is the current sensor we're querying self._sensors = self.Property('sensor_definitions').values() self._sensor_values = [] if self._sensors: # Loop and get all values self._GetSensorValue() else: # No sensors found, make sure we get a NR_DATA_OUT_OF_RANGE self.AddIfGetSupported(self.NackGetResult(RDMNack.NR_DATA_OUT_OF_RANGE)) self.SendGet(ROOT_DEVICE, self.pid, [0]) def _GetSensorValue(self): if not self._sensors: # Finished self.SetProperty('sensor_values', self._sensor_values) self.Stop() return sensor_index = self._sensors[0]['sensor_number'] self.AddExpectedResults([ self.AckGetResult(action=self._GetNextSensor), self.NackGetResult( RDMNack.NR_HARDWARE_FAULT, advisory="Sensor %d NACK'ed GET SENSOR_VALUE with NR_HARDWARE_FAULT" % sensor_index, action=self._GetNextSensor) ]) self.SendGet(ROOT_DEVICE, self.pid, [sensor_index]) def _GetNextSensor(self): self._sensors.pop(0) self._GetSensorValue() def VerifyResult(self, response, fields): if not response.WasAcked(): return sensor_def = self._sensors[0] sensor_number = fields['sensor_number'] if sensor_def['sensor_number'] != sensor_number: self.AddWarning( 'Requested sensor value for %d, message returned sensor %d' % (sensor_def['sensor_number'], fields['sensor_number'])) return self._sensor_values.append(fields) range_min = sensor_def['range_min'] range_max = sensor_def['range_max'] # Perform sanity checks on the sensor infomation self._CheckValueWithinRange(sensor_number, fields, 'present_value', range_min, range_max) if sensor_def['supports_recording'] & self.HIGHEST_LOWEST_MASK: self._CheckValueWithinRange(sensor_number, fields, 'lowest', range_min, range_max) self._CheckValueWithinRange(sensor_number, fields, 'highest', range_min, range_max) else: self._CheckForZeroField(sensor_number, fields, 'lowest') self._CheckForZeroField(sensor_number, fields, 'highest') if sensor_def['supports_recording'] & self.RECORDED_VALUE_MASK: self._CheckValueWithinRange(sensor_number, fields, 'recorded', range_min, range_max) else: self._CheckForZeroField(sensor_number, fields, 'recorded') def _CheckValueWithinRange(self, sensor_number, fields, name, min, max): if fields[name] < min or fields[name] > max: self.AddWarning( '%s for sensor %d not within range %d - %d, was %d' % (name, sensor_number, min, max, fields[name])) def _CheckForZeroField(self, sensor_number, fields, name): if fields[name]: self.AddWarning( '%s value for sensor %d non-0, but support not declared, was %d' % (name, sensor_number, fields[name])) class GetUndefinedSensorValues(OptionalParameterTestFixture): """Attempt to get sensor values for all sensors that weren't defined.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'SENSOR_VALUE' REQUIRES = ['sensor_definitions'] def Test(self): sensors = self.Property('sensor_definitions') self._missing_sensors = [] for i in xrange(0, 0xff): if i not in sensors: self._missing_sensors.append(i) if self._missing_sensors: # Loop and get all values self._GetSensorValue() else: self.SetNotRun('All sensors declared') return def _GetSensorValue(self): if not self._missing_sensors: self.Stop() return self.AddIfGetSupported( self.NackGetResult(RDMNack.NR_DATA_OUT_OF_RANGE, action=self._GetSensorValue)) self.SendGet(ROOT_DEVICE, self.pid, [self._missing_sensors.pop(0)]) class GetInvalidSensorValue(OptionalParameterTestFixture): """Get the sensor value with the all sensor value (0xff).""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'SENSOR_VALUE' def Test(self): self.AddIfGetSupported(self.NackGetResult(RDMNack.NR_DATA_OUT_OF_RANGE)) data = struct.pack('!B', 0xff) self.SendRawGet(ROOT_DEVICE, self.pid, data) class GetSensorValueWithNoData(TestMixins.GetWithNoDataMixin, OptionalParameterTestFixture): """GET sensor value without any sensor number.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'SENSOR_VALUE' class ResetSensorValue(OptionalParameterTestFixture): """Reset sensor values for all defined sensors.""" CATEGORY = TestCategory.SENSORS PID = 'SENSOR_VALUE' REQUIRES = ['sensor_definitions'] def Test(self): # The head of the list is the current sensor we're querying self._sensors = self.Property('sensor_definitions').values() self._sensor_values = [] if self._sensors: # Loop and get all values self._ResetSensor() else: # No sensors found, make sure we get a NR_DATA_OUT_OF_RANGE self.AddIfSetSupported([ self.NackSetResult(RDMNack.NR_DATA_OUT_OF_RANGE), self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS), ]) self.SendSet(ROOT_DEVICE, self.pid, [0]) def _ResetSensor(self): if not self._sensors: # Finished self.Stop() return sensor_index = self._sensors[0]['sensor_number'] self.AddExpectedResults([ self.AckSetResult(action=self._ResetNextSensor), self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS, action=self._ResetNextSensor), self.NackSetResult( RDMNack.NR_HARDWARE_FAULT, advisory="Sensor %d NACK'ed Set SENSOR_VALUE with NR_HARDWARE_FAULT" % sensor_index, action=self._ResetNextSensor) ]) self.SendSet(ROOT_DEVICE, self.pid, [sensor_index]) def _ResetNextSensor(self): self._sensors.pop(0) self._ResetSensor() def VerifyResult(self, response, fields): # It's not clear at all what to expect in this case. # See http://www.rdmprotocol.org/showthread.php?p=2160 # TODO(simonn, E1.20 task group): figure this out pass class ResetAllSensorValues(OptionalParameterTestFixture): """Set SENSOR_VALUE with sensor number set to 0xff.""" CATEGORY = TestCategory.SENSORS PID = 'SENSOR_VALUE' REQUIRES = ['sensor_definitions'] RECORDED_VALUE_MASK = 0x01 ALL_SENSORS = 0xff def Test(self): supports_recording = False for sensor_def in self.Property('sensor_definitions').values(): supports_recording |= ( sensor_def['supports_recording'] & self.RECORDED_VALUE_MASK) # Some devices don't have set results = [self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS)] if supports_recording: results = [ self.AckSetResult(), self.NackSetResult( RDMNack.NR_UNSUPPORTED_COMMAND_CLASS, warning="One or more recorded sensors found but Set SENSOR_VALUE " "wasn't supported") ] else: results = [ self.AckSetResult(), self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS) ] self.AddIfSetSupported(results) self.SendSet(ROOT_DEVICE, self.pid, [self.ALL_SENSORS]) class ResetUndefinedSensorValues(TestMixins.SetUndefinedSensorValues, OptionalParameterTestFixture): """Attempt to reset sensor values for all sensors that weren't defined.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'SENSOR_VALUE' REQUIRES = ['sensor_definitions'] class ResetSensorValueWithNoData(OptionalParameterTestFixture): """SET sensor value without any sensor number.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'SENSOR_VALUE' def Test(self): self.AddIfSetSupported([ self.NackSetResult(RDMNack.NR_FORMAT_ERROR), self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS), ]) self.SendRawSet(ROOT_DEVICE, self.pid, '') class AllSubDevicesGetSensorValue(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get SENSOR_VALUE to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'SENSOR_VALUE' DATA = [1] # Record Sensors # ----------------------------------------------------------------------------- class GetRecordSensors(TestMixins.UnsupportedGetMixin, OptionalParameterTestFixture): """GET record sensors.""" CATEGORY = TestCategory.SENSORS PID = 'RECORD_SENSORS' class RecordSensorValues(OptionalParameterTestFixture): """Record values for all defined sensors.""" CATEGORY = TestCategory.SENSORS PID = 'RECORD_SENSORS' REQUIRES = ['sensor_definitions'] RECORDED_VALUE_MASK = 0x01 def Test(self): # The head of the list is the current sensor we're querying self._sensors = self.Property('sensor_definitions').values() self._sensor_values = [] if self._sensors: # Loop and get all values self._RecordSensor() else: # No sensors found, make sure we get a NR_DATA_OUT_OF_RANGE self.AddIfSetSupported(self.NackSetResult(RDMNack.NR_DATA_OUT_OF_RANGE)) self.SendSet(ROOT_DEVICE, self.pid, [0]) def _RecordSensor(self): if not self._sensors: # Finished self.Stop() return sensor_def = self._sensors[0] if sensor_def['supports_recording'] & self.RECORDED_VALUE_MASK: self.AddExpectedResults(self.AckSetResult(action=self._RecordNextSensor)) else: message = ("Sensor %d ack'ed RECORD_SENSOR but recorded support was not " "declared" % sensor_def['sensor_number']) self.AddIfSetSupported([ self.NackSetResult(RDMNack.NR_DATA_OUT_OF_RANGE, action=self._RecordNextSensor), self.AckSetResult(action=self._RecordNextSensor, advisory=message), ]) self.SendSet(ROOT_DEVICE, self.pid, [self._sensors[0]['sensor_number']]) def _RecordNextSensor(self): self._sensors.pop(0) self._RecordSensor() class RecordAllSensorValues(OptionalParameterTestFixture): """Set RECORD_SENSORS with sensor number set to 0xff.""" CATEGORY = TestCategory.SENSORS PID = 'RECORD_SENSORS' REQUIRES = ['sensor_recording_supported'] ALL_SENSORS = 0xff def Test(self): if self.Property('sensor_recording_supported'): self.AddIfSetSupported(self.AckSetResult()) else: self.AddIfSetSupported(self.NackSetResult(RDMNack.NR_DATA_OUT_OF_RANGE)) self.SendSet(ROOT_DEVICE, self.pid, [self.ALL_SENSORS]) class RecordUndefinedSensorValues(TestMixins.SetUndefinedSensorValues, OptionalParameterTestFixture): """Attempt to reset sensor values for all sensors that weren't defined.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'RECORD_SENSORS' REQUIRES = ['sensor_definitions'] class RecordSensorValueWithNoData(TestMixins.SetWithNoDataMixin, OptionalParameterTestFixture): """SET record sensors without any sensor number.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'RECORD_SENSORS' # Device Hours # ----------------------------------------------------------------------------- class GetDeviceHours(TestMixins.GetMixin, OptionalParameterTestFixture): """GET the device hours.""" CATEGORY = TestCategory.POWER_LAMP_SETTINGS PID = 'DEVICE_HOURS' EXPECTED_FIELDS = ['hours'] PROVIDES = ['device_hours'] class GetDeviceHoursWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """GET the device hours with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'DEVICE_HOURS' class SetDeviceHours(TestMixins.SetUInt32Mixin, OptionalParameterTestFixture): """Attempt to SET the device hours.""" CATEGORY = TestCategory.POWER_LAMP_SETTINGS PID = 'DEVICE_HOURS' EXPECTED_FIELDS = ['hours'] PROVIDES = ['set_device_hours_supported'] REQUIRES = ['device_hours'] def OldValue(self): return self.Property('device_hours') def VerifyResult(self, response, fields): if response.command_class == PidStore.RDM_SET: set_supported = ( response.WasAcked() or response.nack_reason != RDMNack.NR_UNSUPPORTED_COMMAND_CLASS) self.SetProperty('set_device_hours_supported', set_supported) class SetDeviceHoursWithNoData(OptionalParameterTestFixture): """Set the device hours with no param data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'DEVICE_HOURS' REQUIRES = ['set_device_hours_supported'] def Test(self): if self.Property('set_device_hours_supported'): expected_result = RDMNack.NR_FORMAT_ERROR else: expected_result = RDMNack.NR_UNSUPPORTED_COMMAND_CLASS self.AddIfSetSupported(self.NackSetResult(expected_result)) self.SendRawSet(ROOT_DEVICE, self.pid, '') class AllSubDevicesGetDeviceHours(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get DEVICE_HOURS to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'DEVICE_HOURS' # Lamp Hours # ----------------------------------------------------------------------------- class GetLampHours(TestMixins.GetMixin, OptionalParameterTestFixture): """GET the device hours.""" CATEGORY = TestCategory.POWER_LAMP_SETTINGS PID = 'LAMP_HOURS' EXPECTED_FIELDS = ['hours'] PROVIDES = ['lamp_hours'] class GetLampHoursWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """GET the device hours with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'LAMP_HOURS' class SetLampHours(TestMixins.SetUInt32Mixin, OptionalParameterTestFixture): """Attempt to SET the device hours.""" CATEGORY = TestCategory.POWER_LAMP_SETTINGS PID = 'LAMP_HOURS' EXPECTED_FIELDS = ['hours'] PROVIDES = ['set_lamp_hours_supported'] REQUIRES = ['lamp_hours'] def OldValue(self): return self.Property('lamp_hours') def VerifyResult(self, response, fields): if response.command_class == PidStore.RDM_SET: set_supported = ( response.WasAcked() or response.nack_reason != RDMNack.NR_UNSUPPORTED_COMMAND_CLASS) self.SetProperty('set_lamp_hours_supported', set_supported) class SetLampHoursWithNoData(OptionalParameterTestFixture): """Set the device hours with no param data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'LAMP_HOURS' REQUIRES = ['set_lamp_hours_supported'] def Test(self): if self.Property('set_lamp_hours_supported'): expected_result = RDMNack.NR_FORMAT_ERROR else: expected_result = RDMNack.NR_UNSUPPORTED_COMMAND_CLASS self.AddIfSetSupported(self.NackSetResult(expected_result)) self.SendRawSet(ROOT_DEVICE, self.pid, '') class AllSubDevicesGetLampHours(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get LAMP_HOURS to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'LAMP_HOURS' # Lamp Strikes # ----------------------------------------------------------------------------- class GetLampStrikes(TestMixins.GetMixin, OptionalParameterTestFixture): """GET the lamp strikes.""" CATEGORY = TestCategory.POWER_LAMP_SETTINGS PID = 'LAMP_STRIKES' EXPECTED_FIELDS = ['strikes'] PROVIDES = ['lamp_strikes'] class GetLampStrikesWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """GET the lamp strikes with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'LAMP_STRIKES' class SetLampStrikes(TestMixins.SetUInt32Mixin, OptionalParameterTestFixture): """Attempt to SET the lamp strikes.""" CATEGORY = TestCategory.POWER_LAMP_SETTINGS PID = 'LAMP_STRIKES' EXPECTED_FIELDS = ['strikes'] PROVIDES = ['set_lamp_strikes_supported'] REQUIRES = ['lamp_strikes'] def OldValue(self): return self.Property('lamp_strikes') def VerifyResult(self, response, fields): if response.command_class == PidStore.RDM_SET: set_supported = ( response.WasAcked() or response.nack_reason != RDMNack.NR_UNSUPPORTED_COMMAND_CLASS) self.SetProperty('set_lamp_strikes_supported', set_supported) class SetLampStrikesWithNoData(OptionalParameterTestFixture): """Set the lamp strikes with no param data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'LAMP_STRIKES' REQUIRES = ['set_lamp_strikes_supported'] def Test(self): if self.Property('set_lamp_strikes_supported'): expected_result = RDMNack.NR_FORMAT_ERROR else: expected_result = RDMNack.NR_UNSUPPORTED_COMMAND_CLASS self.AddIfSetSupported(self.NackSetResult(expected_result)) self.SendRawSet(ROOT_DEVICE, self.pid, '') class AllSubDevicesGetLampStrikes(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get LAMP_STRIKES to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'LAMP_STRIKES' # Lamp State # ----------------------------------------------------------------------------- class GetLampState(TestMixins.GetMixin, OptionalParameterTestFixture): """GET the lamp state.""" CATEGORY = TestCategory.POWER_LAMP_SETTINGS PID = 'LAMP_STATE' EXPECTED_FIELDS = ['state'] PROVIDES = ['lamp_state'] class GetLampStateWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """GET the lamp state with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'LAMP_STATE' class SetLampState(TestMixins.SetBoolMixin, OptionalParameterTestFixture): """Attempt to SET the lamp state.""" CATEGORY = TestCategory.POWER_LAMP_SETTINGS PID = 'LAMP_STATE' EXPECTED_FIELDS = ['state'] REQUIRES = ['lamp_state'] def OldValue(self): # We use a bool here so we toggle between off and on # Some responders may not support standby & strike return bool(self.Property('lamp_state')) class SetLampStateWithNoData(TestMixins.SetWithNoDataMixin, OptionalParameterTestFixture): """Set the device state with no param data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'LAMP_STATE' class AllSubDevicesGetLampState(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get LAMP_STATE to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'LAMP_STATE' # Lamp On Mode # ----------------------------------------------------------------------------- class GetLampOnMode(TestMixins.GetMixin, OptionalParameterTestFixture): """GET the lamp on mode.""" CATEGORY = TestCategory.POWER_LAMP_SETTINGS PID = 'LAMP_ON_MODE' EXPECTED_FIELDS = ['mode'] PROVIDES = ['lamp_on_mode'] class GetLampOnModeWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """GET the lamp on mode with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'LAMP_ON_MODE' class SetLampOnMode(TestMixins.SetMixin, OptionalParameterTestFixture): """Attempt to SET the lamp on mode.""" CATEGORY = TestCategory.POWER_LAMP_SETTINGS PID = 'LAMP_ON_MODE' EXPECTED_FIELDS = ['mode'] REQUIRES = ['lamp_on_mode'] ALLOWED_MODES = [0, 1, 2] ALL_MODES = ALLOWED_MODES + [3] + range(0x80, 0xe0) def OldValue(self): old = self.Property('lamp_on_mode') if old in self.ALL_MODES: return old return self.ALL_MODES[0] def NewValue(self): old_value = self.OldValue() try: self.ALLOWED_MODES.index(old_value) except ValueError: return self.ALLOWED_MODES[0] return self.ALLOWED_MODES[(old_value + 1) % len(self.ALLOWED_MODES)] class SetLampOnModeWithNoData(TestMixins.SetWithNoDataMixin, OptionalParameterTestFixture): """Set the device on mode with no param data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'LAMP_ON_MODE' class AllSubDevicesGetLampOnMode(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get LAMP_ON_MODE to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'LAMP_ON_MODE' # Device Hours # ----------------------------------------------------------------------------- class GetDevicePowerCycles(TestMixins.GetMixin, OptionalParameterTestFixture): """GET the device power_cycles.""" CATEGORY = TestCategory.POWER_LAMP_SETTINGS PID = 'DEVICE_POWER_CYCLES' EXPECTED_FIELDS = ['power_cycles'] PROVIDES = ['power_cycles'] class GetDevicePowerCyclesWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """GET the device power_cycles with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'DEVICE_POWER_CYCLES' class ResetDevicePowerCycles(TestMixins.SetUInt32Mixin, OptionalParameterTestFixture): """Attempt to SET the device power_cycles to zero.""" CATEGORY = TestCategory.POWER_LAMP_SETTINGS PID = 'DEVICE_POWER_CYCLES' EXPECTED_FIELDS = ['power_cycles'] REQUIRES = ['power_cycles'] PROVIDES = ['set_device_power_cycles_supported'] def OldValue(self): return self.Property('power_cycles') def NewValue(self): return 0 def VerifyResult(self, response, fields): if response.command_class == PidStore.RDM_SET: set_supported = ( response.WasAcked() or response.nack_reason != RDMNack.NR_UNSUPPORTED_COMMAND_CLASS) self.SetProperty('set_device_power_cycles_supported', set_supported) class SetDevicePowerCycles(TestMixins.SetUInt32Mixin, OptionalParameterTestFixture): """Attempt to SET the device power_cycles.""" CATEGORY = TestCategory.POWER_LAMP_SETTINGS PID = 'DEVICE_POWER_CYCLES' EXPECTED_FIELDS = ['power_cycles'] REQUIRES = ['power_cycles'] def OldValue(self): return self.Property('power_cycles') def Test(self): self.AddIfSetSupported([ self.AckSetResult(action=self.VerifySet), self.NackSetResult(RDMNack.NR_DATA_OUT_OF_RANGE), self.NackSetResult( RDMNack.NR_UNSUPPORTED_COMMAND_CLASS, advisory='SET for %s returned unsupported command class' % self.PID), ]) self.SendSet(ROOT_DEVICE, self.pid, [self.NewValue()]) class SetDevicePowerCyclesWithNoData(OptionalParameterTestFixture): """Set the device power_cycles with no param data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'DEVICE_POWER_CYCLES' REQUIRES = ['set_device_power_cycles_supported'] def Test(self): if self.Property('set_device_power_cycles_supported'): expected_result = RDMNack.NR_FORMAT_ERROR else: expected_result = RDMNack.NR_UNSUPPORTED_COMMAND_CLASS self.AddIfSetSupported(self.NackSetResult(expected_result)) self.SendRawSet(ROOT_DEVICE, self.pid, '') class AllSubDevicesGetDevicePowerCycles(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get DEVICE_POWER_CYCLES to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'DEVICE_POWER_CYCLES' # Display Invert # ----------------------------------------------------------------------------- class GetDisplayInvert(TestMixins.GetMixin, OptionalParameterTestFixture): """GET the display invert setting.""" CATEGORY = TestCategory.DISPLAY_SETTINGS PID = 'DISPLAY_INVERT' EXPECTED_FIELDS = ['invert_status'] PROVIDES = ['display_invert'] class GetDisplayInvertWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """GET the pan invert setting with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'DISPLAY_INVERT' class SetDisplayInvert(TestMixins.SetMixin, OptionalParameterTestFixture): """Attempt to SET the display invert setting.""" CATEGORY = TestCategory.DISPLAY_SETTINGS PID = 'DISPLAY_INVERT' EXPECTED_FIELDS = ['invert_status'] REQUIRES = ['display_invert'] # Some devices can't do auto so we just use on and off here ALLOWED_MODES = [0, 1] ALL_MODES = ALLOWED_MODES + [2] def OldValue(self): old = self.Property('display_invert') if old in self.ALL_MODES: return old return self.ALL_MODES[0] def NewValue(self): old_value = self.OldValue() try: self.ALLOWED_MODES.index(old_value) except ValueError: return self.ALLOWED_MODES[0] return self.ALLOWED_MODES[(old_value + 1) % len(self.ALLOWED_MODES)] class SetDisplayInvertWithNoData(TestMixins.SetWithNoDataMixin, OptionalParameterTestFixture): """Set the display invert with no param data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'DISPLAY_INVERT' class AllSubDevicesGetDisplayInvert(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get DISPLAY_INVERT to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'DISPLAY_INVERT' # Display Level # ----------------------------------------------------------------------------- class GetDisplayLevel(TestMixins.GetMixin, OptionalParameterTestFixture): """GET the display level setting.""" CATEGORY = TestCategory.DISPLAY_SETTINGS PID = 'DISPLAY_LEVEL' EXPECTED_FIELDS = ['level'] PROVIDES = ['display_level'] class GetDisplayLevelWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """GET the pan invert setting with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'DISPLAY_LEVEL' class SetDisplayLevel(TestMixins.SetUInt8Mixin, OptionalParameterTestFixture): """Attempt to SET the display level setting.""" CATEGORY = TestCategory.DISPLAY_SETTINGS PID = 'DISPLAY_LEVEL' EXPECTED_FIELDS = ['level'] REQUIRES = ['display_level'] def OldValue(self): return self.Property('display_level') class SetDisplayLevelWithNoData(TestMixins.SetWithNoDataMixin, OptionalParameterTestFixture): """Set the display level with no param data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'DISPLAY_LEVEL' class AllSubDevicesGetDisplayLevel(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get DISPLAY_LEVEL to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'DISPLAY_LEVEL' # Pan Invert # ----------------------------------------------------------------------------- class GetPanInvert(TestMixins.GetMixin, OptionalParameterTestFixture): """GET the pan invert setting.""" CATEGORY = TestCategory.CONFIGURATION PID = 'PAN_INVERT' EXPECTED_FIELDS = ['invert'] PROVIDES = ['pan_invert'] class GetPanInvertWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """GET the pan invert setting with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'PAN_INVERT' class SetPanInvert(TestMixins.SetBoolMixin, OptionalParameterTestFixture): """Attempt to SET the pan invert setting.""" CATEGORY = TestCategory.CONFIGURATION PID = 'PAN_INVERT' EXPECTED_FIELDS = ['invert'] REQUIRES = ['pan_invert'] def OldValue(self): return self.Property('pan_invert') class SetPanInvertWithNoData(TestMixins.SetWithNoDataMixin, OptionalParameterTestFixture): """Set the pan invert with no param data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'PAN_INVERT' class AllSubDevicesGetPanInvert(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get PAN_INVERT to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'PAN_INVERT' # Tilt Invert # ----------------------------------------------------------------------------- class GetTiltInvert(TestMixins.GetMixin, OptionalParameterTestFixture): """GET the tilt invert setting.""" CATEGORY = TestCategory.CONFIGURATION PID = 'TILT_INVERT' EXPECTED_FIELDS = ['invert'] PROVIDES = ['tilt_invert'] class GetTiltInvertWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """GET the tilt invert setting with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'TILT_INVERT' class SetTiltInvert(TestMixins.SetBoolMixin, OptionalParameterTestFixture): """Attempt to SET the tilt invert setting.""" CATEGORY = TestCategory.CONFIGURATION PID = 'TILT_INVERT' EXPECTED_FIELDS = ['invert'] REQUIRES = ['tilt_invert'] def OldValue(self): return self.Property('tilt_invert') class SetTiltInvertWithNoData(TestMixins.SetWithNoDataMixin, OptionalParameterTestFixture): """Set the tilt invert with no param data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'TILT_INVERT' class AllSubDevicesGetTiltInvert(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get TILT_INVERT to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'TILT_INVERT' # Pan Tilt Swap # ----------------------------------------------------------------------------- class GetPanTiltSwap(TestMixins.GetMixin, OptionalParameterTestFixture): """GET the pan tilt swap setting.""" CATEGORY = TestCategory.CONFIGURATION PID = 'PAN_TILT_SWAP' EXPECTED_FIELDS = ['swap'] PROVIDES = ['pan_tilt_swap'] class GetPanTiltSwapWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """GET the pan tilt swap setting with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'PAN_TILT_SWAP' class SetPanTiltSwap(TestMixins.SetBoolMixin, OptionalParameterTestFixture): """Attempt to SET the pan tilt swap setting.""" CATEGORY = TestCategory.CONFIGURATION PID = 'PAN_TILT_SWAP' EXPECTED_FIELDS = ['swap'] REQUIRES = ['pan_tilt_swap'] def OldValue(self): return self.Property('pan_tilt_swap') class SetPanTiltSwapWithNoData(TestMixins.SetWithNoDataMixin, OptionalParameterTestFixture): """Set the pan tilt swap with no param data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'PAN_TILT_SWAP' class AllSubDevicesGetPanTiltSwap(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get PAN_TILT_SWAP to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'PAN_TILT_SWAP' # Real time clock # ----------------------------------------------------------------------------- class GetRealTimeClock(OptionalParameterTestFixture): """GET the real time clock setting.""" CATEGORY = TestCategory.CONFIGURATION PID = 'REAL_TIME_CLOCK' ALLOWED_RANGES = { 'year': (2003, 65535), 'month': (1, 12), 'day': (1, 31), 'hour': (0, 23), 'minute': (0, 59), } def Test(self): self.AddIfGetSupported( self.AckGetResult(field_names=self.ALLOWED_RANGES.keys() + ['second'])) self.SendGet(ROOT_DEVICE, self.pid) def VerifyResult(self, response, fields): if not response.WasAcked(): return for field, range in self.ALLOWED_RANGES.iteritems(): value = fields[field] if value < range[0] or value > range[1]: self.AddWarning('%s in GET %s is out of range, was %d, expected %s' % (field, self.PID, value, range)) class GetRealTimeClockWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """GET the teal time clock with data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'REAL_TIME_CLOCK' class SetRealTimeClock(OptionalParameterTestFixture): """Set the real time clock.""" CATEGORY = TestCategory.CONFIGURATION PID = 'REAL_TIME_CLOCK' def Test(self): n = datetime.datetime.now() self.AddIfSetSupported([ self.AckSetResult(), self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS), ]) args = [n.year, n.month, n.day, n.hour, n.minute, n.second] self.SendSet(ROOT_DEVICE, self.pid, args) class SetRealTimeClockWithNoData(OptionalParameterTestFixture): """Set the real time clock without any data.""" CATEGORY = TestCategory.CONFIGURATION PID = 'REAL_TIME_CLOCK' def Test(self): self.AddIfSetSupported([ self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS), self.NackSetResult(RDMNack.NR_FORMAT_ERROR), ]) self.SendRawSet(ROOT_DEVICE, self.pid, '') class AllSubDevicesGetRealTimeClock(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get REAL_TIME_CLOCK to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'REAL_TIME_CLOCK' # Identify Device # ----------------------------------------------------------------------------- class GetIdentifyDevice(TestMixins.GetRequiredMixin, ResponderTestFixture): """Get the identify state.""" CATEGORY = TestCategory.CONTROL PID = 'IDENTIFY_DEVICE' PROVIDES = ['identify_state'] EXPECTED_FIELDS = ['identify_state'] class GetIdentifyDeviceWithData(TestMixins.GetMandatoryPIDWithDataMixin, ResponderTestFixture): """Get the identify state with data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'IDENTIFY_DEVICE' class SetIdentifyDevice(ResponderTestFixture): """Set the identify state.""" CATEGORY = TestCategory.CONTROL PID = 'IDENTIFY_DEVICE' REQUIRES = ['identify_state'] def Test(self): self.identify_mode = self.Property('identify_state') self.new_mode = not self.identify_mode self.AddExpectedResults( self.AckSetResult(action=self.VerifyIdentifyMode)) self.SendSet(ROOT_DEVICE, self.pid, [self.new_mode]) def VerifyIdentifyMode(self): self.AddExpectedResults( self.AckGetResult(field_values={'identify_state': self.new_mode})) self.SendGet(ROOT_DEVICE, self.pid) def ResetState(self): # Reset back to the old value self.SendSet(ROOT_DEVICE, self.pid, [self.identify_mode]) self._wrapper.Run() class SetOutOfRangeIdentifyDevice(ResponderTestFixture): """Set the identify state to a value which is out of range.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'IDENTIFY_DEVICE' REQUIRES = ['identify_state'] def Test(self): self.AddExpectedResults( self.NackSetResult(RDMNack.NR_DATA_OUT_OF_RANGE)) self.SendSet(ROOT_DEVICE, self.pid, [2]) def ResetState(self): # Reset back to the old value self.SendSet(ROOT_DEVICE, self.pid, [self.Property('identify_state')]) self._wrapper.Run() class SetVendorcastIdentifyDevice(TestMixins.SetNonUnicastIdentifyMixin, ResponderTestFixture): """Set the identify state using the vendorcast uid.""" CATEGORY = TestCategory.CONTROL PID = 'IDENTIFY_DEVICE' def Uid(self): return UID.VendorcastAddress(self._uid.manufacturer_id) class SetBroadcastIdentifyDevice(TestMixins.SetNonUnicastIdentifyMixin, ResponderTestFixture): """Set the identify state using the broadcast uid.""" CATEGORY = TestCategory.CONTROL PID = 'IDENTIFY_DEVICE' def Uid(self): return UID.AllDevices() class SetOtherVendorcastIdentifyDevice(TestMixins.SetNonUnicastIdentifyMixin, ResponderTestFixture): """Send a vendorcast identify off to another manufacturer's ID.""" CATEGORY = TestCategory.CONTROL PID = 'IDENTIFY_DEVICE' def States(self): return [ self.TurnOn, self.VerifyOn, self.TurnOff, self.VerifyOn, ] def Uid(self): # Use a different vendor's vendorcast address vendorcast_id = self._uid.manufacturer_id if vendorcast_id == 0: vendorcast_id += 1 else: vendorcast_id -= 1 return UID(vendorcast_id, 0xffffffff) class SetIdentifyDeviceWithNoData(ResponderTestFixture): """Set the identify state with no data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'IDENTIFY_DEVICE' REQUIRES = ['identify_state'] def Test(self): self.AddExpectedResults(self.NackSetResult(RDMNack.NR_FORMAT_ERROR)) self.SendRawSet(ROOT_DEVICE, self.pid, '') def ResetState(self): self.SendSet(ROOT_DEVICE, self.pid, [self.Property('identify_state')]) self._wrapper.Run() class AllSubDevicesGetIdentifyDevice(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get IDENTIFY_DEVICE to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'IDENTIFY_DEVICE' class GetSubDeviceIdentifyDevice(ResponderTestFixture): """Check that IDENTIFY_DEVICE is supported on all sub devices.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'IDENTIFY_DEVICE' REQUIRES = ['sub_device_addresses'] def Test(self): self._sub_devices = self.Property('sub_device_addresses').keys() self._sub_devices.reverse() self._GetIdentifyDevice() def _GetIdentifyDevice(self): if not self._sub_devices: self.Stop() return self.AddExpectedResults(self.AckGetResult(action=self._GetIdentifyDevice)) sub_device = self._sub_devices.pop() self.SendGet(sub_device, self.pid) # Power State # ----------------------------------------------------------------------------- class GetPowerState(TestMixins.GetMixin, OptionalParameterTestFixture): """Get the power state mode.""" CATEGORY = TestCategory.CONTROL PID = 'POWER_STATE' PROVIDES = ['power_state'] EXPECTED_FIELDS = ['power_state'] # The allowed power states ALLOWED_STATES = [0, 1, 2, 0xff] def VerifyResult(self, response, fields): super(GetPowerState, self).VerifyResult(response, fields) if response.WasAcked(): if fields['power_state'] not in self.ALLOWED_STATES: self.AddWarning('Power state of 0x%hx is not defined' % fields['power_state']) class GetPowerStateWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """Get the power state mode with data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'POWER_STATE' class SetPowerState(TestMixins.SetMixin, OptionalParameterTestFixture): """Set the power state.""" CATEGORY = TestCategory.CONTROL PID = 'POWER_STATE' REQUIRES = ['power_state'] EXPECTED_FIELDS = ['power_state'] def OldValue(self): old = self.Property('power_state') if old in GetPowerState.ALLOWED_STATES: return old return GetPowerState.ALLOWED_STATES[0] def NewValue(self): old_value = self.Property('power_state') try: GetPowerState.ALLOWED_STATES.index(old_value) except ValueError: return GetPowerState.ALLOWED_STATES[0] length = len(GetPowerState.ALLOWED_STATES) return GetPowerState.ALLOWED_STATES[(old_value + 1) % length] def ResetState(self): if not self.OldValue(): return # Reset back to the old value self.SendSet(ROOT_DEVICE, self.pid, [self.OldValue()]) self._wrapper.Run() class SetPowerStateWithNoData(TestMixins.SetWithNoDataMixin, OptionalParameterTestFixture): """Set the power state with no data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'POWER_STATE' class AllSubDevicesGetPowerState(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get POWER_STATE to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'POWER_STATE' # Self Test # ----------------------------------------------------------------------------- class GetPerformSelfTest(TestMixins.GetMixin, OptionalParameterTestFixture): """Get the current self test settings.""" CATEGORY = TestCategory.CONTROL PID = 'PERFORM_SELFTEST' EXPECTED_FIELDS = ['tests_active'] class GetPerformSelfTestWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """Get the current self test settings with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'PERFORM_SELFTEST' class SetPerformSelfTest(TestMixins.SetMixin, OptionalParameterTestFixture): """Turn any running self tests off.""" CATEGORY = TestCategory.CONTROL PID = 'PERFORM_SELFTEST' EXPECTED_FIELDS = ['tests_active'] def NewValue(self): return False def ResetState(self): # Override this so we don't reset pass class SetPerformSelfTestWithNoData(TestMixins.SetWithNoDataMixin, OptionalParameterTestFixture): """Set the perform self test setting but don't provide any data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'PERFORM_SELFTEST' class AllSubDevicesGetPerformSelfTest(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get PERFORM_SELFTEST to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'PERFORM_SELFTEST' # Self Test Description # ----------------------------------------------------------------------------- class GetSelfTestDescription(OptionalParameterTestFixture): """Get the self test description.""" CATEGORY = TestCategory.CONTROL PID = 'SELF_TEST_DESCRIPTION' def Test(self): self.AddIfGetSupported([ self.AckGetResult(), self.NackGetResult(RDMNack.NR_DATA_OUT_OF_RANGE), ]) # Try to get a description for the first self test self.SendGet(ROOT_DEVICE, self.pid, [1]) def VerifyResult(self, response, fields): if not response.WasAcked(): return if ContainsUnprintable(fields['description']): self.AddAdvisory( 'Description field in self test description for test number %d ' 'contains unprintable characters, was %s' % (1, fields['description'].encode('string-escape'))) class GetSelfTestDescriptionWithNoData(TestMixins.GetWithNoDataMixin, OptionalParameterTestFixture): """Get the self test description with no data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'SELF_TEST_DESCRIPTION' class FindSelfTests(OptionalParameterTestFixture): """Locate the self tests by sending SELF_TEST_DESCRIPTION messages.""" CATEGORY = TestCategory.CONTROL PID = 'SELF_TEST_DESCRIPTION' PROVIDES = ['self_test_descriptions'] def Test(self): self._self_tests = {} # Stores the discovered self tests self._current_index = 0 # The current self test we're trying to query self._CheckForSelfTest() def _CheckForSelfTest(self): # For each message we should either see a NR_DATA_OUT_OF_RANGE or an ack if self._current_index == 255: self.SetProperty('self_test_descriptions', self._self_tests) self.Stop() return if self.PidSupported(): self.AddExpectedResults([ self.NackGetResult(RDMNack.NR_DATA_OUT_OF_RANGE, action=self._CheckForSelfTest), self.AckGetResult(action=self._CheckForSelfTest) ]) else: self.AddExpectedResults(self.NackGetResult(RDMNack.NR_UNKNOWN_PID)) self._current_index += 1 self.SendGet(ROOT_DEVICE, self.pid, [self._current_index]) def VerifyResult(self, response, fields): if response.WasAcked(): if self._current_index != fields['test_number']: self.AddWarning( 'Requested self test %d, message returned self test %d' % (self._current_index, fields['test_number'])) else: self._self_tests[self._current_index] = fields['description'] if ContainsUnprintable(fields['description']): self.AddAdvisory( 'Description field in self test description for test number %d ' 'contains unprintable characters, was %s' % (fields['test_number'], fields['description'].encode('string-escape'))) class AllSubDevicesGetSelfTestDescription(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get SELF_TEST_DESCRIPTION to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'SELF_TEST_DESCRIPTION' DATA = [1] # Factory Defaults # ----------------------------------------------------------------------------- class GetFactoryDefaults(OptionalParameterTestFixture): """GET the factory defaults pid.""" CATEGORY = TestCategory.PRODUCT_INFORMATION PID = 'FACTORY_DEFAULTS' def Test(self): self.AddIfGetSupported(self.AckGetResult(field_names=['using_defaults'])) self.SendGet(ROOT_DEVICE, self.pid) class GetFactoryDefaultsWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """GET the factory defaults pid with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'FACTORY_DEFAULTS' class ResetFactoryDefaults(OptionalParameterTestFixture): """Reset to factory defaults.""" CATEGORY = TestCategory.PRODUCT_INFORMATION PID = 'FACTORY_DEFAULTS' # Dependencies so that we don't reset the fields before checking them. DEPS = [GetStartAddress, GetPersonality] def Test(self): self.AddIfSetSupported(self.AckSetResult(action=self.VerifySet)) self.SendSet(ROOT_DEVICE, self.pid) def VerifySet(self): self.AddIfGetSupported( self.AckGetResult(field_values={'using_defaults': True})) self.SendGet(ROOT_DEVICE, self.pid) class ResetFactoryDefaultsWithData(TestMixins.SetWithDataMixin, OptionalParameterTestFixture): """Reset to factory defaults with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'FACTORY_DEFAULTS' class AllSubDevicesGetFactoryDefaults(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get FACTORY_DEFAULTS to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'FACTORY_DEFAULTS' # CAPTURE_PRESET # ----------------------------------------------------------------------------- class GetCapturePreset(TestMixins.UnsupportedGetMixin, OptionalParameterTestFixture): """GET capture preset.""" CATEGORY = TestCategory.CONTROL PID = 'CAPTURE_PRESET' class SetCapturePresetWithNoData(TestMixins.SetWithNoDataMixin, OptionalParameterTestFixture): """Set capture preset with no data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'CAPTURE_PRESET' class CapturePreset(TestMixins.SetWithNoDataMixin, OptionalParameterTestFixture): """Capture preset information.""" CATEGORY = TestCategory.CONTROL PID = 'CAPTURE_PRESET' def Test(self): # This test doesn't check much because the standard is rather vague in this # area. There is also no way to read back preset data so it's impossible to # tell if this worked. self.AddIfSetSupported(self.AckSetResult()) # Scene 1, no timing information self.SendSet(ROOT_DEVICE, self.pid, [1, 0, 0, 0]) # PRESET_PLAYBACK # ----------------------------------------------------------------------------- class GetPresetPlaybackWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """Get the preset playback with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'PRESET_PLAYBACK' class GetPresetPlayback(TestMixins.GetMixin, OptionalParameterTestFixture): """Get the preset playback.""" CATEGORY = TestCategory.CONTROL PID = 'PRESET_PLAYBACK' EXPECTED_FIELDS = ['mode'] class SetPresetPlaybackWithNoData(TestMixins.SetWithNoDataMixin, OptionalParameterTestFixture): """Set preset playback with no data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'PRESET_PLAYBACK' class SetPresetPlayback(OptionalParameterTestFixture): """Set the preset playback.""" CATEGORY = TestCategory.CONTROL PID = 'PRESET_PLAYBACK' OFF = 0 FULL = 0xff def Test(self): self.AddIfSetSupported(self.AckSetResult(action=self.VerifySet)) self.SendSet(ROOT_DEVICE, self.pid, [self.OFF, self.FULL]) def VerifySet(self): self.AddExpectedResults( self.AckGetResult(field_values={ 'mode': self.OFF, 'level': self.FULL})) self.SendGet(ROOT_DEVICE, self.pid) class AllSubDevicesGetPresetPlayback(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get PRESET_PLAYBACK to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'PRESET_PLAYBACK' # E1.37 PIDS # ============================================================================= # IDENTIFY_MODE # ----------------------------------------------------------------------------- class GetIdentifyMode(TestMixins.GetMixin, OptionalParameterTestFixture): """Get IDENTIFY_MODE.""" CATEGORY = TestCategory.CONTROL PID = 'IDENTIFY_MODE' PROVIDES = ['identify_mode'] EXPECTED_FIELDS = ['identify_mode'] class GetIdentifyModeWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """Get IDENTIFY_MODE with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'IDENTIFY_MODE' class SetIdentifyMode(TestMixins.SetMixin, OptionalParameterTestFixture): """Set IDENTIFY_MODE with extra data.""" CATEGORY = TestCategory.CONTROL PID = 'IDENTIFY_MODE' REQUIRES = ['identify_mode'] LOUD = 0xff QUIET = 0x00 EXPECTED_FIELDS = ['identify_mode'] def OldValue(self): return self.Property('identify_mode') def NewValue(self): old_value = self.OldValue() if old_value is None: return self.QUIET if old_value: return self.QUIET else: return self.LOUD class SetIdentifyModeWithNoData(TestMixins.SetWithNoDataMixin, OptionalParameterTestFixture): """Set IDENTIFY_MODE with no data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'IDENTIFY_MODE' class AllSubDevicesGetIdentifyMode(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Get IDENTIFY_MODE addressed to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'IDENTIFY_MODE' # DMX_BLOCK_ADDRESS # ----------------------------------------------------------------------------- class GetDMXBlockAddress(OptionalParameterTestFixture): """Get DMX_BLOCK_ADDRESS.""" CATEGORY = TestCategory.DMX_SETUP PID = 'DMX_BLOCK_ADDRESS' PROVIDES = ['total_sub_device_footprint', 'base_dmx_address'] REQUIRES = ['sub_device_addresses', 'sub_device_footprints'] NON_CONTIGUOUS = 0xffff def Test(self): self.expected_footprint = sum( self.Property('sub_device_footprints').values()) self.AddIfGetSupported(self.AckGetResult()) self.SendGet(ROOT_DEVICE, self.pid) def VerifyResult(self, response, fields): footprint = None base_address = None if response.WasAcked(): footprint = fields['sub_device_footprint'] base_address = fields['base_dmx_address'] if footprint > MAX_DMX_ADDRESS: self.AddWarning('Sub device footprint > 512, was %d' % footprint) if (base_address == 0 or (base_address > MAX_DMX_ADDRESS and base_address != self.NON_CONTIGUOUS)): self.AddWarning('Base DMX address is outside range 1-512, was %d' % base_address) if footprint != self.expected_footprint: self.SetFailed( "Sub device footprint (%d) didn't match sum of sub-device " "footprints (%d)" % (fields['sub_device_footprint'], self.expected_footprint)) is_contiguous = self.CheckForContiguousSubDevices() if is_contiguous and base_address == self.NON_CONTIGUOUS: self.SetFailed( 'Sub device addresses are contiguous, but block address returned ' '0xffff') elif not (is_contiguous or base_address == self.NON_CONTIGUOUS): self.SetFailed( "Sub device addresses aren't contiguous, but block address " "didn't return 0xffff") self.SetProperty('total_sub_device_footprint', footprint) self.SetProperty('base_dmx_address', base_address) def CheckForContiguousSubDevices(self): addresses = self.Property('sub_device_addresses') footprints = self.Property('sub_device_footprints') next_address = None for index in sorted(addresses): if next_address is None: next_address = addresses[index] + footprints[index] elif addresses[index] != next_address: return False else: next_address += footprints[index] return True class CheckBlockAddressConsistency(ResponderTestFixture): """Check that the device has subdevices if DMX_BLOCK_ADDRESS is supported.""" CATEGORY = TestCategory.CONTROL REQUIRES = ['sub_device_count', 'supported_parameters'] def Test(self): pid = self.LookupPid('DMX_BLOCK_ADDRESS') if (pid.value in self.Property('supported_parameters') and self.Property('sub_device_count') == 0): self.AddAdvisory('DMX_BLOCK_ADDRESS supported but sub device count was 0') self.SetPassed() self.Stop() class GetDMXBlockAddressWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """Get DMX_BLOCK_ADDRESS with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'DMX_BLOCK_ADDRESS' class SetDMXBlockAddress(TestMixins.SetMixin, OptionalParameterTestFixture): """SET the DMX_BLOCK_ADDRESS.""" CATEGORY = TestCategory.DMX_SETUP PID = 'DMX_BLOCK_ADDRESS' REQUIRES = ['total_sub_device_footprint', 'base_dmx_address'] EXPECTED_FIELDS = ['base_dmx_address'] def NewValue(self): base_address = self.Property('base_dmx_address') footprint = self.Property('total_sub_device_footprint') if base_address is None or footprint is None: return 1 if base_address == GetDMXBlockAddress.NON_CONTIGUOUS: return 1 new_address = base_address + 1 if new_address + footprint > MAX_DMX_ADDRESS: new_address = 1 return new_address def ResetState(self): # We can't reset as the addresses may not have been contiguous pass class SetZeroDMXBlockAddress(TestMixins.SetZeroUInt16Mixin, OptionalParameterTestFixture): """Set DMX_BLOCK_ADDRESS to 0.""" PID = 'DMX_BLOCK_ADDRESS' DEPS = [SetDMXBlockAddress] class SetOversizedDMXBlockAddress(OptionalParameterTestFixture): """Set DMX_BLOCK_ADDRESS to 513.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'DMX_BLOCK_ADDRESS' DEPS = [SetDMXBlockAddress] def Test(self): self.AddIfSetSupported(self.NackSetResult(RDMNack.NR_DATA_OUT_OF_RANGE)) data = struct.pack('!H', MAX_DMX_ADDRESS + 1) self.SendRawSet(ROOT_DEVICE, self.pid, data) class SetDMXBlockAddressWithNoData(TestMixins.SetWithNoDataMixin, OptionalParameterTestFixture): """Set DMX_BLOCK_ADDRESS with no data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'DMX_BLOCK_ADDRESS' class AllSubDevicesGetDmxBlockAddress(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Get DMX_BLOCK_ADDRESS addressed to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'DMX_BLOCK_ADDRESS' # DMX_FAIL_MODE # ----------------------------------------------------------------------------- class GetDmxFailMode(OptionalParameterTestFixture): """GET DMX_FAIL_MODE.""" CATEGORY = TestCategory.DMX_SETUP PID = 'DMX_FAIL_MODE' PROVIDES = ['dmx_fail_settings'] def Test(self): self.AddIfGetSupported(self.AckGetResult()) self.SendGet(ROOT_DEVICE, self.pid) def VerifyResult(self, response, fields): if fields is None: fields = {} self.SetProperty('dmx_fail_settings', fields) class GetFailUpModeWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """GET DMX_FAIL_MODE with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'DMX_FAIL_MODE' class SetDmxFailMode(OptionalParameterTestFixture): """Set DMX_FAIL_MODE without changing the settings.""" CATEGORY = TestCategory.DMX_SETUP PID = 'DMX_FAIL_MODE' PROVIDES = ['set_dmx_fail_mode_supported'] REQUIRES = ['dmx_fail_settings'] def Test(self): settings = self.Property('dmx_fail_settings', {}) self.AddIfSetSupported([ self.AckSetResult(), self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS), ]) self.SendSet( ROOT_DEVICE, self.pid, [settings.get('scene_number', 0), settings.get('hold_time', 0), settings.get('loss_of_signal_delay', 0), settings.get('level', 0)] ) def VerifyResult(self, response, fields): self.SetProperty('set_dmx_fail_mode_supported', response.WasAcked()) class SetDmxFailModeMinimumTime(TestMixins.SetDmxFailModeMixin, OptionalParameterTestFixture): """Verify the minimum times in PRESET_INFO are supported in DMX_FAIL_MODE.""" def Test(self): self.in_get = False if self.Property('set_dmx_fail_mode_supported'): self.AddIfSetSupported(self.AckSetResult(action=self.GetFailMode)) else: self.AddIfSetSupported( self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS)) preset_info = self.Property('preset_info', {}) self.known_limits = preset_info != {} self.delay_time = preset_info.get('min_fail_delay_time', 0) self.hold_time = preset_info.get('min_fail_hold_time', 0) self.SendSet(ROOT_DEVICE, self.pid, [0, self.delay_time, self.hold_time, 255]) def GetFailMode(self): self.in_get = True fields = {} if self.known_limits: fields['loss_of_signal_delay'] = self.delay_time fields['hold_time'] = self.hold_time self.AddIfGetSupported(self.AckGetResult(field_values=fields)) self.SendGet(ROOT_DEVICE, self.pid) class SetDmxFailModeMaximumTime(TestMixins.SetDmxFailModeMixin, OptionalParameterTestFixture): """Verify the maximum times in PRESET_INFO are supported in DMX_FAIL_MODE.""" def Test(self): self.in_get = False if self.Property('set_dmx_fail_mode_supported'): self.AddIfSetSupported(self.AckSetResult(action=self.GetFailMode)) else: self.AddIfSetSupported( self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS)) preset_info = self.Property('preset_info', {}) self.known_limits = preset_info != {} self.delay_time = preset_info.get('max_fail_delay_time', self.INFINITE_TIME) self.hold_time = preset_info.get('max_fail_hold_time', self.INFINITE_TIME) self.SendSet(ROOT_DEVICE, self.pid, [0, self.delay_time, self.hold_time, 255]) def GetFailMode(self): self.in_get = True fields = {} if self.known_limits: fields['loss_of_signal_delay'] = self.delay_time fields['hold_time'] = self.hold_time self.AddIfGetSupported(self.AckGetResult(field_values=fields)) self.SendGet(ROOT_DEVICE, self.pid) class SetDmxFailModeInfiniteTimes(TestMixins.SetDmxFailModeMixin, OptionalParameterTestFixture): """Check if infinite times are supported for DMX_FAIL_MODE.""" def Test(self): self.in_get = False if self.Property('set_dmx_fail_mode_supported'): self.AddIfSetSupported(self.AckSetResult(action=self.GetFailMode)) else: self.AddIfSetSupported( self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS)) self.SendSet(ROOT_DEVICE, self.pid, [0, 'infinite', 'infinite', 255]) def GetFailMode(self): self.in_get = True self.AddIfGetSupported(self.AckGetResult()) self.SendGet(ROOT_DEVICE, self.pid) def VerifyResult(self, response, fields): if not response.WasAcked() or not self.in_get: return self.CheckField( 'delay time', self.Property('preset_info', {}).get('fail_infinite_delay_supported'), fields['loss_of_signal_delay']) self.CheckField( 'hold time', self.Property('preset_info', {}).get('fail_infinite_hold_supported'), fields['hold_time']) def CheckField(self, field_name, is_supported, new_value): if is_supported is None: # We can't tell is the new value is correct or not return if is_supported and new_value != self.INFINITE_TIME: self.SetFailed( 'infinite %s was supported, but the value was truncated after a set.' ' Expected %d, got %d' % (field_name, self.INFINITE_TIME, new_value)) elif not is_supported and new_value == self.INFINITE_TIME: self.SetFailed( 'infinite %s was not supported, but the value was not truncated ' 'after a set.' % field_name) class SetDmxFailModeOutOfRangeMaximumTime(TestMixins.SetDmxFailModeMixin, OptionalParameterTestFixture): """Check that the maximum times for DMX_FAIL_MODE are honored.""" def Test(self): self.in_get = False preset_info = self.Property('preset_info', {}) self.max_delay_time = preset_info.get('max_fail_delay_time') self.max_hold_time = preset_info.get('max_fail_hold_time') if self.max_delay_time is None or self.max_hold_time is None: self.SetNotRun("Max times unknown - PRESET_INFO wasn't acked") return delay_time = self.max_delay_time delay_time_field = self.pid.GetRequestField(RDM_SET, 'loss_of_signal_delay') # 0xffff means 'fail mode not supported' if delay_time_field.RawValue(self.max_delay_time) < 0xffff - 1: delay_time = delay_time_field.DisplayValue( delay_time_field.RawValue(self.max_delay_time) + 1) # Increment by 1 hold_time = self.max_hold_time hold_time_field = self.pid.GetRequestField(RDM_SET, 'hold_time') # 0xffff means 'fail mode not supported' if hold_time_field.RawValue(self.max_hold_time) < 0xffff - 1: hold_time = hold_time_field.DisplayValue( hold_time_field.RawValue(self.max_hold_time) + 1) # Increment by 1 if self.Property('set_dmx_fail_mode_supported'): self.AddIfSetSupported(self.AckSetResult(action=self.GetFailMode)) else: self.AddIfSetSupported( self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS)) self.SendSet(ROOT_DEVICE, self.pid, [0, delay_time, hold_time, 255]) def GetFailMode(self): self.in_get = True fields = { 'loss_of_signal_delay': self.max_delay_time, 'hold_time': self.max_hold_time, } self.AddIfGetSupported(self.AckGetResult(field_values=fields)) self.SendGet(ROOT_DEVICE, self.pid) class SetDmxFailModeOutOfRangeMinimumTime(TestMixins.SetDmxFailModeMixin, OptionalParameterTestFixture): """Check that the minimum times for DMX_FAIL_MODE are honored.""" def Test(self): self.in_get = False preset_info = self.Property('preset_info', {}) self.min_delay_time = preset_info.get('min_fail_delay_time') self.min_hold_time = preset_info.get('min_fail_hold_time') if self.min_delay_time is None or self.min_hold_time is None: self.SetNotRun("Max times unknown - PRESET_INFO wasn't acked") return delay_time = self.min_delay_time delay_time_field = self.pid.GetRequestField(RDM_SET, 'loss_of_signal_delay') # 0xffff means 'fail mode not supported' if (delay_time_field.RawValue(self.min_delay_time) > 1 and delay_time_field.RawValue(self.min_delay_time) < 0xffff): delay_time = delay_time_field.DisplayValue( delay_time_field.RawValue(self.min_delay_time) - 1) # Decrement by 1 hold_time = self.min_hold_time hold_time_field = self.pid.GetRequestField(RDM_SET, 'hold_time') # 0xffff means 'fail mode not supported' if (hold_time_field.RawValue(self.min_hold_time) > 1 and hold_time_field.RawValue(self.min_hold_time) < 0xffff): hold_time = hold_time_field.DisplayValue( hold_time_field.RawValue(self.min_hold_time) - 1) # Decrement by 1 if self.Property('set_dmx_fail_mode_supported'): self.AddIfSetSupported(self.AckSetResult(action=self.GetFailMode)) else: self.AddIfSetSupported( self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS)) self.SendSet(ROOT_DEVICE, self.pid, [0, delay_time, hold_time, 255]) def GetFailMode(self): self.in_get = True fields = { 'loss_of_signal_delay': self.min_delay_time, 'hold_time': self.min_hold_time, } self.AddIfGetSupported(self.AckGetResult(field_values=fields)) self.SendGet(ROOT_DEVICE, self.pid) class SetFailModeWithNoData(TestMixins.SetWithNoDataMixin, OptionalParameterTestFixture): """Set DMX_FAIL_MODE with no data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'DMX_FAIL_MODE' class AllSubDevicesGetDmxFailMode(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Get DMX_FAIL_MODE addressed to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'DMX_FAIL_MODE' # DMX_STARTUP_MODE # ----------------------------------------------------------------------------- class GetDmxStartupMode(OptionalParameterTestFixture): """Get DMX_STARTUP_MODE.""" CATEGORY = TestCategory.DMX_SETUP PID = 'DMX_STARTUP_MODE' PROVIDES = ['dmx_startup_settings'] def Test(self): self.AddIfGetSupported(self.AckGetResult()) self.SendGet(ROOT_DEVICE, self.pid) def VerifyResult(self, response, fields): if fields is None: fields = {} self.SetProperty('dmx_startup_settings', fields) class GetStartUpModeWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """Get DMX_STARTUP_MODE with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'DMX_STARTUP_MODE' class SetDmxStartupMode(OptionalParameterTestFixture): """Set DMX_STARTUP_MODE without changing the settings.""" CATEGORY = TestCategory.DMX_SETUP PID = 'DMX_FAIL_MODE' PROVIDES = ['set_dmx_startup_mode_supported'] REQUIRES = ['dmx_startup_settings'] def Test(self): settings = self.Property('dmx_startup_settings', {}) self.AddIfSetSupported([ self.AckSetResult(), self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS), ]) self.SendSet( ROOT_DEVICE, self.pid, [settings.get('scene_number', 0), settings.get('hold_time', 0), settings.get('startup_delay', 0), settings.get('level', 0)] ) def VerifyResult(self, response, fields): self.SetProperty('set_dmx_startup_mode_supported', response.WasAcked()) class SetDmxStartupModeMinimumTime(TestMixins.SetDmxStartupModeMixin, OptionalParameterTestFixture): """Verify DMX_STARTUP_MODE supports the min. times from PRESET_INFO.""" def Test(self): self.in_get = False if self.Property('set_dmx_startup_mode_supported'): self.AddIfSetSupported(self.AckSetResult(action=self.GetStartupMode)) else: self.AddIfSetSupported( self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS)) preset_info = self.Property('preset_info', {}) self.known_limits = preset_info != {} self.delay_time = preset_info.get('min_startup_delay_time', 0) self.hold_time = preset_info.get('min_startup_hold_time', 0) self.SendSet(ROOT_DEVICE, self.pid, [0, self.delay_time, self.hold_time, 255]) def GetStartupMode(self): self.in_get = True fields = {} if self.known_limits: fields['startup_delay'] = self.delay_time fields['hold_time'] = self.hold_time self.AddIfGetSupported(self.AckGetResult(field_values=fields)) self.SendGet(ROOT_DEVICE, self.pid) class SetDmxStartupModeMaximumTime(TestMixins.SetDmxStartupModeMixin, OptionalParameterTestFixture): """Verify DMX_STARTUP_MODE supports the max. times from PRESET_INFO.""" def Test(self): self.in_get = False if self.Property('set_dmx_startup_mode_supported'): self.AddIfSetSupported(self.AckSetResult(action=self.GetStartupMode)) else: self.AddIfSetSupported( self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS)) preset_info = self.Property('preset_info', {}) self.known_limits = preset_info != {} self.delay_time = preset_info.get('max_startup_delay_time', self.INFINITE_TIME) self.hold_time = preset_info.get('max_startup_hold_time', self.INFINITE_TIME) self.SendSet(ROOT_DEVICE, self.pid, [0, self.delay_time, self.hold_time, 255]) def GetStartupMode(self): self.in_get = True fields = {} if self.known_limits: fields['startup_delay'] = self.delay_time fields['hold_time'] = self.hold_time self.AddIfGetSupported(self.AckGetResult(field_values=fields)) self.SendGet(ROOT_DEVICE, self.pid) class SetDmxStartupModeInfiniteTimes(TestMixins.SetDmxStartupModeMixin, OptionalParameterTestFixture): """Check if infinite times are supported for DMX_STARTUP_MODE.""" def Test(self): self.in_get = False if self.Property('set_dmx_startup_mode_supported'): self.AddIfSetSupported(self.AckSetResult(action=self.GetStartupMode)) else: self.AddIfSetSupported( self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS)) self.SendSet(ROOT_DEVICE, self.pid, [0, 'infinite', 'infinite', 255]) def GetStartupMode(self): self.in_get = True self.AddIfGetSupported(self.AckGetResult()) self.SendGet(ROOT_DEVICE, self.pid) def VerifyResult(self, response, fields): if not response.WasAcked() or not self.in_get: return self.CheckField( 'delay time', self.Property('preset_info', {}).get( 'startup_infinite_delay_supported'), fields['startup_delay']) self.CheckField( 'hold time', self.Property('preset_info', {}).get('startup_infinite_hold_supported'), fields['hold_time']) def CheckField(self, field_name, is_supported, new_value): if is_supported is None: # We can't tell is the new value is correct or not return if is_supported and new_value != self.INFINITE_TIME: self.SetFailed( 'infinite %s was supported, but the value was truncated after a set.' ' Expected %d, got %d' % (field_name, self.INFINITE_TIME, new_value)) elif not is_supported and new_value == self.INFINITE_TIME: self.SetFailed( 'infinite %s was not supported, but the value was not truncated ' 'after a set.' % field_name) class SetDmxStartupModeOutOfRangeMaximumTime(TestMixins.SetDmxStartupModeMixin, OptionalParameterTestFixture): """Check that the maximum times for DMX_STARTUP_MODE are honored.""" def Test(self): self.in_get = False preset_info = self.Property('preset_info', {}) self.max_delay_time = preset_info.get('max_startup_delay_time') self.max_hold_time = preset_info.get('max_startup_hold_time') if self.max_delay_time is None or self.max_hold_time is None: self.SetNotRun("Max times unknown - PRESET_INFO wasn't acked") return delay_time = self.max_delay_time delay_time_field = self.pid.GetRequestField(RDM_SET, 'startup_delay') # 0xffff means 'startup mode not supported' if delay_time_field.RawValue(self.max_delay_time) < (0xffff - 1): delay_time = delay_time_field.DisplayValue( delay_time_field.RawValue(self.max_delay_time) + 1) # Increment by 1 hold_time = self.max_hold_time hold_time_field = self.pid.GetRequestField(RDM_SET, 'hold_time') # 0xffff means 'startup mode not supported' if hold_time_field.RawValue(self.max_hold_time) < (0xffff - 1): hold_time = hold_time_field.DisplayValue( hold_time_field.RawValue(self.max_hold_time) + 1) # Increment by 1 if self.Property('set_dmx_startup_mode_supported'): self.AddIfSetSupported(self.AckSetResult(action=self.GetStartupMode)) else: self.AddIfSetSupported( self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS)) self.SendSet(ROOT_DEVICE, self.pid, [0, delay_time, hold_time, 255]) def GetStartupMode(self): self.in_get = True fields = { 'startup_delay': self.max_delay_time, 'hold_time': self.max_hold_time, } self.AddIfGetSupported(self.AckGetResult(field_values=fields)) self.SendGet(ROOT_DEVICE, self.pid) class SetDmxStartupModeOutOfRangeMinimumTime(TestMixins.SetDmxStartupModeMixin, OptionalParameterTestFixture): """Check that the minimum times for DMX_STARTUP_MODE are honored.""" def Test(self): self.in_get = False preset_info = self.Property('preset_info', {}) self.min_delay_time = preset_info.get('min_startup_delay_time') self.min_hold_time = preset_info.get('min_startup_hold_time') if self.min_delay_time is None or self.min_hold_time is None: self.SetNotRun("Max times unknown - PRESET_INFO wasn't acked") return delay_time = self.min_delay_time delay_time_field = self.pid.GetRequestField(RDM_SET, 'startup_delay') # 0xffff means 'startup mode not supported' if (delay_time_field.RawValue(self.min_delay_time) > 1 and delay_time_field.RawValue(self.min_delay_time) < 0xffff): delay_time = delay_time_field.DisplayValue( delay_time_field.RawValue(self.min_delay_time) - 1) # Decrement by 1 hold_time = self.min_hold_time hold_time_field = self.pid.GetRequestField(RDM_SET, 'hold_time') # 0xffff means 'startup mode not supported' if (hold_time_field.RawValue(self.min_hold_time) > 1 and hold_time_field.RawValue(self.min_hold_time) < 0xffff): hold_time = hold_time_field.DisplayValue( hold_time_field.RawValue(self.min_hold_time) - 1) # Decrement by 1 if self.Property('set_dmx_startup_mode_supported'): self.AddIfSetSupported(self.AckSetResult(action=self.GetStartupMode)) else: self.AddIfSetSupported( self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS)) self.SendSet(ROOT_DEVICE, self.pid, [0, delay_time, hold_time, 255]) def GetStartupMode(self): self.in_get = True fields = { 'startup_delay': self.min_delay_time, 'hold_time': self.min_hold_time, } self.AddIfGetSupported(self.AckGetResult(field_values=fields)) self.SendGet(ROOT_DEVICE, self.pid) class SetStartupModeWithNoData(TestMixins.SetWithNoDataMixin, OptionalParameterTestFixture): """Set DMX_STARTUP_MODE with no data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'DMX_STARTUP_MODE' class AllSubDevicesGetDmxStartupMode(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Get DMX_STARTUP_MODE addressed to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'DMX_STARTUP_MODE' # POWER_ON_SELF_TEST # ----------------------------------------------------------------------------- class GetPowerOnSelfTest(TestMixins.GetMixin, OptionalParameterTestFixture): """Get the POWER_ON_SELF_TEST.""" CATEGORY = TestCategory.CONTROL PID = 'POWER_ON_SELF_TEST' EXPECTED_FIELDS = ['power_on_self_test'] PROVIDES = ['power_on_self_test'] class GetPowerOnSelfTestWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """Get the POWER_ON_SELF_TEST with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'POWER_ON_SELF_TEST' class SetPowerOnSelfTest(TestMixins.SetBoolMixin, OptionalParameterTestFixture): """Set POWER_ON_SELF_TEST.""" CATEGORY = TestCategory.CONTROL PID = 'POWER_ON_SELF_TEST' EXPECTED_FIELDS = ['power_on_self_test'] REQUIRES = ['power_on_self_test'] def OldValue(self): return self.Property('power_on_self_test') class SetPowerOnSelfTestWithNoData(TestMixins.SetWithNoDataMixin, OptionalParameterTestFixture): """Set the POWER_ON_SELF_TEST with no param data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'POWER_ON_SELF_TEST' class AllSubDevicesGetPowerOnSelfTest(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Get POWER_ON_SELF_TEST addressed to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'POWER_ON_SELF_TEST' # LOCK_STATE # ----------------------------------------------------------------------------- class GetLockState(TestMixins.GetMixin, OptionalParameterTestFixture): """Get LOCK_STATE.""" CATEGORY = TestCategory.CONFIGURATION PID = "LOCK_STATE" PROVIDES = ['current_lock_state', 'number_of_lock_states'] def Test(self): self.AddIfGetSupported(self.AckGetResult()) self.SendGet(ROOT_DEVICE, self.pid) def VerifyResult(self, response, fields): if not response.WasAcked(): for key in self.PROVIDES: self.SetProperty(key, None) return self.SetPropertyFromDict(fields, 'current_lock_state') self.SetPropertyFromDict(fields, 'number_of_lock_states') if fields['current_lock_state'] > fields['number_of_lock_states']: self.SetFailed('Lock State %d exceeded number of lock states %d' % (fields['current_lock_state'], fields['number_of_lock_states'])) return class GetLockStateWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """Get LOCK_STATE with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'LOCK_STATE' class AllSubDevicesGetLockState(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Get LOCK_STATE addressed to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'LOCK_STATE' class SetLockStateWithNoData(TestMixins.SetWithNoDataMixin, OptionalParameterTestFixture): """Set LOCK_STATE without no data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'LOCK_STATE' class SetLockState(OptionalParameterTestFixture): """Set LOCK_STATE.""" CATEGORY = TestCategory.CONFIGURATION PID = 'LOCK_STATE' REQUIRES = ['current_lock_state', 'pin_code'] def Test(self): self.lock_state = self.Property('current_lock_state') if self.lock_state is None: self.SetNotRun('Unable to determine pin code') return self.pin = self.Property('pin_code') if self.pin is None: # Try setting to a static value, we make old and new the same just on the # off chance this is actually the pin # http://www.datagenetics.com/blog/september32012/ self.AddIfSetSupported([ self.AckSetResult(), self.NackSetResult(RDMNack.NR_DATA_OUT_OF_RANGE), ]) self.SendSet(PidStore.ROOT_DEVICE, self.pid, [439, self.lock_state]) else: self.AddIfSetSupported([ self.AckSetResult(action=self.VerifySet), self.NackSetResult( RDMNack.NR_UNSUPPORTED_COMMAND_CLASS, advisory='SET for %s returned unsupported command class' % self.PID), ]) self.SendSet(PidStore.ROOT_DEVICE, self.pid, [self.pin, self.lock_state]) def VerifySet(self): self.AddExpectedResults( self.AckGetResult(field_values={'current_lock_state': self.lock_state})) self.SendGet(PidStore.ROOT_DEVICE, self.pid) # LOCK_STATE_DESCRIPTION # ----------------------------------------------------------------------------- class GetLockStateDescription(TestMixins.GetSettingDescriptionsRangeMixin, OptionalParameterTestFixture): """Get LOCK_STATE_DESCRIPTION for all known states.""" CATEGORY = TestCategory.DIMMER_SETTINGS PID = 'LOCK_STATE_DESCRIPTION' REQUIRES = ['number_of_lock_states'] EXPECTED_FIELDS = ['lock_state'] DESCRIPTION_FIELD = 'lock_state_description' class GetLockStateDescriptionWithNoData(TestMixins.GetWithNoDataMixin, OptionalParameterTestFixture): """Get LOCK_STATE_DESCRIPTION with no lock state specified.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'LOCK_STATE_DESCRIPTION' class GetLockStateDescriptionWithExtraData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """Get LOCK_STATE_DESCRIPTION with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'LOCK_STATE_DESCRIPTION' class GetZeroLockStateDescription(TestMixins.GetZeroUInt8Mixin, OptionalParameterTestFixture): """Get LOCK_STATE_DESCRIPTION for lock state 0.""" PID = 'LOCK_STATE_DESCRIPTION' class GetOutOfRangeLockStateDescription(TestMixins.GetOutOfRangeByteMixin, OptionalParameterTestFixture): """Get LOCK_STATE_DESCRIPTION for an out-of-range lock state.""" PID = 'LOCK_STATE_DESCRIPTION' REQUIRES = ['number_of_lock_states'] LABEL = 'lock states' class SetLockStateDescription(TestMixins.UnsupportedSetMixin, ResponderTestFixture): """Set the LOCK_STATE_DESCRIPTION.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'LOCK_STATE_DESCRIPTION' class AllSubDevicesGetLockStateDescription(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Get LOCK_STATE_DESCRIPTION addressed to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'LOCK_STATE_DESCRIPTION' DATA = [1] # LOCK_PIN # ----------------------------------------------------------------------------- class GetLockPin(TestMixins.GetMixin, OptionalParameterTestFixture): """Get LOCK_PIN.""" CATEGORY = TestCategory.CONFIGURATION PID = 'LOCK_PIN' EXPECTED_FIELDS = ['pin_code'] PROVIDES = ['pin_code'] # Some responders may not let you GET the pin. ALLOWED_NACKS = [RDMNack.NR_UNSUPPORTED_COMMAND_CLASS] class GetLockPinWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """Get LOCK_PIN with data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'LOCK_PIN' DATA = 'foo' # Some responders may not let you GET the pin. ALLOWED_NACKS = [RDMNack.NR_UNSUPPORTED_COMMAND_CLASS] class AllSubDevicesGetLockPin(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Get LOCK_PIN addressed to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'LOCK_PIN' class SetLockPinWithNoData(TestMixins.SetWithNoDataMixin, OptionalParameterTestFixture): """Set LOCK_PIN with no param data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'LOCK_PIN' class SetLockPin(OptionalParameterTestFixture): """Set LOCK_PIN.""" CATEGORY = TestCategory.CONFIGURATION PID = 'LOCK_PIN' REQUIRES = ['pin_code'] def Test(self): self.pin = self.Property('pin_code') if self.pin is None: # Try setting to a static value, we make old and new the same just on the # off chance this is actually the pin # http://www.datagenetics.com/blog/september32012/ self.AddIfSetSupported([ self.AckSetResult(), self.NackSetResult(RDMNack.NR_DATA_OUT_OF_RANGE), ]) self.SendSet(PidStore.ROOT_DEVICE, self.pid, [439, 439]) else: self.AddIfSetSupported([ self.AckSetResult(action=self.VerifySet), self.NackSetResult( RDMNack.NR_UNSUPPORTED_COMMAND_CLASS, advisory='SET for %s returned unsupported command class' % self.PID), ]) self.SendSet(PidStore.ROOT_DEVICE, self.pid, [self.pin, self.pin]) def VerifySet(self): self.AddExpectedResults([ self.AckGetResult(field_values={'pin_code': self.pin}), self.NackGetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS), ]) self.SendGet(PidStore.ROOT_DEVICE, self.pid) class SetInvalidLockPin(OptionalParameterTestFixture): """Set LOCK_PIN with the wrong pin code.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'LOCK_PIN' REQUIRES = ['pin_code'] def Test(self): self.pin = self.Property('pin_code') if self.pin is None: self.SetNotRun('Unable to determine pin code') return bad_pin = (self.pin + 1) % 10000 self.AddIfSetSupported(self.NackSetResult(RDMNack.NR_DATA_OUT_OF_RANGE)) self.SendSet(ROOT_DEVICE, self.pid, [0, bad_pin]) class SetOutOfRangeLockPin(OptionalParameterTestFixture): """Set LOCK_PIN with an out-of-range pin code.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'LOCK_PIN' REQUIRES = ['pin_code'] def Test(self): self.pin = self.Property('pin_code') if self.pin is None: self.SetNotRun('Unable to determine pin code') return # Section 3.9, out of range pins return NR_FORMAT_ERROR rather than # NR_DATA_OUT_OF_RANGE like one may expect. NR_DATA_OUT_OF_RANGE is # reserved for reporting when an incorrect PIN is used. self.AddIfSetSupported(self.NackSetResult(RDMNack.NR_FORMAT_ERROR)) data = struct.pack('!HH', 10001, self.pin) self.SendRawSet(ROOT_DEVICE, self.pid, data) # BURN_IN # ----------------------------------------------------------------------------- class GetBurnIn(TestMixins.GetMixin, OptionalParameterTestFixture): """GET BURN_IN.""" CATEGORY = TestCategory.POWER_LAMP_SETTINGS PID = 'BURN_IN' EXPECTED_FIELDS = ['hours_remaining'] PROVIDES = ['burn_in_hours'] class GetBurnInWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """Get BURN_IN with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'BURN_IN' class SetBurnIn(TestMixins.SetUInt8Mixin, OptionalParameterTestFixture): """Set BURN_IN.""" CATEGORY = TestCategory.POWER_LAMP_SETTINGS PID = 'BURN_IN' EXPECTED_FIELDS = ['hours_remaining'] REQUIRES = ['burn_in_hours'] def OldValue(self): return self.Property('burn_in_hours') def VerifySet(self): new_value = self.NewValue() results = [ self.AckGetResult( field_names=self.EXPECTED_FIELDS, field_values={self.EXPECTED_FIELDS[0]: self.NewValue()}), ] # Since this is hours remaining, it may be decremented before we can read # it back if new_value: results.append( self.AckGetResult( field_names=self.EXPECTED_FIELDS, field_values={self.EXPECTED_FIELDS[0]: new_value - 1})) self.AddExpectedResults(results) self.SendGet(ROOT_DEVICE, self.pid) class SetBurnInWithNoData(TestMixins.SetWithNoDataMixin, OptionalParameterTestFixture): """Set BURN_IN with no param data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'BURN_IN' class AllSubDevicesGetBurnIn(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Get BURN_IN addressed to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'BURN_IN' # DIMMER_INFO # ----------------------------------------------------------------------------- class GetDimmerInfo(OptionalParameterTestFixture): """GET dimmer info.""" CATEGORY = TestCategory.DIMMER_SETTINGS PID = 'DIMMER_INFO' REQUIRES = ['supported_parameters'] PROVIDES = ['minimum_level_lower', 'minimum_level_upper', 'maximum_level_lower', 'maximum_level_upper', 'number_curves_supported', 'levels_resolution', 'split_levels_supported'] def Test(self): self.AddIfGetSupported(self.AckGetResult()) self.SendGet(ROOT_DEVICE, self.pid) def VerifyResult(self, response, fields): if not response.WasAcked(): for field in self.PROVIDES: self.SetProperty(field, None) return if fields['minimum_level_lower'] > fields['minimum_level_upper']: self.AddAdvisory('minimum_level_lower (%d) > minimum_level_upper (%d)' % (fields['minimum_level_lower'], fields['minimum_level_upper'])) if fields['maximum_level_lower'] > fields['maximum_level_upper']: self.AddAdvisory('maximum_level_lower (%d) > maximum_level_upper (%d)' % (fields['maximum_level_lower'], fields['maximum_level_upper'])) self.SetPropertyFromDict(fields, 'minimum_level_lower') self.SetPropertyFromDict(fields, 'minimum_level_upper') self.SetPropertyFromDict(fields, 'maximum_level_lower') self.SetPropertyFromDict(fields, 'maximum_level_upper') self.SetPropertyFromDict(fields, 'number_curves_supported') self.SetPropertyFromDict(fields, 'levels_resolution') self.SetProperty('split_levels_supported', fields['split_levels_supported']) self.CheckFieldsAreUnsupported( 'MINIMUM_LEVEL', fields, {'minimum_level_lower': 0, 'minimum_level_upper': 0, 'split_levels_supported': 0}) self.CheckFieldsAreUnsupported( 'MAXIMUM_LEVEL', fields, {'maximum_level_lower': 0xffff, 'maximum_level_upper': 0xffff}) def CheckFieldsAreUnsupported(self, pid_name, fields, keys): if self.LookupPid(pid_name).value in self.Property('supported_parameters'): return for key, expected_value in keys.iteritems(): if fields[key] != expected_value: self.AddWarning( "%s isn't supported but %s in DIMMER_INFO was not %hx" % (pid_name, key, expected_value)) class GetDimmerInfoWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """Get DIMMER_INFO with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'DIMMER_INFO' class SetDimmerInfo(TestMixins.UnsupportedSetMixin, ResponderTestFixture): """Set DIMMER_INFO.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'DIMMER_INFO' class AllSubDevicesGetDimmerInfo(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Get DIMMER_INFO addressed to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'DIMMER_INFO' # MINIMUM_LEVEL # ----------------------------------------------------------------------------- class GetMinimumLevel(TestMixins.GetMixin, OptionalParameterTestFixture): """Get MINIMUM_LEVEL.""" CATEGORY = TestCategory.DIMMER_SETTINGS PID = "MINIMUM_LEVEL" REQUIRES = ['minimum_level_lower', 'minimum_level_upper', 'split_levels_supported'] PROVIDES = ['minimum_level_settings'] def Test(self): self.AddIfGetSupported(self.AckGetResult()) self.SendGet(ROOT_DEVICE, self.pid) def VerifyResult(self, response, fields): if fields is None: fields = {} self.SetProperty('minimum_level_settings', fields) if not response.WasAcked(): return min_increasing = fields['minimum_level_increasing'] min_decreasing = fields['minimum_level_decreasing'] lower_limit = self.Property('minimum_level_lower') upper_limit = self.Property('minimum_level_upper') if lower_limit is not None and upper_limit is not None: if min_increasing < lower_limit or min_increasing > upper_limit: self.SetFailed( 'minimum_level_increasing is outside the range [%d, %d] from ' 'DIMMER_INFO' % (lower_limit, upper_limit)) return if min_decreasing < lower_limit or min_decreasing > upper_limit: self.SetFailed( 'minimum_level_decreasing is outside the range [%d, %d] from ' 'DIMMER_INFO' % (lower_limit, upper_limit)) return split_supported = self.Property('split_levels_supported') if split_supported is not None: if not split_supported and min_increasing != min_decreasing: self.SetFailed( 'Split min levels not supported but min level increasing (%d)' ' != min level decreasing (%d)' % (min_increasing, min_decreasing)) class GetMinimumLevelWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """Get MINIMUM_LEVEL with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'MINIMUM_LEVEL' class AllSubDevicesGetMinimumLevel(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Get MINIMUM_LEVEL addressed to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'MINIMUM_LEVEL' class SetMinimumLevel(OptionalParameterTestFixture): """Set MINIMUM_LEVEL without changing the settings.""" CATEGORY = TestCategory.DIMMER_SETTINGS PID = 'MINIMUM_LEVEL' REQUIRES = ['minimum_level_settings'] PROVIDES = ['set_minimum_level_supported'] def Test(self): settings = self.Property('minimum_level_settings') if not settings: self.SetNotRun('Unable to determine current MINIMUM_LEVEL settings') return self.AddIfSetSupported([ self.AckSetResult(), self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS), ]) self.SendSet( ROOT_DEVICE, self.pid, [settings['minimum_level_increasing'], settings['minimum_level_decreasing'], settings['on_below_minimum']]) def VerifyResult(self, response, fields): self.SetProperty('set_minimum_level_supported', response.WasAcked()) class SetLowerIncreasingMiniumLevel(TestMixins.SetMinimumLevelMixin, OptionalParameterTestFixture): """Set MINIMUM_LEVEL to the smallest value from DIMMER_INFO.""" REQUIRES = TestMixins.SetMinimumLevelMixin.REQUIRES + ['minimum_level_lower'] def MinLevelIncreasing(self): return self.Property('minimum_level_lower') class SetUpperIncreasingMiniumLevel(TestMixins.SetMinimumLevelMixin, OptionalParameterTestFixture): """Set MINIMUM_LEVEL to the largest value from DIMMER_INFO.""" REQUIRES = TestMixins.SetMinimumLevelMixin.REQUIRES + ['minimum_level_upper'] def MinLevelIncreasing(self): return self.Property('minimum_level_upper') class SetOutOfRangeLowerIncreasingMiniumLevel(TestMixins.SetMinimumLevelMixin, OptionalParameterTestFixture): """Set MINIMUM_LEVEL to one less than the smallest value from DIMMER_INFO.""" REQUIRES = TestMixins.SetMinimumLevelMixin.REQUIRES + ['minimum_level_lower'] def ExpectedResults(self): return self.NackSetResult(RDMNack.NR_DATA_OUT_OF_RANGE) def ShouldSkip(self): self.lower = self.Property('minimum_level_lower') if self.lower == 0: self.SetNotRun('All values supported') return True return False def MinLevelIncreasing(self): return self.lower - 1 class SetOutOfRangeUpperIncreasingMiniumLevel(TestMixins.SetMinimumLevelMixin, OptionalParameterTestFixture): """Set MINIMUM_LEVEL to one more than the largest value from DIMMER_INFO.""" REQUIRES = TestMixins.SetMinimumLevelMixin.REQUIRES + ['minimum_level_upper'] def ExpectedResults(self): return self.NackSetResult(RDMNack.NR_DATA_OUT_OF_RANGE) def ShouldSkip(self): self.upper = self.Property('minimum_level_upper') if self.upper == 0xfffe: self.SetNotRun('All values supported') return True return False def MinLevelIncreasing(self): return self.upper + 1 # MAXIMUM_LEVEL # ----------------------------------------------------------------------------- class GetMaximumLevel(TestMixins.GetMixin, OptionalParameterTestFixture): """Get MAXIMUM_LEVEL.""" CATEGORY = TestCategory.DIMMER_SETTINGS PID = "MAXIMUM_LEVEL" PROVIDES = ['maximum_level'] EXPECTED_FIELDS = ['maximum_level'] class GetMaximumLevelWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """Get MAXIMUM_LEVEL with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'MAXIMUM_LEVEL' class SetMaximumLevel(OptionalParameterTestFixture): """Set MAXIMUM_LEVEL without changing the settings.""" CATEGORY = TestCategory.DIMMER_SETTINGS PID = 'MAXIMUM_LEVEL' REQUIRES = ['maximum_level'] PROVIDES = ['set_maximum_level_supported'] def Test(self): current_value = self.Property('maximum_level') if current_value is None: current_value = 0xffff self.AddIfSetSupported([ self.AckSetResult(), self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS), ]) self.SendSet(ROOT_DEVICE, self.pid, [current_value]) def VerifyResult(self, response, fields): self.SetProperty('set_maximum_level_supported', response.WasAcked()) class SetLowerMaximumLevel(TestMixins.SetMaximumLevelMixin, OptionalParameterTestFixture): """Set MAXIMUM_LEVEL to the smallest value from DIMMER_INFO.""" REQUIRES = TestMixins.SetMaximumLevelMixin.REQUIRES + ['maximum_level_lower'] def Test(self): self.value = self.Property('maximum_level_lower') if self.value is None: self.SetNotRun('No lower maximum level from DIMMER_INFO') return if self.Property('set_maximum_level_supported'): self.AddIfSetSupported(self.AckSetResult(action=self.GetMaxLevel)) else: self.AddIfSetSupported( self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS)) self.SendSet(ROOT_DEVICE, self.pid, [self.value]) def GetMaxLevel(self): self.AddIfGetSupported(self.AckGetResult( field_values={'maximum_level': self.value})) self.SendGet(ROOT_DEVICE, self.pid) class SetUpperMaximumLevel(TestMixins.SetMaximumLevelMixin, OptionalParameterTestFixture): """Set MAXIMUM_LEVEL to the largest value from DIMMER_INFO.""" REQUIRES = TestMixins.SetMaximumLevelMixin.REQUIRES + ['maximum_level_upper'] def Test(self): self.value = self.Property('maximum_level_upper') if self.value is None: self.SetNotRun('No upper maximum level from DIMMER_INFO') return if self.Property('set_maximum_level_supported'): self.AddIfSetSupported(self.AckSetResult(action=self.GetMaxLevel)) else: self.AddIfSetSupported( self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS)) self.SendSet(ROOT_DEVICE, self.pid, [self.value]) def GetMaxLevel(self): self.AddIfGetSupported(self.AckGetResult( field_values={'maximum_level': self.value})) self.SendGet(ROOT_DEVICE, self.pid) class SetLowerOutOfRangeMaximumLevel(OptionalParameterTestFixture): """Set MAXIMUM_LEVEL a value smaller than the minimum.""" CATEGORY = TestCategory.DIMMER_SETTINGS PID = 'MAXIMUM_LEVEL' REQUIRES = ['maximum_level_lower', 'set_maximum_level_supported'] def Test(self): self.value = self.Property('maximum_level_lower') if self.value is None: self.SetNotRun('No lower maximum level from DIMMER_INFO') return if self.value == 0: self.SetNotRun('Range for maximum level begins at 0') return self.value -= 1 if self.Property('set_maximum_level_supported'): self.AddIfSetSupported(self.NackSetResult(RDMNack.NR_DATA_OUT_OF_RANGE)) else: self.AddIfSetSupported( self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS)) self.SendSet(ROOT_DEVICE, self.pid, [self.value]) class SetUpperOutOfRangeMaximumLevel(OptionalParameterTestFixture): """Set MAXIMUM_LEVEL a value larger than the maximum.""" CATEGORY = TestCategory.DIMMER_SETTINGS PID = 'MAXIMUM_LEVEL' REQUIRES = ['maximum_level_upper', 'set_maximum_level_supported'] def Test(self): self.value = self.Property('maximum_level_upper') if self.value is None: self.SetNotRun('No upper maximum level from DIMMER_INFO') return if self.value == 0xffff: self.SetNotRun('Range for maximum level ends at 0xffff') return self.value += 1 if self.Property('set_maximum_level_supported'): self.AddIfSetSupported(self.NackSetResult(RDMNack.NR_DATA_OUT_OF_RANGE)) else: self.AddIfSetSupported( self.NackSetResult(RDMNack.NR_UNSUPPORTED_COMMAND_CLASS)) self.SendSet(ROOT_DEVICE, self.pid, [self.value]) class AllSubDevicesGetMaximumLevel(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Get MAXIMUM_LEVEL addressed to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'MAXIMUM_LEVEL' # CURVE # ----------------------------------------------------------------------------- class GetCurve(TestMixins.GetMixin, OptionalParameterTestFixture): """Get CURVE.""" CATEGORY = TestCategory.DIMMER_SETTINGS PID = "CURVE" REQUIRES = ['number_curves_supported'] PROVIDES = ['current_curve', 'number_curves'] def Test(self): self.AddIfGetSupported(self.AckGetResult()) self.SendGet(ROOT_DEVICE, self.pid) def VerifyResult(self, response, fields): if not response.WasAcked(): for key in self.PROVIDES: self.SetProperty(key, None) return self.SetPropertyFromDict(fields, 'current_curve') self.SetPropertyFromDict(fields, 'number_curves') if fields['current_curve'] == 0: self.SetFailed('Curves must be numbered from 1') return if fields['current_curve'] > fields['number_curves']: self.SetFailed('Curve %d exceeded number of curves %d' % (fields['current_curve'], fields['number_curves'])) return expected_curves = self.Property('number_curves_supported') if expected_curves is not None: if expected_curves != fields['number_curves']: self.AddWarning( 'The number of curves reported in DIMMER_INFO (%d) does not ' 'match the number from CURVE (%d)' % (expected_curves, fields['number_curves'])) class GetCurveWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """Get CURVE with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'CURVE' class SetCurve(OptionalParameterTestFixture): """Set CURVE.""" CATEGORY = TestCategory.DIMMER_SETTINGS PID = "CURVE" REQUIRES = ['current_curve', 'number_curves'] def Test(self): curves = self.Property('number_curves') if curves: self.curves = [i + 1 for i in xrange(curves)] self._SetCurve() else: # Check we get a NR_UNKNOWN_PID self.AddExpectedResults(self.NackSetResult(RDMNack.NR_UNKNOWN_PID)) self.curve = 1 # Can use anything here really self.SendSet(ROOT_DEVICE, self.pid, [1]) def _SetCurve(self): if not self.curves: # End of the list, we're done self.Stop() return self.AddIfSetSupported(self.AckSetResult(action=self.VerifySet)) self.SendSet(ROOT_DEVICE, self.pid, [self.curves[0]]) def VerifySet(self): self.AddIfGetSupported( self.AckGetResult( field_values={'current_curve': self.curves[0]}, action=self.NextCurve)) self.SendGet(ROOT_DEVICE, self.pid) def NextCurve(self): self.curves = self.curves[1:] self._SetCurve() def ResetState(self): if not self.PidSupported() or not self.Property('current_curve'): return self.SendSet(ROOT_DEVICE, self.pid, [self.Property('current_curve')]) self._wrapper.Run() class SetZeroCurve(TestMixins.SetZeroUInt8Mixin, OptionalParameterTestFixture): """Set CURVE to 0.""" PID = 'CURVE' class SetOutOfRangeCurve(TestMixins.SetOutOfRangeByteMixin, OptionalParameterTestFixture): """Set CURVE to an out-of-range value.""" PID = 'CURVE' REQUIRES = ['number_curves'] LABEL = 'curves' class SetCurveWithNoData(TestMixins.SetWithNoDataMixin, OptionalParameterTestFixture): """Set CURVE without any data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'CURVE' class AllSubDevicesGetCurve(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Get CURVE addressed to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'CURVE' # CURVE_DESCRIPTION # ----------------------------------------------------------------------------- class GetCurveDescription(TestMixins.GetSettingDescriptionsRangeMixin, OptionalParameterTestFixture): """Get the CURVE_DESCRIPTION for all known curves.""" CATEGORY = TestCategory.DIMMER_SETTINGS PID = 'CURVE_DESCRIPTION' REQUIRES = ['number_curves'] EXPECTED_FIELDS = ['curve_number'] DESCRIPTION_FIELD = 'curve_description' class GetCurveDescriptionWithNoData(TestMixins.GetWithNoDataMixin, OptionalParameterTestFixture): """Get CURVE_DESCRIPTION with no curve number specified.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'CURVE_DESCRIPTION' class GetCurveDescriptionWithExtraData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """Get CURVE_DESCRIPTION with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'CURVE_DESCRIPTION' class GetZeroCurveDescription(TestMixins.GetZeroUInt8Mixin, OptionalParameterTestFixture): """Get CURVE_DESCRIPTION for curve 0.""" PID = 'CURVE_DESCRIPTION' class GetOutOfRangeCurveDescription(TestMixins.GetOutOfRangeByteMixin, OptionalParameterTestFixture): """Get CURVE_DESCRIPTION for an out-of-range curve.""" PID = 'CURVE_DESCRIPTION' REQUIRES = ['number_curves'] LABEL = 'curves' class SetCurveDescription(TestMixins.UnsupportedSetMixin, ResponderTestFixture): """Set the CURVE_DESCRIPTION.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'CURVE_DESCRIPTION' class AllSubDevicesGetCurveDescription(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Get CURVE_DESCRIPTION addressed to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'CURVE_DESCRIPTION' DATA = [1] # OUTPUT_RESPONSE_TIME # ----------------------------------------------------------------------------- class GetOutputResponseTime(TestMixins.GetMixin, OptionalParameterTestFixture): """Get OUTPUT_RESPONSE_TIME.""" CATEGORY = TestCategory.DIMMER_SETTINGS PID = "OUTPUT_RESPONSE_TIME" PROVIDES = ['current_response_time', 'number_response_options'] def Test(self): self.AddIfGetSupported(self.AckGetResult()) self.SendGet(ROOT_DEVICE, self.pid) def VerifyResult(self, response, fields): if not response.WasAcked(): for key in self.PROVIDES: self.SetProperty(key, None) return self.SetPropertyFromDict(fields, 'current_response_time') self.SetPropertyFromDict(fields, 'number_response_options') if fields['current_response_time'] == 0: self.SetFailed('Output response times must be numbered from 1') return if fields['current_response_time'] > fields['number_response_options']: self.SetFailed( 'Output response time %d exceeded number of response times %d' % (fields['current_response_time'], fields['number_response_options'])) return class GetOutputResponseTimeWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """Get OUTPUT_RESPONSE_TIME with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'OUTPUT_RESPONSE_TIME' class SetOutputResponseTime(OptionalParameterTestFixture): """Set OUTPUT_RESPONSE_TIME.""" CATEGORY = TestCategory.DIMMER_SETTINGS PID = "OUTPUT_RESPONSE_TIME" REQUIRES = ['current_response_time', 'number_response_options'] def Test(self): times = self.Property('number_response_options') if times: self.output_response_times = [i + 1 for i in xrange(times)] self._SetOutputResponseTime() else: # Check we get a NR_UNKNOWN_PID self.AddExpectedResults(self.NackSetResult(RDMNack.NR_UNKNOWN_PID)) self.current_response_time = 1 # Can use anything here really self.SendSet(ROOT_DEVICE, self.pid, [1]) def _SetOutputResponseTime(self): if not self.output_response_times: # End of the list, we're done self.Stop() return self.AddIfSetSupported(self.AckSetResult(action=self.VerifySet)) self.SendSet(ROOT_DEVICE, self.pid, [self.output_response_times[0]]) def VerifySet(self): self.AddIfGetSupported( self.AckGetResult( field_values={'current_response_time': self.output_response_times[0]}, action=self.NextOutputResponseTime)) self.SendGet(ROOT_DEVICE, self.pid) def NextOutputResponseTime(self): self.output_response_times = self.output_response_times[1:] self._SetOutputResponseTime() def ResetState(self): if not self.PidSupported() or not self.Property('current_response_time'): return self.SendSet(ROOT_DEVICE, self.pid, [self.Property('current_response_time')]) self._wrapper.Run() class SetZeroOutputResponseTime(TestMixins.SetZeroUInt8Mixin, OptionalParameterTestFixture): """Set OUTPUT_RESPONSE_TIME to 0.""" PID = 'OUTPUT_RESPONSE_TIME' class SetOutOfRangeOutputResponseTime(TestMixins.SetOutOfRangeByteMixin, OptionalParameterTestFixture): """Set OUTPUT_RESPONSE_TIME to an out-of-range value.""" PID = 'OUTPUT_RESPONSE_TIME' REQUIRES = ['number_response_options'] LABEL = 'output response times' class SetOutputResponseTimeWithNoData(TestMixins.SetWithNoDataMixin, OptionalParameterTestFixture): """Set OUTPUT_RESPONSE_TIME without any data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'OUTPUT_RESPONSE_TIME' class AllSubDevicesGetOutputResponseTime(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Get OUTPUT_RESPONSE_TIME addressed to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'OUTPUT_RESPONSE_TIME' # OUTPUT_RESPONSE_TIME_DESCRIPTION # ----------------------------------------------------------------------------- class GetOutputResponseTimeDescription( TestMixins.GetSettingDescriptionsRangeMixin, OptionalParameterTestFixture): """Get the OUTPUT_RESPONSE_TIME_DESCRIPTION for all response times.""" CATEGORY = TestCategory.DIMMER_SETTINGS PID = 'OUTPUT_RESPONSE_TIME_DESCRIPTION' REQUIRES = ['number_response_options'] EXPECTED_FIELDS = ['response_time'] DESCRIPTION_FIELD = 'response_time_description' class GetOutputResponseTimeDescriptionWithNoData(TestMixins.GetWithNoDataMixin, OptionalParameterTestFixture): """Get OUTPUT_RESPONSE_TIME_DESCRIPTION with no response time number.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'OUTPUT_RESPONSE_TIME_DESCRIPTION' class GetOutputResponseTimeDescriptionWithExtraData( TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """Get OUTPUT_RESPONSE_TIME_DESCRIPTION with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'OUTPUT_RESPONSE_TIME_DESCRIPTION' class GetZeroOutputResponseTimeDescription(TestMixins.GetZeroUInt8Mixin, OptionalParameterTestFixture): """Get OUTPUT_RESPONSE_TIME_DESCRIPTION for response_time 0.""" PID = 'OUTPUT_RESPONSE_TIME_DESCRIPTION' class GetOutOfRangeOutputResponseTimeDescription( TestMixins.GetOutOfRangeByteMixin, OptionalParameterTestFixture): """Get OUTPUT_RESPONSE_TIME_DESCRIPTION for an out-of-range response time.""" PID = 'OUTPUT_RESPONSE_TIME_DESCRIPTION' REQUIRES = ['number_response_options'] LABEL = 'response times' class SetOutputResponseTimeDescription(TestMixins.UnsupportedSetMixin, ResponderTestFixture): """SET OUTPUT_RESPONSE_TIME_DESCRIPTION.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'OUTPUT_RESPONSE_TIME_DESCRIPTION' class AllSubDevicesGetOutputResponseTimeDescription( TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Get OUTPUT_RESPONSE_TIME_DESCRIPTION addressed to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'OUTPUT_RESPONSE_TIME_DESCRIPTION' DATA = [1] # MODULATION_FREQUENCY # ----------------------------------------------------------------------------- class GetModulationFrequency(TestMixins.GetMixin, OptionalParameterTestFixture): """Get MODULATION_FREQUENCY.""" CATEGORY = TestCategory.DIMMER_SETTINGS PID = "MODULATION_FREQUENCY" PROVIDES = ['current_modulation_frequency', 'number_modulation_frequencies'] def Test(self): self.AddIfGetSupported(self.AckGetResult()) self.SendGet(ROOT_DEVICE, self.pid) def VerifyResult(self, response, fields): if not response.WasAcked(): for key in self.PROVIDES: self.SetProperty(key, None) return self.SetPropertyFromDict(fields, 'current_modulation_frequency') self.SetPropertyFromDict(fields, 'number_modulation_frequencies') if fields['current_modulation_frequency'] == 0: self.SetFailed('Modulation frequency must be numbered from 1') return if (fields['current_modulation_frequency'] > fields['number_modulation_frequencies']): self.SetFailed( 'Modulation frequency %d exceeded number of modulation frequencies %d' % (fields['current_modulation_frequency'], fields['number_modulation_frequencies'])) return class GetModulationFrequencyWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """Get MODULATION_FREQUENCY with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'MODULATION_FREQUENCY' class SetModulationFrequency(OptionalParameterTestFixture): """Set MODULATION_FREQUENCY.""" CATEGORY = TestCategory.DIMMER_SETTINGS PID = "MODULATION_FREQUENCY" REQUIRES = ['current_modulation_frequency', 'number_modulation_frequencies'] def Test(self): items = self.Property('number_modulation_frequencies') if items: self.frequencies = [i + 1 for i in xrange(items)] self._SetModulationFrequency() else: # Check we get a NR_UNKNOWN_PID self.AddExpectedResults(self.NackSetResult(RDMNack.NR_UNKNOWN_PID)) self.frequency = 1 # Can use anything here really self.SendSet(ROOT_DEVICE, self.pid, [1]) def _SetModulationFrequency(self): if not self.frequencies: # End of the list, we're done self.Stop() return self.AddIfSetSupported(self.AckSetResult(action=self.VerifySet)) self.SendSet(ROOT_DEVICE, self.pid, [self.frequencies[0]]) def VerifySet(self): self.AddIfGetSupported( self.AckGetResult( field_values={'current_modulation_frequency': self.frequencies[0]}, action=self.NextModulationFrequency)) self.SendGet(ROOT_DEVICE, self.pid) def NextModulationFrequency(self): self.frequencies = self.frequencies[1:] self._SetModulationFrequency() def ResetState(self): if (not self.PidSupported() or not self.Property('current_modulation_frequency')): return self.SendSet(ROOT_DEVICE, self.pid, [self.Property('current_modulation_frequency')]) self._wrapper.Run() class SetZeroModulationFrequency(TestMixins.SetZeroUInt8Mixin, OptionalParameterTestFixture): """Set MODULATION_FREQUENCY with a frequency setting of 0.""" PID = 'MODULATION_FREQUENCY' class SetOutOfRangeModulationFrequency(TestMixins.SetOutOfRangeByteMixin, OptionalParameterTestFixture): """Set MODULATION_FREQUENCY to an out-of-range value.""" PID = 'MODULATION_FREQUENCY' REQUIRES = ['number_modulation_frequencies'] LABEL = 'modulation frequencies' class SetModulationFrequencyWithNoData(TestMixins.SetWithNoDataMixin, OptionalParameterTestFixture): """Set MODULATION_FREQUENCY without any data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'MODULATION_FREQUENCY' class AllSubDevicesGetModulationFrequency(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Get MODULATION_FREQUENCY addressed to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'MODULATION_FREQUENCY' # MODULATION_FREQUENCY_DESCRIPTION # ----------------------------------------------------------------------------- class GetModulationFrequencyDescription( TestMixins.GetSettingDescriptionsRangeMixin, OptionalParameterTestFixture): """Get the MODULATION_FREQUENCY_DESCRIPTION for all frequencies.""" CATEGORY = TestCategory.DIMMER_SETTINGS PID = 'MODULATION_FREQUENCY_DESCRIPTION' REQUIRES = ['number_modulation_frequencies'] EXPECTED_FIELDS = ['modulation_frequency'] DESCRIPTION_FIELD = 'modulation_frequency_description' class GetModulationFrequencyDescriptionWithNoData(TestMixins.GetWithNoDataMixin, OptionalParameterTestFixture): """Get MODULATION_FREQUENCY_DESCRIPTION with no frequency number.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'MODULATION_FREQUENCY_DESCRIPTION' class GetModulationFrequencyDescriptionWithExtraData( TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """Get MODULATION_FREQUENCY_DESCRIPTION with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'MODULATION_FREQUENCY_DESCRIPTION' class GetZeroModulationFrequencyDescription(TestMixins.GetZeroUInt8Mixin, OptionalParameterTestFixture): """Get MODULATION_FREQUENCY_DESCRIPTION for frequency 0.""" PID = 'MODULATION_FREQUENCY_DESCRIPTION' class GetOutOfRangeModulationFrequencyDescription( TestMixins.GetOutOfRangeByteMixin, OptionalParameterTestFixture): """Get MODULATION_FREQUENCY_DESCRIPTION for an out-of-range frequency.""" PID = 'MODULATION_FREQUENCY_DESCRIPTION' REQUIRES = ['number_modulation_frequencies'] LABEL = 'modulation frequencies' class SetModulationFrequencyDescription(TestMixins.UnsupportedSetMixin, ResponderTestFixture): """SET MODULATION_FREQUENCY_DESCRIPTION.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'MODULATION_FREQUENCY_DESCRIPTION' class AllSubDevicesGetModulationFrequencyDescription( TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Get MODULATION_FREQUENCY_DESCRIPTION addressed to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'MODULATION_FREQUENCY_DESCRIPTION' DATA = [1] # PRESET_INFO # ----------------------------------------------------------------------------- class GetPresetInfo(TestMixins.GetMixin, OptionalParameterTestFixture): """Get PRESET_INFO.""" CATEGORY = TestCategory.CONTROL PID = 'PRESET_INFO' PROVIDES = ['preset_info', 'max_scene_number'] def Test(self): self.AddIfGetSupported(self.AckGetResult()) self.SendGet(ROOT_DEVICE, self.pid) def VerifyResult(self, response, fields): if not response.WasAcked(): self.SetProperty('preset_info', {}) self.SetProperty('max_scene_number', None) return self.CheckBounds(fields, 'preset_fade_time') self.CheckBounds(fields, 'preset_wait_time') self.CheckBounds(fields, 'fail_delay_time') self.CheckBounds(fields, 'fail_hold_time') self.CheckBounds(fields, 'startup_delay_time') self.CheckBounds(fields, 'startup_hold_time') if fields['max_scene_number'] == 0xffff: self.AddWarning('PRESET_INFO had max_scene_number of 0xffff') self.CrossCheckPidSupportIsZero('DMX_FAIL_MODE', fields, 'fail_infinite_hold_supported') self.CrossCheckPidSupportIsZero('DMX_FAIL_MODE', fields, 'fail_infinite_delay_supported') self.CrossCheckPidSupportIsZero('DMX_STARTUP_MODE', fields, 'startup_infinite_hold_supported') self.CrossCheckPidSupportIsMax('DMX_FAIL_MODE', fields, 'fail_delay_time') self.CrossCheckPidSupportIsMax('DMX_FAIL_MODE', fields, 'fail_hold_time') self.CrossCheckPidSupportIsMax('DMX_STARTUP_MODE', fields, 'startup_delay_time') self.CrossCheckPidSupportIsMax('DMX_STARTUP_MODE', fields, 'startup_hold_time') self.SetProperty('preset_info', fields) self.SetProperty('max_scene_number', fields['max_scene_number']) def CrossCheckPidSupportIsZero(self, pid_name, fields, key): if not (self.IsSupported(pid_name) or fields[key] is False): self.AddWarning('%s not supported, but %s in PRESET_INFO is non-0' % (pid_name, key)) def CrossCheckPidSupportIsMax(self, pid_name, fields, key): for key in ['min_%s' % key, 'max_%s' % key]: if not (self.IsSupported(pid_name) or fields[key] == self.pid.GetResponseField( RDM_GET, key).DisplayValue(0xffff)): self.AddWarning( '%s not supported, but %s in PRESET_INFO is not 0xffff' % (pid_name, key)) def IsSupported(self, pid_name): pid = self.LookupPid(pid_name) return pid.value in self.Property('supported_parameters') def CheckBounds(self, fields, key): min_key = 'min_%s' % key max_key = 'max_%s' % key if fields[min_key] > fields[max_key]: self.AddAdvisory('%s (%d) > %s (%d)' % (min_key, fields[min_key], max_key, fields[max_key])) class GetPresetInfoWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """Get PRESET_INFO with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'PRESET_INFO' class SetPresetInfo(TestMixins.UnsupportedSetMixin, OptionalParameterTestFixture): """Set PRESET_INFO.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'PRESET_INFO' class AllSubDevicesGetPresetInfo(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Get PRESET_INFO addressed 0to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'PRESET_INFO' # PRESET_STATUS # ----------------------------------------------------------------------------- class GetPresetStatusPresetOff(OptionalParameterTestFixture): """Get the PRESET_STATUS for PRESET_PLAYBACK_OFF.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'PRESET_STATUS' def Test(self): self.AddIfGetSupported(self.NackGetResult(RDMNack.NR_DATA_OUT_OF_RANGE)) data = struct.pack('!H', 0) self.SendRawGet(ROOT_DEVICE, self.pid, data) class GetPresetStatusPresetScene(OptionalParameterTestFixture): """Get the PRESET_STATUS for PRESET_PLAYBACK_SCENE.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'PRESET_STATUS' def Test(self): self.AddIfGetSupported(self.NackGetResult(RDMNack.NR_DATA_OUT_OF_RANGE)) data = struct.pack('!H', 0xffff) self.SendRawGet(ROOT_DEVICE, self.pid, data) class GetOutOfRangePresetStatus(OptionalParameterTestFixture): """Get the PRESET_STATUS for max_scene + 1.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'PRESET_STATUS' REQUIRES = ['max_scene_number'] def Test(self): max_scene = self.Property('max_scene_number') if max_scene is None or max_scene == 0xfffe: self.SetNotRun('Device supports all scenes') return self.AddIfGetSupported(self.NackGetResult(RDMNack.NR_DATA_OUT_OF_RANGE)) self.SendGet(ROOT_DEVICE, self.pid, [max_scene + 1]) class GetPresetStatus(OptionalParameterTestFixture): """Get the PRESET_STATUS for all scenes.""" CATEGORY = TestCategory.CONTROL PID = 'PRESET_STATUS' REQUIRES = ['max_scene_number', 'preset_info'] PROVIDES = ['scene_writable_states'] NOT_PROGRAMMED = 0 PROGRAMMED = 1 READ_ONLY = 2 def Test(self): self.scene_writable_states = {} self.index = 0 self.max_scene = self.Property('max_scene_number') preset_info = self.Property('preset_info') self.min_fade = preset_info.get('min_preset_fade_time', 0) self.max_fade = preset_info.get( 'max_preset_fade_time', self.pid.GetResponseField(RDM_GET, 'up_fade_time').RawValue(0xffff)) self.min_wait = preset_info.get('min_preset_wait_time', 0) self.max_wait = preset_info.get( 'max_preset_wait_time', self.pid.GetResponseField(RDM_GET, 'wait_time').RawValue(0xffff)) if self.max_scene is None or self.max_scene == 0: self.SetNotRun('No scenes supported') return self.FetchNextScene() def FetchNextScene(self): self.index += 1 if self.index > self.max_scene: self.SetProperty('scene_writable_states', self.scene_writable_states) self.Stop() return self.AddIfGetSupported(self.AckGetResult(action=self.FetchNextScene)) self.SendGet(ROOT_DEVICE, self.pid, [self.index]) def VerifyResult(self, response, fields): if not response.WasAcked(): return if fields['scene_number'] != self.index: self.SetFailed('Scene number mismatch, expected %d, got %d' % (self.index, fields['scene_number'])) self.Stop() if fields['programmed'] == self.NOT_PROGRAMMED: # Assume that NOT_PROGRAMMED means that it's writable. self.scene_writable_states[self.index] = True self.CheckFieldIsZero(fields, 'down_fade_time') self.CheckFieldIsZero(fields, 'up_fade_time') self.CheckFieldIsZero(fields, 'wait_time') return elif fields['programmed'] == self.READ_ONLY: self.scene_writable_states[self.index] = False else: self.scene_writable_states[self.index] = True for key in ['up_fade_time', 'down_fade_time']: self.CheckFieldIsBetween(fields, key, self.min_fade, self.max_fade) self.CheckFieldIsBetween(fields, 'wait_time', self.min_wait, self.max_wait) def CheckFieldIsZero(self, fields, key): if fields[key] != 0: self.AddWarning( '%s for scene %d was not zero, value is %d' % (key, self.index, fields[key])) def CheckFieldIsBetween(self, fields, key, min_value, max_value): if fields[key] < min_value: self.AddWarning( '%s for scene %d (%d s) is less than the min of %s' % (key, self.index, fields[key], min_value)) if fields[key] > max_value: self.AddWarning( '%s for scene %d (%d s) is more than the min of %s' % (key, self.index, fields[key], max_value)) class GetPresetStatusWithNoData(TestMixins.GetWithNoDataMixin, OptionalParameterTestFixture): """Get the PRESET_STATUS with no preset number specified.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'PRESET_STATUS' class SetPresetStatusWithNoData(TestMixins.SetWithNoDataMixin, OptionalParameterTestFixture): """Set PRESET_STATUS without any data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'PRESET_STATUS' class SetPresetStatusPresetOff(TestMixins.SetPresetStatusMixin, OptionalParameterTestFixture): """Set the PRESET_STATUS for PRESET_PLAYBACK_OFF.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'PRESET_STATUS' def Test(self): self.AddIfSetSupported(self.NackSetResult(RDMNack.NR_DATA_OUT_OF_RANGE)) data = self.BuildPresetStatus(0) self.SendRawSet(ROOT_DEVICE, self.pid, data) class SetPresetStatusPresetScene(TestMixins.SetPresetStatusMixin, OptionalParameterTestFixture): """Set the PRESET_STATUS for PRESET_PLAYBACK_SCENE.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'PRESET_STATUS' def Test(self): self.AddIfSetSupported(self.NackSetResult(RDMNack.NR_DATA_OUT_OF_RANGE)) data = self.BuildPresetStatus(0xffff) self.SendRawSet(ROOT_DEVICE, self.pid, data) class SetOutOfRangePresetStatus(TestMixins.SetPresetStatusMixin, OptionalParameterTestFixture): """Set the PRESET_STATUS for max_scene + 1.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'PRESET_STATUS' REQUIRES = ['max_scene_number', 'preset_info'] def Test(self): max_scene = self.Property('max_scene_number') if max_scene is None or max_scene == 0xfffe: self.SetNotRun('Device supports all scenes') return self.AddIfSetSupported(self.NackSetResult(RDMNack.NR_DATA_OUT_OF_RANGE)) data = self.BuildPresetStatus(max_scene + 1) self.SendRawSet(ROOT_DEVICE, self.pid, data) class ClearReadOnlyPresetStatus(OptionalParameterTestFixture): """Attempt to clear a read only preset.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'PRESET_STATUS' REQUIRES = ['scene_writable_states', 'preset_info'] def Test(self): self.scene = None scene_writable_states = self.Property('scene_writable_states') if scene_writable_states is not None: for scene_number, is_writeable in scene_writable_states.iteritems(): if not is_writeable: self.scene = scene_number break if self.scene is None: self.SetNotRun('No read-only scenes found') return preset_info = self.Property('preset_info') fade_time = 0 wait_time = 0 if preset_info: fade_time = preset_info['min_preset_fade_time'] wait_time = preset_info['min_preset_wait_time'] # Don't use AddIfSetSupported here, because we don't want to log an # advisory for NR_WRITE_PROTECT if self.PidSupported(): results = self.NackSetResult(RDMNack.NR_WRITE_PROTECT) else: results = self.NackSetResult(RDMNack.NR_UNKNOWN_PID) self.AddExpectedResults(results) self.SendSet(ROOT_DEVICE, self.pid, [self.scene, fade_time, fade_time, wait_time, True]) class SetPresetStatus(OptionalParameterTestFixture): """Set the PRESET_STATUS.""" CATEGORY = TestCategory.CONTROL PID = 'PRESET_STATUS' REQUIRES = ['scene_writable_states', 'preset_info'] def Test(self): self.scene = None scene_writable_states = self.Property('scene_writable_states') if scene_writable_states is not None: for scene_number, is_writeable in scene_writable_states.iteritems(): if is_writeable: self.scene = scene_number break if self.scene is None: self.SetNotRun('No writeable scenes found') return self.max_fade = round(self.pid.GetRequestField( RDM_SET, 'up_fade_time').RawValue(0xffff), 1) self.max_wait = round(self.pid.GetRequestField( RDM_SET, 'wait_time').RawValue(0xffff), 1) preset_info = self.Property('preset_info') if preset_info is not None: self.max_fade = round(preset_info['max_preset_fade_time'], 1) self.max_wait = round(preset_info['max_preset_wait_time'], 1) self.AddIfSetSupported(self.AckSetResult(action=self.VerifySet)) self.SendSet(ROOT_DEVICE, self.pid, [self.scene, self.max_fade, self.max_fade, self.max_wait, False]) def VerifySet(self): self.AddExpectedResults(self.AckGetResult(field_values={ 'up_fade_time': self.max_fade, 'wait_time': self.max_wait, 'scene_number': self.scene, 'down_fade_time': self.max_fade, })) self.SendGet(ROOT_DEVICE, self.pid, [self.scene]) class ClearPresetStatus(OptionalParameterTestFixture): """Set the PRESET_STATUS with clear preset = 1""" CATEGORY = TestCategory.CONTROL PID = 'PRESET_STATUS' REQUIRES = ['scene_writable_states', 'preset_info'] def Test(self): self.scene = None scene_writable_states = self.Property('scene_writable_states') if scene_writable_states is not None: for scene_number, is_writeable in scene_writable_states.iteritems(): if is_writeable: self.scene = scene_number break if self.scene is None: self.SetNotRun('No writeable scenes found') return self.AddIfSetSupported(self.AckSetResult(action=self.VerifySet)) # We use made up values here to check that the device doesn't use them self.SendSet(ROOT_DEVICE, self.pid, [self.scene, 10, 10, 20, True]) def VerifySet(self): self.AddExpectedResults(self.AckGetResult(field_values={ 'up_fade_time': 0.0, 'wait_time': 0.0, 'scene_number': self.scene, 'programmed': 0, 'down_fade_time': 0.0, })) self.SendGet(ROOT_DEVICE, self.pid, [self.scene]) class AllSubDevicesGetPresetStatus(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Get PRESET_STATUS addressed to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'PRESET_STATUS' DATA = [1] # PRESET_MERGEMODE # ----------------------------------------------------------------------------- class GetPresetMergeMode(TestMixins.GetMixin, OptionalParameterTestFixture): """Get PRESET_MERGEMODE.""" CATEGORY = TestCategory.CONTROL PID = 'PRESET_MERGEMODE' PROVIDES = ['preset_mergemode'] def Test(self): self.AddIfGetSupported(self.AckGetResult()) self.SendGet(ROOT_DEVICE, self.pid) def VerifyResult(self, response, fields): if not response.WasAcked(): self.SetProperty('preset_mergemode', None) return self.SetProperty('preset_mergemode', fields['merge_mode']) class GetPresetMergeModeWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """Get PRESET_MERGEMODE with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'PRESET_MERGEMODE' class SetPresetMergeMode(OptionalParameterTestFixture): """Set PRESET_MERGEMODE.""" CATEGORY = TestCategory.CONTROL PID = 'PRESET_MERGEMODE' REQUIRES = ['preset_mergemode'] PROVIDES = ['set_preset_mergemode_supported'] def Test(self): self.value = self.Property('preset_mergemode') if self.value is None: self.value = 0 self.in_set = True self.AddIfSetSupported([ self.AckSetResult(action=self.VerifySet), self.NackSetResult( RDMNack.NR_UNSUPPORTED_COMMAND_CLASS, advisory='SET for %s returned unsupported command class' % self.PID), ]) self.SendSet(ROOT_DEVICE, self.pid, [self.value]) def VerifySet(self): self.AddExpectedResults( self.AckGetResult(field_values={'merge_mode': self.value})) self.SendGet(ROOT_DEVICE, self.pid) def VerifyResult(self, response, fields): if self.in_set: self.SetProperty(self.PROVIDES[0], response.WasAcked()) self.in_set = False class SetAllPresetMergeModes(OptionalParameterTestFixture): """Set PRESET_MERGEMODE to each of the defined values.""" CATEGORY = TestCategory.CONTROL PID = 'PRESET_MERGEMODE' REQUIRES = ['preset_mergemode', 'set_preset_mergemode_supported'] MODES = [0, 1, 2, 3, 0xff] def Test(self): if not self.Property('set_preset_mergemode_supported'): self.SetNotRun('SET PRESET_MERGEMODE not supported') return self.old_value = self.Property('preset_mergemode') self.merge_modes = [m for m in self.MODES if m != self.old_value] # PerformSet pop's the last value, so we add a dummy value to the end of # the list. self.merge_modes.append(self.old_value) self.PerformSet() def PerformSet(self): self.merge_modes.pop() if not self.merge_modes: self.Stop() return self.AddIfSetSupported([ self.AckSetResult(action=self.VerifySet), self.NackSetResult(RDMNack.NR_DATA_OUT_OF_RANGE, action=self.PerformSet), ]) self.SendSet(ROOT_DEVICE, self.pid, [self.merge_modes[-1]]) def VerifySet(self): self.AddExpectedResults( self.AckGetResult(field_values={'merge_mode': self.merge_modes[-1]}, action=self.PerformSet)) self.SendGet(ROOT_DEVICE, self.pid) def ResetState(self): self.AddExpectedResults(self.AckSetResult()) self.SendSet(ROOT_DEVICE, self.pid, [self.old_value]) self._wrapper.Run() class SetPresetMergeModeWithNoData(TestMixins.SetWithNoDataMixin, OptionalParameterTestFixture): """Set PRESET_MERGEMODE without any data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'PRESET_MERGEMODE' class AllSubDevicesGetPresetMergeMode(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Get PRESET_MERGEMODE addressed to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'PRESET_MERGEMODE' # LIST_INTERFACES # ----------------------------------------------------------------------------- class GetListInterfaces(TestMixins.GetMixin, OptionalParameterTestFixture): """Get LIST_INTERFACES.""" CATEGORY = TestCategory.IP_DNS_CONFIGURATION PID = 'LIST_INTERFACES' PROVIDES = ['interface_list'] def Test(self): self.AddIfGetSupported(self.AckGetResult()) self.SendGet(ROOT_DEVICE, self.pid) def VerifyResult(self, response, fields): if not response.WasAcked(): self.SetProperty(self.PROVIDES[0], []) return interfaces = [] for interface in fields['interfaces']: interface_id = interface['interface_identifier'] interfaces.append(interface_id) if (interface_id < RDM_INTERFACE_INDEX_MIN or interface_id > RDM_INTERFACE_INDEX_MAX): self.AddWarning('Interface index %d is outside allowed range (%d to ' '%d)' % (interface_id, RDM_INTERFACE_INDEX_MIN, RDM_INTERFACE_INDEX_MAX)) if (interface['interface_hardware_type'] != INTERFACE_HARDWARE_TYPE_ETHERNET): self.AddAdvisory('Possible error, found unusual hardware type %d for ' 'interface %d' % (interface['interface_hardware_type'], interface_id)) self.SetProperty(self.PROVIDES[0], interfaces) class GetListInterfacesWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """Get LIST_INTERFACES with extra data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'LIST_INTERFACES' class SetListInterfaces(TestMixins.UnsupportedSetMixin, OptionalParameterTestFixture): """Attempt to SET list interfaces.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'LIST_INTERFACES' # DNS_HOSTNAME # ----------------------------------------------------------------------------- class GetDNSHostname(TestMixins.GetStringMixin, OptionalParameterTestFixture): """GET the DNS hostname.""" CATEGORY = TestCategory.IP_DNS_CONFIGURATION PID = 'DNS_HOSTNAME' EXPECTED_FIELDS = ['dns_hostname'] ALLOWED_NACKS = [RDMNack.NR_HARDWARE_FAULT] MIN_LENGTH = RDM_MIN_HOSTNAME_LENGTH MAX_LENGTH = RDM_MAX_HOSTNAME_LENGTH class GetDNSHostnameWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """Get DNS hostname with param data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'DNS_HOSTNAME' # TODO(Peter): Need to test set class AllSubDevicesGetDNSHostname(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get DNS_HOSTNAME to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'DNS_HOSTNAME' # DNS_DOMAIN_NAME # ----------------------------------------------------------------------------- class GetDNSDomainName(TestMixins.GetStringMixin, OptionalParameterTestFixture): """GET the DNS domain name.""" CATEGORY = TestCategory.IP_DNS_CONFIGURATION PID = 'DNS_DOMAIN_NAME' EXPECTED_FIELDS = ['dns_domain_name'] ALLOWED_NACKS = [RDMNack.NR_HARDWARE_FAULT] MAX_LENGTH = RDM_MAX_DOMAIN_NAME_LENGTH class GetDNSDomainNameWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """Get DNS domain name with param data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'DNS_DOMAIN_NAME' # TODO(Peter): Need to test set class AllSubDevicesGetDNSDomainName(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get DNS_DOMAIN_NAME to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'DNS_DOMAIN_NAME' # IPV4_DEFAULT_ROUTE # ----------------------------------------------------------------------------- class GetIPv4DefaultRoute(TestMixins.GetMixin, OptionalParameterTestFixture): """GET the IPv4 default route.""" # TODO(Peter): Check interface identifier is a valid interface CATEGORY = TestCategory.IP_DNS_CONFIGURATION PID = 'IPV4_DEFAULT_ROUTE' EXPECTED_FIELDS = ['ipv4_address', 'interface_identifier'] class GetIPv4DefaultRouteWithData(TestMixins.GetWithDataMixin, OptionalParameterTestFixture): """Get IPv4 default route with param data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'IPV4_DEFAULT_ROUTE' # TODO(Peter): Need to restrict these somehow so we don't saw off the branch # class SetIPv4DefaultRoute(TestMixins.UnsupportedSetMixin, # OptionalParameterTestFixture): # """Attempt to SET the IPv4 default route with no data.""" # CATEGORY = TestCategory.ERROR_CONDITIONS # PID = 'IPV4_DEFAULT_ROUTE' # # # class SetIPv4DefaultRouteWithData(TestMixins.UnsupportedSetMixin, # OptionalParameterTestFixture): # """SET the IPv4 default route with data.""" # CATEGORY = TestCategory.ERROR_CONDITIONS # PID = 'IPV4_DEFAULT_ROUTE' # DATA = 'FOOBAR' class AllSubDevicesGetIPv4DefaultRoute(TestMixins.AllSubDevicesGetMixin, OptionalParameterTestFixture): """Send a Get IPV4_DEFAULT_ROUTE to ALL_SUB_DEVICES.""" CATEGORY = TestCategory.SUB_DEVICES PID = 'IPV4_DEFAULT_ROUTE' # Interface label # ----------------------------------------------------------------------------- class GetInterfaceLabels(TestMixins.GetSettingDescriptionsListMixin, OptionalParameterTestFixture): """Get the interface labels for all defined interfaces.""" CATEGORY = TestCategory.IP_DNS_CONFIGURATION PID = 'INTERFACE_LABEL' REQUIRES = ['interface_list'] EXPECTED_FIELDS = ['interface_identifier'] DESCRIPTION_FIELD = 'interface_label' class GetInterfaceLabelWithNoData(TestMixins.GetWithNoDataMixin, OptionalParameterTestFixture): """Get the interface label with no interface id specified.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'INTERFACE_LABEL' class GetInterfaceLabelWithTooMuchData(OptionalParameterTestFixture): """Get the interface label with more than 4 bytes of data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'INTERFACE_LABEL' def Test(self): self.AddIfGetSupported(self.NackGetResult(RDMNack.NR_FORMAT_ERROR)) self.SendRawGet(ROOT_DEVICE, self.pid, 'foobar') class GetZeroInterfaceLabel(TestMixins.GetZeroUInt32Mixin, OptionalParameterTestFixture): """GET INTERFACE_LABEL for interface 0.""" PID = 'INTERFACE_LABEL' class SetInterfaceLabel(TestMixins.UnsupportedSetMixin, OptionalParameterTestFixture): """Attempt to SET the interface label with no data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'INTERFACE_LABEL' class SetInterfaceLabelWithData(TestMixins.UnsupportedSetMixin, OptionalParameterTestFixture): """SET the interface label with data.""" CATEGORY = TestCategory.ERROR_CONDITIONS PID = 'INTERFACE_LABEL' DATA = 'FOO BAR' # Cross check the control fields with various other properties # ----------------------------------------------------------------------------- class SubDeviceControlField(TestFixture): """Check that the sub device control field is correct.""" CATEGORY = TestCategory.CORE REQUIRES = ['mute_control_fields', 'sub_device_count'] def Test(self): sub_device_field = self.Property('mute_control_fields') & 0x02 if self.Property('sub_device_count') > 0: if sub_device_field == 0: self.SetFailed('Sub devices reported but control field not set') return else: if sub_device_field: self.SetFailed('No Sub devices reported but control field is set') return self.SetPassed() class ProxiedDevicesControlField(TestFixture): """Check that the proxied devices control field is correct.""" CATEGORY = TestCategory.CORE REQUIRES = ['mute_control_fields', 'supported_parameters'] def Test(self): proxied_devices_pid = self.LookupPid('PROXIED_DEVICES') supports_proxied_devices_pid = ( proxied_devices_pid.value in self.Property('supported_parameters')) managed_proxy_field = self.Property('mute_control_fields') & 0x01 if supports_proxied_devices_pid and managed_proxy_field == 0: self.AddWarning( "Support for PROXIED_DEVICES declared but the managed " "proxy control field isn't set") return elif not supports_proxied_devices_pid and managed_proxy_field == 1: self.SetFailed( "Managed proxy control bit is set, but proxied devices isn't " "supported") return self.SetPassed() ola-0.10.5.nojsmin/tools/rdm/static/0000755000175000017500000000000013155164234016675 5ustar wouterwouterola-0.10.5.nojsmin/tools/rdm/static/rdm_tests.js0000644000175000017500000007215013023355232021236 0ustar wouterwouter/** * 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Copyright (C) 2012 Ravindra Nath Kakarla & Simon Newton */ // Global variable that holds the RDMTests object rdmtests = undefined; /** * RDMTests class */ RDMTests = function() { // An array to hold the test results this.test_results = new Array(); this.tests_running = false; // init tabs $('#tabs').tabs({}); // setup dialog windows, one for general notifications and one for the // download options. this.notification = $('#rdm-tests-notification'); this.notification.dialog({ autoOpen: false, closeOnEscape: false, dialogClass: 'no-close', draggable: false, height: 160, modal: true, resizable: false, }); this.save_options = $('#rdm-tests-save-options'); var save_buttons = [ { text: 'Cancel', click: function() { $(this).dialog('close'); } }, { text: 'Download', click: function() { rdmtests.save_results() } }, ]; this.save_options.dialog({ autoOpen: false, draggable: false, height: 200, modal: true, resizable: false, title: 'Download Options', buttons: save_buttons, }); this.error_notification = $('#rdm-error-notification'); var error_buttons = [ { text: 'Dismiss', click: function() { $(this).dialog('close'); } }, { text: 'Report Bug', click: function() { rdmtests.report_bug() } }, ]; this.error_notification.dialog({ autoOpen: false, buttons: error_buttons, draggable: true, height: 300, modal: true, resizable: true, width: 550, }); //Populate the filter with test categories $('#rdm-tests-results-summary-filter-by_catg') .append($('